* Re: [PATCH 2/9] mm: alloc_contig_freed_pages() added
From: Michal Nazarewicz @ 2011-10-24 4:05 UTC (permalink / raw)
To: Marek Szyprowski, Mel Gorman
Cc: Ankita Garg, Daniel Walker, Russell King, Arnd Bergmann,
Jesse Barker, Chunsang Jeong, Jonathan Corbet, linux-kernel,
Dave Hansen, linaro-mm-sig, linux-mm, Kyungmin Park,
KAMEZAWA Hiroyuki, Shariq Hasnain, Andrew Morton,
linux-arm-kernel, linux-media
In-Reply-To: <20111018122109.GB6660@csn.ul.ie>
> On Thu, Oct 06, 2011 at 03:54:42PM +0200, Marek Szyprowski wrote:
>> This commit introduces alloc_contig_freed_pages() function
>> which allocates (ie. removes from buddy system) free pages
>> in range. Caller has to guarantee that all pages in range
>> are in buddy system.
On Tue, 18 Oct 2011 05:21:09 -0700, Mel Gorman <mel@csn.ul.ie> wrote:
> Straight away, I'm wondering why you didn't use
> mm/compaction.c#isolate_freepages()
Does the below look like a step in the right direction?
It basically moves isolate_freepages_block() to page_alloc.c (changing
it name to isolate_freepages_range()) and changes it so that depending
on arguments it treats holes (either invalid PFN or non-free page) as
errors so that CMA can use it.
It also accepts a range rather then just assuming a single pageblock
thus the change moves range calculation in compaction.c from
isolate_freepages_block() up to isolate_freepages().
The change also modifies spilt_free_page() so that it does not try to
change pageblock's migrate type if current migrate type is ISOLATE or
CMA.
---
include/linux/mm.h | 1 -
include/linux/page-isolation.h | 4 +-
mm/compaction.c | 73 +++--------------------
mm/internal.h | 5 ++
mm/page_alloc.c | 128 +++++++++++++++++++++++++---------------
5 files changed, 95 insertions(+), 116 deletions(-)
diff --git a/include/linux/mm.h b/include/linux/mm.h
index fd599f4..98c99c4 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -435,7 +435,6 @@ void put_page(struct page *page);
void put_pages_list(struct list_head *pages);
void split_page(struct page *page, unsigned int order);
-int split_free_page(struct page *page);
/*
* Compound pages have a destructor function. Provide a
diff --git a/include/linux/page-isolation.h b/include/linux/page-isolation.h
index 003c52f..6becc74 100644
--- a/include/linux/page-isolation.h
+++ b/include/linux/page-isolation.h
@@ -48,10 +48,8 @@ static inline void unset_migratetype_isolate(struct page *page)
}
/* The below functions must be run on a range from a single zone. */
-extern unsigned long alloc_contig_freed_pages(unsigned long start,
- unsigned long end, gfp_t flag);
extern int alloc_contig_range(unsigned long start, unsigned long end,
- gfp_t flags, unsigned migratetype);
+ unsigned migratetype);
extern void free_contig_pages(unsigned long pfn, unsigned nr_pages);
/*
diff --git a/mm/compaction.c b/mm/compaction.c
index 9e5cc59..685a19e 100644
--- a/mm/compaction.c
+++ b/mm/compaction.c
@@ -58,77 +58,15 @@ static unsigned long release_freepages(struct list_head *freelist)
return count;
}
-/* Isolate free pages onto a private freelist. Must hold zone->lock */
-static unsigned long isolate_freepages_block(struct zone *zone,
- unsigned long blockpfn,
- struct list_head *freelist)
-{
- unsigned long zone_end_pfn, end_pfn;
- int nr_scanned = 0, total_isolated = 0;
- struct page *cursor;
-
- /* Get the last PFN we should scan for free pages at */
- zone_end_pfn = zone->zone_start_pfn + zone->spanned_pages;
- end_pfn = min(blockpfn + pageblock_nr_pages, zone_end_pfn);
-
- /* Find the first usable PFN in the block to initialse page cursor */
- for (; blockpfn < end_pfn; blockpfn++) {
- if (pfn_valid_within(blockpfn))
- break;
- }
- cursor = pfn_to_page(blockpfn);
-
- /* Isolate free pages. This assumes the block is valid */
- for (; blockpfn < end_pfn; blockpfn++, cursor++) {
- int isolated, i;
- struct page *page = cursor;
-
- if (!pfn_valid_within(blockpfn))
- continue;
- nr_scanned++;
-
- if (!PageBuddy(page))
- continue;
-
- /* Found a free page, break it into order-0 pages */
- isolated = split_free_page(page);
- total_isolated += isolated;
- for (i = 0; i < isolated; i++) {
- list_add(&page->lru, freelist);
- page++;
- }
-
- /* If a page was split, advance to the end of it */
- if (isolated) {
- blockpfn += isolated - 1;
- cursor += isolated - 1;
- }
- }
-
- trace_mm_compaction_isolate_freepages(nr_scanned, total_isolated);
- return total_isolated;
-}
-
/* Returns true if the page is within a block suitable for migration to */
static bool suitable_migration_target(struct page *page)
{
-
int migratetype = get_pageblock_migratetype(page);
/* Don't interfere with memory hot-remove or the min_free_kbytes blocks */
if (migratetype == MIGRATE_ISOLATE || migratetype == MIGRATE_RESERVE)
return false;
- /* Keep MIGRATE_CMA alone as well. */
- /*
- * XXX Revisit. We currently cannot let compaction touch CMA
- * pages since compaction insists on changing their migration
- * type to MIGRATE_MOVABLE (see split_free_page() called from
- * isolate_freepages_block() above).
- */
- if (is_migrate_cma(migratetype))
- return false;
-
/* If the page is a large free page, then allow migration */
if (PageBuddy(page) && page_order(page) >= pageblock_order)
return true;
@@ -149,7 +87,7 @@ static void isolate_freepages(struct zone *zone,
struct compact_control *cc)
{
struct page *page;
- unsigned long high_pfn, low_pfn, pfn;
+ unsigned long high_pfn, low_pfn, pfn, zone_end_pfn, end_pfn;
unsigned long flags;
int nr_freepages = cc->nr_freepages;
struct list_head *freelist = &cc->freepages;
@@ -169,6 +107,8 @@ static void isolate_freepages(struct zone *zone,
*/
high_pfn = min(low_pfn, pfn);
+ zone_end_pfn = zone->zone_start_pfn + zone->spanned_pages;
+
/*
* Isolate free pages until enough are available to migrate the
* pages on cc->migratepages. We stop searching if the migrate
@@ -176,7 +116,7 @@ static void isolate_freepages(struct zone *zone,
*/
for (; pfn > low_pfn && cc->nr_migratepages > nr_freepages;
pfn -= pageblock_nr_pages) {
- unsigned long isolated;
+ unsigned isolated, scanned;
if (!pfn_valid(pfn))
continue;
@@ -205,7 +145,10 @@ static void isolate_freepages(struct zone *zone,
isolated = 0;
spin_lock_irqsave(&zone->lock, flags);
if (suitable_migration_target(page)) {
- isolated = isolate_freepages_block(zone, pfn, freelist);
+ end_pfn = min(pfn + pageblock_nr_pages, zone_end_pfn);
+ isolated = isolate_freepages_range(zone, pfn,
+ end_pfn, freelist, &scanned);
+ trace_mm_compaction_isolate_freepages(scanned, isolated);
nr_freepages += isolated;
}
spin_unlock_irqrestore(&zone->lock, flags);
diff --git a/mm/internal.h b/mm/internal.h
index d071d380..4a9bb3f 100644
--- a/mm/internal.h
+++ b/mm/internal.h
@@ -263,3 +263,8 @@ extern u64 hwpoison_filter_flags_mask;
extern u64 hwpoison_filter_flags_value;
extern u64 hwpoison_filter_memcg;
extern u32 hwpoison_filter_enable;
+
+unsigned isolate_freepages_range(struct zone *zone,
+ unsigned long start, unsigned long end,
+ struct list_head *freelist,
+ unsigned *scannedp);
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index df69706..adf3f34 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -1300,10 +1300,11 @@ void split_page(struct page *page, unsigned int order)
* Note: this is probably too low level an operation for use in drivers.
* Please consult with lkml before using this in your driver.
*/
-int split_free_page(struct page *page)
+static unsigned split_free_page(struct page *page)
{
unsigned int order;
unsigned long watermark;
+ struct page *endpage;
struct zone *zone;
BUG_ON(!PageBuddy(page));
@@ -1326,14 +1327,18 @@ int split_free_page(struct page *page)
set_page_refcounted(page);
split_page(page, order);
- if (order >= pageblock_order - 1) {
- struct page *endpage = page + (1 << order) - 1;
- for (; page < endpage; page += pageblock_nr_pages)
- if (!is_pageblock_cma(page))
- set_pageblock_migratetype(page,
- MIGRATE_MOVABLE);
+ if (order < pageblock_order - 1)
+ goto done;
+
+ endpage = page + (1 << order) - 1;
+ for (; page < endpage; page += pageblock_nr_pages) {
+ int mt = get_pageblock_migratetype(page);
+ /* Don't change CMA nor ISOLATE */
+ if (!is_migrate_cma(mt) && mt != MIGRATE_ISOLATE)
+ set_pageblock_migratetype(page, MIGRATE_MOVABLE);
}
+done:
return 1 << order;
}
@@ -5723,57 +5728,76 @@ out:
spin_unlock_irqrestore(&zone->lock, flags);
}
-unsigned long alloc_contig_freed_pages(unsigned long start, unsigned long end,
- gfp_t flag)
+/**
+ * isolate_freepages_range() - isolate free pages, must hold zone->lock.
+ * @zone: Zone pages are in.
+ * @start: The first PFN to start isolating.
+ * @end: The one-past-last PFN.
+ * @freelist: A list to save isolated pages to.
+ * @scannedp: Optional pointer where to save number of scanned pages.
+ *
+ * If @freelist is not provided, holes in range (either non-free pages
+ * or invalid PFN) are considered an error and function undos its
+ * actions and returns zero.
+ *
+ * If @freelist is provided, function will simply skip non-free and
+ * missing pages and put only the ones isolated on the list. It will
+ * also call trace_mm_compaction_isolate_freepages() at the end.
+ *
+ * Returns number of isolated pages. This may be more then end-start
+ * if end fell in a middle of a free page.
+ */
+unsigned isolate_freepages_range(struct zone *zone,
+ unsigned long start, unsigned long end,
+ struct list_head *freelist, unsigned *scannedp)
{
- unsigned long pfn = start, count;
+ unsigned nr_scanned = 0, total_isolated = 0;
+ unsigned long pfn = start;
struct page *page;
- struct zone *zone;
- int order;
VM_BUG_ON(!pfn_valid(start));
- page = pfn_to_page(start);
- zone = page_zone(page);
- spin_lock_irq(&zone->lock);
+ /* Isolate free pages. This assumes the block is valid */
+ page = pfn_to_page(pfn);
+ while (pfn < end) {
+ unsigned isolated = 1;
- for (;;) {
- VM_BUG_ON(!page_count(page) || !PageBuddy(page) ||
- page_zone(page) != zone);
+ VM_BUG_ON(page_zone(page) != zone);
- list_del(&page->lru);
- order = page_order(page);
- count = 1UL << order;
- zone->free_area[order].nr_free--;
- rmv_page_order(page);
- __mod_zone_page_state(zone, NR_FREE_PAGES, -(long)count);
+ if (!pfn_valid_within(blockpfn))
+ goto skip;
+ ++nr_scanned;
- pfn += count;
- if (pfn >= end)
- break;
- VM_BUG_ON(!pfn_valid(pfn));
-
- if (zone_pfn_same_memmap(pfn - count, pfn))
- page += count;
- else
- page = pfn_to_page(pfn);
- }
+ if (!PageBuddy(page)) {
+skip:
+ if (freelist)
+ goto next;
+ for (; start < pfn; ++start)
+ __free_page(pfn_to_page(pfn));
+ return 0;
+ }
- spin_unlock_irq(&zone->lock);
+ /* Found a free page, break it into order-0 pages */
+ isolated = split_free_page(page);
+ total_isolated += isolated;
+ if (freelist) {
+ struct page *p = page;
+ unsigned i = isolated;
+ for (; i--; ++page)
+ list_add(&p->lru, freelist);
+ }
- /* After this, pages in the range can be freed one be one */
- count = pfn - start;
- pfn = start;
- for (page = pfn_to_page(pfn); count; --count) {
- prep_new_page(page, 0, flag);
- ++pfn;
- if (likely(zone_pfn_same_memmap(pfn - 1, pfn)))
- ++page;
+next: /* Advance to the next page */
+ pfn += isolated;
+ if (zone_pfn_same_memmap(pfn - isolated, pfn))
+ page += isolated;
else
page = pfn_to_page(pfn);
}
- return pfn;
+ if (scannedp)
+ *scannedp = nr_scanned;
+ return total_isolated;
}
static unsigned long pfn_to_maxpage(unsigned long pfn)
@@ -5837,7 +5861,6 @@ static int __alloc_contig_migrate_range(unsigned long start, unsigned long end)
* alloc_contig_range() -- tries to allocate given range of pages
* @start: start PFN to allocate
* @end: one-past-the-last PFN to allocate
- * @flags: flags passed to alloc_contig_freed_pages().
* @migratetype: migratetype of the underlaying pageblocks (either
* #MIGRATE_MOVABLE or #MIGRATE_CMA). All pageblocks
* in range must have the same migratetype and it must
@@ -5853,9 +5876,10 @@ static int __alloc_contig_migrate_range(unsigned long start, unsigned long end)
* need to be freed with free_contig_pages().
*/
int alloc_contig_range(unsigned long start, unsigned long end,
- gfp_t flags, unsigned migratetype)
+ unsigned migratetype)
{
unsigned long outer_start, outer_end;
+ struct zone *zone;
int ret;
/*
@@ -5910,7 +5934,17 @@ int alloc_contig_range(unsigned long start, unsigned long end,
return -EINVAL;
outer_start = start & (~0UL << ret);
- outer_end = alloc_contig_freed_pages(outer_start, end, flags);
+
+ zone = page_zone(pfn_to_page(outer_start));
+ spin_lock_irq(&zone->lock);
+ outer_end = isolate_freepages_range(zone, outer_start, end, NULL, NULL);
+ spin_unlock_irq(&zone->lock);
+
+ if (!outer_end) {
+ ret = -EBUSY;
+ goto done;
+ }
+ outer_end += outer_start;
/* Free head and tail (if any) */
if (start != outer_start)
--
1.7.3.1
^ permalink raw reply related
* Re: [PATCH 2/9] mm: alloc_contig_freed_pages() added
From: Michal Nazarewicz @ 2011-10-24 4:05 UTC (permalink / raw)
To: Marek Szyprowski, Mel Gorman
Cc: linux-kernel, linux-arm-kernel, linux-media, linux-mm,
linaro-mm-sig, Kyungmin Park, Russell King, Andrew Morton,
KAMEZAWA Hiroyuki, Ankita Garg, Daniel Walker, Arnd Bergmann,
Jesse Barker, Jonathan Corbet, Shariq Hasnain, Chunsang Jeong,
Dave Hansen
In-Reply-To: <20111018122109.GB6660@csn.ul.ie>
> On Thu, Oct 06, 2011 at 03:54:42PM +0200, Marek Szyprowski wrote:
>> This commit introduces alloc_contig_freed_pages() function
>> which allocates (ie. removes from buddy system) free pages
>> in range. Caller has to guarantee that all pages in range
>> are in buddy system.
On Tue, 18 Oct 2011 05:21:09 -0700, Mel Gorman <mel@csn.ul.ie> wrote:
> Straight away, I'm wondering why you didn't use
> mm/compaction.c#isolate_freepages()
Does the below look like a step in the right direction?
It basically moves isolate_freepages_block() to page_alloc.c (changing
it name to isolate_freepages_range()) and changes it so that depending
on arguments it treats holes (either invalid PFN or non-free page) as
errors so that CMA can use it.
It also accepts a range rather then just assuming a single pageblock
thus the change moves range calculation in compaction.c from
isolate_freepages_block() up to isolate_freepages().
The change also modifies spilt_free_page() so that it does not try to
change pageblock's migrate type if current migrate type is ISOLATE or
CMA.
---
include/linux/mm.h | 1 -
include/linux/page-isolation.h | 4 +-
mm/compaction.c | 73 +++--------------------
mm/internal.h | 5 ++
mm/page_alloc.c | 128 +++++++++++++++++++++++++---------------
5 files changed, 95 insertions(+), 116 deletions(-)
diff --git a/include/linux/mm.h b/include/linux/mm.h
index fd599f4..98c99c4 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -435,7 +435,6 @@ void put_page(struct page *page);
void put_pages_list(struct list_head *pages);
void split_page(struct page *page, unsigned int order);
-int split_free_page(struct page *page);
/*
* Compound pages have a destructor function. Provide a
diff --git a/include/linux/page-isolation.h b/include/linux/page-isolation.h
index 003c52f..6becc74 100644
--- a/include/linux/page-isolation.h
+++ b/include/linux/page-isolation.h
@@ -48,10 +48,8 @@ static inline void unset_migratetype_isolate(struct page *page)
}
/* The below functions must be run on a range from a single zone. */
-extern unsigned long alloc_contig_freed_pages(unsigned long start,
- unsigned long end, gfp_t flag);
extern int alloc_contig_range(unsigned long start, unsigned long end,
- gfp_t flags, unsigned migratetype);
+ unsigned migratetype);
extern void free_contig_pages(unsigned long pfn, unsigned nr_pages);
/*
diff --git a/mm/compaction.c b/mm/compaction.c
index 9e5cc59..685a19e 100644
--- a/mm/compaction.c
+++ b/mm/compaction.c
@@ -58,77 +58,15 @@ static unsigned long release_freepages(struct list_head *freelist)
return count;
}
-/* Isolate free pages onto a private freelist. Must hold zone->lock */
-static unsigned long isolate_freepages_block(struct zone *zone,
- unsigned long blockpfn,
- struct list_head *freelist)
-{
- unsigned long zone_end_pfn, end_pfn;
- int nr_scanned = 0, total_isolated = 0;
- struct page *cursor;
-
- /* Get the last PFN we should scan for free pages at */
- zone_end_pfn = zone->zone_start_pfn + zone->spanned_pages;
- end_pfn = min(blockpfn + pageblock_nr_pages, zone_end_pfn);
-
- /* Find the first usable PFN in the block to initialse page cursor */
- for (; blockpfn < end_pfn; blockpfn++) {
- if (pfn_valid_within(blockpfn))
- break;
- }
- cursor = pfn_to_page(blockpfn);
-
- /* Isolate free pages. This assumes the block is valid */
- for (; blockpfn < end_pfn; blockpfn++, cursor++) {
- int isolated, i;
- struct page *page = cursor;
-
- if (!pfn_valid_within(blockpfn))
- continue;
- nr_scanned++;
-
- if (!PageBuddy(page))
- continue;
-
- /* Found a free page, break it into order-0 pages */
- isolated = split_free_page(page);
- total_isolated += isolated;
- for (i = 0; i < isolated; i++) {
- list_add(&page->lru, freelist);
- page++;
- }
-
- /* If a page was split, advance to the end of it */
- if (isolated) {
- blockpfn += isolated - 1;
- cursor += isolated - 1;
- }
- }
-
- trace_mm_compaction_isolate_freepages(nr_scanned, total_isolated);
- return total_isolated;
-}
-
/* Returns true if the page is within a block suitable for migration to */
static bool suitable_migration_target(struct page *page)
{
-
int migratetype = get_pageblock_migratetype(page);
/* Don't interfere with memory hot-remove or the min_free_kbytes blocks */
if (migratetype == MIGRATE_ISOLATE || migratetype == MIGRATE_RESERVE)
return false;
- /* Keep MIGRATE_CMA alone as well. */
- /*
- * XXX Revisit. We currently cannot let compaction touch CMA
- * pages since compaction insists on changing their migration
- * type to MIGRATE_MOVABLE (see split_free_page() called from
- * isolate_freepages_block() above).
- */
- if (is_migrate_cma(migratetype))
- return false;
-
/* If the page is a large free page, then allow migration */
if (PageBuddy(page) && page_order(page) >= pageblock_order)
return true;
@@ -149,7 +87,7 @@ static void isolate_freepages(struct zone *zone,
struct compact_control *cc)
{
struct page *page;
- unsigned long high_pfn, low_pfn, pfn;
+ unsigned long high_pfn, low_pfn, pfn, zone_end_pfn, end_pfn;
unsigned long flags;
int nr_freepages = cc->nr_freepages;
struct list_head *freelist = &cc->freepages;
@@ -169,6 +107,8 @@ static void isolate_freepages(struct zone *zone,
*/
high_pfn = min(low_pfn, pfn);
+ zone_end_pfn = zone->zone_start_pfn + zone->spanned_pages;
+
/*
* Isolate free pages until enough are available to migrate the
* pages on cc->migratepages. We stop searching if the migrate
@@ -176,7 +116,7 @@ static void isolate_freepages(struct zone *zone,
*/
for (; pfn > low_pfn && cc->nr_migratepages > nr_freepages;
pfn -= pageblock_nr_pages) {
- unsigned long isolated;
+ unsigned isolated, scanned;
if (!pfn_valid(pfn))
continue;
@@ -205,7 +145,10 @@ static void isolate_freepages(struct zone *zone,
isolated = 0;
spin_lock_irqsave(&zone->lock, flags);
if (suitable_migration_target(page)) {
- isolated = isolate_freepages_block(zone, pfn, freelist);
+ end_pfn = min(pfn + pageblock_nr_pages, zone_end_pfn);
+ isolated = isolate_freepages_range(zone, pfn,
+ end_pfn, freelist, &scanned);
+ trace_mm_compaction_isolate_freepages(scanned, isolated);
nr_freepages += isolated;
}
spin_unlock_irqrestore(&zone->lock, flags);
diff --git a/mm/internal.h b/mm/internal.h
index d071d380..4a9bb3f 100644
--- a/mm/internal.h
+++ b/mm/internal.h
@@ -263,3 +263,8 @@ extern u64 hwpoison_filter_flags_mask;
extern u64 hwpoison_filter_flags_value;
extern u64 hwpoison_filter_memcg;
extern u32 hwpoison_filter_enable;
+
+unsigned isolate_freepages_range(struct zone *zone,
+ unsigned long start, unsigned long end,
+ struct list_head *freelist,
+ unsigned *scannedp);
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index df69706..adf3f34 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -1300,10 +1300,11 @@ void split_page(struct page *page, unsigned int order)
* Note: this is probably too low level an operation for use in drivers.
* Please consult with lkml before using this in your driver.
*/
-int split_free_page(struct page *page)
+static unsigned split_free_page(struct page *page)
{
unsigned int order;
unsigned long watermark;
+ struct page *endpage;
struct zone *zone;
BUG_ON(!PageBuddy(page));
@@ -1326,14 +1327,18 @@ int split_free_page(struct page *page)
set_page_refcounted(page);
split_page(page, order);
- if (order >= pageblock_order - 1) {
- struct page *endpage = page + (1 << order) - 1;
- for (; page < endpage; page += pageblock_nr_pages)
- if (!is_pageblock_cma(page))
- set_pageblock_migratetype(page,
- MIGRATE_MOVABLE);
+ if (order < pageblock_order - 1)
+ goto done;
+
+ endpage = page + (1 << order) - 1;
+ for (; page < endpage; page += pageblock_nr_pages) {
+ int mt = get_pageblock_migratetype(page);
+ /* Don't change CMA nor ISOLATE */
+ if (!is_migrate_cma(mt) && mt != MIGRATE_ISOLATE)
+ set_pageblock_migratetype(page, MIGRATE_MOVABLE);
}
+done:
return 1 << order;
}
@@ -5723,57 +5728,76 @@ out:
spin_unlock_irqrestore(&zone->lock, flags);
}
-unsigned long alloc_contig_freed_pages(unsigned long start, unsigned long end,
- gfp_t flag)
+/**
+ * isolate_freepages_range() - isolate free pages, must hold zone->lock.
+ * @zone: Zone pages are in.
+ * @start: The first PFN to start isolating.
+ * @end: The one-past-last PFN.
+ * @freelist: A list to save isolated pages to.
+ * @scannedp: Optional pointer where to save number of scanned pages.
+ *
+ * If @freelist is not provided, holes in range (either non-free pages
+ * or invalid PFN) are considered an error and function undos its
+ * actions and returns zero.
+ *
+ * If @freelist is provided, function will simply skip non-free and
+ * missing pages and put only the ones isolated on the list. It will
+ * also call trace_mm_compaction_isolate_freepages() at the end.
+ *
+ * Returns number of isolated pages. This may be more then end-start
+ * if end fell in a middle of a free page.
+ */
+unsigned isolate_freepages_range(struct zone *zone,
+ unsigned long start, unsigned long end,
+ struct list_head *freelist, unsigned *scannedp)
{
- unsigned long pfn = start, count;
+ unsigned nr_scanned = 0, total_isolated = 0;
+ unsigned long pfn = start;
struct page *page;
- struct zone *zone;
- int order;
VM_BUG_ON(!pfn_valid(start));
- page = pfn_to_page(start);
- zone = page_zone(page);
- spin_lock_irq(&zone->lock);
+ /* Isolate free pages. This assumes the block is valid */
+ page = pfn_to_page(pfn);
+ while (pfn < end) {
+ unsigned isolated = 1;
- for (;;) {
- VM_BUG_ON(!page_count(page) || !PageBuddy(page) ||
- page_zone(page) != zone);
+ VM_BUG_ON(page_zone(page) != zone);
- list_del(&page->lru);
- order = page_order(page);
- count = 1UL << order;
- zone->free_area[order].nr_free--;
- rmv_page_order(page);
- __mod_zone_page_state(zone, NR_FREE_PAGES, -(long)count);
+ if (!pfn_valid_within(blockpfn))
+ goto skip;
+ ++nr_scanned;
- pfn += count;
- if (pfn >= end)
- break;
- VM_BUG_ON(!pfn_valid(pfn));
-
- if (zone_pfn_same_memmap(pfn - count, pfn))
- page += count;
- else
- page = pfn_to_page(pfn);
- }
+ if (!PageBuddy(page)) {
+skip:
+ if (freelist)
+ goto next;
+ for (; start < pfn; ++start)
+ __free_page(pfn_to_page(pfn));
+ return 0;
+ }
- spin_unlock_irq(&zone->lock);
+ /* Found a free page, break it into order-0 pages */
+ isolated = split_free_page(page);
+ total_isolated += isolated;
+ if (freelist) {
+ struct page *p = page;
+ unsigned i = isolated;
+ for (; i--; ++page)
+ list_add(&p->lru, freelist);
+ }
- /* After this, pages in the range can be freed one be one */
- count = pfn - start;
- pfn = start;
- for (page = pfn_to_page(pfn); count; --count) {
- prep_new_page(page, 0, flag);
- ++pfn;
- if (likely(zone_pfn_same_memmap(pfn - 1, pfn)))
- ++page;
+next: /* Advance to the next page */
+ pfn += isolated;
+ if (zone_pfn_same_memmap(pfn - isolated, pfn))
+ page += isolated;
else
page = pfn_to_page(pfn);
}
- return pfn;
+ if (scannedp)
+ *scannedp = nr_scanned;
+ return total_isolated;
}
static unsigned long pfn_to_maxpage(unsigned long pfn)
@@ -5837,7 +5861,6 @@ static int __alloc_contig_migrate_range(unsigned long start, unsigned long end)
* alloc_contig_range() -- tries to allocate given range of pages
* @start: start PFN to allocate
* @end: one-past-the-last PFN to allocate
- * @flags: flags passed to alloc_contig_freed_pages().
* @migratetype: migratetype of the underlaying pageblocks (either
* #MIGRATE_MOVABLE or #MIGRATE_CMA). All pageblocks
* in range must have the same migratetype and it must
@@ -5853,9 +5876,10 @@ static int __alloc_contig_migrate_range(unsigned long start, unsigned long end)
* need to be freed with free_contig_pages().
*/
int alloc_contig_range(unsigned long start, unsigned long end,
- gfp_t flags, unsigned migratetype)
+ unsigned migratetype)
{
unsigned long outer_start, outer_end;
+ struct zone *zone;
int ret;
/*
@@ -5910,7 +5934,17 @@ int alloc_contig_range(unsigned long start, unsigned long end,
return -EINVAL;
outer_start = start & (~0UL << ret);
- outer_end = alloc_contig_freed_pages(outer_start, end, flags);
+
+ zone = page_zone(pfn_to_page(outer_start));
+ spin_lock_irq(&zone->lock);
+ outer_end = isolate_freepages_range(zone, outer_start, end, NULL, NULL);
+ spin_unlock_irq(&zone->lock);
+
+ if (!outer_end) {
+ ret = -EBUSY;
+ goto done;
+ }
+ outer_end += outer_start;
/* Free head and tail (if any) */
if (start != outer_start)
--
1.7.3.1
^ permalink raw reply related
* [PATCH 2/9] mm: alloc_contig_freed_pages() added
From: Michal Nazarewicz @ 2011-10-24 4:05 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20111018122109.GB6660@csn.ul.ie>
> On Thu, Oct 06, 2011 at 03:54:42PM +0200, Marek Szyprowski wrote:
>> This commit introduces alloc_contig_freed_pages() function
>> which allocates (ie. removes from buddy system) free pages
>> in range. Caller has to guarantee that all pages in range
>> are in buddy system.
On Tue, 18 Oct 2011 05:21:09 -0700, Mel Gorman <mel@csn.ul.ie> wrote:
> Straight away, I'm wondering why you didn't use
> mm/compaction.c#isolate_freepages()
Does the below look like a step in the right direction?
It basically moves isolate_freepages_block() to page_alloc.c (changing
it name to isolate_freepages_range()) and changes it so that depending
on arguments it treats holes (either invalid PFN or non-free page) as
errors so that CMA can use it.
It also accepts a range rather then just assuming a single pageblock
thus the change moves range calculation in compaction.c from
isolate_freepages_block() up to isolate_freepages().
The change also modifies spilt_free_page() so that it does not try to
change pageblock's migrate type if current migrate type is ISOLATE or
CMA.
---
include/linux/mm.h | 1 -
include/linux/page-isolation.h | 4 +-
mm/compaction.c | 73 +++--------------------
mm/internal.h | 5 ++
mm/page_alloc.c | 128 +++++++++++++++++++++++++---------------
5 files changed, 95 insertions(+), 116 deletions(-)
diff --git a/include/linux/mm.h b/include/linux/mm.h
index fd599f4..98c99c4 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -435,7 +435,6 @@ void put_page(struct page *page);
void put_pages_list(struct list_head *pages);
void split_page(struct page *page, unsigned int order);
-int split_free_page(struct page *page);
/*
* Compound pages have a destructor function. Provide a
diff --git a/include/linux/page-isolation.h b/include/linux/page-isolation.h
index 003c52f..6becc74 100644
--- a/include/linux/page-isolation.h
+++ b/include/linux/page-isolation.h
@@ -48,10 +48,8 @@ static inline void unset_migratetype_isolate(struct page *page)
}
/* The below functions must be run on a range from a single zone. */
-extern unsigned long alloc_contig_freed_pages(unsigned long start,
- unsigned long end, gfp_t flag);
extern int alloc_contig_range(unsigned long start, unsigned long end,
- gfp_t flags, unsigned migratetype);
+ unsigned migratetype);
extern void free_contig_pages(unsigned long pfn, unsigned nr_pages);
/*
diff --git a/mm/compaction.c b/mm/compaction.c
index 9e5cc59..685a19e 100644
--- a/mm/compaction.c
+++ b/mm/compaction.c
@@ -58,77 +58,15 @@ static unsigned long release_freepages(struct list_head *freelist)
return count;
}
-/* Isolate free pages onto a private freelist. Must hold zone->lock */
-static unsigned long isolate_freepages_block(struct zone *zone,
- unsigned long blockpfn,
- struct list_head *freelist)
-{
- unsigned long zone_end_pfn, end_pfn;
- int nr_scanned = 0, total_isolated = 0;
- struct page *cursor;
-
- /* Get the last PFN we should scan for free pages at */
- zone_end_pfn = zone->zone_start_pfn + zone->spanned_pages;
- end_pfn = min(blockpfn + pageblock_nr_pages, zone_end_pfn);
-
- /* Find the first usable PFN in the block to initialse page cursor */
- for (; blockpfn < end_pfn; blockpfn++) {
- if (pfn_valid_within(blockpfn))
- break;
- }
- cursor = pfn_to_page(blockpfn);
-
- /* Isolate free pages. This assumes the block is valid */
- for (; blockpfn < end_pfn; blockpfn++, cursor++) {
- int isolated, i;
- struct page *page = cursor;
-
- if (!pfn_valid_within(blockpfn))
- continue;
- nr_scanned++;
-
- if (!PageBuddy(page))
- continue;
-
- /* Found a free page, break it into order-0 pages */
- isolated = split_free_page(page);
- total_isolated += isolated;
- for (i = 0; i < isolated; i++) {
- list_add(&page->lru, freelist);
- page++;
- }
-
- /* If a page was split, advance to the end of it */
- if (isolated) {
- blockpfn += isolated - 1;
- cursor += isolated - 1;
- }
- }
-
- trace_mm_compaction_isolate_freepages(nr_scanned, total_isolated);
- return total_isolated;
-}
-
/* Returns true if the page is within a block suitable for migration to */
static bool suitable_migration_target(struct page *page)
{
-
int migratetype = get_pageblock_migratetype(page);
/* Don't interfere with memory hot-remove or the min_free_kbytes blocks */
if (migratetype == MIGRATE_ISOLATE || migratetype == MIGRATE_RESERVE)
return false;
- /* Keep MIGRATE_CMA alone as well. */
- /*
- * XXX Revisit. We currently cannot let compaction touch CMA
- * pages since compaction insists on changing their migration
- * type to MIGRATE_MOVABLE (see split_free_page() called from
- * isolate_freepages_block() above).
- */
- if (is_migrate_cma(migratetype))
- return false;
-
/* If the page is a large free page, then allow migration */
if (PageBuddy(page) && page_order(page) >= pageblock_order)
return true;
@@ -149,7 +87,7 @@ static void isolate_freepages(struct zone *zone,
struct compact_control *cc)
{
struct page *page;
- unsigned long high_pfn, low_pfn, pfn;
+ unsigned long high_pfn, low_pfn, pfn, zone_end_pfn, end_pfn;
unsigned long flags;
int nr_freepages = cc->nr_freepages;
struct list_head *freelist = &cc->freepages;
@@ -169,6 +107,8 @@ static void isolate_freepages(struct zone *zone,
*/
high_pfn = min(low_pfn, pfn);
+ zone_end_pfn = zone->zone_start_pfn + zone->spanned_pages;
+
/*
* Isolate free pages until enough are available to migrate the
* pages on cc->migratepages. We stop searching if the migrate
@@ -176,7 +116,7 @@ static void isolate_freepages(struct zone *zone,
*/
for (; pfn > low_pfn && cc->nr_migratepages > nr_freepages;
pfn -= pageblock_nr_pages) {
- unsigned long isolated;
+ unsigned isolated, scanned;
if (!pfn_valid(pfn))
continue;
@@ -205,7 +145,10 @@ static void isolate_freepages(struct zone *zone,
isolated = 0;
spin_lock_irqsave(&zone->lock, flags);
if (suitable_migration_target(page)) {
- isolated = isolate_freepages_block(zone, pfn, freelist);
+ end_pfn = min(pfn + pageblock_nr_pages, zone_end_pfn);
+ isolated = isolate_freepages_range(zone, pfn,
+ end_pfn, freelist, &scanned);
+ trace_mm_compaction_isolate_freepages(scanned, isolated);
nr_freepages += isolated;
}
spin_unlock_irqrestore(&zone->lock, flags);
diff --git a/mm/internal.h b/mm/internal.h
index d071d380..4a9bb3f 100644
--- a/mm/internal.h
+++ b/mm/internal.h
@@ -263,3 +263,8 @@ extern u64 hwpoison_filter_flags_mask;
extern u64 hwpoison_filter_flags_value;
extern u64 hwpoison_filter_memcg;
extern u32 hwpoison_filter_enable;
+
+unsigned isolate_freepages_range(struct zone *zone,
+ unsigned long start, unsigned long end,
+ struct list_head *freelist,
+ unsigned *scannedp);
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index df69706..adf3f34 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -1300,10 +1300,11 @@ void split_page(struct page *page, unsigned int order)
* Note: this is probably too low level an operation for use in drivers.
* Please consult with lkml before using this in your driver.
*/
-int split_free_page(struct page *page)
+static unsigned split_free_page(struct page *page)
{
unsigned int order;
unsigned long watermark;
+ struct page *endpage;
struct zone *zone;
BUG_ON(!PageBuddy(page));
@@ -1326,14 +1327,18 @@ int split_free_page(struct page *page)
set_page_refcounted(page);
split_page(page, order);
- if (order >= pageblock_order - 1) {
- struct page *endpage = page + (1 << order) - 1;
- for (; page < endpage; page += pageblock_nr_pages)
- if (!is_pageblock_cma(page))
- set_pageblock_migratetype(page,
- MIGRATE_MOVABLE);
+ if (order < pageblock_order - 1)
+ goto done;
+
+ endpage = page + (1 << order) - 1;
+ for (; page < endpage; page += pageblock_nr_pages) {
+ int mt = get_pageblock_migratetype(page);
+ /* Don't change CMA nor ISOLATE */
+ if (!is_migrate_cma(mt) && mt != MIGRATE_ISOLATE)
+ set_pageblock_migratetype(page, MIGRATE_MOVABLE);
}
+done:
return 1 << order;
}
@@ -5723,57 +5728,76 @@ out:
spin_unlock_irqrestore(&zone->lock, flags);
}
-unsigned long alloc_contig_freed_pages(unsigned long start, unsigned long end,
- gfp_t flag)
+/**
+ * isolate_freepages_range() - isolate free pages, must hold zone->lock.
+ * @zone: Zone pages are in.
+ * @start: The first PFN to start isolating.
+ * @end: The one-past-last PFN.
+ * @freelist: A list to save isolated pages to.
+ * @scannedp: Optional pointer where to save number of scanned pages.
+ *
+ * If @freelist is not provided, holes in range (either non-free pages
+ * or invalid PFN) are considered an error and function undos its
+ * actions and returns zero.
+ *
+ * If @freelist is provided, function will simply skip non-free and
+ * missing pages and put only the ones isolated on the list. It will
+ * also call trace_mm_compaction_isolate_freepages() at the end.
+ *
+ * Returns number of isolated pages. This may be more then end-start
+ * if end fell in a middle of a free page.
+ */
+unsigned isolate_freepages_range(struct zone *zone,
+ unsigned long start, unsigned long end,
+ struct list_head *freelist, unsigned *scannedp)
{
- unsigned long pfn = start, count;
+ unsigned nr_scanned = 0, total_isolated = 0;
+ unsigned long pfn = start;
struct page *page;
- struct zone *zone;
- int order;
VM_BUG_ON(!pfn_valid(start));
- page = pfn_to_page(start);
- zone = page_zone(page);
- spin_lock_irq(&zone->lock);
+ /* Isolate free pages. This assumes the block is valid */
+ page = pfn_to_page(pfn);
+ while (pfn < end) {
+ unsigned isolated = 1;
- for (;;) {
- VM_BUG_ON(!page_count(page) || !PageBuddy(page) ||
- page_zone(page) != zone);
+ VM_BUG_ON(page_zone(page) != zone);
- list_del(&page->lru);
- order = page_order(page);
- count = 1UL << order;
- zone->free_area[order].nr_free--;
- rmv_page_order(page);
- __mod_zone_page_state(zone, NR_FREE_PAGES, -(long)count);
+ if (!pfn_valid_within(blockpfn))
+ goto skip;
+ ++nr_scanned;
- pfn += count;
- if (pfn >= end)
- break;
- VM_BUG_ON(!pfn_valid(pfn));
-
- if (zone_pfn_same_memmap(pfn - count, pfn))
- page += count;
- else
- page = pfn_to_page(pfn);
- }
+ if (!PageBuddy(page)) {
+skip:
+ if (freelist)
+ goto next;
+ for (; start < pfn; ++start)
+ __free_page(pfn_to_page(pfn));
+ return 0;
+ }
- spin_unlock_irq(&zone->lock);
+ /* Found a free page, break it into order-0 pages */
+ isolated = split_free_page(page);
+ total_isolated += isolated;
+ if (freelist) {
+ struct page *p = page;
+ unsigned i = isolated;
+ for (; i--; ++page)
+ list_add(&p->lru, freelist);
+ }
- /* After this, pages in the range can be freed one be one */
- count = pfn - start;
- pfn = start;
- for (page = pfn_to_page(pfn); count; --count) {
- prep_new_page(page, 0, flag);
- ++pfn;
- if (likely(zone_pfn_same_memmap(pfn - 1, pfn)))
- ++page;
+next: /* Advance to the next page */
+ pfn += isolated;
+ if (zone_pfn_same_memmap(pfn - isolated, pfn))
+ page += isolated;
else
page = pfn_to_page(pfn);
}
- return pfn;
+ if (scannedp)
+ *scannedp = nr_scanned;
+ return total_isolated;
}
static unsigned long pfn_to_maxpage(unsigned long pfn)
@@ -5837,7 +5861,6 @@ static int __alloc_contig_migrate_range(unsigned long start, unsigned long end)
* alloc_contig_range() -- tries to allocate given range of pages
* @start: start PFN to allocate
* @end: one-past-the-last PFN to allocate
- * @flags: flags passed to alloc_contig_freed_pages().
* @migratetype: migratetype of the underlaying pageblocks (either
* #MIGRATE_MOVABLE or #MIGRATE_CMA). All pageblocks
* in range must have the same migratetype and it must
@@ -5853,9 +5876,10 @@ static int __alloc_contig_migrate_range(unsigned long start, unsigned long end)
* need to be freed with free_contig_pages().
*/
int alloc_contig_range(unsigned long start, unsigned long end,
- gfp_t flags, unsigned migratetype)
+ unsigned migratetype)
{
unsigned long outer_start, outer_end;
+ struct zone *zone;
int ret;
/*
@@ -5910,7 +5934,17 @@ int alloc_contig_range(unsigned long start, unsigned long end,
return -EINVAL;
outer_start = start & (~0UL << ret);
- outer_end = alloc_contig_freed_pages(outer_start, end, flags);
+
+ zone = page_zone(pfn_to_page(outer_start));
+ spin_lock_irq(&zone->lock);
+ outer_end = isolate_freepages_range(zone, outer_start, end, NULL, NULL);
+ spin_unlock_irq(&zone->lock);
+
+ if (!outer_end) {
+ ret = -EBUSY;
+ goto done;
+ }
+ outer_end += outer_start;
/* Free head and tail (if any) */
if (start != outer_start)
--
1.7.3.1
^ permalink raw reply related
* [PATCH meta-oe] memtester: Import from OE classic
From: Joel A Fernandes @ 2011-10-24 3:40 UTC (permalink / raw)
To: openembedded-devel; +Cc: Joel A Fernandes
Added LIC_FILES_CHKSUM
Signed-off-by: Joel A Fernandes <joelagnel@ti.com>
---
This package is required by the beaglebone-tester
.../memtester/files/Makefile.patch | 15 +++++++++++
.../recipes-benchmark/memtester/memtester_4.1.3.bb | 27 ++++++++++++++++++++
2 files changed, 42 insertions(+), 0 deletions(-)
create mode 100644 meta-oe/recipes-benchmark/memtester/files/Makefile.patch
create mode 100644 meta-oe/recipes-benchmark/memtester/memtester_4.1.3.bb
diff --git a/meta-oe/recipes-benchmark/memtester/files/Makefile.patch b/meta-oe/recipes-benchmark/memtester/files/Makefile.patch
new file mode 100644
index 0000000..57a0464
--- /dev/null
+++ b/meta-oe/recipes-benchmark/memtester/files/Makefile.patch
@@ -0,0 +1,15 @@
+Index: memtester-4.0.5/Makefile
+===================================================================
+--- memtester-4.0.5.orig/Makefile 2005-03-14 06:02:30.000000000 -0800
++++ memtester-4.0.5/Makefile 2006-07-08 23:53:42.000000000 -0700
+@@ -24,8 +24,8 @@
+ auto-ccld.sh: \
+ conf-cc conf-ld warn-auto.sh
+ ( cat warn-auto.sh; \
+- echo CC=\'`head -1 conf-cc`\'; \
+- echo LD=\'`head -1 conf-ld`\' \
++ echo CC=\'`head -n 1 conf-cc`\'; \
++ echo LD=\'`head -n 1 conf-ld`\' \
+ ) > auto-ccld.sh
+
+ compile: \
diff --git a/meta-oe/recipes-benchmark/memtester/memtester_4.1.3.bb b/meta-oe/recipes-benchmark/memtester/memtester_4.1.3.bb
new file mode 100644
index 0000000..9f4e53e
--- /dev/null
+++ b/meta-oe/recipes-benchmark/memtester/memtester_4.1.3.bb
@@ -0,0 +1,27 @@
+SECTION = "console/utils"
+DESCRIPTION = "Utility to test for faulty memory subsystem"
+LICENSE = "GPLv2"
+
+LIC_FILES_CHKSUM = "file://COPYING;md5=0636e73ff0215e8d672dc4c32c317bb3"
+
+SRC_URI = "http://pyropus.ca/software/memtester/old-versions/memtester-${PV}.tar.gz"
+SRC_URI += "file://Makefile.patch"
+
+SRC_URI[md5sum] = "e562451620cf5343016950462bc0dc38"
+SRC_URI[sha256sum] = "ac56f0b6d6d6e58bcf2a3fa7f2c9b29894f5177871f21115a1906c535106acf6"
+
+S = "${WORKDIR}/memtester-${PV}"
+
+do_compile () {
+ echo '${CC} ${CFLAGS} -DPOSIX -c' > conf-cc
+ echo '${CC} ${LDFLAGS}' > conf-ld
+ oe_runmake
+}
+
+do_install () {
+ install -d ${D}${bindir}
+ install -d ${D}${mandir}/man8
+ install -m 0755 memtester ${D}${bindir}/
+ install -m 0755 memtester.8 ${D}${mandir}/man8/
+}
+
--
1.7.0.4
^ permalink raw reply related
* Re: Flow classifier proto-dst and TOS (and proto-src)
From: Eric Dumazet @ 2011-10-24 4:02 UTC (permalink / raw)
To: Dan Siemon; +Cc: netdev
In-Reply-To: <1319418232.20602.16.camel@ganymede>
Le dimanche 23 octobre 2011 à 21:03 -0400, Dan Siemon a écrit :
> On Mon, 2011-10-17 at 08:09 +0200, Eric Dumazet wrote:
> > Le samedi 15 octobre 2011 à 12:51 -0400, Dan Siemon a écrit :
> > > cls_flow.c: flow_get_proto_dst()
> > >
> > > The proto-dst key returns the destination port for UDP, TCP and a few
> > > other protocols [see proto_ports_offset()]. For ICMP and IPIP it falls
> > > back to:
> > >
> > > return addr_fold(skb_dst(skb)) ^ (__force u16)skb->protocol;
> > >
> > > Since Linux maintains a dst_entry for each TOS value this causes the
> > > returned value to be affected by the TOS which is unexpected and
> > > probably broken.
> >
> > Hi Dan
> >
> > I think Patrick did this on purpose, because of of the lack of
> > perturbation in cls_flow.c : If all these frames were mapped to a single
> > flow, they might interfere with an other regular flow and hurt it.
> >
> > I dont qualify existing code as buggy. Its about fallback behavior
> > anyway (I dont think its even documented)
>
> Thanks for the review Eric.
>
> Won't virtually all uses of proto-dst also use the dst key anyway? In
> which case this fallback does nothing except make the TOS effect the
> hash output because the dst will be the same and dst_entry would be the
> same if it wasn't for the different TOS (by far the common case). I
> don't see the value of the unintuitive behavior.
>
> I'm not certain this is a problem but also note that including TOS will
> mean that packets within a tunnel will be reordered if 'tos inherit' is
> set on the tunnel and only the typical src,dst,proto,proto-src,proto-dst
> is used. Again, probably not expected.
Hmm, it seems cls_flow now supports "perturbation", so my prior argument
is not true anymore. I guess your patch would be fine, but I prefer
waiting Patrick review on it ;)
^ permalink raw reply
* Re: [PATCH net -v2] [BUGFIX] bonding: use flush_delayed_work_sync in bond_close
From: HAYASAKA Mitsuo @ 2011-10-24 4:00 UTC (permalink / raw)
To: Jay Vosburgh
Cc: netdev, Américo Wang, Stephen Hemminger, Andy Gospodarek,
linux-kernel, yrl.pp-manager.tt
In-Reply-To: <14766.1319245142@death>
(2011/10/22 9:59), Jay Vosburgh wrote:
> Jay Vosburgh <fubar@us.ibm.com> wrote:
>
>> Américo Wang <xiyou.wangcong@gmail.com> wrote:
>>
>>> On Thu, Oct 20, 2011 at 3:09 AM, Jay Vosburgh <fubar@us.ibm.com> wrote:
>>>> Stephen Hemminger <shemminger@vyatta.com> wrote:
>>>>
>>>>> On Wed, 19 Oct 2011 11:01:02 -0700
>>>>> Jay Vosburgh <fubar@us.ibm.com> wrote:
>>>>>
>>>>>> Mitsuo Hayasaka <mitsuo.hayasaka.hu@hitachi.com> wrote:
>>>>>>
>>>>>>> The bond_close() calls cancel_delayed_work() to cancel delayed works.
>>>>>>> It, however, cannot cancel works that were already queued in workqueue.
>>>>>>> The bond_open() initializes work->data, and proccess_one_work() refers
>>>>>>> get_work_cwq(work)->wq->flags. The get_work_cwq() returns NULL when
>>>>>>> work->data has been initialized. Thus, a panic occurs.
>>>>>>>
>>>>>>> This patch uses flush_delayed_work_sync() instead of cancel_delayed_work()
>>>>>>> in bond_close(). It cancels delayed timer and waits for work to finish
>>>>>>> execution. So, it can avoid the null pointer dereference due to the
>>>>>>> parallel executions of proccess_one_work() and initializing proccess
>>>>>>> of bond_open().
>>>>>>
>>>>>> I'm setting up to test this. I have a dim recollection that we
>>>>>> tried this some years ago, and there was a different deadlock that
>>>>>> manifested through the flush path. Perhaps changes since then have
>>>>>> removed that problem.
>>>>>>
>>>>>> -J
>>>>>
>>>>> Won't this deadlock on RTNL. The problem is that:
>>>>>
>>>>> CPU0 CPU1
>>>>> rtnl_lock
>>>>> bond_close
>>>>> delayed_work
>>>>> mii_work
>>>>> read_lock(bond->lock);
>>>>> read_unlock(bond->lock);
>>>>> rtnl_lock... waiting for CPU0
>>>>> flush_delayed_work_sync
>>>>> waiting for delayed_work to finish...
>>>>
>>>> Yah, that was it. We discussed this a couple of years ago in
>>>> regards to a similar patch:
>>>>
>>>> http://lists.openwall.net/netdev/2009/12/17/3
>>>>
>>>> The short version is that we could rework the rtnl_lock inside
>>>> the montiors to be conditional and retry on failure (where "retry" means
>>>> "reschedule the work and try again later," not "spin retrying on rtnl").
>>>> That should permit the use of flush or cancel to terminate the work
>>>> items.
>>>
>>> Yes? Even if we use rtnl_trylock(), doesn't flush_delayed_work_sync()
>>> still queue the pending delayed work and wait for it to be finished?
>>
>> Yes, it does. The original patch wants to use flush instead of
>> cancel to wait for the work to finish, because there's evidently a
>> possibility of getting back into bond_open before the work item
>> executes, and bond_open would reinitialize the work queue and corrupt
>> the queued work item.
>>
>> The original patch series, and recipe for destruction, is here:
>>
>> http://www.spinics.net/lists/netdev/msg176382.html
>>
>> I've been unable to reproduce the work queue panic locally,
>> although it sounds plausible.
>>
>> Mitsuo: can you provide the precise bonding configuration you're
>> using to induce the problem? Driver options, number and type of slaves,
>> etc.
>>
>>> Maybe I am too blind, why do we need rtnl_lock for cancel_delayed_work()
>>> inside bond_close()?
>>
>> We don't need RTNL for cancel/flush. However, bond_close is an
>> ndo_stop operation, and is called in the dev_close path, which always
>> occurs under RTNL. The mii / arp monitor work functions separately
>> acquire RTNL if they need to perform various failover related
>> operations.
>>
>> I'm working on a patch that should resolve the mii / arp monitor
>> RTNL problem as I described above (if rtnl_trylock fails, punt and
>> reschedule the work). I need to rearrange the netdev_bonding_change
>> stuff a bit as well, since it acquires RTNL separately.
>>
>> Once these changes are made to mii / arp monitor, then
>> bond_close can call flush instead of cancel, which should eliminate the
>> original problem described at the top.
>
> Just an update: there are three functions that may deadlock if
> the cancel work calls are changed to flush_sync. There are two
> rtnl_lock calls in each of the bond_mii_monitor and
> bond_activebackup_arp_mon functions, and one more in the
> bond_alb_monitor.
>
> Still testing to make sure I haven't missed anything, and I
> still haven't been able to reproduce Mitsuo's original failure.
The interval of mii_mon was set to 1 to reproduce this bug easily and
the 802.3ad mode was used. Then, I executed the following command.
# while true; do ifconfig bond0 down; done &
# while true; do ifconfig bond0 up; done &
This bug rarely occurs since it is the severe timing problem.
I found that it is more easily to reproduce this bug when using guest OS.
For example, it took one to three days for me to reproduce it on host OS,
but some hours on guest OS.
Thanks.
>
> -J
>
> ---
> -Jay Vosburgh, IBM Linux Technology Center, fubar@us.ibm.com
>
>
^ permalink raw reply
* Re: [PATCH] cls_flow: Add tunnel support to the flow classifier
From: Eric Dumazet @ 2011-10-24 3:59 UTC (permalink / raw)
To: Dan Siemon; +Cc: netdev
In-Reply-To: <1319426081.2517.20.camel@edumazet-laptop>
Le lundi 24 octobre 2011 à 05:14 +0200, Eric Dumazet a écrit :
> If you prefer, I can do the preliminary work
>
Since it is a bit tricky, I finished it.
It'll be easier for you to use existing functions without copy/paste,
since I added an "nhoff" argument that you can play with (skipping
tunnel header)
Please test it !
Thanks
[PATCH net-next] net_sched: cls_flow: use skb_header_pointer()
Dan Siemon would like to add tunnelling support to cls_flow
This preliminary patch introduces use of skb_header_pointer() to help
this task, while avoiding skb head reallocation because of deep packet
inspection.
Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
---
net/sched/cls_flow.c | 188 ++++++++++++++++++++---------------------
1 file changed, 96 insertions(+), 92 deletions(-)
diff --git a/net/sched/cls_flow.c b/net/sched/cls_flow.c
index 6994214..9e087d8 100644
--- a/net/sched/cls_flow.c
+++ b/net/sched/cls_flow.c
@@ -65,132 +65,134 @@ static inline u32 addr_fold(void *addr)
return (a & 0xFFFFFFFF) ^ (BITS_PER_LONG > 32 ? a >> 32 : 0);
}
-static u32 flow_get_src(struct sk_buff *skb)
+static u32 flow_get_src(const struct sk_buff *skb, int nhoff)
{
+ __be32 *data = NULL, hdata;
+
switch (skb->protocol) {
case htons(ETH_P_IP):
- if (pskb_network_may_pull(skb, sizeof(struct iphdr)))
- return ntohl(ip_hdr(skb)->saddr);
+ data = skb_header_pointer(skb,
+ nhoff + offsetof(struct iphdr,
+ saddr),
+ 4, &hdata);
break;
case htons(ETH_P_IPV6):
- if (pskb_network_may_pull(skb, sizeof(struct ipv6hdr)))
- return ntohl(ipv6_hdr(skb)->saddr.s6_addr32[3]);
+ data = skb_header_pointer(skb,
+ nhoff + offsetof(struct ipv6hdr,
+ saddr.s6_addr32[3]),
+ 4, &hdata);
break;
}
+ if (data)
+ return ntohl(*data);
return addr_fold(skb->sk);
}
-static u32 flow_get_dst(struct sk_buff *skb)
+static u32 flow_get_dst(const struct sk_buff *skb, int nhoff)
{
+ __be32 *data = NULL, hdata;
+
switch (skb->protocol) {
case htons(ETH_P_IP):
- if (pskb_network_may_pull(skb, sizeof(struct iphdr)))
- return ntohl(ip_hdr(skb)->daddr);
+ data = skb_header_pointer(skb,
+ nhoff + offsetof(struct iphdr,
+ daddr),
+ 4, &hdata);
break;
case htons(ETH_P_IPV6):
- if (pskb_network_may_pull(skb, sizeof(struct ipv6hdr)))
- return ntohl(ipv6_hdr(skb)->daddr.s6_addr32[3]);
+ data = skb_header_pointer(skb,
+ nhoff + offsetof(struct ipv6hdr,
+ daddr.s6_addr32[3]),
+ 4, &hdata);
break;
}
+ if (data)
+ return ntohl(*data);
return addr_fold(skb_dst(skb)) ^ (__force u16)skb->protocol;
}
-static u32 flow_get_proto(struct sk_buff *skb)
+static u32 flow_get_proto(const struct sk_buff *skb, int nhoff)
{
+ __u8 *data = NULL, hdata;
+
switch (skb->protocol) {
case htons(ETH_P_IP):
- return pskb_network_may_pull(skb, sizeof(struct iphdr)) ?
- ip_hdr(skb)->protocol : 0;
+ data = skb_header_pointer(skb,
+ nhoff + offsetof(struct iphdr,
+ protocol),
+ 1, &hdata);
+ break;
case htons(ETH_P_IPV6):
- return pskb_network_may_pull(skb, sizeof(struct ipv6hdr)) ?
- ipv6_hdr(skb)->nexthdr : 0;
- default:
- return 0;
+ data = skb_header_pointer(skb,
+ nhoff + offsetof(struct ipv6hdr,
+ nexthdr),
+ 1, &hdata);
+ break;
}
+ if (data)
+ return *data;
+ return 0;
}
-static u32 flow_get_proto_src(struct sk_buff *skb)
+/* helper function to get either src or dst port */
+static __be16 *flow_get_proto_common(const struct sk_buff *skb, int nhoff,
+ __be16 *_port, int dst)
{
+ __be16 *port = NULL;
+ int poff;
+
switch (skb->protocol) {
case htons(ETH_P_IP): {
- struct iphdr *iph;
- int poff;
+ struct iphdr *iph, _iph;
- if (!pskb_network_may_pull(skb, sizeof(*iph)))
+ iph = skb_header_pointer(skb, nhoff, sizeof(_iph), &_iph);
+ if (!iph)
break;
- iph = ip_hdr(skb);
if (ip_is_fragment(iph))
break;
poff = proto_ports_offset(iph->protocol);
- if (poff >= 0 &&
- pskb_network_may_pull(skb, iph->ihl * 4 + 2 + poff)) {
- iph = ip_hdr(skb);
- return ntohs(*(__be16 *)((void *)iph + iph->ihl * 4 +
- poff));
- }
+ if (poff >= 0)
+ port = skb_header_pointer(skb,
+ nhoff + iph->ihl * 4 + poff + dst,
+ sizeof(*_port), _port);
break;
}
case htons(ETH_P_IPV6): {
- struct ipv6hdr *iph;
- int poff;
+ struct ipv6hdr *iph, _iph;
- if (!pskb_network_may_pull(skb, sizeof(*iph)))
+ iph = skb_header_pointer(skb, nhoff, sizeof(_iph), &_iph);
+ if (!iph)
break;
- iph = ipv6_hdr(skb);
poff = proto_ports_offset(iph->nexthdr);
- if (poff >= 0 &&
- pskb_network_may_pull(skb, sizeof(*iph) + poff + 2)) {
- iph = ipv6_hdr(skb);
- return ntohs(*(__be16 *)((void *)iph + sizeof(*iph) +
- poff));
- }
+ if (poff >= 0)
+ port = skb_header_pointer(skb,
+ nhoff + sizeof(*iph) + poff + dst,
+ sizeof(*_port), _port);
break;
}
}
- return addr_fold(skb->sk);
+ return port;
}
-static u32 flow_get_proto_dst(struct sk_buff *skb)
+static u32 flow_get_proto_src(const struct sk_buff *skb, int nhoff)
{
- switch (skb->protocol) {
- case htons(ETH_P_IP): {
- struct iphdr *iph;
- int poff;
+ __be16 _port, *port = flow_get_proto_common(skb, nhoff, &_port, 0);
- if (!pskb_network_may_pull(skb, sizeof(*iph)))
- break;
- iph = ip_hdr(skb);
- if (ip_is_fragment(iph))
- break;
- poff = proto_ports_offset(iph->protocol);
- if (poff >= 0 &&
- pskb_network_may_pull(skb, iph->ihl * 4 + 4 + poff)) {
- iph = ip_hdr(skb);
- return ntohs(*(__be16 *)((void *)iph + iph->ihl * 4 +
- 2 + poff));
- }
- break;
- }
- case htons(ETH_P_IPV6): {
- struct ipv6hdr *iph;
- int poff;
+ if (port)
+ return ntohs(*port);
- if (!pskb_network_may_pull(skb, sizeof(*iph)))
- break;
- iph = ipv6_hdr(skb);
- poff = proto_ports_offset(iph->nexthdr);
- if (poff >= 0 &&
- pskb_network_may_pull(skb, sizeof(*iph) + poff + 4)) {
- iph = ipv6_hdr(skb);
- return ntohs(*(__be16 *)((void *)iph + sizeof(*iph) +
- poff + 2));
- }
- break;
- }
- }
+ return addr_fold(skb->sk);
+}
+
+static u32 flow_get_proto_dst(const struct sk_buff *skb, int nhoff)
+{
+ __be16 _port, *port = flow_get_proto_common(skb, nhoff, &_port, 2);
+
+ if (port)
+ return ntohs(*port);
return addr_fold(skb_dst(skb)) ^ (__force u16)skb->protocol;
}
@@ -223,7 +225,7 @@ static u32 flow_get_nfct(const struct sk_buff *skb)
#define CTTUPLE(skb, member) \
({ \
enum ip_conntrack_info ctinfo; \
- struct nf_conn *ct = nf_ct_get(skb, &ctinfo); \
+ const struct nf_conn *ct = nf_ct_get(skb, &ctinfo); \
if (ct == NULL) \
goto fallback; \
ct->tuplehash[CTINFO2DIR(ctinfo)].tuple.member; \
@@ -236,7 +238,7 @@ static u32 flow_get_nfct(const struct sk_buff *skb)
})
#endif
-static u32 flow_get_nfct_src(struct sk_buff *skb)
+static u32 flow_get_nfct_src(const struct sk_buff *skb, int nhoff)
{
switch (skb->protocol) {
case htons(ETH_P_IP):
@@ -245,10 +247,10 @@ static u32 flow_get_nfct_src(struct sk_buff *skb)
return ntohl(CTTUPLE(skb, src.u3.ip6[3]));
}
fallback:
- return flow_get_src(skb);
+ return flow_get_src(skb, nhoff);
}
-static u32 flow_get_nfct_dst(struct sk_buff *skb)
+static u32 flow_get_nfct_dst(const struct sk_buff *skb, int nhoff)
{
switch (skb->protocol) {
case htons(ETH_P_IP):
@@ -257,21 +259,21 @@ static u32 flow_get_nfct_dst(struct sk_buff *skb)
return ntohl(CTTUPLE(skb, dst.u3.ip6[3]));
}
fallback:
- return flow_get_dst(skb);
+ return flow_get_dst(skb, nhoff);
}
-static u32 flow_get_nfct_proto_src(struct sk_buff *skb)
+static u32 flow_get_nfct_proto_src(const struct sk_buff *skb, int nhoff)
{
return ntohs(CTTUPLE(skb, src.u.all));
fallback:
- return flow_get_proto_src(skb);
+ return flow_get_proto_src(skb, nhoff);
}
-static u32 flow_get_nfct_proto_dst(struct sk_buff *skb)
+static u32 flow_get_nfct_proto_dst(const struct sk_buff *skb, int nhoff)
{
return ntohs(CTTUPLE(skb, dst.u.all));
fallback:
- return flow_get_proto_dst(skb);
+ return flow_get_proto_dst(skb, nhoff);
}
static u32 flow_get_rtclassid(const struct sk_buff *skb)
@@ -313,17 +315,19 @@ static u32 flow_get_rxhash(struct sk_buff *skb)
static u32 flow_key_get(struct sk_buff *skb, int key)
{
+ int nhoff = skb_network_offset(skb);
+
switch (key) {
case FLOW_KEY_SRC:
- return flow_get_src(skb);
+ return flow_get_src(skb, nhoff);
case FLOW_KEY_DST:
- return flow_get_dst(skb);
+ return flow_get_dst(skb, nhoff);
case FLOW_KEY_PROTO:
- return flow_get_proto(skb);
+ return flow_get_proto(skb, nhoff);
case FLOW_KEY_PROTO_SRC:
- return flow_get_proto_src(skb);
+ return flow_get_proto_src(skb, nhoff);
case FLOW_KEY_PROTO_DST:
- return flow_get_proto_dst(skb);
+ return flow_get_proto_dst(skb, nhoff);
case FLOW_KEY_IIF:
return flow_get_iif(skb);
case FLOW_KEY_PRIORITY:
@@ -333,13 +337,13 @@ static u32 flow_key_get(struct sk_buff *skb, int key)
case FLOW_KEY_NFCT:
return flow_get_nfct(skb);
case FLOW_KEY_NFCT_SRC:
- return flow_get_nfct_src(skb);
+ return flow_get_nfct_src(skb, nhoff);
case FLOW_KEY_NFCT_DST:
- return flow_get_nfct_dst(skb);
+ return flow_get_nfct_dst(skb, nhoff);
case FLOW_KEY_NFCT_PROTO_SRC:
- return flow_get_nfct_proto_src(skb);
+ return flow_get_nfct_proto_src(skb, nhoff);
case FLOW_KEY_NFCT_PROTO_DST:
- return flow_get_nfct_proto_dst(skb);
+ return flow_get_nfct_proto_dst(skb, nhoff);
case FLOW_KEY_RTCLASSID:
return flow_get_rtclassid(skb);
case FLOW_KEY_SKUID:
^ permalink raw reply related
* RE: [PATCHv4] DMAEngine: Define interleaved transfer request api
From: Vinod Koul @ 2011-10-24 3:49 UTC (permalink / raw)
To: Bounine, Alexandre
Cc: Jassi Brar, Russell King, Williams, Dan J, Barry Song,
linux-kernel, DL-SHA-WorkGroupLinux, Dave Jiang
In-Reply-To: <0CE8B6BE3C4AD74AB97D9D29BD24E552023672A3@CORPEXCH1.na.ads.idt.com>
On Tue, 2011-10-18 at 10:57 -0700, Bounine, Alexandre wrote:
Sorry for delayed response, been quite busy with upcoming festival, and
other stuff :(
> > >
> > Thanks for the detailed explanation.
> >
> > RapidIO is a packet switched interconnect with parallel or serial
> > interface.
> > Among other things, a packet contains 32, 48 or 64 bit offset into the
> > remote-endpoint's address space. So I don't get how any of the above
> > 6 points apply here.
> >
> > Though I agree it is peculiar for a networking technology to expose a
> > DMAEngine interface. But I assume Alex has good reasons for it, who
> > knows RIO better than us.
> To keep it simple, look at this as a peer-to-peer networking with HW ability
> to directly address memory of the link partner.
>
> RapidIO supports messaging which is closer to traditional networking and is
> supported by RIONET driver (pretending to be Ethernet). But in some situations
> messaging cannot be used. In these cases addressed memory read/write
> operations take place.
>
> I would like to put a simple example of RIO based system that may help to
> understand our DMA requirements.
>
> Consider a platform with one host CPU and several DSP cards connected
> to it through a switched backplane (transparent for purpose of this example).
>
> The host CPU has one or more RIO-capable DMA channel and runs device
> drivers for connected DSP cards. Each device driver is required to load
> an individual program code into corresponding DSP(s). Directly addressed
> writes have a lot of sense.
>
> After DSP code is loaded device drivers start DSP program and may
> participate in data transfers between DSP cards and host CPU. Again
> messaging type transfers may add unnecessary overhead here compared
> to direct data reads/writes.
>
> Configuration of each DSP card may be different but from host's
> POV is RIO spec compliant.
I think we all agree that this fits the dma_slave case :)
As for changing in dmaengine to u64, if we are thinking this as slave
usage, then ideally we should not make assumption of the address type of
peripheral so we should only move the dma_slave_config address fields to
u64, if that helps in RIO case. Moving other usages would be insane.
At this point we have two proposals
a) to make RIO exceptional case and add RIO specific stuff.
b) make dmaengine transparent and add additional argument
in .device_prep_slave_sg() callback which is subsystem dependent.
Current dmacs and those who don't need it will ignore it.
ATM, I am leaning towards the latter, for the main reason to keep
dmaengine away from subsystem details.
--
~Vinod
^ permalink raw reply
* [U-Boot] [PATCH] arch/powerpc/lib/board.c: fix build warning
From: Simon Glass @ 2011-10-24 3:49 UTC (permalink / raw)
To: u-boot
In-Reply-To: <1319407132-6590-1-git-send-email-wd@denx.de>
Hi Wolfgang,
On Sun, Oct 23, 2011 at 2:58 PM, Wolfgang Denk <wd@denx.de> wrote:
> Commit 1272592 "powerpc: Use getenv_ulong() in place of getenv(),
> strtoul" instroduced a build warning for some PPC systems:
>
> board.c: In function 'board_init_r':
> board.c:626: warning: unused variable 's'
>
> Fix it.
>
> Signed-off-by: Wolfgang Denk <wd@denx.de>
I sent an alternative to this but they are roughly equivalent so:
Acked-by: Simon Glass <sjg@chromium.org>
Thanks for fixing this.
Regards,
Simon
> ---
> ?arch/powerpc/lib/board.c | ? ?5 +++--
> ?1 files changed, 3 insertions(+), 2 deletions(-)
>
> diff --git a/arch/powerpc/lib/board.c b/arch/powerpc/lib/board.c
> index 6cb0ed6..aff1a0c 100644
> --- a/arch/powerpc/lib/board.c
> +++ b/arch/powerpc/lib/board.c
> @@ -623,10 +623,11 @@ void board_init_f (ulong bootflag)
> ?*/
> ?void board_init_r (gd_t *id, ulong dest_addr)
> ?{
> - ? ? ? char *s;
> ? ? ? ?bd_t *bd;
> ? ? ? ?ulong malloc_start;
> -
> +#if defined(CONFIG_SYS_FLASH_CHECKSUM) || defined(CONFIG_CMD_NET)
> + ? ? ? char *s;
> +#endif
> ?#ifndef CONFIG_SYS_NO_FLASH
> ? ? ? ?ulong flash_size;
> ?#endif
> --
> 1.7.6.2
>
> _______________________________________________
> U-Boot mailing list
> U-Boot at lists.denx.de
> http://lists.denx.de/mailman/listinfo/u-boot
>
^ permalink raw reply
* Re: system hangs after deleting bad file
From: dima @ 2011-10-24 3:48 UTC (permalink / raw)
To: linux-btrfs
In-Reply-To: <BwKod0ky1uB@helmut.hullen.de>
Hello,
I had a similar problem.
Some files (2-3) got corrupted in my /home subvolume for no apparent reason.
Trying to access the files gives kernel oops. Sometimes it freezes the machine,
sometimes I am back to my console without any problems.
Then I switched to the latest 3.1rc and freezes were gone (though I still had
the kernel oops).
(I did not try the repair program fearing that it would do more bad than good.
After all, my / subvolume was fine and i still could mount /home)
But to tackle the problems with corrupted files I had to create a new subvolume
for /home, tranfer the files from the old one (minus the corrupted files) and
delete the old subvolume.
Though still btrfsck would give me errors trying to access some inode. But I
could mount and use all my subvolumes with no problems.
Then... I re-created btrfs with the latest btrfs-tools and installed the latest
3.1rc from the very beginning.
So far, it is working fine and the situation with disk I/O has greatly improved.
I think you may want to try to upgrade to the latest 3.1rc and at the very least
you (hopefully) should not be getting hard freezes any more.
best
~dima
^ permalink raw reply
* Re: [PATCH] block: Remove the control of complete cpu from bio.
From: Tao Ma @ 2011-10-24 3:46 UTC (permalink / raw)
To: LKML; +Cc: Jens Axboe
In-Reply-To: <1316166108-6465-1-git-send-email-tm@tao.ma>
ping.
For the detailed discussion, please refer to
https://lkml.org/lkml/2011/9/15/98
Thanks
Tao
On 09/16/2011 05:41 PM, Tao Ma wrote:
> From: Tao Ma <boyu.mt@taobao.com>
>
> bio originally has the functionality to set the complete cpu, but
> it is broken.
>
> Chirstoph said that "This code is unused, and from the all the
> discussions lately pretty obviously broken. The only thing keeping
> it serves is creating more confusion and possibly more bugs."
>
> And Jens replied with "We can kill bio_set_completion_cpu(). I'm fine
> with leaving cpu control to the request based drivers, they are the
> only ones that can toggle the setting anyway".
>
> So this patch tries to remove all the work of controling complete cpu
> from a bio.
>
> Cc: Shaohua Li <shaohua.li@intel.com>
> Cc: Christoph Hellwig <hch@infradead.org>
> Cc: Jens Axboe <jaxboe@fusionio.com>
> Signed-off-by: Tao Ma <boyu.mt@taobao.com>
> ---
> block/blk-core.c | 4 +---
> drivers/md/raid1.c | 1 -
> fs/bio.c | 1 -
> include/linux/bio.h | 8 --------
> include/linux/blk_types.h | 11 ++++-------
> 5 files changed, 5 insertions(+), 20 deletions(-)
>
> diff --git a/block/blk-core.c b/block/blk-core.c
> index 90e1ffd..8a57916 100644
> --- a/block/blk-core.c
> +++ b/block/blk-core.c
> @@ -1200,7 +1200,6 @@ out:
>
> void init_request_from_bio(struct request *req, struct bio *bio)
> {
> - req->cpu = bio->bi_comp_cpu;
> req->cmd_type = REQ_TYPE_FS;
>
> req->cmd_flags |= bio->bi_rw & REQ_COMMON_MASK;
> @@ -1281,8 +1280,7 @@ get_rq:
> */
> init_request_from_bio(req, bio);
>
> - if (test_bit(QUEUE_FLAG_SAME_COMP, &q->queue_flags) ||
> - bio_flagged(bio, BIO_CPU_AFFINE))
> + if (test_bit(QUEUE_FLAG_SAME_COMP, &q->queue_flags))
> req->cpu = raw_smp_processor_id();
>
> plug = current->plug;
> diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c
> index 32323f0..3107bcc 100644
> --- a/drivers/md/raid1.c
> +++ b/drivers/md/raid1.c
> @@ -2170,7 +2170,6 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i
> bio->bi_next = NULL;
> bio->bi_flags &= ~(BIO_POOL_MASK-1);
> bio->bi_flags |= 1 << BIO_UPTODATE;
> - bio->bi_comp_cpu = -1;
> bio->bi_rw = READ;
> bio->bi_vcnt = 0;
> bio->bi_idx = 0;
> diff --git a/fs/bio.c b/fs/bio.c
> index 9bfade8..41c93c7 100644
> --- a/fs/bio.c
> +++ b/fs/bio.c
> @@ -255,7 +255,6 @@ void bio_init(struct bio *bio)
> {
> memset(bio, 0, sizeof(*bio));
> bio->bi_flags = 1 << BIO_UPTODATE;
> - bio->bi_comp_cpu = -1;
> atomic_set(&bio->bi_cnt, 1);
> }
> EXPORT_SYMBOL(bio_init);
> diff --git a/include/linux/bio.h b/include/linux/bio.h
> index ce33e68..a3c071c 100644
> --- a/include/linux/bio.h
> +++ b/include/linux/bio.h
> @@ -269,14 +269,6 @@ extern void bvec_free_bs(struct bio_set *, struct bio_vec *, unsigned int);
> extern unsigned int bvec_nr_vecs(unsigned short idx);
>
> /*
> - * Allow queuer to specify a completion CPU for this bio
> - */
> -static inline void bio_set_completion_cpu(struct bio *bio, unsigned int cpu)
> -{
> - bio->bi_comp_cpu = cpu;
> -}
> -
> -/*
> * bio_set is used to allow other portions of the IO system to
> * allocate their own private memory pools for bio and iovec structures.
> * These memory pools in turn all allocate from the bio_slab
> diff --git a/include/linux/blk_types.h b/include/linux/blk_types.h
> index 32f0076..174bc3a 100644
> --- a/include/linux/blk_types.h
> +++ b/include/linux/blk_types.h
> @@ -59,8 +59,6 @@ struct bio {
>
> unsigned int bi_max_vecs; /* max bvl_vecs we can hold */
>
> - unsigned int bi_comp_cpu; /* completion CPU */
> -
> atomic_t bi_cnt; /* pin count */
>
> struct bio_vec *bi_io_vec; /* the actual vec list */
> @@ -93,11 +91,10 @@ struct bio {
> #define BIO_BOUNCED 5 /* bio is a bounce bio */
> #define BIO_USER_MAPPED 6 /* contains user pages */
> #define BIO_EOPNOTSUPP 7 /* not supported */
> -#define BIO_CPU_AFFINE 8 /* complete bio on same CPU as submitted */
> -#define BIO_NULL_MAPPED 9 /* contains invalid user pages */
> -#define BIO_FS_INTEGRITY 10 /* fs owns integrity data, not block layer */
> -#define BIO_QUIET 11 /* Make BIO Quiet */
> -#define BIO_MAPPED_INTEGRITY 12/* integrity metadata has been remapped */
> +#define BIO_NULL_MAPPED 8 /* contains invalid user pages */
> +#define BIO_FS_INTEGRITY 9 /* fs owns integrity data, not block layer */
> +#define BIO_QUIET 10 /* Make BIO Quiet */
> +#define BIO_MAPPED_INTEGRITY 11/* integrity metadata has been remapped */
> #define bio_flagged(bio, flag) ((bio)->bi_flags & (1 << (flag)))
>
> /*
^ permalink raw reply
* [U-Boot] [PATCH v2] arm: Correct build error introduced by getenv_ulong() patch
From: Simon Glass @ 2011-10-24 3:44 UTC (permalink / raw)
To: u-boot
In-Reply-To: <1319415273-3915-1-git-send-email-sjg@chromium.org>
Commit dc8bbea removed a local variable that is used in most ARM boards.
Since we want to avoid an 'unused variable' warning with later compilers,
and the #ifdef logic of whether this variable is required is bit painful,
this declares the variable local to the block of code that needs it.
Signed-off-by: Simon Glass <sjg@chromium.org>
---
Changes in v2:
- Tidy up to call getenv() in declaration
arch/arm/lib/board.c | 12 ++++++++----
1 files changed, 8 insertions(+), 4 deletions(-)
diff --git a/arch/arm/lib/board.c b/arch/arm/lib/board.c
index c764844..7434b34 100644
--- a/arch/arm/lib/board.c
+++ b/arch/arm/lib/board.c
@@ -477,13 +477,14 @@ void board_init_r(gd_t *id, ulong dest_addr)
flash_size = flash_init();
if (flash_size > 0) {
# ifdef CONFIG_SYS_FLASH_CHECKSUM
+ char *s = getenv("flashchecksum");
+
print_size(flash_size, "");
/*
* Compute and print flash CRC if flashchecksum is set to 'y'
*
* NOTE: Maybe we should add some WATCHDOG_RESET()? XXX
*/
- s = getenv("flashchecksum");
if (s && (*s == 'y')) {
printf(" CRC: %08X", crc32(0,
(const unsigned char *) CONFIG_SYS_FLASH_BASE,
@@ -566,9 +567,12 @@ void board_init_r(gd_t *id, ulong dest_addr)
/* Initialize from environment */
load_addr = getenv_ulong("loadaddr", 16, load_addr);
#if defined(CONFIG_CMD_NET)
- s = getenv("bootfile");
- if (s != NULL)
- copy_filename(BootFile, s, sizeof(BootFile));
+ {
+ char *s = getenv("bootfile");
+
+ if (s != NULL)
+ copy_filename(BootFile, s, sizeof(BootFile));
+ }
#endif
#ifdef BOARD_LATE_INIT
--
1.7.3.1
^ permalink raw reply related
* [U-Boot] [PATCH] powerpc: Correct build warning introduced by getenv_ulong() patch
From: Simon Glass @ 2011-10-24 3:41 UTC (permalink / raw)
To: u-boot
Commit 1272592 introduced a warning since the variable 's' is no longer
always used, depending on the CONFIG options.
Signed-off-by: Simon Glass <sjg@chromium.org>
---
arch/powerpc/lib/board.c | 10 +++++++---
1 files changed, 7 insertions(+), 3 deletions(-)
diff --git a/arch/powerpc/lib/board.c b/arch/powerpc/lib/board.c
index 6cb0ed6..508075f 100644
--- a/arch/powerpc/lib/board.c
+++ b/arch/powerpc/lib/board.c
@@ -623,7 +623,6 @@ void board_init_f (ulong bootflag)
*/
void board_init_r (gd_t *id, ulong dest_addr)
{
- char *s;
bd_t *bd;
ulong malloc_start;
@@ -727,6 +726,8 @@ void board_init_r (gd_t *id, ulong dest_addr)
flash_size = 0;
} else if ((flash_size = flash_init ()) > 0) {
# ifdef CONFIG_SYS_FLASH_CHECKSUM
+ char *s;
+
print_size (flash_size, "");
/*
* Compute and print flash CRC if flashchecksum is set to 'y'
@@ -927,8 +928,11 @@ void board_init_r (gd_t *id, ulong dest_addr)
/* Initialize from environment */
load_addr = getenv_ulong("loadaddr", 16, load_addr);
#if defined(CONFIG_CMD_NET)
- if ((s = getenv ("bootfile")) != NULL) {
- copy_filename (BootFile, s, sizeof (BootFile));
+ {
+ char *s = getenv("bootfile");
+
+ if (s != NULL)
+ copy_filename(BootFile, s, sizeof(BootFile));
}
#endif
--
1.7.3.1
^ permalink raw reply related
* Re: [PATCH v3 0/4] dmaengine: Device Tree support for Atmel DMA
From: Vinod Koul @ 2011-10-24 3:28 UTC (permalink / raw)
To: Nicolas Ferre, robherring2
Cc: linux-arm-kernel, devicetree-discuss, linux-kernel
In-Reply-To: <4E9C258D.3030509@atmel.com>
On Mon, 2011-10-17 at 14:54 +0200, Nicolas Ferre wrote:
> On 10/12/2011 06:57 PM, Nicolas Ferre :
> > This series add the device tree support to Atmel DMA controller driver:
> > at_hdmac.
> > The removal of platform data ease the conversion to device tree. It also have
> > the additional benefit of being simpler and cleaner.
> >
> > Nicolas Ferre (4):
> > dmaengine: at_hdmac: platform data move to use .id_table
> > dmaengine: at_hdmac: add device tree support
> > ARM: at91/dma: remove platform data from DMA controller
> > ARM: at91/dma: DMA controller registering with DT support
> >
> > .../devicetree/bindings/dma/atmel-dma.txt | 14 ++++
> > arch/arm/mach-at91/at91sam9g45_devices.c | 17 ++---
> > arch/arm/mach-at91/at91sam9rl_devices.c | 8 +--
> > arch/arm/mach-at91/include/mach/at_hdmac.h | 10 ---
> > drivers/dma/at_hdmac.c | 76 +++++++++++++++++---
> > drivers/dma/at_hdmac_regs.h | 8 ++
> > 6 files changed, 97 insertions(+), 36 deletions(-)
> > create mode 100644 Documentation/devicetree/bindings/dma/atmel-dma.txt
>
> Vinod,
>
> I have just rebased the dmaengine at_hdmac driver patches on top of your
> "next" branch as a "v4" series. I send it to you with Grant's "Acked-by"
> right now.
I manged to fail the compliation with this patch
drivers/dma/at_hdmac.c: In function 'at_dma_get_driver_data':
drivers/dma/at_hdmac.c:1211: error: implicit declaration of function 'of_match_node'
drivers/dma/at_hdmac.c:1211: error: 'atmel_dma_dt_ids' undeclared (first use in this function)
drivers/dma/at_hdmac.c:1211: error: (Each undeclared identifier is reported only once
drivers/dma/at_hdmac.c:1211: error: for each function it appears in.)
drivers/dma/at_hdmac.c:1211: warning: assignment makes pointer from integer without a cast
drivers/dma/at_hdmac.c: At top level:
drivers/dma/at_hdmac.c:1558: error: implicit declaration of function 'of_match_ptr'
drivers/dma/at_hdmac.c:1558: error: 'atmel_dma_dt_ids' undeclared here (not in a function)
drivers/dma/at_hdmac.c:1558: error: initializer element is not constant
drivers/dma/at_hdmac.c:1558: error: (near initialization for 'at_dma_driver.driver.of_match_table')
make[1]: *** [drivers/dma/at_hdmac.o] Error 1
Which, IMO are triggered as one of my configs for at_hdmac did not have
CONFIG_OF enabled. I think at_hdmac should select or depend on this. I
did latter and still I get compilation error :(
drivers/dma/at_hdmac.c:1558: error: implicit declaration of function 'of_match_ptr'
drivers/dma/at_hdmac.c:1558: error: initializer element is not constant
drivers/dma/at_hdmac.c:1558: error: (near initialization for 'at_dma_driver.driver.of_match_table')
make[1]: *** [drivers/dma/at_hdmac.o] Error 1
--
~Vinod
^ permalink raw reply
* Yocto weekly bug trend charts -- WW43
From: Xu, Jiajun @ 2011-10-24 3:36 UTC (permalink / raw)
To: yocto@yoctoproject.org
Hi all,
The overall open bug trend keep flat last week. Open bug and WDD number increased to 140 and 699. Yocto 1.1 released last week. Bug status of WW43 could be found on https://wiki.yoctoproject.org/wiki/Yocto_Bug_Trend.
Best Regards,
Jiajun
^ permalink raw reply
* [U-Boot] [PATCH 1/2] Flatten and solidify block_dev_desc layout
From: Che-liang Chiou @ 2011-10-24 3:36 UTC (permalink / raw)
To: u-boot
In-Reply-To: <20111021190914.8C7DB18AE81C@gemini.denx.de>
Dear Wolfgang Denk,
I guess I have to put this patchset on hold. I will get you back if we
could proceed with this patchset.
Regards,
Che-Liang
On Sat, Oct 22, 2011 at 3:09 AM, Wolfgang Denk <wd@denx.de> wrote:
> Dear Che-Liang Chiou,
>
> In message <1319178708-10881-2-git-send-email-clchiou@chromium.org> you wrote:
>> The block_dev_desc struct has #ifdef on lba48 and variable-size on lba
>> and so its layout varies from config to config. ?At least part_efi.c has
>> partially complained about this.
>>
>> This patch makes lba48 be always defined and lba be fixed to largest
>> size that an LBA would need so that the block_dev_desc layout would be
>> an invariant with respect to configurations.
>>
>> Doing so would waste a few extra bytes per struct block_dev_desc, which
>> I believe is not critical.
>
> How much exactly is "a few bytes"?
>
>
> Best regards,
>
> Wolfgang Denk
>
> --
> DENX Software Engineering GmbH, ? ? MD: Wolfgang Denk & Detlev Zundel
> HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
> Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
> As long as we're going to reinvent the wheel again, we might as ?well
> try making it round this time. ? ? ? ? ? ? ? ? ? ? ? ?- Mike Dennison
>
^ permalink raw reply
* [PATCH] scheduler rate controller
From: Lv, Hui @ 2011-10-24 3:36 UTC (permalink / raw)
To: xen-devel@lists.xensource.com
Cc: Duan, Jiangang, Tian, Kevin, keir@xen.org, Dong, Eddie
As one of the topics presented in Xen summit2011 in SC, we proposed one method scheduler rate controller (SRC) to control high frequency of scheduling under some conditions. You can find the slides at
http://www.slideshare.net/xen_com_mgr/9-hui-lvtacklingthemanagementchallengesofserverconsolidationonmulticoresystems
In the followings, we have tested it with 2-socket multi-core system with many rounds and got the positive results and improve the performance greatly either with the consolidation workload SPECvirt_2010 or some small workloads such as sysbench and SPECjbb. So I posted it here for review.
>From Xen scheduling mechanism, hypervisor kicks related VCPUs by raising schedule softirq during processing external interrupts. Therefore, if the number of IRQ is very large, the scheduling happens more frequent. Frequent scheduling will
1) bring more overhead for hypervisor and
2) increase cache miss rate.
In our consolidation workloads, SPECvirt_sc2010, SR-IOV & iSCSI solution are adopted to bypass software emulation but bring heavy network traffic. Correspondingly, 15k scheduling happened per second on each physical core, which means the average running time is very short, only 60us. We proposed SRC in XEN to mitigate this problem.
The performance benefits brought by this patch is very huge at peak throughput with no influence when system loads are low.
SRC improved SPECvirt performance by 14%.
1)It reduced CPU utilization, which allows more load to be added.
2)Response time (QoS) became better at the same CPU %.
3)The better response time allowed us to push the CPU % at peak performance to an even higher level (CPU was not saturated in SPECvirt).
SRC reduced context switch rate significantly, resulted in
2)Smaller Path Length
3)Less cache misses thus lower CPI
4)Better performance for both Guest and Hypervisor sides.
With this patch, from our SPECvirt_sc2010 results, the performance of xen catches up the other open sourced hypervisor.
Signed-off-by: Hui Lv hui.lv@intel.com
diff -ruNp xen.org/common/schedule.c xen/common/schedule.c
--- xen.org/common/schedule.c 2011-10-20 03:29:44.000000000 -0400
+++ xen/common/schedule.c 2011-10-23 21:41:14.000000000 -0400
@@ -98,6 +98,31 @@ static inline void trace_runstate_change
__trace_var(event, 1/*tsc*/, sizeof(d), &d);
}
+/*
+ *opt_sched_rate_control: parameter to turn on/off scheduler rate controller (SRC)
+ *opt_sched_rate_high: scheduling frequency threshold, default value is 50.
+
+ *Suggest to set the value of opt_sched_rate_high larger than 50.
+ *It means if the scheduling frequency number, calculated during SCHED_SRC_INTERVAL (default 10 millisecond), is larger than opt_sched_rate_high, SRC works.
+*/
+bool_t opt_sched_rate_control = 0;
+unsigned int opt_sched_rate_high = 50;
+boolean_param("sched_rate_control", opt_sched_rate_control);
+integer_param("sched_rate_high", opt_sched_rate_high);
+
+
+/* The following function is the scheduling rate controller (SRC). It is triggered when
+ * the frequency of scheduling is excessive high. (larger than opt_sched_rate_high)
+ *
+ * Rules to control the scheduling frequency
+ * 1)if the frequency of scheduling (sd->s_csnum), calculated during the period of SCHED_SRC_INTERVAL,
+ * is larger than the threshold opt_sched_rate_high, SRC is enabled to work by setting sd->s_src_control = 1
+ * 2)if SRC works, it returns previous vcpu directly if previous vcpu is still runnalbe and not the idle vcpu.
+ * This method can decrease the frequency of scheduling when the scheduling frequency is excessive.
+*/
+
+void src_controller(struct schedule_data *sd, struct vcpu *prev, s_time_t now);
+
static inline void trace_continue_running(struct vcpu *v)
{
@@ -1033,6 +1058,29 @@ static void vcpu_periodic_timer_work(str
set_timer(&v->periodic_timer, periodic_next_event);
}
+void src_controller(struct schedule_data *sd, struct vcpu *prev, s_time_t now)
+{
+ sd->s_csnum++;
+ if ((now - sd->s_src_loop_begin) >= MILLISECS(SCHED_SRC_INTERVAL))
+ {
+ if (sd->s_csnum >= opt_sched_rate_high)
+ sd->s_src_control = 1;
+ else
+ sd->s_src_control = 0;
+ sd->s_src_loop_begin = now;
+ sd->s_csnum = 0;
+ }
+ if (sd->s_src_control)
+ {
+ if (!is_idle_vcpu(prev) && vcpu_runnable(prev))
+ {
+ perfc_incr(sched_src);
+ return continue_running(prev);
+ }
+ perfc_incr(sched_nosrc);
+ }
+}
+
/*
* The main function
* - deschedule the current domain (scheduler independent).
@@ -1054,6 +1102,8 @@ static void schedule(void)
sd = &this_cpu(schedule_data);
+ if (opt_sched_rate_control)
+ src_controller(sd,prev,now);
/* Update tasklet scheduling status. */
switch ( *tasklet_work )
{
@@ -1197,6 +1247,9 @@ static int cpu_schedule_up(unsigned int
sd->curr = idle_vcpu[cpu];
init_timer(&sd->s_timer, s_timer_fn, NULL, cpu);
atomic_set(&sd->urgent_count, 0);
+ sd->s_csnum=0;
+ sd->s_src_loop_begin=NOW();
+ sd->s_src_control=0;
/* Boot CPU is dealt with later in schedule_init(). */
if ( cpu == 0 )
diff -ruNp xen.org/include/xen/perfc_defn.h xen/include/xen/perfc_defn.h
--- xen.org/include/xen/perfc_defn.h 2011-10-20 03:29:44.000000000 -0400
+++ xen/include/xen/perfc_defn.h 2011-10-23 21:08:28.000000000 -0400
@@ -15,6 +15,8 @@ PERFCOUNTER(ipis, "#IP
PERFCOUNTER(sched_irq, "sched: timer")
PERFCOUNTER(sched_run, "sched: runs through scheduler")
PERFCOUNTER(sched_ctx, "sched: context switches")
+PERFCOUNTER(sched_src, "sched: src triggered")
+PERFCOUNTER(sched_nosrc, "sched: src not triggered")
PERFCOUNTER(vcpu_check, "csched: vcpu_check")
PERFCOUNTER(schedule, "csched: schedule")
diff -ruNp xen.org/include/xen/sched-if.h xen/include/xen/sched-if.h
--- xen.org/include/xen/sched-if.h 2011-10-20 03:29:44.000000000 -0400
+++ xen/include/xen/sched-if.h 2011-10-23 21:20:57.000000000 -0400
@@ -15,6 +15,11 @@ extern struct cpupool *cpupool0;
/* cpus currently in no cpupool */
extern cpumask_t cpupool_free_cpus;
+/*SRC judge whether to trigger scheduling controller based on the comparison
+ *between the scheduling frequency, counted during SCHED_SRC_INTERVAL, and the threshold opt_sched_rate_high
+ *Suggest to set SCHED_SRC_INTERVAL to 10 (millisecond)
+*/
+#define SCHED_SRC_INTERVAL 10
/*
* In order to allow a scheduler to remap the lock->cpu mapping,
@@ -32,6 +37,9 @@ struct schedule_data {
struct vcpu *curr; /* current task */
void *sched_priv;
struct timer s_timer; /* scheduling timer */
+ int s_csnum; /* scheduling number based on last period */
+ s_time_t s_src_loop_begin; /* SRC conting start point */
+ bool_t s_src_control; /*indicate whether src should be triggered */
atomic_t urgent_count; /* how many urgent vcpus */
};
^ permalink raw reply
* [U-Boot] [PATCH 0/2] api: extend accessible set of block device attributes
From: Che-liang Chiou @ 2011-10-24 3:36 UTC (permalink / raw)
To: u-boot
In-Reply-To: <m24nz2pbvg.fsf@ohwell.denx.de>
Hi Detlev,
Oops, I did not know it is intentionally to keep the external apps API
as it is now.
I am working on an open source secure bootloader based on U-Boot.
Mostly I wrote boot logic (by boot logic I mean prompting user and
listing available devices sort of things). If you see U-Boot as a
platform, you can think of my project as an application running on top
of U-Boot, except that my application is statically linked with
U-Boot.
The boot logic is running on ARM and x86. Through the project I have
learned that certain APIs would be helpful, such as enumerating all
available block device and drawing bitmaps on screen regardless of
which driver (video or LCD) you are using.
It was probably a misleading finding when I searched the code base: I
saw only the external apps API implemented an API for enumerating
available block device. So I thought improving the external apps API
was the right place to go.
Alternatively (if not go the external apps API), we could have like
common/cmd_enum_block_dev.c that does what I am planning to do, and I
am happy to do this. What do you think?
Regards,
Che-Liang
On Sat, Oct 22, 2011 at 12:06 AM, Detlev Zundel <dzu@denx.de> wrote:
> Hi,
>
>> struct device_info in api_public.h defined its own subset of attributes
>> of block_dev_desc, which limits the capability of external apps.
>>
>> This patch set let external apps access the same set of block device
>> attributes as U-Boot.
>
> Generally speaking, we are intentionally limiting our API to external
> applications. ?It should be easier to extend U-Boot itself (and
> everybody will profit from the new code under a free license) rather
> than writing proprietary applications.
>
> Can you pleas tell us what the intention of the extension is? ?We surely
> will not accept patches gradually exposing all of the U-Boot internals
> through the API and paving the way for proprietary applications. ?So
> every extension has to be balanced and discussed.
>
> Thanks
> ?Detlev
>
> --
> Insider comment on Microsoft releasing Linux Hyper-V driver code under GPLv2:
> ? ? ? ? ? ? "It looks like hell just froze over."
> --
> DENX Software Engineering GmbH, ? ? ?MD: Wolfgang Denk & Detlev Zundel
> HRB 165235 Munich, ?Office: Kirchenstr.5, D-82194 Groebenzell, Germany
> Phone: (+49)-8142-66989-40 Fax: (+49)-8142-66989-80 Email: dzu at denx.de
>
^ permalink raw reply
* [PATCH 1/1] qmmp: update to 0.5.2
From: Xiaofeng Yan @ 2011-10-24 3:37 UTC (permalink / raw)
To: openembedded-core
In-Reply-To: <cover.1319427162.git.xiaofeng.yan@windriver.com>
From: Xiaofeng Yan <xiaofeng.yan@windriver.com>
Use do_split_package for each grouping and name them correctly besides updating package.
The format to name plugins of qmmp:
qmmp-plugin-<group>-<library> with the Description: Qmmp <Group> plugin for %s"
Signed-off-by: Xiaofeng Yan <xiaofeng.yan@windriver.com>
---
meta/recipes-qt/qt-apps/qmmp_0.5.2.bb | 60 +++++++++++++++++++++++++++++++++
1 files changed, 60 insertions(+), 0 deletions(-)
create mode 100644 meta/recipes-qt/qt-apps/qmmp_0.5.2.bb
diff --git a/meta/recipes-qt/qt-apps/qmmp_0.5.2.bb b/meta/recipes-qt/qt-apps/qmmp_0.5.2.bb
new file mode 100644
index 0000000..58dd825
--- /dev/null
+++ b/meta/recipes-qt/qt-apps/qmmp_0.5.2.bb
@@ -0,0 +1,60 @@
+dESCRIPTION = "Qmmp (Qt-based Multimedia Player) is an audio-player, written with help of Qt library"
+HOMEPAGE = "http://qmmp.ylsoftware.com"
+LICENSE = "GPLv2"
+LIC_FILES_CHKSUM = "file://COPYING;md5=393a5ca445f6965873eca0259a17f833"
+SECTION = "multimedia"
+
+PR = "r4"
+
+PROVIDES = "qmmp"
+DEPENDS = "qt4-x11-free taglib libmad libvorbis libogg alsa-lib"
+RDEPENDS_${PN} += "taglib alsa-lib libmad curl"
+
+SRC_URI = "http://qmmp.ylsoftware.com/files/${BPN}-${PV}.tar.bz2"
+
+SRC_URI[md5sum] = "20852f3cce3471bfc5affa9b2e947dc6"
+SRC_URI[sha256sum] = "6391dec020d2a381d7f4b7890fae6c49eadf88b3c9aef571fe3c5e96140822ec"
+
+
+PARALLEL_MAKE = ""
+
+inherit qmake2 cmake package
+
+export EXTRA_OECMAKE = "-DQT_QMAKE_EXECUTABLE=${OE_QMAKE_QMAKE} \
+ -DQT_LRELEASE_EXECUTABLE=${OE_QMAKE_LRELEASE} \
+ -DQT_MOC_EXECUTABLE=${OE_QMAKE_MOC} \
+ -DQT_UIC_EXECUTABLE=${OE_QMAKE_UIC} \
+ -DQT_RCC_EXECUTABLE=${OE_QMAKE_RCC} \
+ -DQT_LIBRARY_DIR=${OE_QMAKE_LIBDIR_QT} \
+ -DQT_HEADERS_DIR=${OE_QMAKE_INCDIR_QT} \
+ -DQT_QTCORE_INCLUDE_DIR=${OE_QMAKE_INCDIR_QT}/QtCore \
+ "
+PACKAGES_DYNAMIC = "qmmp-plugin-* "
+
+
+python populate_packages_prepend () {
+ import os
+ qmmp_libdir = bb.data.expand('${libdir}/qmmp', d)
+ gd = bb.data.expand('${D}/${libdir}/qmmp', d)
+ plug_dirs = os.listdir(gd)
+
+ for plug_dir in plug_dirs:
+ g_plug_dir = os.path.join(qmmp_libdir,plug_dir)
+ do_split_packages(d, g_plug_dir, '^lib(.*)\.so$', 'qmmp-plugin-' + plug_dir + '-%s', 'Qmmp' + plug_dir + 'plugin for %s')
+
+
+
+}
+
+FILES_${PN} = "\
+ ${bindir}/qmmp \
+ ${libdir}/lib*${SOLIBS} \
+ ${datadir}/icons/* \
+ ${datadir}/qmmp/images/* \
+ ${datadir}/applications/* \
+ "
+
+FILES_${PN}-dbg += "\
+ ${libdir}/qmmp/*/.debug/* \
+ "
+
--
1.7.0.4
^ permalink raw reply related
* [PATCH 0/1] qmmp: update to 0.5.2
From: Xiaofeng Yan @ 2011-10-24 3:37 UTC (permalink / raw)
To: openembedded-core
From: Xiaofeng Yan <xiaofeng.yan@windriver.com>
Hi saul,
Use do_split_package for each grouping and name them correctly besides updating package.
The format to name plugins of qmmp:
qmmp-plugin-<group>-<library> with the Description: Qmmp <Group> plugin for %s"
Pull URL: git://git.pokylinux.org/poky-contrib.git
Branch: xiaofeng/qmmp_update
Browse: http://git.pokylinux.org/cgit.cgi/poky-contrib/log/?h=xiaofeng/qmmp_update
Thanks,
Xiaofeng Yan <xiaofeng.yan@windriver.com>
---
Xiaofeng Yan (1):
qmmp: update to 0.5.2
meta/recipes-qt/qt-apps/qmmp_0.5.2.bb | 60 +++++++++++++++++++++++++++++++++
1 files changed, 60 insertions(+), 0 deletions(-)
create mode 100644 meta/recipes-qt/qt-apps/qmmp_0.5.2.bb
^ permalink raw reply
* [RFC][PATCH 3/3] ASoC: wm8940: Do not left shift the div parameter in wm8940_set_dai_clkdiv
From: Axel Lin @ 2011-10-24 3:35 UTC (permalink / raw)
To: linux-kernel; +Cc: Mark Brown, Dimitris Papastamos, Liam Girdwood, alsa-devel
In-Reply-To: <1319427161.5773.3.camel@phoenix>
Just check with other codec drivers, we do left shit div for
the corresponding bits from the caller in all other drivers.
I don't find the caller calling wm8940_set_dai_clkdiv now,
just make the behavior consistent with other drivers.
Signed-off-by: Axel Lin <axel.lin@gmail.com>
---
sound/soc/codecs/wm8940.c | 6 +++---
1 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/sound/soc/codecs/wm8940.c b/sound/soc/codecs/wm8940.c
index fec3892..72cec5b 100644
--- a/sound/soc/codecs/wm8940.c
+++ b/sound/soc/codecs/wm8940.c
@@ -620,15 +620,15 @@ static int wm8940_set_dai_clkdiv(struct snd_soc_dai *codec_dai,
switch (div_id) {
case WM8940_BCLKDIV:
reg = snd_soc_read(codec, WM8940_CLOCK) & 0xFEF3;
- ret = snd_soc_write(codec, WM8940_CLOCK, reg | (div << 2));
+ ret = snd_soc_write(codec, WM8940_CLOCK, reg | div);
break;
case WM8940_MCLKDIV:
reg = snd_soc_read(codec, WM8940_CLOCK) & 0xFF1F;
- ret = snd_soc_write(codec, WM8940_CLOCK, reg | (div << 5));
+ ret = snd_soc_write(codec, WM8940_CLOCK, reg | div);
break;
case WM8940_OPCLKDIV:
reg = snd_soc_read(codec, WM8940_GPIO) & 0xFFCF;
- ret = snd_soc_write(codec, WM8940_GPIO, reg | (div << 4));
+ ret = snd_soc_write(codec, WM8940_GPIO, reg | div);
break;
}
return ret;
--
1.7.5.4
^ permalink raw reply related
* [RFC][PATCH 3/3] ASoC: wm8940: Do not left shift the div parameter in wm8940_set_dai_clkdiv
From: Axel Lin @ 2011-10-24 3:35 UTC (permalink / raw)
To: linux-kernel; +Cc: Dimitris Papastamos, alsa-devel, Mark Brown, Liam Girdwood
In-Reply-To: <1319427161.5773.3.camel@phoenix>
Just check with other codec drivers, we do left shit div for
the corresponding bits from the caller in all other drivers.
I don't find the caller calling wm8940_set_dai_clkdiv now,
just make the behavior consistent with other drivers.
Signed-off-by: Axel Lin <axel.lin@gmail.com>
---
sound/soc/codecs/wm8940.c | 6 +++---
1 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/sound/soc/codecs/wm8940.c b/sound/soc/codecs/wm8940.c
index fec3892..72cec5b 100644
--- a/sound/soc/codecs/wm8940.c
+++ b/sound/soc/codecs/wm8940.c
@@ -620,15 +620,15 @@ static int wm8940_set_dai_clkdiv(struct snd_soc_dai *codec_dai,
switch (div_id) {
case WM8940_BCLKDIV:
reg = snd_soc_read(codec, WM8940_CLOCK) & 0xFEF3;
- ret = snd_soc_write(codec, WM8940_CLOCK, reg | (div << 2));
+ ret = snd_soc_write(codec, WM8940_CLOCK, reg | div);
break;
case WM8940_MCLKDIV:
reg = snd_soc_read(codec, WM8940_CLOCK) & 0xFF1F;
- ret = snd_soc_write(codec, WM8940_CLOCK, reg | (div << 5));
+ ret = snd_soc_write(codec, WM8940_CLOCK, reg | div);
break;
case WM8940_OPCLKDIV:
reg = snd_soc_read(codec, WM8940_GPIO) & 0xFFCF;
- ret = snd_soc_write(codec, WM8940_GPIO, reg | (div << 4));
+ ret = snd_soc_write(codec, WM8940_GPIO, reg | div);
break;
}
return ret;
--
1.7.5.4
^ permalink raw reply related
* [PATCH 2/3] ASoC: wm8940: Fix a typo for the mask of setting WM8940_BCLKDIV
From: Axel Lin @ 2011-10-24 3:33 UTC (permalink / raw)
To: linux-kernel; +Cc: Mark Brown, Dimitris Papastamos, Liam Girdwood, alsa-devel
In-Reply-To: <1319427161.5773.3.camel@phoenix>
The registers are 16 bits, thus remove an extra F for the mask.
Signed-off-by: Axel Lin <axel.lin@gmail.com>
---
sound/soc/codecs/wm8940.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/sound/soc/codecs/wm8940.c b/sound/soc/codecs/wm8940.c
index 3cc3bce..fec3892 100644
--- a/sound/soc/codecs/wm8940.c
+++ b/sound/soc/codecs/wm8940.c
@@ -619,7 +619,7 @@ static int wm8940_set_dai_clkdiv(struct snd_soc_dai *codec_dai,
switch (div_id) {
case WM8940_BCLKDIV:
- reg = snd_soc_read(codec, WM8940_CLOCK) & 0xFFEF3;
+ reg = snd_soc_read(codec, WM8940_CLOCK) & 0xFEF3;
ret = snd_soc_write(codec, WM8940_CLOCK, reg | (div << 2));
break;
case WM8940_MCLKDIV:
--
1.7.5.4
^ permalink raw reply related
* [PATCH 2/3] ASoC: wm8940: Fix a typo for the mask of setting WM8940_BCLKDIV
From: Axel Lin @ 2011-10-24 3:33 UTC (permalink / raw)
To: linux-kernel; +Cc: Dimitris Papastamos, alsa-devel, Mark Brown, Liam Girdwood
In-Reply-To: <1319427161.5773.3.camel@phoenix>
The registers are 16 bits, thus remove an extra F for the mask.
Signed-off-by: Axel Lin <axel.lin@gmail.com>
---
sound/soc/codecs/wm8940.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/sound/soc/codecs/wm8940.c b/sound/soc/codecs/wm8940.c
index 3cc3bce..fec3892 100644
--- a/sound/soc/codecs/wm8940.c
+++ b/sound/soc/codecs/wm8940.c
@@ -619,7 +619,7 @@ static int wm8940_set_dai_clkdiv(struct snd_soc_dai *codec_dai,
switch (div_id) {
case WM8940_BCLKDIV:
- reg = snd_soc_read(codec, WM8940_CLOCK) & 0xFFEF3;
+ reg = snd_soc_read(codec, WM8940_CLOCK) & 0xFEF3;
ret = snd_soc_write(codec, WM8940_CLOCK, reg | (div << 2));
break;
case WM8940_MCLKDIV:
--
1.7.5.4
^ permalink raw reply related
* [PATCH 1/3] ASoC: wm8940: Fix setting PLL Output clock division ratio
From: Axel Lin @ 2011-10-24 3:32 UTC (permalink / raw)
To: linux-kernel; +Cc: Mark Brown, Dimitris Papastamos, Liam Girdwood, alsa-devel
According to the datasheet:
The PLL Output clock division ratio is controlled by BIT[5:4] of
WM8940_GPIO register(08h).
Current code read/write the WM8940_ADDCNTRL(07h) register which is wrong.
Signed-off-by: Axel Lin <axel.lin@gmail.com>
---
sound/soc/codecs/wm8940.c | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/sound/soc/codecs/wm8940.c b/sound/soc/codecs/wm8940.c
index a4abfdf..3cc3bce 100644
--- a/sound/soc/codecs/wm8940.c
+++ b/sound/soc/codecs/wm8940.c
@@ -627,8 +627,8 @@ static int wm8940_set_dai_clkdiv(struct snd_soc_dai *codec_dai,
ret = snd_soc_write(codec, WM8940_CLOCK, reg | (div << 5));
break;
case WM8940_OPCLKDIV:
- reg = snd_soc_read(codec, WM8940_ADDCNTRL) & 0xFFCF;
- ret = snd_soc_write(codec, WM8940_ADDCNTRL, reg | (div << 4));
+ reg = snd_soc_read(codec, WM8940_GPIO) & 0xFFCF;
+ ret = snd_soc_write(codec, WM8940_GPIO, reg | (div << 4));
break;
}
return ret;
--
1.7.5.4
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.