From 38b3439d84f4a310bd29e3dbc21dffe9119ef157 Mon Sep 17 00:00:00 2001 From: Mike Crowe Date: Wed, 12 Jan 2011 00:53:52 -0500 Subject: [PATCH 0001/2822] setlocalversion: update mercurial tag parsing The tag output of hg doesn't quite match what setlocalversion currently expects, so update it to handle the latest format. Signed-off-by: Mike Crowe Signed-off-by: Mike Frysinger Signed-off-by: Michal Marek --- scripts/setlocalversion | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/scripts/setlocalversion b/scripts/setlocalversion index ef8729f48586d..4d403844e137a 100755 --- a/scripts/setlocalversion +++ b/scripts/setlocalversion @@ -86,12 +86,16 @@ scm_version() # Check for mercurial and a mercurial repo. if test -d .hg && hgid=`hg id 2>/dev/null`; then - tag=`printf '%s' "$hgid" | cut -s -d' ' -f2` - - # Do we have an untagged version? - if [ -z "$tag" -o "$tag" = tip ]; then - id=`printf '%s' "$hgid" | sed 's/[+ ].*//'` + # Do we have an tagged version? If so, latesttagdistance == 1 + if [ "`hg log -r . --template '{latesttagdistance}'`" == "1" ]; then + id=`hg log -r . --template '{latesttag}'` printf '%s%s' -hg "$id" + else + tag=`printf '%s' "$hgid" | cut -d' ' -f2` + if [ -z "$tag" -o "$tag" = tip ]; then + id=`printf '%s' "$hgid" | sed 's/[+ ].*//'` + printf '%s%s' -hg "$id" + fi fi # Are there uncommitted changes? -- GitLab From f4ed1009fcea8502d1191ef3e435e9d83c286b80 Mon Sep 17 00:00:00 2001 From: Jianbin Kang Date: Fri, 14 Jan 2011 20:07:05 +0800 Subject: [PATCH 0002/2822] kbuild: add GNU GLOBAL tags generation GNU GLOBAL (http://www.gnu.org/software/global/) is a source code tagging system It is really cheap to support it in kbuild system. Signed-off-by: Jianbin Kang Signed-off-by: Michal Marek --- Makefile | 7 ++++--- scripts/tags.sh | 9 +++++++++ 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index 6619720f50dd6..d4a9d5b81a14e 100644 --- a/Makefile +++ b/Makefile @@ -420,7 +420,7 @@ endif # of make so .config is not included in this case either (for *config). no-dot-config-targets := clean mrproper distclean \ - cscope TAGS tags help %docs check% coccicheck \ + cscope gtags TAGS tags help %docs check% coccicheck \ include/linux/version.h headers_% \ kernelversion %src-pkg @@ -1134,7 +1134,7 @@ CLEAN_FILES += vmlinux System.map \ MRPROPER_DIRS += include/config usr/include include/generated MRPROPER_FILES += .config .config.old .version .old_version \ include/linux/version.h \ - Module.symvers tags TAGS cscope* + Module.symvers tags TAGS cscope* GPATH GTAGS GRTAGS GSYMS # clean - Delete most, but leave enough to build external modules # @@ -1221,6 +1221,7 @@ help: @echo ' modules_prepare - Set up for building external modules' @echo ' tags/TAGS - Generate tags file for editors' @echo ' cscope - Generate cscope index' + @echo ' gtags - Generate GNU GLOBAL index' @echo ' kernelrelease - Output the release version string' @echo ' kernelversion - Output the version stored in Makefile' @echo ' headers_install - Install sanitised kernel headers to INSTALL_HDR_PATH'; \ @@ -1379,7 +1380,7 @@ clean: $(clean-dirs) quiet_cmd_tags = GEN $@ cmd_tags = $(CONFIG_SHELL) $(srctree)/scripts/tags.sh $@ -tags TAGS cscope: FORCE +tags TAGS cscope gtags: FORCE $(call cmd,tags) # Scripts to check various things for consistency diff --git a/scripts/tags.sh b/scripts/tags.sh index e091db312ddb0..5d17c71a81613 100755 --- a/scripts/tags.sh +++ b/scripts/tags.sh @@ -114,6 +114,11 @@ docscope() cscope -b -f cscope.out } +dogtags() +{ + all_sources | gtags -f - +} + exuberant() { all_sources | xargs $1 -a \ @@ -185,6 +190,10 @@ case "$1" in docscope ;; + "gtags") + dogtags + ;; + "tags") rm -f tags xtags ctags -- GitLab From f311847c2fcebd81912e2f0caf8a461dec28db41 Mon Sep 17 00:00:00 2001 From: James Bottomley Date: Wed, 22 Dec 2010 10:22:11 -0600 Subject: [PATCH 0003/2822] parisc: flush pages through tmpalias space The kernel has an 8M tmpailas space (originally designed for copying and clearing pages but now only used for clearing). The idea is to place zeros into the cache above a physical page rather than into the physical page and flush the cache, because often the zeros end up being replaced quickly anyway. We can also use the tmpalias space for flushing a page. The difference here is that we have to do tmpalias processing in the non access data and instruction traps. The principle is the same: as long as we know the physical address and have a virtual address congruent to the real one, the flush will be effective. In order to use the tmpalias space, the icache miss path has to be enhanced to check for the alias region to make the fic instruction effective. Signed-off-by: James Bottomley --- arch/parisc/include/asm/cacheflush.h | 7 +- arch/parisc/kernel/cache.c | 109 ++---------- arch/parisc/kernel/entry.S | 194 +++++++++++++++------ arch/parisc/kernel/pacache.S | 245 ++++++++++++--------------- 4 files changed, 272 insertions(+), 283 deletions(-) diff --git a/arch/parisc/include/asm/cacheflush.h b/arch/parisc/include/asm/cacheflush.h index f388a85bba113..dc9286a4dcc79 100644 --- a/arch/parisc/include/asm/cacheflush.h +++ b/arch/parisc/include/asm/cacheflush.h @@ -26,8 +26,6 @@ void flush_user_dcache_range_asm(unsigned long, unsigned long); void flush_kernel_dcache_range_asm(unsigned long, unsigned long); void flush_kernel_dcache_page_asm(void *); void flush_kernel_icache_page(void *); -void flush_user_dcache_page(unsigned long); -void flush_user_icache_page(unsigned long); void flush_user_dcache_range(unsigned long, unsigned long); void flush_user_icache_range(unsigned long, unsigned long); @@ -90,12 +88,15 @@ void flush_cache_page(struct vm_area_struct *vma, unsigned long vmaddr, unsigned void flush_cache_range(struct vm_area_struct *vma, unsigned long start, unsigned long end); +/* defined in pacache.S exported in cache.c used by flush_anon_page */ +void flush_dcache_page_asm(unsigned long phys_addr, unsigned long vaddr); + #define ARCH_HAS_FLUSH_ANON_PAGE static inline void flush_anon_page(struct vm_area_struct *vma, struct page *page, unsigned long vmaddr) { if (PageAnon(page)) - flush_user_dcache_page(vmaddr); + flush_dcache_page_asm(page_to_phys(page), vmaddr); } #define ARCH_HAS_FLUSH_KERNEL_DCACHE_PAGE diff --git a/arch/parisc/kernel/cache.c b/arch/parisc/kernel/cache.c index d054f3da3ff51..3f11331c27755 100644 --- a/arch/parisc/kernel/cache.c +++ b/arch/parisc/kernel/cache.c @@ -27,12 +27,17 @@ #include #include #include +#include int split_tlb __read_mostly; int dcache_stride __read_mostly; int icache_stride __read_mostly; EXPORT_SYMBOL(dcache_stride); +void flush_dcache_page_asm(unsigned long phys_addr, unsigned long vaddr); +EXPORT_SYMBOL(flush_dcache_page_asm); +void flush_icache_page_asm(unsigned long phys_addr, unsigned long vaddr); + /* On some machines (e.g. ones with the Merced bus), there can be * only a single PxTLB broadcast at a time; this must be guaranteed @@ -259,81 +264,13 @@ void disable_sr_hashing(void) panic("SpaceID hashing is still on!\n"); } -/* Simple function to work out if we have an existing address translation - * for a user space vma. */ -static inline int translation_exists(struct vm_area_struct *vma, - unsigned long addr, unsigned long pfn) -{ - pgd_t *pgd = pgd_offset(vma->vm_mm, addr); - pmd_t *pmd; - pte_t pte; - - if(pgd_none(*pgd)) - return 0; - - pmd = pmd_offset(pgd, addr); - if(pmd_none(*pmd) || pmd_bad(*pmd)) - return 0; - - /* We cannot take the pte lock here: flush_cache_page is usually - * called with pte lock already held. Whereas flush_dcache_page - * takes flush_dcache_mmap_lock, which is lower in the hierarchy: - * the vma itself is secure, but the pte might come or go racily. - */ - pte = *pte_offset_map(pmd, addr); - /* But pte_unmap() does nothing on this architecture */ - - /* Filter out coincidental file entries and swap entries */ - if (!(pte_val(pte) & (_PAGE_FLUSH|_PAGE_PRESENT))) - return 0; - - return pte_pfn(pte) == pfn; -} - -/* Private function to flush a page from the cache of a non-current - * process. cr25 contains the Page Directory of the current user - * process; we're going to hijack both it and the user space %sr3 to - * temporarily make the non-current process current. We have to do - * this because cache flushing may cause a non-access tlb miss which - * the handlers have to fill in from the pgd of the non-current - * process. */ static inline void -flush_user_cache_page_non_current(struct vm_area_struct *vma, - unsigned long vmaddr) +__flush_cache_page(struct vm_area_struct *vma, unsigned long vmaddr, + unsigned long physaddr) { - /* save the current process space and pgd */ - unsigned long space = mfsp(3), pgd = mfctl(25); - - /* we don't mind taking interrupts since they may not - * do anything with user space, but we can't - * be preempted here */ - preempt_disable(); - - /* make us current */ - mtctl(__pa(vma->vm_mm->pgd), 25); - mtsp(vma->vm_mm->context, 3); - - flush_user_dcache_page(vmaddr); - if(vma->vm_flags & VM_EXEC) - flush_user_icache_page(vmaddr); - - /* put the old current process back */ - mtsp(space, 3); - mtctl(pgd, 25); - preempt_enable(); -} - - -static inline void -__flush_cache_page(struct vm_area_struct *vma, unsigned long vmaddr) -{ - if (likely(vma->vm_mm->context == mfsp(3))) { - flush_user_dcache_page(vmaddr); - if (vma->vm_flags & VM_EXEC) - flush_user_icache_page(vmaddr); - } else { - flush_user_cache_page_non_current(vma, vmaddr); - } + flush_dcache_page_asm(physaddr, vmaddr); + if (vma->vm_flags & VM_EXEC) + flush_icache_page_asm(physaddr, vmaddr); } void flush_dcache_page(struct page *page) @@ -342,10 +279,8 @@ void flush_dcache_page(struct page *page) struct vm_area_struct *mpnt; struct prio_tree_iter iter; unsigned long offset; - unsigned long addr; + unsigned long addr, old_addr = 0; pgoff_t pgoff; - unsigned long pfn = page_to_pfn(page); - if (mapping && !mapping_mapped(mapping)) { set_bit(PG_dcache_dirty, &page->flags); @@ -369,20 +304,11 @@ void flush_dcache_page(struct page *page) offset = (pgoff - mpnt->vm_pgoff) << PAGE_SHIFT; addr = mpnt->vm_start + offset; - /* Flush instructions produce non access tlb misses. - * On PA, we nullify these instructions rather than - * taking a page fault if the pte doesn't exist. - * This is just for speed. If the page translation - * isn't there, there's no point exciting the - * nadtlb handler into a nullification frenzy. - * - * Make sure we really have this page: the private - * mappings may cover this area but have COW'd this - * particular page. - */ - if (translation_exists(mpnt, addr, pfn)) { - __flush_cache_page(mpnt, addr); - break; + if (old_addr == 0 || (old_addr & (SHMLBA - 1)) != (addr & (SHMLBA - 1))) { + __flush_cache_page(mpnt, addr, page_to_phys(page)); + if (old_addr) + printk(KERN_ERR "INEQUIVALENT ALIASES 0x%lx and 0x%lx in file %s\n", old_addr, addr, mpnt->vm_file ? mpnt->vm_file->f_path.dentry->d_name.name : "(null)"); + old_addr = addr; } } flush_dcache_mmap_unlock(mapping); @@ -573,7 +499,6 @@ flush_cache_page(struct vm_area_struct *vma, unsigned long vmaddr, unsigned long { BUG_ON(!vma->vm_mm->context); - if (likely(translation_exists(vma, vmaddr, pfn))) - __flush_cache_page(vma, vmaddr); + __flush_cache_page(vma, vmaddr, page_to_phys(pfn_to_page(pfn))); } diff --git a/arch/parisc/kernel/entry.S b/arch/parisc/kernel/entry.S index 6337adef30f64..e8c119b61fc72 100644 --- a/arch/parisc/kernel/entry.S +++ b/arch/parisc/kernel/entry.S @@ -225,22 +225,13 @@ #ifndef CONFIG_64BIT /* * naitlb miss interruption handler (parisc 1.1 - 32 bit) - * - * Note: naitlb misses will be treated - * as an ordinary itlb miss for now. - * However, note that naitlb misses - * have the faulting address in the - * IOR/ISR. */ .macro naitlb_11 code mfctl %isr,spc - b itlb_miss_11 + b naitlb_miss_11 mfctl %ior,va - /* FIXME: If user causes a naitlb miss, the priv level may not be in - * lower bits of va, where the itlb miss handler is expecting them - */ .align 32 .endm @@ -248,26 +239,17 @@ /* * naitlb miss interruption handler (parisc 2.0) - * - * Note: naitlb misses will be treated - * as an ordinary itlb miss for now. - * However, note that naitlb misses - * have the faulting address in the - * IOR/ISR. */ .macro naitlb_20 code mfctl %isr,spc #ifdef CONFIG_64BIT - b itlb_miss_20w + b naitlb_miss_20w #else - b itlb_miss_20 + b naitlb_miss_20 #endif mfctl %ior,va - /* FIXME: If user causes a naitlb miss, the priv level may not be in - * lower bits of va, where the itlb miss handler is expecting them - */ .align 32 .endm @@ -581,7 +563,24 @@ copy \va,\tmp1 depi 0,31,23,\tmp1 cmpb,COND(<>),n \tmp,\tmp1,\fault - ldi (_PAGE_DIRTY|_PAGE_WRITE|_PAGE_READ),\prot + mfctl %cr19,\tmp /* iir */ + /* get the opcode (first six bits) into \tmp */ + extrw,u \tmp,5,6,\tmp + /* + * Only setting the T bit prevents data cache movein + * Setting access rights to zero prevents instruction cache movein + * + * Note subtlety here: _PAGE_GATEWAY, _PAGE_EXEC and _PAGE_WRITE go + * to type field and _PAGE_READ goes to top bit of PL1 + */ + ldi (_PAGE_REFTRAP|_PAGE_READ|_PAGE_WRITE),\prot + /* + * so if the opcode is one (i.e. this is a memory management + * instruction) nullify the next load so \prot is only T. + * Otherwise this is a normal data operation + */ + cmpiclr,= 0x01,\tmp,%r0 + ldi (_PAGE_DIRTY|_PAGE_READ|_PAGE_WRITE),\prot depd,z \prot,8,7,\prot /* * OK, it is in the temp alias region, check whether "from" or "to". @@ -631,11 +630,7 @@ ENTRY(fault_vector_20) def 13 def 14 dtlb_20 15 -#if 0 naitlb_20 16 -#else - def 16 -#endif nadtlb_20 17 def 18 def 19 @@ -678,11 +673,7 @@ ENTRY(fault_vector_11) def 13 def 14 dtlb_11 15 -#if 0 naitlb_11 16 -#else - def 16 -#endif nadtlb_11 17 def 18 def 19 @@ -1203,7 +1194,7 @@ nadtlb_miss_20w: get_pgd spc,ptp space_check spc,t0,nadtlb_fault - L3_ptep ptp,pte,t0,va,nadtlb_check_flush_20w + L3_ptep ptp,pte,t0,va,nadtlb_check_alias_20w update_ptep ptp,pte,t0,t1 @@ -1214,6 +1205,14 @@ nadtlb_miss_20w: rfir nop +nadtlb_check_alias_20w: + do_alias spc,t0,t1,va,pte,prot,nadtlb_check_flush_20w + + idtlbt pte,prot + + rfir + nop + nadtlb_check_flush_20w: bb,>=,n pte,_PAGE_FLUSH_BIT,nadtlb_emulate @@ -1255,25 +1254,7 @@ dtlb_miss_11: nop dtlb_check_alias_11: - - /* Check to see if fault is in the temporary alias region */ - - cmpib,<>,n 0,spc,dtlb_fault /* forward */ - ldil L%(TMPALIAS_MAP_START),t0 - copy va,t1 - depwi 0,31,23,t1 - cmpb,<>,n t0,t1,dtlb_fault /* forward */ - ldi (_PAGE_DIRTY|_PAGE_WRITE|_PAGE_READ),prot - depw,z prot,8,7,prot - - /* - * OK, it is in the temp alias region, check whether "from" or "to". - * Check "subtle" note in pacache.S re: r23/r26. - */ - - extrw,u,= va,9,1,r0 - or,tr %r23,%r0,pte /* If "from" use "from" page */ - or %r26,%r0,pte /* else "to", use "to" page */ + do_alias spc,t0,t1,va,pte,prot,dtlb_fault idtlba pte,(va) idtlbp prot,(va) @@ -1286,7 +1267,7 @@ nadtlb_miss_11: space_check spc,t0,nadtlb_fault - L2_ptep ptp,pte,t0,va,nadtlb_check_flush_11 + L2_ptep ptp,pte,t0,va,nadtlb_check_alias_11 update_ptep ptp,pte,t0,t1 @@ -1304,6 +1285,15 @@ nadtlb_miss_11: rfir nop +nadtlb_check_alias_11: + do_alias spc,t0,t1,va,pte,prot,nadtlb_check_flush_11 + + idtlba pte,(va) + idtlbp prot,(va) + + rfir + nop + nadtlb_check_flush_11: bb,>=,n pte,_PAGE_FLUSH_BIT,nadtlb_emulate @@ -1359,7 +1349,7 @@ nadtlb_miss_20: space_check spc,t0,nadtlb_fault - L2_ptep ptp,pte,t0,va,nadtlb_check_flush_20 + L2_ptep ptp,pte,t0,va,nadtlb_check_alias_20 update_ptep ptp,pte,t0,t1 @@ -1372,6 +1362,14 @@ nadtlb_miss_20: rfir nop +nadtlb_check_alias_20: + do_alias spc,t0,t1,va,pte,prot,nadtlb_check_flush_20 + + idtlbt pte,prot + + rfir + nop + nadtlb_check_flush_20: bb,>=,n pte,_PAGE_FLUSH_BIT,nadtlb_emulate @@ -1484,6 +1482,36 @@ itlb_miss_20w: rfir nop +naitlb_miss_20w: + + /* + * I miss is a little different, since we allow users to fault + * on the gateway page which is in the kernel address space. + */ + + space_adjust spc,va,t0 + get_pgd spc,ptp + space_check spc,t0,naitlb_fault + + L3_ptep ptp,pte,t0,va,naitlb_check_alias_20w + + update_ptep ptp,pte,t0,t1 + + make_insert_tlb spc,pte,prot + + iitlbt pte,prot + + rfir + nop + +naitlb_check_alias_20w: + do_alias spc,t0,t1,va,pte,prot,naitlb_fault + + iitlbt pte,prot + + rfir + nop + #else itlb_miss_11: @@ -1508,6 +1536,38 @@ itlb_miss_11: rfir nop +naitlb_miss_11: + get_pgd spc,ptp + + space_check spc,t0,naitlb_fault + + L2_ptep ptp,pte,t0,va,naitlb_check_alias_11 + + update_ptep ptp,pte,t0,t1 + + make_insert_tlb_11 spc,pte,prot + + mfsp %sr1,t0 /* Save sr1 so we can use it in tlb inserts */ + mtsp spc,%sr1 + + iitlba pte,(%sr1,va) + iitlbp prot,(%sr1,va) + + mtsp t0, %sr1 /* Restore sr1 */ + + rfir + nop + +naitlb_check_alias_11: + do_alias spc,t0,t1,va,pte,prot,itlb_fault + + iitlba pte,(%sr0, va) + iitlbp prot,(%sr0, va) + + rfir + nop + + itlb_miss_20: get_pgd spc,ptp @@ -1526,6 +1586,32 @@ itlb_miss_20: rfir nop +naitlb_miss_20: + get_pgd spc,ptp + + space_check spc,t0,naitlb_fault + + L2_ptep ptp,pte,t0,va,naitlb_check_alias_20 + + update_ptep ptp,pte,t0,t1 + + make_insert_tlb spc,pte,prot + + f_extend pte,t0 + + iitlbt pte,prot + + rfir + nop + +naitlb_check_alias_20: + do_alias spc,t0,t1,va,pte,prot,naitlb_fault + + iitlbt pte,prot + + rfir + nop + #endif #ifdef CONFIG_64BIT @@ -1662,6 +1748,10 @@ nadtlb_fault: b intr_save ldi 17,%r8 +naitlb_fault: + b intr_save + ldi 16,%r8 + dtlb_fault: b intr_save ldi 15,%r8 diff --git a/arch/parisc/kernel/pacache.S b/arch/parisc/kernel/pacache.S index 09b77b2553c6b..a85823668cba0 100644 --- a/arch/parisc/kernel/pacache.S +++ b/arch/parisc/kernel/pacache.S @@ -608,93 +608,131 @@ ENTRY(__clear_user_page_asm) .procend ENDPROC(__clear_user_page_asm) -ENTRY(flush_kernel_dcache_page_asm) +ENTRY(flush_dcache_page_asm) .proc .callinfo NO_CALLS .entry + ldil L%(TMPALIAS_MAP_START), %r28 +#ifdef CONFIG_64BIT +#if (TMPALIAS_MAP_START >= 0x80000000) + depdi 0, 31,32, %r28 /* clear any sign extension */ + /* FIXME: page size dependend */ +#endif + extrd,u %r26, 56,32, %r26 /* convert phys addr to tlb insert format */ + depd %r25, 63,22, %r28 /* Form aliased virtual address 'to' */ + depdi 0, 63,12, %r28 /* Clear any offset bits */ +#else + extrw,u %r26, 24,25, %r26 /* convert phys addr to tlb insert format */ + depw %r25, 31,22, %r28 /* Form aliased virtual address 'to' */ + depwi 0, 31,12, %r28 /* Clear any offset bits */ +#endif + + /* Purge any old translation */ + + pdtlb 0(%r28) + ldil L%dcache_stride, %r1 - ldw R%dcache_stride(%r1), %r23 + ldw R%dcache_stride(%r1), %r1 #ifdef CONFIG_64BIT depdi,z 1, 63-PAGE_SHIFT,1, %r25 #else depwi,z 1, 31-PAGE_SHIFT,1, %r25 #endif - add %r26, %r25, %r25 - sub %r25, %r23, %r25 - - -1: fdc,m %r23(%r26) - fdc,m %r23(%r26) - fdc,m %r23(%r26) - fdc,m %r23(%r26) - fdc,m %r23(%r26) - fdc,m %r23(%r26) - fdc,m %r23(%r26) - fdc,m %r23(%r26) - fdc,m %r23(%r26) - fdc,m %r23(%r26) - fdc,m %r23(%r26) - fdc,m %r23(%r26) - fdc,m %r23(%r26) - fdc,m %r23(%r26) - fdc,m %r23(%r26) - cmpb,COND(<<) %r26, %r25,1b - fdc,m %r23(%r26) + add %r28, %r25, %r25 + sub %r25, %r1, %r25 + + +1: fdc,m %r1(%r28) + fdc,m %r1(%r28) + fdc,m %r1(%r28) + fdc,m %r1(%r28) + fdc,m %r1(%r28) + fdc,m %r1(%r28) + fdc,m %r1(%r28) + fdc,m %r1(%r28) + fdc,m %r1(%r28) + fdc,m %r1(%r28) + fdc,m %r1(%r28) + fdc,m %r1(%r28) + fdc,m %r1(%r28) + fdc,m %r1(%r28) + fdc,m %r1(%r28) + cmpb,COND(<<) %r28, %r25,1b + fdc,m %r1(%r28) sync bv %r0(%r2) - nop + pdtlb (%r25) .exit .procend -ENDPROC(flush_kernel_dcache_page_asm) - -ENTRY(flush_user_dcache_page) +ENDPROC(flush_dcache_page_asm) + +ENTRY(flush_icache_page_asm) .proc .callinfo NO_CALLS .entry - ldil L%dcache_stride, %r1 - ldw R%dcache_stride(%r1), %r23 - + ldil L%(TMPALIAS_MAP_START), %r28 #ifdef CONFIG_64BIT - depdi,z 1,63-PAGE_SHIFT,1, %r25 +#if (TMPALIAS_MAP_START >= 0x80000000) + depdi 0, 31,32, %r28 /* clear any sign extension */ + /* FIXME: page size dependend */ +#endif + extrd,u %r26, 56,32, %r26 /* convert phys addr to tlb insert format */ + depd %r25, 63,22, %r28 /* Form aliased virtual address 'to' */ + depdi 0, 63,12, %r28 /* Clear any offset bits */ #else - depwi,z 1,31-PAGE_SHIFT,1, %r25 + extrw,u %r26, 24,25, %r26 /* convert phys addr to tlb insert format */ + depw %r25, 31,22, %r28 /* Form aliased virtual address 'to' */ + depwi 0, 31,12, %r28 /* Clear any offset bits */ #endif - add %r26, %r25, %r25 - sub %r25, %r23, %r25 + /* Purge any old translation */ -1: fdc,m %r23(%sr3, %r26) - fdc,m %r23(%sr3, %r26) - fdc,m %r23(%sr3, %r26) - fdc,m %r23(%sr3, %r26) - fdc,m %r23(%sr3, %r26) - fdc,m %r23(%sr3, %r26) - fdc,m %r23(%sr3, %r26) - fdc,m %r23(%sr3, %r26) - fdc,m %r23(%sr3, %r26) - fdc,m %r23(%sr3, %r26) - fdc,m %r23(%sr3, %r26) - fdc,m %r23(%sr3, %r26) - fdc,m %r23(%sr3, %r26) - fdc,m %r23(%sr3, %r26) - fdc,m %r23(%sr3, %r26) - cmpb,COND(<<) %r26, %r25,1b - fdc,m %r23(%sr3, %r26) + pitlb (%sr0,%r28) + + ldil L%icache_stride, %r1 + ldw R%icache_stride(%r1), %r1 + +#ifdef CONFIG_64BIT + depdi,z 1, 63-PAGE_SHIFT,1, %r25 +#else + depwi,z 1, 31-PAGE_SHIFT,1, %r25 +#endif + add %r28, %r25, %r25 + sub %r25, %r1, %r25 + + +1: fic,m %r1(%r28) + fic,m %r1(%r28) + fic,m %r1(%r28) + fic,m %r1(%r28) + fic,m %r1(%r28) + fic,m %r1(%r28) + fic,m %r1(%r28) + fic,m %r1(%r28) + fic,m %r1(%r28) + fic,m %r1(%r28) + fic,m %r1(%r28) + fic,m %r1(%r28) + fic,m %r1(%r28) + fic,m %r1(%r28) + fic,m %r1(%r28) + cmpb,COND(<<) %r28, %r25,1b + fic,m %r1(%r28) sync bv %r0(%r2) - nop + pitlb (%sr0,%r25) .exit .procend -ENDPROC(flush_user_dcache_page) +ENDPROC(flush_icache_page_asm) -ENTRY(flush_user_icache_page) +ENTRY(flush_kernel_dcache_page_asm) .proc .callinfo NO_CALLS .entry @@ -711,23 +749,23 @@ ENTRY(flush_user_icache_page) sub %r25, %r23, %r25 -1: fic,m %r23(%sr3, %r26) - fic,m %r23(%sr3, %r26) - fic,m %r23(%sr3, %r26) - fic,m %r23(%sr3, %r26) - fic,m %r23(%sr3, %r26) - fic,m %r23(%sr3, %r26) - fic,m %r23(%sr3, %r26) - fic,m %r23(%sr3, %r26) - fic,m %r23(%sr3, %r26) - fic,m %r23(%sr3, %r26) - fic,m %r23(%sr3, %r26) - fic,m %r23(%sr3, %r26) - fic,m %r23(%sr3, %r26) - fic,m %r23(%sr3, %r26) - fic,m %r23(%sr3, %r26) +1: fdc,m %r23(%r26) + fdc,m %r23(%r26) + fdc,m %r23(%r26) + fdc,m %r23(%r26) + fdc,m %r23(%r26) + fdc,m %r23(%r26) + fdc,m %r23(%r26) + fdc,m %r23(%r26) + fdc,m %r23(%r26) + fdc,m %r23(%r26) + fdc,m %r23(%r26) + fdc,m %r23(%r26) + fdc,m %r23(%r26) + fdc,m %r23(%r26) + fdc,m %r23(%r26) cmpb,COND(<<) %r26, %r25,1b - fic,m %r23(%sr3, %r26) + fdc,m %r23(%r26) sync bv %r0(%r2) @@ -735,8 +773,7 @@ ENTRY(flush_user_icache_page) .exit .procend -ENDPROC(flush_user_icache_page) - +ENDPROC(flush_kernel_dcache_page_asm) ENTRY(purge_kernel_dcache_page) .proc @@ -780,69 +817,6 @@ ENTRY(purge_kernel_dcache_page) .procend ENDPROC(purge_kernel_dcache_page) -#if 0 - /* Currently not used, but it still is a possible alternate - * solution. - */ - -ENTRY(flush_alias_page) - .proc - .callinfo NO_CALLS - .entry - - tophys_r1 %r26 - - ldil L%(TMPALIAS_MAP_START), %r28 -#ifdef CONFIG_64BIT - extrd,u %r26, 56,32, %r26 /* convert phys addr to tlb insert format */ - depd %r25, 63,22, %r28 /* Form aliased virtual address 'to' */ - depdi 0, 63,12, %r28 /* Clear any offset bits */ -#else - extrw,u %r26, 24,25, %r26 /* convert phys addr to tlb insert format */ - depw %r25, 31,22, %r28 /* Form aliased virtual address 'to' */ - depwi 0, 31,12, %r28 /* Clear any offset bits */ -#endif - - /* Purge any old translation */ - - pdtlb 0(%r28) - - ldil L%dcache_stride, %r1 - ldw R%dcache_stride(%r1), %r23 - -#ifdef CONFIG_64BIT - depdi,z 1, 63-PAGE_SHIFT,1, %r29 -#else - depwi,z 1, 31-PAGE_SHIFT,1, %r29 -#endif - add %r28, %r29, %r29 - sub %r29, %r23, %r29 - -1: fdc,m %r23(%r28) - fdc,m %r23(%r28) - fdc,m %r23(%r28) - fdc,m %r23(%r28) - fdc,m %r23(%r28) - fdc,m %r23(%r28) - fdc,m %r23(%r28) - fdc,m %r23(%r28) - fdc,m %r23(%r28) - fdc,m %r23(%r28) - fdc,m %r23(%r28) - fdc,m %r23(%r28) - fdc,m %r23(%r28) - fdc,m %r23(%r28) - fdc,m %r23(%r28) - cmpb,COND(<<) %r28, %r29, 1b - fdc,m %r23(%r28) - - sync - bv %r0(%r2) - nop - .exit - - .procend -#endif .export flush_user_dcache_range_asm @@ -865,7 +839,6 @@ flush_user_dcache_range_asm: .exit .procend -ENDPROC(flush_alias_page) ENTRY(flush_kernel_dcache_range_asm) .proc -- GitLab From 8b4ae3342dbcb6a0def3a7b3ae7aee633a81e758 Mon Sep 17 00:00:00 2001 From: James Bottomley Date: Wed, 22 Dec 2010 10:24:36 -0600 Subject: [PATCH 0004/2822] eliminate special FLUSH flag from page table This was used to flush a region even if the page table entry had been cleared. In theory this was never necessary, but now we've switched to alias based flushing, the whole set of code associated with it can be dumped. Signed-off-by: James Bottomley Signed-off-by: James Bottomley --- arch/parisc/include/asm/pgtable.h | 14 ++----- arch/parisc/kernel/entry.S | 61 ++----------------------------- 2 files changed, 7 insertions(+), 68 deletions(-) diff --git a/arch/parisc/include/asm/pgtable.h b/arch/parisc/include/asm/pgtable.h index 865f37a8a8816..f3c09737e89ca 100644 --- a/arch/parisc/include/asm/pgtable.h +++ b/arch/parisc/include/asm/pgtable.h @@ -136,8 +136,7 @@ #define _PAGE_NO_CACHE_BIT 24 /* (0x080) Uncached Page (U bit) */ #define _PAGE_ACCESSED_BIT 23 /* (0x100) Software: Page Accessed */ #define _PAGE_PRESENT_BIT 22 /* (0x200) Software: translation valid */ -#define _PAGE_FLUSH_BIT 21 /* (0x400) Software: translation valid */ - /* for cache flushing only */ +/* bit 21 was formerly the FLUSH bit but is now unused */ #define _PAGE_USER_BIT 20 /* (0x800) Software: User accessible page */ /* N.B. The bits are defined in terms of a 32 bit word above, so the */ @@ -171,7 +170,6 @@ #define _PAGE_NO_CACHE (1 << xlate_pabit(_PAGE_NO_CACHE_BIT)) #define _PAGE_ACCESSED (1 << xlate_pabit(_PAGE_ACCESSED_BIT)) #define _PAGE_PRESENT (1 << xlate_pabit(_PAGE_PRESENT_BIT)) -#define _PAGE_FLUSH (1 << xlate_pabit(_PAGE_FLUSH_BIT)) #define _PAGE_USER (1 << xlate_pabit(_PAGE_USER_BIT)) #define _PAGE_FILE (1 << xlate_pabit(_PAGE_FILE_BIT)) @@ -211,7 +209,6 @@ #define PAGE_KERNEL_RO __pgprot(_PAGE_KERNEL & ~_PAGE_WRITE) #define PAGE_KERNEL_UNC __pgprot(_PAGE_KERNEL | _PAGE_NO_CACHE) #define PAGE_GATEWAY __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_ACCESSED | _PAGE_GATEWAY| _PAGE_READ) -#define PAGE_FLUSH __pgprot(_PAGE_FLUSH) /* @@ -259,7 +256,7 @@ extern unsigned long *empty_zero_page; #define ZERO_PAGE(vaddr) (virt_to_page(empty_zero_page)) -#define pte_none(x) ((pte_val(x) == 0) || (pte_val(x) & _PAGE_FLUSH)) +#define pte_none(x) (pte_val(x) == 0) #define pte_present(x) (pte_val(x) & _PAGE_PRESENT) #define pte_clear(mm,addr,xp) do { pte_val(*(xp)) = 0; } while (0) @@ -442,13 +439,10 @@ struct mm_struct; static inline pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep) { pte_t old_pte; - pte_t pte; spin_lock(&pa_dbit_lock); - pte = old_pte = *ptep; - pte_val(pte) &= ~_PAGE_PRESENT; - pte_val(pte) |= _PAGE_FLUSH; - set_pte_at(mm,addr,ptep,pte); + old_pte = *ptep; + pte_clear(mm,addr,ptep); spin_unlock(&pa_dbit_lock); return old_pte; diff --git a/arch/parisc/kernel/entry.S b/arch/parisc/kernel/entry.S index e8c119b61fc72..e5477092a5d4c 100644 --- a/arch/parisc/kernel/entry.S +++ b/arch/parisc/kernel/entry.S @@ -1206,23 +1206,7 @@ nadtlb_miss_20w: nop nadtlb_check_alias_20w: - do_alias spc,t0,t1,va,pte,prot,nadtlb_check_flush_20w - - idtlbt pte,prot - - rfir - nop - -nadtlb_check_flush_20w: - bb,>=,n pte,_PAGE_FLUSH_BIT,nadtlb_emulate - - /* Insert a "flush only" translation */ - - depdi,z 7,7,3,prot - depdi 1,10,1,prot - - /* Drop prot bits from pte and convert to page addr for idtlbt */ - convert_for_tlb_insert20 pte + do_alias spc,t0,t1,va,pte,prot,nadtlb_emulate idtlbt pte,prot @@ -1286,7 +1270,7 @@ nadtlb_miss_11: nop nadtlb_check_alias_11: - do_alias spc,t0,t1,va,pte,prot,nadtlb_check_flush_11 + do_alias spc,t0,t1,va,pte,prot,nadtlb_emulate idtlba pte,(va) idtlbp prot,(va) @@ -1294,30 +1278,6 @@ nadtlb_check_alias_11: rfir nop -nadtlb_check_flush_11: - bb,>=,n pte,_PAGE_FLUSH_BIT,nadtlb_emulate - - /* Insert a "flush only" translation */ - - zdepi 7,7,3,prot - depi 1,10,1,prot - - /* Get rid of prot bits and convert to page addr for idtlba */ - - depi 0,31,ASM_PFN_PTE_SHIFT,pte - SHRREG pte,(ASM_PFN_PTE_SHIFT-(31-26)),pte - - mfsp %sr1,t0 /* Save sr1 so we can use it in tlb inserts */ - mtsp spc,%sr1 - - idtlba pte,(%sr1,va) - idtlbp prot,(%sr1,va) - - mtsp t0, %sr1 /* Restore sr1 */ - - rfir - nop - dtlb_miss_20: space_adjust spc,va,t0 get_pgd spc,ptp @@ -1363,28 +1323,13 @@ nadtlb_miss_20: nop nadtlb_check_alias_20: - do_alias spc,t0,t1,va,pte,prot,nadtlb_check_flush_20 + do_alias spc,t0,t1,va,pte,prot,nadtlb_emulate idtlbt pte,prot rfir nop -nadtlb_check_flush_20: - bb,>=,n pte,_PAGE_FLUSH_BIT,nadtlb_emulate - - /* Insert a "flush only" translation */ - - depdi,z 7,7,3,prot - depdi 1,10,1,prot - - /* Drop prot bits from pte and convert to page addr for idtlbt */ - convert_for_tlb_insert20 pte - - idtlbt pte,prot - - rfir - nop #endif nadtlb_emulate: -- GitLab From fccdd7c4aeb7ed639b51126941545bc5b3824dab Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 20 Jan 2011 22:47:47 -0800 Subject: [PATCH 0005/2822] Input: ad7877 - convert to dev_pm_ops There is a move to deprecate bus-specific PM operations and move to using dev_pm_ops instead in order to reduce the amount of boilerplate code in buses and facilitate updates to the PM core. Do this move for the ad7879 SPI driver. Signed-off-by: Mark Brown Acked-by: Michael Hennerich Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/ad7877.c | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/drivers/input/touchscreen/ad7877.c b/drivers/input/touchscreen/ad7877.c index a1952fcc083e1..714d4e0f9f95f 100644 --- a/drivers/input/touchscreen/ad7877.c +++ b/drivers/input/touchscreen/ad7877.c @@ -41,6 +41,7 @@ #include #include #include +#include #include #include #include @@ -826,39 +827,37 @@ static int __devexit ad7877_remove(struct spi_device *spi) return 0; } -#ifdef CONFIG_PM -static int ad7877_suspend(struct spi_device *spi, pm_message_t message) +#ifdef CONFIG_PM_SLEEP +static int ad7877_suspend(struct device *dev) { - struct ad7877 *ts = dev_get_drvdata(&spi->dev); + struct ad7877 *ts = dev_get_drvdata(dev); ad7877_disable(ts); return 0; } -static int ad7877_resume(struct spi_device *spi) +static int ad7877_resume(struct device *dev) { - struct ad7877 *ts = dev_get_drvdata(&spi->dev); + struct ad7877 *ts = dev_get_drvdata(dev); ad7877_enable(ts); return 0; } -#else -#define ad7877_suspend NULL -#define ad7877_resume NULL #endif +static SIMPLE_DEV_PM_OPS(ad7877_pm, ad7877_suspend, ad7877_resume); + static struct spi_driver ad7877_driver = { .driver = { .name = "ad7877", .bus = &spi_bus_type, .owner = THIS_MODULE, + .pm = &ad7877_pm, }, .probe = ad7877_probe, .remove = __devexit_p(ad7877_remove), - .suspend = ad7877_suspend, - .resume = ad7877_resume, }; static int __init ad7877_init(void) -- GitLab From c7848c8e1a26ca6075d6cb538657f5381afcadc4 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 20 Jan 2011 22:48:44 -0800 Subject: [PATCH 0006/2822] Input: ad7879 - convert SPI to dev_pm_ops There is a move to deprecate bus-specific PM operations and move to using dev_pm_ops instead in order to reduce the amount of boilerplate code in buses and facilitate updates to the PM core. Do this move for the ad7879 SPI driver. Signed-off-by: Mark Brown Acked-by: Michael Hennerich Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/ad7879-spi.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/drivers/input/touchscreen/ad7879-spi.c b/drivers/input/touchscreen/ad7879-spi.c index 59c6e68c43250..ddf732f3cafcd 100644 --- a/drivers/input/touchscreen/ad7879-spi.c +++ b/drivers/input/touchscreen/ad7879-spi.c @@ -7,6 +7,7 @@ */ #include /* BUS_SPI */ +#include #include #include "ad7879.h" @@ -20,9 +21,10 @@ #define AD7879_WRITECMD(reg) (AD7879_CMD(reg)) #define AD7879_READCMD(reg) (AD7879_CMD(reg) | AD7879_CMD_READ) -#ifdef CONFIG_PM -static int ad7879_spi_suspend(struct spi_device *spi, pm_message_t message) +#ifdef CONFIG_PM_SLEEP +static int ad7879_spi_suspend(struct device *dev) { + struct spi_device *spi = to_spi_device(dev); struct ad7879 *ts = spi_get_drvdata(spi); ad7879_suspend(ts); @@ -30,19 +32,19 @@ static int ad7879_spi_suspend(struct spi_device *spi, pm_message_t message) return 0; } -static int ad7879_spi_resume(struct spi_device *spi) +static int ad7879_spi_resume(struct device *dev) { + struct spi_device *spi = to_spi_device(dev); struct ad7879 *ts = spi_get_drvdata(spi); ad7879_resume(ts); return 0; } -#else -# define ad7879_spi_suspend NULL -# define ad7879_spi_resume NULL #endif +static SIMPLE_DEV_PM_OPS(ad7879_spi_pm, ad7879_spi_suspend, ad7879_spi_resume); + /* * ad7879_read/write are only used for initial setup and for sysfs controls. * The main traffic is done in ad7879_collect(). @@ -173,11 +175,10 @@ static struct spi_driver ad7879_spi_driver = { .name = "ad7879", .bus = &spi_bus_type, .owner = THIS_MODULE, + .pm = &ad7879_spi_pm, }, .probe = ad7879_spi_probe, .remove = __devexit_p(ad7879_spi_remove), - .suspend = ad7879_spi_suspend, - .resume = ad7879_spi_resume, }; static int __init ad7879_spi_init(void) -- GitLab From 3c36e719033ddc09aded770472cbdb477fcb4479 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 20 Jan 2011 22:51:26 -0800 Subject: [PATCH 0007/2822] Input: ads7846 - convert to dev_pm_ops There is a move to deprecate bus-specific PM operations and move to using dev_pm_ops instead in order to reduce the amount of boilerplate code in buses and facilitate updates to the PM core. Do this move for the ads7846 driver. Signed-off-by: Mark Brown Acked-by: Michael Hennerich Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/ads7846.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/drivers/input/touchscreen/ads7846.c b/drivers/input/touchscreen/ads7846.c index 14ea54b78e464..b31e90f0d44be 100644 --- a/drivers/input/touchscreen/ads7846.c +++ b/drivers/input/touchscreen/ads7846.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -892,9 +893,10 @@ static irqreturn_t ads7846_irq(int irq, void *handle) return IRQ_HANDLED; } -static int ads7846_suspend(struct spi_device *spi, pm_message_t message) +#ifdef CONFIG_PM_SLEEP +static int ads7846_suspend(struct device *dev) { - struct ads7846 *ts = dev_get_drvdata(&spi->dev); + struct ads7846 *ts = dev_get_drvdata(dev); mutex_lock(&ts->lock); @@ -914,9 +916,9 @@ static int ads7846_suspend(struct spi_device *spi, pm_message_t message) return 0; } -static int ads7846_resume(struct spi_device *spi) +static int ads7846_resume(struct device *dev) { - struct ads7846 *ts = dev_get_drvdata(&spi->dev); + struct ads7846 *ts = dev_get_drvdata(dev); mutex_lock(&ts->lock); @@ -935,6 +937,9 @@ static int ads7846_resume(struct spi_device *spi) return 0; } +#endif + +static SIMPLE_DEV_PM_OPS(ads7846_pm, ads7846_suspend, ads7846_resume); static int __devinit ads7846_setup_pendown(struct spi_device *spi, struct ads7846 *ts) { @@ -1402,11 +1407,10 @@ static struct spi_driver ads7846_driver = { .name = "ads7846", .bus = &spi_bus_type, .owner = THIS_MODULE, + .pm = &ads7846_pm, }, .probe = ads7846_probe, .remove = __devexit_p(ads7846_remove), - .suspend = ads7846_suspend, - .resume = ads7846_resume, }; static int __init ads7846_init(void) -- GitLab From 3cbea4366f17dcb22f3bf5f253eeb86b622d24d0 Mon Sep 17 00:00:00 2001 From: Tony Finch Date: Tue, 18 Jan 2011 20:12:49 +0000 Subject: [PATCH 0008/2822] unifdef: update to upstream version 2.5 Fix a long-standing cpp compatibility bug. The -DFOO argument (without an explicit value) should define FOO to 1 not to the empty string. Add a -o option to support overwriting a file in place, and a -S option to list the nesting depth of symbols. Include line numbers in debugging output. Support CRLF newlines. Signed-off-by: Tony Finch Signed-off-by: Michal Marek --- scripts/unifdef.c | 247 ++++++++++++++++++++++++++++++++++------------ 1 file changed, 184 insertions(+), 63 deletions(-) diff --git a/scripts/unifdef.c b/scripts/unifdef.c index 44d39785e50da..7493c0ee51cc9 100644 --- a/scripts/unifdef.c +++ b/scripts/unifdef.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002 - 2009 Tony Finch + * Copyright (c) 2002 - 2011 Tony Finch * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -24,23 +24,14 @@ */ /* + * unifdef - remove ifdef'ed lines + * * This code was derived from software contributed to Berkeley by Dave Yost. * It was rewritten to support ANSI C by Tony Finch. The original version * of unifdef carried the 4-clause BSD copyright licence. None of its code * remains in this version (though some of the names remain) so it now * carries a more liberal licence. * - * The latest version is available from http://dotat.at/prog/unifdef - */ - -static const char * const copyright[] = { - "@(#) Copyright (c) 2002 - 2009 Tony Finch \n", - "$dotat: unifdef/unifdef.c,v 1.190 2009/11/27 17:21:26 fanf2 Exp $", -}; - -/* - * unifdef - remove ifdef'ed lines - * * Wishlist: * provide an option which will append the name of the * appropriate symbol after #else's and #endif's @@ -48,12 +39,16 @@ static const char * const copyright[] = { * #else's and #endif's to see that they match their * corresponding #ifdef or #ifndef * - * The first two items above require better buffer handling, which would - * also make it possible to handle all "dodgy" directives correctly. + * These require better buffer handling, which would also make + * it possible to handle all "dodgy" directives correctly. */ +#include +#include + #include #include +#include #include #include #include @@ -61,6 +56,12 @@ static const char * const copyright[] = { #include #include +const char copyright[] = + "@(#) $Version: unifdef-2.5 $\n" + "@(#) $Author: Tony Finch (dot@dotat.at) $\n" + "@(#) $URL: http://dotat.at/prog/unifdef $\n" +; + /* types of input lines: */ typedef enum { LT_TRUEI, /* a true #if with ignore flag */ @@ -152,6 +153,11 @@ static char const * const linestate_name[] = { */ #define EDITSLOP 10 +/* + * For temporary filenames + */ +#define TEMPLATE "unifdef.XXXXXX" + /* * Globals. */ @@ -165,6 +171,7 @@ static bool strictlogic; /* -K: keep ambiguous #ifs */ static bool killconsts; /* -k: eval constant #ifs */ static bool lnnum; /* -n: add #line directives */ static bool symlist; /* -s: output symbol list */ +static bool symdepth; /* -S: output symbol depth */ static bool text; /* -t: this is a text file */ static const char *symname[MAXSYMS]; /* symbol name */ @@ -175,10 +182,18 @@ static int nsyms; /* number of symbols */ static FILE *input; /* input file pointer */ static const char *filename; /* input file name */ static int linenum; /* current line number */ +static FILE *output; /* output file pointer */ +static const char *ofilename; /* output file name */ +static bool overwriting; /* output overwrites input */ +static char tempname[FILENAME_MAX]; /* used when overwriting */ static char tline[MAXLINE+EDITSLOP];/* input buffer plus space */ static char *keyword; /* used for editing #elif's */ +static const char *newline; /* input file format */ +static const char newline_unix[] = "\n"; +static const char newline_crlf[] = "\r\n"; + static Comment_state incomment; /* comment parser state */ static Line_state linestate; /* #if line parser state */ static Ifstate ifstate[MAXDEPTH]; /* #if processor state */ @@ -189,10 +204,13 @@ static int delcount; /* count of deleted lines */ static unsigned blankcount; /* count of blank lines */ static unsigned blankmax; /* maximum recent blankcount */ static bool constexpr; /* constant #if expression */ +static bool zerosyms = true; /* to format symdepth output */ +static bool firstsym; /* ditto */ static int exitstat; /* program exit status */ static void addsym(bool, bool, char *); +static void closeout(void); static void debug(const char *, ...); static void done(void); static void error(const char *); @@ -212,6 +230,7 @@ static void state(Ifstate); static int strlcmp(const char *, const char *, size_t); static void unnest(void); static void usage(void); +static void version(void); #define endsym(c) (!isalnum((unsigned char)c) && c != '_') @@ -223,7 +242,7 @@ main(int argc, char *argv[]) { int opt; - while ((opt = getopt(argc, argv, "i:D:U:I:BbcdeKklnst")) != -1) + while ((opt = getopt(argc, argv, "i:D:U:I:o:bBcdeKklnsStV")) != -1) switch (opt) { case 'i': /* treat stuff controlled by these symbols as text */ /* @@ -245,16 +264,15 @@ main(int argc, char *argv[]) case 'U': /* undef a symbol */ addsym(false, false, optarg); break; - case 'I': - /* no-op for compatibility with cpp */ - break; - case 'B': /* compress blank lines around removed section */ - compblank = true; + case 'I': /* no-op for compatibility with cpp */ break; case 'b': /* blank deleted lines instead of omitting them */ case 'l': /* backwards compatibility */ lnblank = true; break; + case 'B': /* compress blank lines around removed section */ + compblank = true; + break; case 'c': /* treat -D as -U and vice versa */ complement = true; break; @@ -273,12 +291,20 @@ main(int argc, char *argv[]) case 'n': /* add #line directive after deleted lines */ lnnum = true; break; + case 'o': /* output to a file */ + ofilename = optarg; + break; case 's': /* only output list of symbols that control #ifs */ symlist = true; break; + case 'S': /* list symbols with their nesting depth */ + symlist = symdepth = true; + break; case 't': /* don't parse C comments */ text = true; break; + case 'V': /* print version */ + version(); default: usage(); } @@ -290,21 +316,68 @@ main(int argc, char *argv[]) errx(2, "can only do one file"); } else if (argc == 1 && strcmp(*argv, "-") != 0) { filename = *argv; - input = fopen(filename, "r"); + input = fopen(filename, "rb"); if (input == NULL) err(2, "can't open %s", filename); } else { filename = "[stdin]"; input = stdin; } + if (ofilename == NULL) { + ofilename = "[stdout]"; + output = stdout; + } else { + struct stat ist, ost; + if (stat(ofilename, &ost) == 0 && + fstat(fileno(input), &ist) == 0) + overwriting = (ist.st_dev == ost.st_dev + && ist.st_ino == ost.st_ino); + if (overwriting) { + const char *dirsep; + int ofd; + + dirsep = strrchr(ofilename, '/'); + if (dirsep != NULL) + snprintf(tempname, sizeof(tempname), + "%.*s/" TEMPLATE, + (int)(dirsep - ofilename), ofilename); + else + snprintf(tempname, sizeof(tempname), + TEMPLATE); + ofd = mkstemp(tempname); + if (ofd != -1) + output = fdopen(ofd, "wb+"); + if (output == NULL) + err(2, "can't create temporary file"); + fchmod(ofd, ist.st_mode & (S_IRWXU|S_IRWXG|S_IRWXO)); + } else { + output = fopen(ofilename, "wb"); + if (output == NULL) + err(2, "can't open %s", ofilename); + } + } process(); abort(); /* bug */ } +static void +version(void) +{ + const char *c = copyright; + for (;;) { + while (*++c != '$') + if (*c == '\0') + exit(0); + while (*++c != '$') + putc(*c, stderr); + putc('\n', stderr); + } +} + static void usage(void) { - fprintf(stderr, "usage: unifdef [-BbcdeKknst] [-Ipath]" + fprintf(stderr, "usage: unifdef [-bBcdeKknsStV] [-Ipath]" " [-Dsym[=val]] [-Usym] [-iDsym[=val]] [-iUsym] ... [file]\n"); exit(2); } @@ -322,7 +395,8 @@ usage(void) * When we have processed a group that starts off with a known-false * #if/#elif sequence (which has therefore been deleted) followed by a * #elif that we don't understand and therefore must keep, we edit the - * latter into a #if to keep the nesting correct. + * latter into a #if to keep the nesting correct. We use strncpy() to + * overwrite the 4 byte token "elif" with "if " without a '\0' byte. * * When we find a true #elif in a group, the following block will * always be kept and the rest of the sequence after the next #elif or @@ -375,11 +449,11 @@ static void Oelif (void) { if (!iocccok) Eioccc(); Pelif(); } static void Idrop (void) { Fdrop(); ignoreon(); } static void Itrue (void) { Ftrue(); ignoreon(); } static void Ifalse(void) { Ffalse(); ignoreon(); } -/* edit this line */ +/* modify this line */ static void Mpass (void) { strncpy(keyword, "if ", 4); Pelif(); } -static void Mtrue (void) { keywordedit("else\n"); state(IS_TRUE_MIDDLE); } -static void Melif (void) { keywordedit("endif\n"); state(IS_FALSE_TRAILER); } -static void Melse (void) { keywordedit("endif\n"); state(IS_FALSE_ELSE); } +static void Mtrue (void) { keywordedit("else"); state(IS_TRUE_MIDDLE); } +static void Melif (void) { keywordedit("endif"); state(IS_FALSE_TRAILER); } +static void Melse (void) { keywordedit("endif"); state(IS_FALSE_ELSE); } static state_fn * const trans_table[IS_COUNT][LT_COUNT] = { /* IS_OUTSIDE */ @@ -431,13 +505,6 @@ static state_fn * const trans_table[IS_COUNT][LT_COUNT] = { * State machine utility functions */ static void -done(void) -{ - if (incomment) - error("EOF in comment"); - exit(exitstat); -} -static void ignoreoff(void) { if (depth == 0) @@ -452,14 +519,8 @@ ignoreon(void) static void keywordedit(const char *replacement) { - size_t size = tline + sizeof(tline) - keyword; - char *dst = keyword; - const char *src = replacement; - if (size != 0) { - while ((--size != 0) && (*src != '\0')) - *dst++ = *src++; - *dst = '\0'; - } + snprintf(keyword, tline + sizeof(tline) - keyword, + "%s%s", replacement, newline); print(); } static void @@ -494,24 +555,26 @@ flushline(bool keep) if (symlist) return; if (keep ^ complement) { - bool blankline = tline[strspn(tline, " \t\n")] == '\0'; + bool blankline = tline[strspn(tline, " \t\r\n")] == '\0'; if (blankline && compblank && blankcount != blankmax) { delcount += 1; blankcount += 1; } else { if (lnnum && delcount > 0) - printf("#line %d\n", linenum); - fputs(tline, stdout); + printf("#line %d%s", linenum, newline); + fputs(tline, output); delcount = 0; blankmax = blankcount = blankline ? blankcount + 1 : 0; } } else { if (lnblank) - putc('\n', stdout); + fputs(newline, output); exitstat = 1; delcount += 1; blankcount = 0; } + if (debugging) + fflush(output); } /* @@ -520,21 +583,54 @@ flushline(bool keep) static void process(void) { - Linetype lineval; - /* When compressing blank lines, act as if the file is preceded by a large number of blank lines. */ blankmax = blankcount = 1000; for (;;) { - linenum++; - lineval = parseline(); + Linetype lineval = parseline(); trans_table[ifstate[depth]][lineval](); - debug("process %s -> %s depth %d", - linetype_name[lineval], + debug("process line %d %s -> %s depth %d", + linenum, linetype_name[lineval], ifstate_name[ifstate[depth]], depth); } } +/* + * Flush the output and handle errors. + */ +static void +closeout(void) +{ + if (symdepth && !zerosyms) + printf("\n"); + if (fclose(output) == EOF) { + warn("couldn't write to %s", ofilename); + if (overwriting) { + unlink(tempname); + errx(2, "%s unchanged", filename); + } else { + exit(2); + } + } +} + +/* + * Clean up and exit. + */ +static void +done(void) +{ + if (incomment) + error("EOF in comment"); + closeout(); + if (overwriting && rename(tempname, ofilename) == -1) { + warn("couldn't rename temporary file"); + unlink(tempname); + errx(2, "%s unchanged", ofilename); + } + exit(exitstat); +} + /* * Parse a line and determine its type. We keep the preprocessor line * parser state between calls in the global variable linestate, with @@ -549,14 +645,22 @@ parseline(void) Linetype retval; Comment_state wascomment; + linenum++; if (fgets(tline, MAXLINE, input) == NULL) return (LT_EOF); + if (newline == NULL) { + if (strrchr(tline, '\n') == strrchr(tline, '\r') + 1) + newline = newline_crlf; + else + newline = newline_unix; + } retval = LT_PLAIN; wascomment = incomment; cp = skipcomment(tline); if (linestate == LS_START) { if (*cp == '#') { linestate = LS_HASH; + firstsym = true; cp = skipcomment(cp + 1); } else if (*cp != '\0') linestate = LS_DIRTY; @@ -566,7 +670,8 @@ parseline(void) cp = skipsym(cp); kwlen = cp - keyword; /* no way can we deal with a continuation inside a keyword */ - if (strncmp(cp, "\\\n", 2) == 0) + if (strncmp(cp, "\\\r\n", 3) == 0 || + strncmp(cp, "\\\n", 2) == 0) Eioccc(); if (strlcmp("ifdef", keyword, kwlen) == 0 || strlcmp("ifndef", keyword, kwlen) == 0) { @@ -617,9 +722,8 @@ parseline(void) size_t len = cp - tline; if (fgets(tline + len, MAXLINE - len, input) == NULL) { /* append the missing newline */ - tline[len+0] = '\n'; - tline[len+1] = '\0'; - cp++; + strcpy(tline + len, newline); + cp += strlen(newline); linestate = LS_START; } else { linestate = LS_DIRTY; @@ -630,7 +734,7 @@ parseline(void) while (*cp != '\0') cp = skipcomment(cp + 1); } - debug("parser %s comment %s line", + debug("parser line %d state %s comment %s line", linenum, comment_name[incomment], linestate_name[linestate]); return (retval); } @@ -875,11 +979,16 @@ skipcomment(const char *cp) } while (*cp != '\0') /* don't reset to LS_START after a line continuation */ - if (strncmp(cp, "\\\n", 2) == 0) + if (strncmp(cp, "\\\r\n", 3) == 0) + cp += 3; + else if (strncmp(cp, "\\\n", 2) == 0) cp += 2; else switch (incomment) { case NO_COMMENT: - if (strncmp(cp, "/\\\n", 3) == 0) { + if (strncmp(cp, "/\\\r\n", 4) == 0) { + incomment = STARTING_COMMENT; + cp += 4; + } else if (strncmp(cp, "/\\\n", 3) == 0) { incomment = STARTING_COMMENT; cp += 3; } else if (strncmp(cp, "/*", 2) == 0) { @@ -899,7 +1008,7 @@ skipcomment(const char *cp) } else if (strncmp(cp, "\n", 1) == 0) { linestate = LS_START; cp += 1; - } else if (strchr(" \t", *cp) != NULL) { + } else if (strchr(" \r\t", *cp) != NULL) { cp += 1; } else return (cp); @@ -931,7 +1040,10 @@ skipcomment(const char *cp) cp += 1; continue; case C_COMMENT: - if (strncmp(cp, "*\\\n", 3) == 0) { + if (strncmp(cp, "*\\\r\n", 4) == 0) { + incomment = FINISHING_COMMENT; + cp += 4; + } else if (strncmp(cp, "*\\\n", 3) == 0) { incomment = FINISHING_COMMENT; cp += 3; } else if (strncmp(cp, "*/", 2) == 0) { @@ -1015,7 +1127,13 @@ findsym(const char *str) if (cp == str) return (-1); if (symlist) { - printf("%.*s\n", (int)(cp-str), str); + if (symdepth && firstsym) + printf("%s%3d", zerosyms ? "" : "\n", depth); + firstsym = zerosyms = false; + printf("%s%.*s%s", + symdepth ? " " : "", + (int)(cp-str), str, + symdepth ? "" : "\n"); /* we don't care about the value of the symbol */ return (0); } @@ -1052,7 +1170,7 @@ addsym(bool ignorethis, bool definethis, char *sym) value[symind] = val+1; *val = '\0'; } else if (*val == '\0') - value[symind] = ""; + value[symind] = "1"; else usage(); } else { @@ -1060,6 +1178,8 @@ addsym(bool ignorethis, bool definethis, char *sym) usage(); value[symind] = NULL; } + debug("addsym %s=%s", symname[symind], + value[symind] ? value[symind] : "undef"); } /* @@ -1100,5 +1220,6 @@ error(const char *msg) else warnx("%s: %d: %s (#if line %d depth %d)", filename, linenum, msg, stifline[depth], depth); + closeout(); errx(2, "output may be truncated"); } -- GitLab From f117a3e3004381ccadadc5156178c283815ca393 Mon Sep 17 00:00:00 2001 From: Clemens Ladisch Date: Mon, 10 Jan 2011 17:21:35 +0100 Subject: [PATCH 0009/2822] firewire: ohci: log dead DMA contexts When a DMA context goes into the dead state (and the controller thus stops working correctly), logging this error and the controller's error code might be helpful for debugging. Signed-off-by: Clemens Ladisch Signed-off-by: Stefan Richter --- drivers/firewire/ohci.c | 59 ++++++++++++++++++++++++++++++++++++++--- 1 file changed, 55 insertions(+), 4 deletions(-) diff --git a/drivers/firewire/ohci.c b/drivers/firewire/ohci.c index bd3c61b6dd8d5..c7394361afcb1 100644 --- a/drivers/firewire/ohci.c +++ b/drivers/firewire/ohci.c @@ -208,9 +208,11 @@ struct fw_ohci { struct context at_request_ctx; struct context at_response_ctx; + u32 it_context_support; u32 it_context_mask; /* unoccupied IT contexts */ struct iso_context *it_context_list; u64 ir_context_channels; /* unoccupied channels */ + u32 ir_context_support; u32 ir_context_mask; /* unoccupied IR contexts */ struct iso_context *ir_context_list; u64 mc_channels; /* channels in use by the multichannel IR context */ @@ -338,7 +340,7 @@ static void log_irqs(u32 evt) !(evt & OHCI1394_busReset)) return; - fw_notify("IRQ %08x%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n", evt, + fw_notify("IRQ %08x%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n", evt, evt & OHCI1394_selfIDComplete ? " selfID" : "", evt & OHCI1394_RQPkt ? " AR_req" : "", evt & OHCI1394_RSPkt ? " AR_resp" : "", @@ -351,6 +353,7 @@ static void log_irqs(u32 evt) evt & OHCI1394_cycle64Seconds ? " cycle64Seconds" : "", evt & OHCI1394_cycleInconsistent ? " cycleInconsistent" : "", evt & OHCI1394_regAccessFail ? " regAccessFail" : "", + evt & OHCI1394_unrecoverableError ? " unrecoverableError" : "", evt & OHCI1394_busReset ? " busReset" : "", evt & ~(OHCI1394_selfIDComplete | OHCI1394_RQPkt | OHCI1394_RSPkt | OHCI1394_reqTxComplete | @@ -1590,6 +1593,47 @@ static void at_context_transmit(struct context *ctx, struct fw_packet *packet) } +static void detect_dead_context(struct fw_ohci *ohci, + const char *name, unsigned int regs) +{ + u32 ctl; + + ctl = reg_read(ohci, CONTROL_SET(regs)); + if (ctl & CONTEXT_DEAD) { +#ifdef CONFIG_FIREWIRE_OHCI_DEBUG + fw_error("DMA context %s has stopped, error code: %s\n", + name, evts[ctl & 0x1f]); +#else + fw_error("DMA context %s has stopped, error code: %#x\n", + name, ctl & 0x1f); +#endif + } +} + +static void handle_dead_contexts(struct fw_ohci *ohci) +{ + unsigned int i; + char name[8]; + + detect_dead_context(ohci, "ATReq", OHCI1394_AsReqTrContextBase); + detect_dead_context(ohci, "ATRsp", OHCI1394_AsRspTrContextBase); + detect_dead_context(ohci, "ARReq", OHCI1394_AsReqRcvContextBase); + detect_dead_context(ohci, "ARRsp", OHCI1394_AsRspRcvContextBase); + for (i = 0; i < 32; ++i) { + if (!(ohci->it_context_support & (1 << i))) + continue; + sprintf(name, "IT%u", i); + detect_dead_context(ohci, name, OHCI1394_IsoXmitContextBase(i)); + } + for (i = 0; i < 32; ++i) { + if (!(ohci->ir_context_support & (1 << i))) + continue; + sprintf(name, "IR%u", i); + detect_dead_context(ohci, name, OHCI1394_IsoRcvContextBase(i)); + } + /* TODO: maybe try to flush and restart the dead contexts */ +} + static u32 cycle_timer_ticks(u32 cycle_timer) { u32 ticks; @@ -1904,6 +1948,9 @@ static irqreturn_t irq_handler(int irq, void *data) fw_notify("isochronous cycle inconsistent\n"); } + if (unlikely(event & OHCI1394_unrecoverableError)) + handle_dead_contexts(ohci); + if (event & OHCI1394_cycle64Seconds) { spin_lock(&ohci->lock); update_bus_time(ohci); @@ -2141,7 +2188,9 @@ static int ohci_enable(struct fw_card *card, OHCI1394_selfIDComplete | OHCI1394_regAccessFail | OHCI1394_cycle64Seconds | - OHCI1394_cycleInconsistent | OHCI1394_cycleTooLong | + OHCI1394_cycleInconsistent | + OHCI1394_unrecoverableError | + OHCI1394_cycleTooLong | OHCI1394_masterIntEnable; if (param_debug & OHCI_PARAM_DEBUG_BUSRESETS) irqs |= OHCI1394_busReset; @@ -3207,15 +3256,17 @@ static int __devinit pci_probe(struct pci_dev *dev, reg_write(ohci, OHCI1394_IsoRecvIntMaskSet, ~0); ohci->ir_context_channels = ~0ULL; - ohci->ir_context_mask = reg_read(ohci, OHCI1394_IsoRecvIntMaskSet); + ohci->ir_context_support = reg_read(ohci, OHCI1394_IsoRecvIntMaskSet); reg_write(ohci, OHCI1394_IsoRecvIntMaskClear, ~0); + ohci->ir_context_mask = ohci->ir_context_support; ohci->n_ir = hweight32(ohci->ir_context_mask); size = sizeof(struct iso_context) * ohci->n_ir; ohci->ir_context_list = kzalloc(size, GFP_KERNEL); reg_write(ohci, OHCI1394_IsoXmitIntMaskSet, ~0); - ohci->it_context_mask = reg_read(ohci, OHCI1394_IsoXmitIntMaskSet); + ohci->it_context_support = reg_read(ohci, OHCI1394_IsoXmitIntMaskSet); reg_write(ohci, OHCI1394_IsoXmitIntMaskClear, ~0); + ohci->it_context_mask = ohci->it_context_support; ohci->n_it = hweight32(ohci->it_context_mask); size = sizeof(struct iso_context) * ohci->n_it; ohci->it_context_list = kzalloc(size, GFP_KERNEL); -- GitLab From 3e204dfcaff0e7f6c4d9873fb8c9d948ec5ab2da Mon Sep 17 00:00:00 2001 From: Clemens Ladisch Date: Mon, 10 Jan 2011 17:28:27 +0100 Subject: [PATCH 0010/2822] firewire: cdev: remove unneeded idr_find() from complete_transaction() Outbound transactions are never aborted with release_client_resource(), so it is not necessary for complete_transaction() to check whether the resource is still registered. Only shutdown_resource() can abort such an transaction, and this is already handled with the in_shutdown check. Signed-off-by: Clemens Ladisch Signed-off-by: "Stefan Richter" --- drivers/firewire/core-cdev.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/drivers/firewire/core-cdev.c b/drivers/firewire/core-cdev.c index 48ae712e21018..4434f7ca11d53 100644 --- a/drivers/firewire/core-cdev.c +++ b/drivers/firewire/core-cdev.c @@ -544,14 +544,8 @@ static void complete_transaction(struct fw_card *card, int rcode, * 1. If called while in shutdown, the idr tree must be left untouched. * The idr handle will be removed and the client reference will be * dropped later. - * 2. If the call chain was release_client_resource -> - * release_transaction -> complete_transaction (instead of a normal - * conclusion of the transaction), i.e. if this resource was already - * unregistered from the idr, the client reference will be dropped - * by release_client_resource and we must not drop it here. */ - if (!client->in_shutdown && - idr_find(&client->resource_idr, e->r.resource.handle)) { + if (!client->in_shutdown) { idr_remove(&client->resource_idr, e->r.resource.handle); /* Drop the idr's reference */ client_put(client); -- GitLab From 5a5e62da9be255439e8ce59f96828775b7b33374 Mon Sep 17 00:00:00 2001 From: Clemens Ladisch Date: Mon, 10 Jan 2011 17:28:39 +0100 Subject: [PATCH 0011/2822] firewire: cdev: always wait for outbound transactions to complete We must not use fw_cancel_transaction() because it cannot correctly abort still-active transactions. The only place in core-cdev where this matters is when the file is released. Instead of trying to abort the transactions, we wait for them to complete normally, i.e., until all outbound transaction resources have been removed from the IDR tree. Signed-off-by: Clemens Ladisch Signed-off-by: "Stefan Richter" --- drivers/firewire/core-cdev.c | 42 ++++++++++++++++++++++++------------ 1 file changed, 28 insertions(+), 14 deletions(-) diff --git a/drivers/firewire/core-cdev.c b/drivers/firewire/core-cdev.c index 4434f7ca11d53..5485c0877b81e 100644 --- a/drivers/firewire/core-cdev.c +++ b/drivers/firewire/core-cdev.c @@ -64,6 +64,7 @@ struct client { struct idr resource_idr; struct list_head event_list; wait_queue_head_t wait; + wait_queue_head_t tx_flush_wait; u64 bus_reset_closure; struct fw_iso_context *iso_context; @@ -251,6 +252,7 @@ static int fw_device_op_open(struct inode *inode, struct file *file) idr_init(&client->resource_idr); INIT_LIST_HEAD(&client->event_list); init_waitqueue_head(&client->wait); + init_waitqueue_head(&client->tx_flush_wait); INIT_LIST_HEAD(&client->phy_receiver_link); kref_init(&client->kref); @@ -520,10 +522,6 @@ static int release_client_resource(struct client *client, u32 handle, static void release_transaction(struct client *client, struct client_resource *resource) { - struct outbound_transaction_resource *r = container_of(resource, - struct outbound_transaction_resource, resource); - - fw_cancel_transaction(client->device->card, &r->transaction); } static void complete_transaction(struct fw_card *card, int rcode, @@ -540,16 +538,9 @@ static void complete_transaction(struct fw_card *card, int rcode, memcpy(rsp->data, payload, rsp->length); spin_lock_irqsave(&client->lock, flags); - /* - * 1. If called while in shutdown, the idr tree must be left untouched. - * The idr handle will be removed and the client reference will be - * dropped later. - */ - if (!client->in_shutdown) { - idr_remove(&client->resource_idr, e->r.resource.handle); - /* Drop the idr's reference */ - client_put(client); - } + idr_remove(&client->resource_idr, e->r.resource.handle); + if (client->in_shutdown) + wake_up(&client->tx_flush_wait); spin_unlock_irqrestore(&client->lock, flags); rsp->type = FW_CDEV_EVENT_RESPONSE; @@ -569,6 +560,8 @@ static void complete_transaction(struct fw_card *card, int rcode, queue_event(client, &e->event, rsp, sizeof(*rsp) + rsp->length, NULL, 0); + /* Drop the idr's reference */ + client_put(client); /* Drop the transaction callback's reference */ client_put(client); } @@ -1672,6 +1665,25 @@ static int fw_device_op_mmap(struct file *file, struct vm_area_struct *vma) return ret; } +static int is_outbound_transaction_resource(int id, void *p, void *data) +{ + struct client_resource *resource = p; + + return resource->release == release_transaction; +} + +static int has_outbound_transactions(struct client *client) +{ + int ret; + + spin_lock_irq(&client->lock); + ret = idr_for_each(&client->resource_idr, + is_outbound_transaction_resource, NULL); + spin_unlock_irq(&client->lock); + + return ret; +} + static int shutdown_resource(int id, void *p, void *data) { struct client_resource *resource = p; @@ -1707,6 +1719,8 @@ static int fw_device_op_release(struct inode *inode, struct file *file) client->in_shutdown = true; spin_unlock_irq(&client->lock); + wait_event(client->tx_flush_wait, !has_outbound_transactions(client)); + idr_for_each(&client->resource_idr, shutdown_resource, client); idr_remove_all(&client->resource_idr); idr_destroy(&client->resource_idr); -- GitLab From dbc9880fa731fe2482a706bbabb4165269233063 Mon Sep 17 00:00:00 2001 From: Clemens Ladisch Date: Mon, 10 Jan 2011 17:29:03 +0100 Subject: [PATCH 0012/2822] firewire: cdev: remove unneeded reference For outbound transactions, the IDR's and the callback's references now have exactly the same lifetime, so we do not need both of them. Signed-off-by: Clemens Ladisch Signed-off-by: "Stefan Richter" --- drivers/firewire/core-cdev.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/drivers/firewire/core-cdev.c b/drivers/firewire/core-cdev.c index 5485c0877b81e..e0c13fb3ae22d 100644 --- a/drivers/firewire/core-cdev.c +++ b/drivers/firewire/core-cdev.c @@ -562,8 +562,6 @@ static void complete_transaction(struct fw_card *card, int rcode, /* Drop the idr's reference */ client_put(client); - /* Drop the transaction callback's reference */ - client_put(client); } static int init_request(struct client *client, @@ -601,9 +599,6 @@ static int init_request(struct client *client, if (ret < 0) goto failed; - /* Get a reference for the transaction callback */ - client_get(client); - fw_send_request(client->device->card, &e->r.transaction, request->tcode, destination_id, request->generation, speed, request->offset, e->response.data, -- GitLab From e71084af58cf15e6043338500eeaf6281d0a62af Mon Sep 17 00:00:00 2001 From: Clemens Ladisch Date: Sat, 22 Jan 2011 15:05:03 +0100 Subject: [PATCH 0013/2822] firewire: core: fix card->reset_jiffies overflow On a 32-bit machine with, e.g., HZ=1000, jiffies will overflow after about 50 days, so if there are between 25 and 50 days between bus resets, the card->reset_jiffies comparisons can get wrong results. To fix this, ensure that this timestamp always uses 64 bits. Signed-off-by: Clemens Ladisch Signed-off-by: "Stefan Richter" --- drivers/firewire/core-card.c | 5 +++-- drivers/firewire/core-cdev.c | 3 ++- drivers/firewire/core-device.c | 3 ++- drivers/firewire/core-topology.c | 2 +- include/linux/firewire.h | 2 +- 5 files changed, 9 insertions(+), 6 deletions(-) diff --git a/drivers/firewire/core-card.c b/drivers/firewire/core-card.c index 24ff35511e2b1..3241dc4e1fc9f 100644 --- a/drivers/firewire/core-card.c +++ b/drivers/firewire/core-card.c @@ -233,7 +233,7 @@ static void br_work(struct work_struct *work) /* Delay for 2s after last reset per IEEE 1394 clause 8.2.1. */ if (card->reset_jiffies != 0 && - time_is_after_jiffies(card->reset_jiffies + 2 * HZ)) { + time_before64(get_jiffies_64(), card->reset_jiffies + 2 * HZ)) { if (!schedule_delayed_work(&card->br_work, 2 * HZ)) fw_card_put(card); return; @@ -316,7 +316,8 @@ static void bm_work(struct work_struct *work) irm_id = card->irm_node->node_id; local_id = card->local_node->node_id; - grace = time_after(jiffies, card->reset_jiffies + DIV_ROUND_UP(HZ, 8)); + grace = time_after64(get_jiffies_64(), + card->reset_jiffies + DIV_ROUND_UP(HZ, 8)); if ((is_next_generation(generation, card->bm_generation) && !card->bm_abdicate) || diff --git a/drivers/firewire/core-cdev.c b/drivers/firewire/core-cdev.c index e0c13fb3ae22d..62ac111af2432 100644 --- a/drivers/firewire/core-cdev.c +++ b/drivers/firewire/core-cdev.c @@ -1205,7 +1205,8 @@ static void iso_resource_work(struct work_struct *work) todo = r->todo; /* Allow 1000ms grace period for other reallocations. */ if (todo == ISO_RES_ALLOC && - time_is_after_jiffies(client->device->card->reset_jiffies + HZ)) { + time_before64(get_jiffies_64(), + client->device->card->reset_jiffies + HZ)) { schedule_iso_resource(r, DIV_ROUND_UP(HZ, 3)); skip = true; } else { diff --git a/drivers/firewire/core-device.c b/drivers/firewire/core-device.c index 6113b896e7901..57461923bacff 100644 --- a/drivers/firewire/core-device.c +++ b/drivers/firewire/core-device.c @@ -747,7 +747,8 @@ static void fw_device_shutdown(struct work_struct *work) container_of(work, struct fw_device, work.work); int minor = MINOR(device->device.devt); - if (time_is_after_jiffies(device->card->reset_jiffies + SHUTDOWN_DELAY) + if (time_before64(get_jiffies_64(), + device->card->reset_jiffies + SHUTDOWN_DELAY) && !list_empty(&device->card->link)) { schedule_delayed_work(&device->work, SHUTDOWN_DELAY); return; diff --git a/drivers/firewire/core-topology.c b/drivers/firewire/core-topology.c index 09be1a635505c..193ed9233144b 100644 --- a/drivers/firewire/core-topology.c +++ b/drivers/firewire/core-topology.c @@ -545,7 +545,7 @@ void fw_core_handle_bus_reset(struct fw_card *card, int node_id, int generation, */ smp_wmb(); card->generation = generation; - card->reset_jiffies = jiffies; + card->reset_jiffies = get_jiffies_64(); card->bm_node_id = 0xffff; card->bm_abdicate = bm_abdicate; fw_schedule_bm_work(card, 0); diff --git a/include/linux/firewire.h b/include/linux/firewire.h index 9a3f5f9383f69..b6d21d5a11a25 100644 --- a/include/linux/firewire.h +++ b/include/linux/firewire.h @@ -89,7 +89,7 @@ struct fw_card { int current_tlabel; u64 tlabel_mask; struct list_head transaction_list; - unsigned long reset_jiffies; + u64 reset_jiffies; u32 split_timeout_hi; u32 split_timeout_lo; -- GitLab From 63310467a3d1ed6a0460ec1f4268126cd1ceec2e Mon Sep 17 00:00:00 2001 From: Christoph Lameter Date: Thu, 20 Jan 2011 11:12:26 -0600 Subject: [PATCH 0014/2822] mm: Remove support for kmem_cache_name() The last user was ext4 and Eric Sandeen removed the call in a recent patch. See the following URL for the discussion: http://marc.info/?l=linux-ext4&m=129546975702198&w=2 Signed-off-by: Christoph Lameter Signed-off-by: Pekka Enberg --- include/linux/slab.h | 1 - mm/slab.c | 8 -------- mm/slob.c | 6 ------ mm/slub.c | 6 ------ 4 files changed, 21 deletions(-) diff --git a/include/linux/slab.h b/include/linux/slab.h index fa9086647eb7a..ad4dd1c8d30aa 100644 --- a/include/linux/slab.h +++ b/include/linux/slab.h @@ -105,7 +105,6 @@ void kmem_cache_destroy(struct kmem_cache *); int kmem_cache_shrink(struct kmem_cache *); void kmem_cache_free(struct kmem_cache *, void *); unsigned int kmem_cache_size(struct kmem_cache *); -const char *kmem_cache_name(struct kmem_cache *); /* * Please use this macro to create slab caches. Simply specify the diff --git a/mm/slab.c b/mm/slab.c index 37961d1f584fe..4bab2d1a8291e 100644 --- a/mm/slab.c +++ b/mm/slab.c @@ -2147,8 +2147,6 @@ static int __init_refok setup_cpu_cache(struct kmem_cache *cachep, gfp_t gfp) * * @name must be valid until the cache is destroyed. This implies that * the module calling this has to destroy the cache before getting unloaded. - * Note that kmem_cache_name() is not guaranteed to return the same pointer, - * therefore applications must manage it themselves. * * The flags are * @@ -3840,12 +3838,6 @@ unsigned int kmem_cache_size(struct kmem_cache *cachep) } EXPORT_SYMBOL(kmem_cache_size); -const char *kmem_cache_name(struct kmem_cache *cachep) -{ - return cachep->name; -} -EXPORT_SYMBOL_GPL(kmem_cache_name); - /* * This initializes kmem_list3 or resizes various caches for all nodes. */ diff --git a/mm/slob.c b/mm/slob.c index 3588eaaef7267..46e0aee33a235 100644 --- a/mm/slob.c +++ b/mm/slob.c @@ -666,12 +666,6 @@ unsigned int kmem_cache_size(struct kmem_cache *c) } EXPORT_SYMBOL(kmem_cache_size); -const char *kmem_cache_name(struct kmem_cache *c) -{ - return c->name; -} -EXPORT_SYMBOL(kmem_cache_name); - int kmem_cache_shrink(struct kmem_cache *d) { return 0; diff --git a/mm/slub.c b/mm/slub.c index e15aa7f193c97..d2f343a54bad2 100644 --- a/mm/slub.c +++ b/mm/slub.c @@ -2399,12 +2399,6 @@ unsigned int kmem_cache_size(struct kmem_cache *s) } EXPORT_SYMBOL(kmem_cache_size); -const char *kmem_cache_name(struct kmem_cache *s) -{ - return s->name; -} -EXPORT_SYMBOL(kmem_cache_name); - static void list_slab_objects(struct kmem_cache *s, struct page *page, const char *text) { -- GitLab From 414b4ff5eecff0097d09c4a7da12e435fd503692 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Tue, 25 Jan 2011 12:43:49 +0100 Subject: [PATCH 0015/2822] block: add REQ_FLUSH_SEQ rq == &q->flush_rq was used to determine whether a rq is part of a flush sequence, which worked because all requests in a flush sequence were sequenced using the single dedicated request. This is about to change, so introduce REQ_FLUSH_SEQ flag to distinguish flush sequence requests. This patch doesn't cause any behavior change. Signed-off-by: Tejun Heo Signed-off-by: Jens Axboe --- block/blk-core.c | 4 ++-- block/blk-flush.c | 1 + block/blk.h | 2 +- include/linux/blk_types.h | 2 ++ 4 files changed, 6 insertions(+), 3 deletions(-) diff --git a/block/blk-core.c b/block/blk-core.c index 4ce953f1b3909..fc7d8ad76f440 100644 --- a/block/blk-core.c +++ b/block/blk-core.c @@ -136,7 +136,7 @@ static void req_bio_endio(struct request *rq, struct bio *bio, { struct request_queue *q = rq->q; - if (&q->flush_rq != rq) { + if (!(rq->cmd_flags & REQ_FLUSH_SEQ)) { if (error) clear_bit(BIO_UPTODATE, &bio->bi_flags); else if (!test_bit(BIO_UPTODATE, &bio->bi_flags)) @@ -1789,7 +1789,7 @@ static void blk_account_io_done(struct request *req) * normal IO on queueing nor completion. Accounting the * containing request is enough. */ - if (blk_do_io_stat(req) && req != &req->q->flush_rq) { + if (blk_do_io_stat(req) && !(req->cmd_flags & REQ_FLUSH_SEQ)) { unsigned long duration = jiffies - req->start_time; const int rw = rq_data_dir(req); struct hd_struct *part; diff --git a/block/blk-flush.c b/block/blk-flush.c index 54b123d6563e6..8592869bcbe73 100644 --- a/block/blk-flush.c +++ b/block/blk-flush.c @@ -130,6 +130,7 @@ static struct request *queue_next_fseq(struct request_queue *q) BUG(); } + rq->cmd_flags |= REQ_FLUSH_SEQ; elv_insert(q, rq, ELEVATOR_INSERT_FRONT); return rq; } diff --git a/block/blk.h b/block/blk.h index 2db8f32838e73..9d2ee8f4d9af4 100644 --- a/block/blk.h +++ b/block/blk.h @@ -61,7 +61,7 @@ static inline struct request *__elv_next_request(struct request_queue *q) while (!list_empty(&q->queue_head)) { rq = list_entry_rq(q->queue_head.next); if (!(rq->cmd_flags & (REQ_FLUSH | REQ_FUA)) || - rq == &q->flush_rq) + (rq->cmd_flags & REQ_FLUSH_SEQ)) return rq; rq = blk_do_flush(q, rq); if (rq) diff --git a/include/linux/blk_types.h b/include/linux/blk_types.h index 46ad5197537af..dddedfc0af811 100644 --- a/include/linux/blk_types.h +++ b/include/linux/blk_types.h @@ -148,6 +148,7 @@ enum rq_flag_bits { __REQ_ALLOCED, /* request came from our alloc pool */ __REQ_COPY_USER, /* contains copies of user pages */ __REQ_FLUSH, /* request for cache flush */ + __REQ_FLUSH_SEQ, /* request for flush sequence */ __REQ_IO_STAT, /* account I/O stat */ __REQ_MIXED_MERGE, /* merge of different types, fail separately */ __REQ_SECURE, /* secure discard (used with __REQ_DISCARD) */ @@ -188,6 +189,7 @@ enum rq_flag_bits { #define REQ_ALLOCED (1 << __REQ_ALLOCED) #define REQ_COPY_USER (1 << __REQ_COPY_USER) #define REQ_FLUSH (1 << __REQ_FLUSH) +#define REQ_FLUSH_SEQ (1 << __REQ_FLUSH_SEQ) #define REQ_IO_STAT (1 << __REQ_IO_STAT) #define REQ_MIXED_MERGE (1 << __REQ_MIXED_MERGE) #define REQ_SECURE (1 << __REQ_SECURE) -- GitLab From 143a87f4c9c629067afea5b6703d66ea88c82f8e Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Tue, 25 Jan 2011 12:43:52 +0100 Subject: [PATCH 0016/2822] block: improve flush bio completion bio's for flush are completed twice - once during the data phase and one more time after the whole sequence is complete. The first completion shouldn't notify completion to the issuer. This was achieved by skipping all bio completion steps in req_bio_endio() for the first completion; however, this has two drawbacks. * Error is not recorded in bio and must be tracked somewhere else. * Partial completion is not supported. Both don't cause problems for the current users; however, they make further improvements difficult. Change req_bio_endio() such that it only skips the actual notification part for the first completion. bio completion is implemented with partial completions on mind anyway so this is as simple as moving the REQ_FLUSH_SEQ conditional such that only calling of bio_endio() is skipped. Signed-off-by: Tejun Heo Signed-off-by: Jens Axboe --- block/blk-core.c | 48 +++++++++++++++++++++--------------------------- 1 file changed, 21 insertions(+), 27 deletions(-) diff --git a/block/blk-core.c b/block/blk-core.c index fc7d8ad76f440..617bb9e40927d 100644 --- a/block/blk-core.c +++ b/block/blk-core.c @@ -136,37 +136,31 @@ static void req_bio_endio(struct request *rq, struct bio *bio, { struct request_queue *q = rq->q; - if (!(rq->cmd_flags & REQ_FLUSH_SEQ)) { - if (error) - clear_bit(BIO_UPTODATE, &bio->bi_flags); - else if (!test_bit(BIO_UPTODATE, &bio->bi_flags)) - error = -EIO; - - if (unlikely(nbytes > bio->bi_size)) { - printk(KERN_ERR "%s: want %u bytes done, %u left\n", - __func__, nbytes, bio->bi_size); - nbytes = bio->bi_size; - } + if (error) + clear_bit(BIO_UPTODATE, &bio->bi_flags); + else if (!test_bit(BIO_UPTODATE, &bio->bi_flags)) + error = -EIO; + + if (unlikely(nbytes > bio->bi_size)) { + printk(KERN_ERR "%s: want %u bytes done, %u left\n", + __func__, nbytes, bio->bi_size); + nbytes = bio->bi_size; + } - if (unlikely(rq->cmd_flags & REQ_QUIET)) - set_bit(BIO_QUIET, &bio->bi_flags); + if (unlikely(rq->cmd_flags & REQ_QUIET)) + set_bit(BIO_QUIET, &bio->bi_flags); - bio->bi_size -= nbytes; - bio->bi_sector += (nbytes >> 9); + bio->bi_size -= nbytes; + bio->bi_sector += (nbytes >> 9); - if (bio_integrity(bio)) - bio_integrity_advance(bio, nbytes); + if (bio_integrity(bio)) + bio_integrity_advance(bio, nbytes); - if (bio->bi_size == 0) - bio_endio(bio, error); - } else { - /* - * Okay, this is the sequenced flush request in - * progress, just record the error; - */ - if (error && !q->flush_err) - q->flush_err = error; - } + /* don't actually finish bio if it's part of flush sequence */ + if (bio->bi_size == 0 && !(rq->cmd_flags & REQ_FLUSH_SEQ)) + bio_endio(bio, error); + else if (error && !q->flush_err) + q->flush_err = error; } void blk_dump_rq_flags(struct request *rq, char *msg) -- GitLab From ae1b1539622fb46e51b4d13b3f9e5f4c713f86ae Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Tue, 25 Jan 2011 12:43:54 +0100 Subject: [PATCH 0017/2822] block: reimplement FLUSH/FUA to support merge The current FLUSH/FUA support has evolved from the implementation which had to perform queue draining. As such, sequencing is done queue-wide one flush request after another. However, with the draining requirement gone, there's no reason to keep the queue-wide sequential approach. This patch reimplements FLUSH/FUA support such that each FLUSH/FUA request is sequenced individually. The actual FLUSH execution is double buffered and whenever a request wants to execute one for either PRE or POSTFLUSH, it queues on the pending queue. Once certain conditions are met, a flush request is issued and on its completion all pending requests proceed to the next sequence. This allows arbitrary merging of different type of flushes. How they are merged can be primarily controlled and tuned by adjusting the above said 'conditions' used to determine when to issue the next flush. This is inspired by Darrick's patches to merge multiple zero-data flushes which helps workloads with highly concurrent fsync requests. * As flush requests are never put on the IO scheduler, request fields used for flush share space with rq->rb_node. rq->completion_data is moved out of the union. This increases the request size by one pointer. As rq->elevator_private* are used only by the iosched too, it is possible to reduce the request size further. However, to do that, we need to modify request allocation path such that iosched data is not allocated for flush requests. * FLUSH/FUA processing happens on insertion now instead of dispatch. - Comments updated as per Vivek and Mike. Signed-off-by: Tejun Heo Cc: "Darrick J. Wong" Cc: Shaohua Li Cc: Christoph Hellwig Cc: Vivek Goyal Cc: Mike Snitzer Signed-off-by: Jens Axboe --- block/blk-core.c | 10 +- block/blk-flush.c | 440 +++++++++++++++++++++++++++------------ block/blk.h | 12 +- block/elevator.c | 7 + include/linux/blkdev.h | 18 +- include/linux/elevator.h | 1 + 6 files changed, 332 insertions(+), 156 deletions(-) diff --git a/block/blk-core.c b/block/blk-core.c index 617bb9e40927d..05746093b45e8 100644 --- a/block/blk-core.c +++ b/block/blk-core.c @@ -134,8 +134,6 @@ EXPORT_SYMBOL(blk_rq_init); static void req_bio_endio(struct request *rq, struct bio *bio, unsigned int nbytes, int error) { - struct request_queue *q = rq->q; - if (error) clear_bit(BIO_UPTODATE, &bio->bi_flags); else if (!test_bit(BIO_UPTODATE, &bio->bi_flags)) @@ -159,8 +157,6 @@ static void req_bio_endio(struct request *rq, struct bio *bio, /* don't actually finish bio if it's part of flush sequence */ if (bio->bi_size == 0 && !(rq->cmd_flags & REQ_FLUSH_SEQ)) bio_endio(bio, error); - else if (error && !q->flush_err) - q->flush_err = error; } void blk_dump_rq_flags(struct request *rq, char *msg) @@ -519,7 +515,9 @@ struct request_queue *blk_alloc_queue_node(gfp_t gfp_mask, int node_id) init_timer(&q->unplug_timer); setup_timer(&q->timeout, blk_rq_timed_out_timer, (unsigned long) q); INIT_LIST_HEAD(&q->timeout_list); - INIT_LIST_HEAD(&q->pending_flushes); + INIT_LIST_HEAD(&q->flush_queue[0]); + INIT_LIST_HEAD(&q->flush_queue[1]); + INIT_LIST_HEAD(&q->flush_data_in_flight); INIT_WORK(&q->unplug_work, blk_unplug_work); kobject_init(&q->kobj, &blk_queue_ktype); @@ -1198,7 +1196,7 @@ static int __make_request(struct request_queue *q, struct bio *bio) spin_lock_irq(q->queue_lock); if (bio->bi_rw & (REQ_FLUSH | REQ_FUA)) { - where = ELEVATOR_INSERT_FRONT; + where = ELEVATOR_INSERT_FLUSH; goto get_rq; } diff --git a/block/blk-flush.c b/block/blk-flush.c index 8592869bcbe73..a867e3f524f33 100644 --- a/block/blk-flush.c +++ b/block/blk-flush.c @@ -1,6 +1,69 @@ /* * Functions to sequence FLUSH and FUA writes. + * + * Copyright (C) 2011 Max Planck Institute for Gravitational Physics + * Copyright (C) 2011 Tejun Heo + * + * This file is released under the GPLv2. + * + * REQ_{FLUSH|FUA} requests are decomposed to sequences consisted of three + * optional steps - PREFLUSH, DATA and POSTFLUSH - according to the request + * properties and hardware capability. + * + * If a request doesn't have data, only REQ_FLUSH makes sense, which + * indicates a simple flush request. If there is data, REQ_FLUSH indicates + * that the device cache should be flushed before the data is executed, and + * REQ_FUA means that the data must be on non-volatile media on request + * completion. + * + * If the device doesn't have writeback cache, FLUSH and FUA don't make any + * difference. The requests are either completed immediately if there's no + * data or executed as normal requests otherwise. + * + * If the device has writeback cache and supports FUA, REQ_FLUSH is + * translated to PREFLUSH but REQ_FUA is passed down directly with DATA. + * + * If the device has writeback cache and doesn't support FUA, REQ_FLUSH is + * translated to PREFLUSH and REQ_FUA to POSTFLUSH. + * + * The actual execution of flush is double buffered. Whenever a request + * needs to execute PRE or POSTFLUSH, it queues at + * q->flush_queue[q->flush_pending_idx]. Once certain criteria are met, a + * flush is issued and the pending_idx is toggled. When the flush + * completes, all the requests which were pending are proceeded to the next + * step. This allows arbitrary merging of different types of FLUSH/FUA + * requests. + * + * Currently, the following conditions are used to determine when to issue + * flush. + * + * C1. At any given time, only one flush shall be in progress. This makes + * double buffering sufficient. + * + * C2. Flush is deferred if any request is executing DATA of its sequence. + * This avoids issuing separate POSTFLUSHes for requests which shared + * PREFLUSH. + * + * C3. The second condition is ignored if there is a request which has + * waited longer than FLUSH_PENDING_TIMEOUT. This is to avoid + * starvation in the unlikely case where there are continuous stream of + * FUA (without FLUSH) requests. + * + * For devices which support FUA, it isn't clear whether C2 (and thus C3) + * is beneficial. + * + * Note that a sequenced FLUSH/FUA request with DATA is completed twice. + * Once while executing DATA and again after the whole sequence is + * complete. The first completion updates the contained bio but doesn't + * finish it so that the bio submitter is notified only after the whole + * sequence is complete. This is implemented by testing REQ_FLUSH_SEQ in + * req_bio_endio(). + * + * The above peculiarity requires that each FLUSH/FUA request has only one + * bio attached to it, which is guaranteed as they aren't allowed to be + * merged in the usual way. */ + #include #include #include @@ -11,185 +74,290 @@ /* FLUSH/FUA sequences */ enum { - QUEUE_FSEQ_STARTED = (1 << 0), /* flushing in progress */ - QUEUE_FSEQ_PREFLUSH = (1 << 1), /* pre-flushing in progress */ - QUEUE_FSEQ_DATA = (1 << 2), /* data write in progress */ - QUEUE_FSEQ_POSTFLUSH = (1 << 3), /* post-flushing in progress */ - QUEUE_FSEQ_DONE = (1 << 4), + REQ_FSEQ_PREFLUSH = (1 << 0), /* pre-flushing in progress */ + REQ_FSEQ_DATA = (1 << 1), /* data write in progress */ + REQ_FSEQ_POSTFLUSH = (1 << 2), /* post-flushing in progress */ + REQ_FSEQ_DONE = (1 << 3), + + REQ_FSEQ_ACTIONS = REQ_FSEQ_PREFLUSH | REQ_FSEQ_DATA | + REQ_FSEQ_POSTFLUSH, + + /* + * If flush has been pending longer than the following timeout, + * it's issued even if flush_data requests are still in flight. + */ + FLUSH_PENDING_TIMEOUT = 5 * HZ, }; -static struct request *queue_next_fseq(struct request_queue *q); +static bool blk_kick_flush(struct request_queue *q); -unsigned blk_flush_cur_seq(struct request_queue *q) +static unsigned int blk_flush_policy(unsigned int fflags, struct request *rq) { - if (!q->flush_seq) - return 0; - return 1 << ffz(q->flush_seq); + unsigned int policy = 0; + + if (fflags & REQ_FLUSH) { + if (rq->cmd_flags & REQ_FLUSH) + policy |= REQ_FSEQ_PREFLUSH; + if (blk_rq_sectors(rq)) + policy |= REQ_FSEQ_DATA; + if (!(fflags & REQ_FUA) && (rq->cmd_flags & REQ_FUA)) + policy |= REQ_FSEQ_POSTFLUSH; + } + return policy; } -static struct request *blk_flush_complete_seq(struct request_queue *q, - unsigned seq, int error) +static unsigned int blk_flush_cur_seq(struct request *rq) { - struct request *next_rq = NULL; - - if (error && !q->flush_err) - q->flush_err = error; - - BUG_ON(q->flush_seq & seq); - q->flush_seq |= seq; - - if (blk_flush_cur_seq(q) != QUEUE_FSEQ_DONE) { - /* not complete yet, queue the next flush sequence */ - next_rq = queue_next_fseq(q); - } else { - /* complete this flush request */ - __blk_end_request_all(q->orig_flush_rq, q->flush_err); - q->orig_flush_rq = NULL; - q->flush_seq = 0; - - /* dispatch the next flush if there's one */ - if (!list_empty(&q->pending_flushes)) { - next_rq = list_entry_rq(q->pending_flushes.next); - list_move(&next_rq->queuelist, &q->queue_head); - } - } - return next_rq; + return 1 << ffz(rq->flush.seq); } -static void blk_flush_complete_seq_end_io(struct request_queue *q, - unsigned seq, int error) +static void blk_flush_restore_request(struct request *rq) { - bool was_empty = elv_queue_empty(q); - struct request *next_rq; - - next_rq = blk_flush_complete_seq(q, seq, error); - /* - * Moving a request silently to empty queue_head may stall the - * queue. Kick the queue in those cases. + * After flush data completion, @rq->bio is %NULL but we need to + * complete the bio again. @rq->biotail is guaranteed to equal the + * original @rq->bio. Restore it. */ - if (was_empty && next_rq) - __blk_run_queue(q); + rq->bio = rq->biotail; + + /* make @rq a normal request */ + rq->cmd_flags &= ~REQ_FLUSH_SEQ; + rq->end_io = NULL; } -static void pre_flush_end_io(struct request *rq, int error) +/** + * blk_flush_complete_seq - complete flush sequence + * @rq: FLUSH/FUA request being sequenced + * @seq: sequences to complete (mask of %REQ_FSEQ_*, can be zero) + * @error: whether an error occurred + * + * @rq just completed @seq part of its flush sequence, record the + * completion and trigger the next step. + * + * CONTEXT: + * spin_lock_irq(q->queue_lock) + * + * RETURNS: + * %true if requests were added to the dispatch queue, %false otherwise. + */ +static bool blk_flush_complete_seq(struct request *rq, unsigned int seq, + int error) { - elv_completed_request(rq->q, rq); - blk_flush_complete_seq_end_io(rq->q, QUEUE_FSEQ_PREFLUSH, error); + struct request_queue *q = rq->q; + struct list_head *pending = &q->flush_queue[q->flush_pending_idx]; + bool queued = false; + + BUG_ON(rq->flush.seq & seq); + rq->flush.seq |= seq; + + if (likely(!error)) + seq = blk_flush_cur_seq(rq); + else + seq = REQ_FSEQ_DONE; + + switch (seq) { + case REQ_FSEQ_PREFLUSH: + case REQ_FSEQ_POSTFLUSH: + /* queue for flush */ + if (list_empty(pending)) + q->flush_pending_since = jiffies; + list_move_tail(&rq->flush.list, pending); + break; + + case REQ_FSEQ_DATA: + list_move_tail(&rq->flush.list, &q->flush_data_in_flight); + list_add(&rq->queuelist, &q->queue_head); + queued = true; + break; + + case REQ_FSEQ_DONE: + /* + * @rq was previously adjusted by blk_flush_issue() for + * flush sequencing and may already have gone through the + * flush data request completion path. Restore @rq for + * normal completion and end it. + */ + BUG_ON(!list_empty(&rq->queuelist)); + list_del_init(&rq->flush.list); + blk_flush_restore_request(rq); + __blk_end_request_all(rq, error); + break; + + default: + BUG(); + } + + return blk_kick_flush(q) | queued; } -static void flush_data_end_io(struct request *rq, int error) +static void flush_end_io(struct request *flush_rq, int error) { - elv_completed_request(rq->q, rq); - blk_flush_complete_seq_end_io(rq->q, QUEUE_FSEQ_DATA, error); + struct request_queue *q = flush_rq->q; + struct list_head *running = &q->flush_queue[q->flush_running_idx]; + bool was_empty = elv_queue_empty(q); + bool queued = false; + struct request *rq, *n; + + BUG_ON(q->flush_pending_idx == q->flush_running_idx); + + /* account completion of the flush request */ + q->flush_running_idx ^= 1; + elv_completed_request(q, flush_rq); + + /* and push the waiting requests to the next stage */ + list_for_each_entry_safe(rq, n, running, flush.list) { + unsigned int seq = blk_flush_cur_seq(rq); + + BUG_ON(seq != REQ_FSEQ_PREFLUSH && seq != REQ_FSEQ_POSTFLUSH); + queued |= blk_flush_complete_seq(rq, seq, error); + } + + /* after populating an empty queue, kick it to avoid stall */ + if (queued && was_empty) + __blk_run_queue(q); } -static void post_flush_end_io(struct request *rq, int error) +/** + * blk_kick_flush - consider issuing flush request + * @q: request_queue being kicked + * + * Flush related states of @q have changed, consider issuing flush request. + * Please read the comment at the top of this file for more info. + * + * CONTEXT: + * spin_lock_irq(q->queue_lock) + * + * RETURNS: + * %true if flush was issued, %false otherwise. + */ +static bool blk_kick_flush(struct request_queue *q) { - elv_completed_request(rq->q, rq); - blk_flush_complete_seq_end_io(rq->q, QUEUE_FSEQ_POSTFLUSH, error); + struct list_head *pending = &q->flush_queue[q->flush_pending_idx]; + struct request *first_rq = + list_first_entry(pending, struct request, flush.list); + + /* C1 described at the top of this file */ + if (q->flush_pending_idx != q->flush_running_idx || list_empty(pending)) + return false; + + /* C2 and C3 */ + if (!list_empty(&q->flush_data_in_flight) && + time_before(jiffies, + q->flush_pending_since + FLUSH_PENDING_TIMEOUT)) + return false; + + /* + * Issue flush and toggle pending_idx. This makes pending_idx + * different from running_idx, which means flush is in flight. + */ + blk_rq_init(q, &q->flush_rq); + q->flush_rq.cmd_type = REQ_TYPE_FS; + q->flush_rq.cmd_flags = WRITE_FLUSH | REQ_FLUSH_SEQ; + q->flush_rq.rq_disk = first_rq->rq_disk; + q->flush_rq.end_io = flush_end_io; + + q->flush_pending_idx ^= 1; + elv_insert(q, &q->flush_rq, ELEVATOR_INSERT_FRONT); + return true; } -static void init_flush_request(struct request *rq, struct gendisk *disk) +static void flush_data_end_io(struct request *rq, int error) { - rq->cmd_type = REQ_TYPE_FS; - rq->cmd_flags = WRITE_FLUSH; - rq->rq_disk = disk; + struct request_queue *q = rq->q; + bool was_empty = elv_queue_empty(q); + + /* after populating an empty queue, kick it to avoid stall */ + if (blk_flush_complete_seq(rq, REQ_FSEQ_DATA, error) && was_empty) + __blk_run_queue(q); } -static struct request *queue_next_fseq(struct request_queue *q) +/** + * blk_insert_flush - insert a new FLUSH/FUA request + * @rq: request to insert + * + * To be called from elv_insert() for %ELEVATOR_INSERT_FLUSH insertions. + * @rq is being submitted. Analyze what needs to be done and put it on the + * right queue. + * + * CONTEXT: + * spin_lock_irq(q->queue_lock) + */ +void blk_insert_flush(struct request *rq) { - struct request *orig_rq = q->orig_flush_rq; - struct request *rq = &q->flush_rq; + struct request_queue *q = rq->q; + unsigned int fflags = q->flush_flags; /* may change, cache */ + unsigned int policy = blk_flush_policy(fflags, rq); - blk_rq_init(q, rq); + BUG_ON(rq->end_io); + BUG_ON(!rq->bio || rq->bio != rq->biotail); - switch (blk_flush_cur_seq(q)) { - case QUEUE_FSEQ_PREFLUSH: - init_flush_request(rq, orig_rq->rq_disk); - rq->end_io = pre_flush_end_io; - break; - case QUEUE_FSEQ_DATA: - init_request_from_bio(rq, orig_rq->bio); - /* - * orig_rq->rq_disk may be different from - * bio->bi_bdev->bd_disk if orig_rq got here through - * remapping drivers. Make sure rq->rq_disk points - * to the same one as orig_rq. - */ - rq->rq_disk = orig_rq->rq_disk; - rq->cmd_flags &= ~(REQ_FLUSH | REQ_FUA); - rq->cmd_flags |= orig_rq->cmd_flags & (REQ_FLUSH | REQ_FUA); - rq->end_io = flush_data_end_io; - break; - case QUEUE_FSEQ_POSTFLUSH: - init_flush_request(rq, orig_rq->rq_disk); - rq->end_io = post_flush_end_io; - break; - default: - BUG(); + /* + * @policy now records what operations need to be done. Adjust + * REQ_FLUSH and FUA for the driver. + */ + rq->cmd_flags &= ~REQ_FLUSH; + if (!(fflags & REQ_FUA)) + rq->cmd_flags &= ~REQ_FUA; + + /* + * If there's data but flush is not necessary, the request can be + * processed directly without going through flush machinery. Queue + * for normal execution. + */ + if ((policy & REQ_FSEQ_DATA) && + !(policy & (REQ_FSEQ_PREFLUSH | REQ_FSEQ_POSTFLUSH))) { + list_add(&rq->queuelist, &q->queue_head); + return; } + /* + * @rq should go through flush machinery. Mark it part of flush + * sequence and submit for further processing. + */ + memset(&rq->flush, 0, sizeof(rq->flush)); + INIT_LIST_HEAD(&rq->flush.list); rq->cmd_flags |= REQ_FLUSH_SEQ; - elv_insert(q, rq, ELEVATOR_INSERT_FRONT); - return rq; + rq->end_io = flush_data_end_io; + + blk_flush_complete_seq(rq, REQ_FSEQ_ACTIONS & ~policy, 0); } -struct request *blk_do_flush(struct request_queue *q, struct request *rq) +/** + * blk_abort_flushes - @q is being aborted, abort flush requests + * @q: request_queue being aborted + * + * To be called from elv_abort_queue(). @q is being aborted. Prepare all + * FLUSH/FUA requests for abortion. + * + * CONTEXT: + * spin_lock_irq(q->queue_lock) + */ +void blk_abort_flushes(struct request_queue *q) { - unsigned int fflags = q->flush_flags; /* may change, cache it */ - bool has_flush = fflags & REQ_FLUSH, has_fua = fflags & REQ_FUA; - bool do_preflush = has_flush && (rq->cmd_flags & REQ_FLUSH); - bool do_postflush = has_flush && !has_fua && (rq->cmd_flags & REQ_FUA); - unsigned skip = 0; + struct request *rq, *n; + int i; /* - * Special case. If there's data but flush is not necessary, - * the request can be issued directly. - * - * Flush w/o data should be able to be issued directly too but - * currently some drivers assume that rq->bio contains - * non-zero data if it isn't NULL and empty FLUSH requests - * getting here usually have bio's without data. + * Requests in flight for data are already owned by the dispatch + * queue or the device driver. Just restore for normal completion. */ - if (blk_rq_sectors(rq) && !do_preflush && !do_postflush) { - rq->cmd_flags &= ~REQ_FLUSH; - if (!has_fua) - rq->cmd_flags &= ~REQ_FUA; - return rq; + list_for_each_entry_safe(rq, n, &q->flush_data_in_flight, flush.list) { + list_del_init(&rq->flush.list); + blk_flush_restore_request(rq); } /* - * Sequenced flushes can't be processed in parallel. If - * another one is already in progress, queue for later - * processing. + * We need to give away requests on flush queues. Restore for + * normal completion and put them on the dispatch queue. */ - if (q->flush_seq) { - list_move_tail(&rq->queuelist, &q->pending_flushes); - return NULL; + for (i = 0; i < ARRAY_SIZE(q->flush_queue); i++) { + list_for_each_entry_safe(rq, n, &q->flush_queue[i], + flush.list) { + list_del_init(&rq->flush.list); + blk_flush_restore_request(rq); + list_add_tail(&rq->queuelist, &q->queue_head); + } } - - /* - * Start a new flush sequence - */ - q->flush_err = 0; - q->flush_seq |= QUEUE_FSEQ_STARTED; - - /* adjust FLUSH/FUA of the original request and stash it away */ - rq->cmd_flags &= ~REQ_FLUSH; - if (!has_fua) - rq->cmd_flags &= ~REQ_FUA; - blk_dequeue_request(rq); - q->orig_flush_rq = rq; - - /* skip unneded sequences and return the first one */ - if (!do_preflush) - skip |= QUEUE_FSEQ_PREFLUSH; - if (!blk_rq_sectors(rq)) - skip |= QUEUE_FSEQ_DATA; - if (!do_postflush) - skip |= QUEUE_FSEQ_POSTFLUSH; - return blk_flush_complete_seq(q, skip, 0); } static void bio_end_flush(struct bio *bio, int err) diff --git a/block/blk.h b/block/blk.h index 9d2ee8f4d9af4..284b500852bd5 100644 --- a/block/blk.h +++ b/block/blk.h @@ -51,21 +51,17 @@ static inline void blk_clear_rq_complete(struct request *rq) */ #define ELV_ON_HASH(rq) (!hlist_unhashed(&(rq)->hash)) -struct request *blk_do_flush(struct request_queue *q, struct request *rq); +void blk_insert_flush(struct request *rq); +void blk_abort_flushes(struct request_queue *q); static inline struct request *__elv_next_request(struct request_queue *q) { struct request *rq; while (1) { - while (!list_empty(&q->queue_head)) { + if (!list_empty(&q->queue_head)) { rq = list_entry_rq(q->queue_head.next); - if (!(rq->cmd_flags & (REQ_FLUSH | REQ_FUA)) || - (rq->cmd_flags & REQ_FLUSH_SEQ)) - return rq; - rq = blk_do_flush(q, rq); - if (rq) - return rq; + return rq; } if (!q->elevator->ops->elevator_dispatch_fn(q, 0)) diff --git a/block/elevator.c b/block/elevator.c index 2569512830d3e..270e0972eb9f1 100644 --- a/block/elevator.c +++ b/block/elevator.c @@ -673,6 +673,11 @@ void elv_insert(struct request_queue *q, struct request *rq, int where) q->elevator->ops->elevator_add_req_fn(q, rq); break; + case ELEVATOR_INSERT_FLUSH: + rq->cmd_flags |= REQ_SOFTBARRIER; + blk_insert_flush(rq); + break; + default: printk(KERN_ERR "%s: bad insertion point %d\n", __func__, where); @@ -785,6 +790,8 @@ void elv_abort_queue(struct request_queue *q) { struct request *rq; + blk_abort_flushes(q); + while (!list_empty(&q->queue_head)) { rq = list_entry_rq(q->queue_head.next); rq->cmd_flags |= REQ_QUIET; diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index 36ab42c9bb991..6d7e9afd08c38 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -99,13 +99,18 @@ struct request { /* * The rb_node is only used inside the io scheduler, requests * are pruned when moved to the dispatch queue. So let the - * completion_data share space with the rb_node. + * flush fields share space with the rb_node. */ union { struct rb_node rb_node; /* sort/lookup */ - void *completion_data; + struct { + unsigned int seq; + struct list_head list; + } flush; }; + void *completion_data; + /* * Three pointers are available for the IO schedulers, if they need * more they have to dynamically allocate it. @@ -362,11 +367,12 @@ struct request_queue * for flush operations */ unsigned int flush_flags; - unsigned int flush_seq; - int flush_err; + unsigned int flush_pending_idx:1; + unsigned int flush_running_idx:1; + unsigned long flush_pending_since; + struct list_head flush_queue[2]; + struct list_head flush_data_in_flight; struct request flush_rq; - struct request *orig_flush_rq; - struct list_head pending_flushes; struct mutex sysfs_lock; diff --git a/include/linux/elevator.h b/include/linux/elevator.h index 4fd978e7eb83e..86120c916fcc0 100644 --- a/include/linux/elevator.h +++ b/include/linux/elevator.h @@ -167,6 +167,7 @@ extern struct request *elv_rb_find(struct rb_root *, sector_t); #define ELEVATOR_INSERT_BACK 2 #define ELEVATOR_INSERT_SORT 3 #define ELEVATOR_INSERT_REQUEUE 4 +#define ELEVATOR_INSERT_FLUSH 5 /* * return values from elevator_may_queue_fn -- GitLab From 95c34f831f0e06cda6dc0a26b4f693ed105c394d Mon Sep 17 00:00:00 2001 From: Nick Bowler Date: Fri, 21 Jan 2011 15:51:06 +0100 Subject: [PATCH 0018/2822] ARM: 6633/1: vexpress: register platform PATA device. The compactflash device on this platform is not usable simply because it is never registered with the kernel. Fix that up. Signed-off-by: Nick Bowler Signed-off-by: Russell King --- arch/arm/Kconfig | 1 + arch/arm/mach-vexpress/v2m.c | 25 +++++++++++++++++++++++++ 2 files changed, 26 insertions(+) diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 5cff165b7eb04..70a017042ef0b 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -269,6 +269,7 @@ config ARCH_VEXPRESS select GENERIC_CLOCKEVENTS select HAVE_CLK select HAVE_SCHED_CLOCK + select HAVE_PATA_PLATFORM select ICST select PLAT_VERSATILE help diff --git a/arch/arm/mach-vexpress/v2m.c b/arch/arm/mach-vexpress/v2m.c index 1edae65a0e72c..f35d646a1bf16 100644 --- a/arch/arm/mach-vexpress/v2m.c +++ b/arch/arm/mach-vexpress/v2m.c @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -249,6 +250,29 @@ static struct platform_device v2m_flash_device = { .dev.platform_data = &v2m_flash_data, }; +static struct pata_platform_info v2m_pata_data = { + .ioport_shift = 2, +}; + +static struct resource v2m_pata_resources[] = { + { + .start = V2M_CF, + .end = V2M_CF + 0xff, + .flags = IORESOURCE_MEM, + }, { + .start = V2M_CF + 0x100, + .end = V2M_CF + SZ_4K - 1, + .flags = IORESOURCE_MEM, + }, +}; + +static struct platform_device v2m_cf_device = { + .name = "pata_platform", + .id = -1, + .resource = v2m_pata_resources, + .num_resources = ARRAY_SIZE(v2m_pata_resources), + .dev.platform_data = &v2m_pata_data, +}; static unsigned int v2m_mmci_status(struct device *dev) { @@ -363,6 +387,7 @@ static int __init v2m_init(void) platform_device_register(&v2m_pcie_i2c_device); platform_device_register(&v2m_ddc_i2c_device); platform_device_register(&v2m_flash_device); + platform_device_register(&v2m_cf_device); platform_device_register(&v2m_eth_device); platform_device_register(&v2m_usb_device); -- GitLab From 335d7c58fcc1b71387a2c38b610b08bb9d3a6fcc Mon Sep 17 00:00:00 2001 From: Guenter Roeck Date: Wed, 26 Jan 2011 11:45:49 -0800 Subject: [PATCH 0019/2822] i2c/busses: Add support for Diolan U2C-12 USB-I2C adapter This patch adds support for the Diolan U2C-12 USB-I2C adapter. It also updates MAINTAINERS to list the author as maintainer. Signed-off-by: Guenter Roeck Signed-off-by: Ben Dooks --- Documentation/i2c/busses/i2c-diolan-u2c | 26 ++ MAINTAINERS | 6 + drivers/i2c/busses/Kconfig | 10 + drivers/i2c/busses/Makefile | 1 + drivers/i2c/busses/i2c-diolan-u2c.c | 535 ++++++++++++++++++++++++ 5 files changed, 578 insertions(+) create mode 100644 Documentation/i2c/busses/i2c-diolan-u2c create mode 100644 drivers/i2c/busses/i2c-diolan-u2c.c diff --git a/Documentation/i2c/busses/i2c-diolan-u2c b/Documentation/i2c/busses/i2c-diolan-u2c new file mode 100644 index 0000000000000..30fe4bb9a069b --- /dev/null +++ b/Documentation/i2c/busses/i2c-diolan-u2c @@ -0,0 +1,26 @@ +Kernel driver i2c-diolan-u2c + +Supported adapters: + * Diolan U2C-12 I2C-USB adapter + Documentation: + http://www.diolan.com/i2c/u2c12.html + +Author: Guenter Roeck + +Description +----------- + +This is the driver for the Diolan U2C-12 USB-I2C adapter. + +The Diolan U2C-12 I2C-USB Adapter provides a low cost solution to connect +a computer to I2C slave devices using a USB interface. It also supports +connectivity to SPI devices. + +This driver only supports the I2C interface of U2C-12. The driver does not use +interrupts. + + +Module parameters +----------------- + +* frequency: I2C bus frequency diff --git a/MAINTAINERS b/MAINTAINERS index cf0f3a5c09cc8..74cad4fa5ae5a 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2093,6 +2093,12 @@ F: Documentation/serial/digiepca.txt F: drivers/char/epca* F: drivers/char/digi* +DIOLAN U2C-12 I2C DRIVER +M: Guenter Roeck +L: linux-i2c@vger.kernel.org +S: Maintained +F: drivers/i2c/busses/i2c-diolan-u2c.c + DIRECTORY NOTIFICATION (DNOTIFY) M: Eric Paris S: Maintained diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig index 113505a6434ed..30f8dbd7e03d1 100644 --- a/drivers/i2c/busses/Kconfig +++ b/drivers/i2c/busses/Kconfig @@ -648,6 +648,16 @@ config I2C_EG20T comment "External I2C/SMBus adapter drivers" +config I2C_DIOLAN_U2C + tristate "Diolan U2C-12 USB adapter" + depends on USB + help + If you say yes to this option, support will be included for Diolan + U2C-12, a USB to I2C interface. + + This driver can also be built as a module. If so, the module + will be called i2c-diolan-u2c. + config I2C_PARPORT tristate "Parallel port adapter" depends on PARPORT diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile index 9d2d0ec7fb232..3c630b7c5663a 100644 --- a/drivers/i2c/busses/Makefile +++ b/drivers/i2c/busses/Makefile @@ -64,6 +64,7 @@ obj-$(CONFIG_I2C_XILINX) += i2c-xiic.o obj-$(CONFIG_I2C_EG20T) += i2c-eg20t.o # External I2C/SMBus adapter drivers +obj-$(CONFIG_I2C_DIOLAN_U2C) += i2c-diolan-u2c.o obj-$(CONFIG_I2C_PARPORT) += i2c-parport.o obj-$(CONFIG_I2C_PARPORT_LIGHT) += i2c-parport-light.o obj-$(CONFIG_I2C_TAOS_EVM) += i2c-taos-evm.o diff --git a/drivers/i2c/busses/i2c-diolan-u2c.c b/drivers/i2c/busses/i2c-diolan-u2c.c new file mode 100644 index 0000000000000..76366716a8543 --- /dev/null +++ b/drivers/i2c/busses/i2c-diolan-u2c.c @@ -0,0 +1,535 @@ +/* + * Driver for the Diolan u2c-12 USB-I2C adapter + * + * Copyright (c) 2010-2011 Ericsson AB + * + * Derived from: + * i2c-tiny-usb.c + * Copyright (C) 2006-2007 Till Harbaum (Till@Harbaum.org) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation, version 2. + */ + +#include +#include +#include +#include +#include +#include +#include + +#define DRIVER_NAME "i2c-diolan-u2c" + +#define USB_VENDOR_ID_DIOLAN 0x0abf +#define USB_DEVICE_ID_DIOLAN_U2C 0x3370 + +#define DIOLAN_OUT_EP 0x02 +#define DIOLAN_IN_EP 0x84 + +/* commands via USB, must match command ids in the firmware */ +#define CMD_I2C_READ 0x01 +#define CMD_I2C_WRITE 0x02 +#define CMD_I2C_SCAN 0x03 /* Returns list of detected devices */ +#define CMD_I2C_RELEASE_SDA 0x04 +#define CMD_I2C_RELEASE_SCL 0x05 +#define CMD_I2C_DROP_SDA 0x06 +#define CMD_I2C_DROP_SCL 0x07 +#define CMD_I2C_READ_SDA 0x08 +#define CMD_I2C_READ_SCL 0x09 +#define CMD_GET_FW_VERSION 0x0a +#define CMD_GET_SERIAL 0x0b +#define CMD_I2C_START 0x0c +#define CMD_I2C_STOP 0x0d +#define CMD_I2C_REPEATED_START 0x0e +#define CMD_I2C_PUT_BYTE 0x0f +#define CMD_I2C_GET_BYTE 0x10 +#define CMD_I2C_PUT_ACK 0x11 +#define CMD_I2C_GET_ACK 0x12 +#define CMD_I2C_PUT_BYTE_ACK 0x13 +#define CMD_I2C_GET_BYTE_ACK 0x14 +#define CMD_I2C_SET_SPEED 0x1b +#define CMD_I2C_GET_SPEED 0x1c +#define CMD_I2C_SET_CLK_SYNC 0x24 +#define CMD_I2C_GET_CLK_SYNC 0x25 +#define CMD_I2C_SET_CLK_SYNC_TO 0x26 +#define CMD_I2C_GET_CLK_SYNC_TO 0x27 + +#define RESP_OK 0x00 +#define RESP_FAILED 0x01 +#define RESP_BAD_MEMADDR 0x04 +#define RESP_DATA_ERR 0x05 +#define RESP_NOT_IMPLEMENTED 0x06 +#define RESP_NACK 0x07 +#define RESP_TIMEOUT 0x09 + +#define U2C_I2C_SPEED_FAST 0 /* 400 kHz */ +#define U2C_I2C_SPEED_STD 1 /* 100 kHz */ +#define U2C_I2C_SPEED_2KHZ 242 /* 2 kHz, minimum speed */ +#define U2C_I2C_SPEED(f) ((DIV_ROUND_UP(1000000, (f)) - 10) / 2 + 1) + +#define U2C_I2C_FREQ_FAST 400000 +#define U2C_I2C_FREQ_STD 100000 +#define U2C_I2C_FREQ(s) (1000000 / (2 * (s - 1) + 10)) + +#define DIOLAN_USB_TIMEOUT 100 /* in ms */ +#define DIOLAN_SYNC_TIMEOUT 20 /* in ms */ + +#define DIOLAN_OUTBUF_LEN 128 +#define DIOLAN_FLUSH_LEN (DIOLAN_OUTBUF_LEN - 4) +#define DIOLAN_INBUF_LEN 256 /* Maximum supported receive length */ + +/* Structure to hold all of our device specific stuff */ +struct i2c_diolan_u2c { + u8 obuffer[DIOLAN_OUTBUF_LEN]; /* output buffer */ + u8 ibuffer[DIOLAN_INBUF_LEN]; /* input buffer */ + struct usb_device *usb_dev; /* the usb device for this device */ + struct usb_interface *interface;/* the interface for this device */ + struct i2c_adapter adapter; /* i2c related things */ + int olen; /* Output buffer length */ + int ocount; /* Number of enqueued messages */ +}; + +static uint frequency = U2C_I2C_FREQ_STD; /* I2C clock frequency in Hz */ + +module_param(frequency, uint, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(frequency, "I2C clock frequency in hertz"); + +/* usb layer */ + +/* Send command to device, and get response. */ +static int diolan_usb_transfer(struct i2c_diolan_u2c *dev) +{ + int ret = 0; + int actual; + int i; + + if (!dev->olen || !dev->ocount) + return -EINVAL; + + ret = usb_bulk_msg(dev->usb_dev, + usb_sndbulkpipe(dev->usb_dev, DIOLAN_OUT_EP), + dev->obuffer, dev->olen, &actual, + DIOLAN_USB_TIMEOUT); + if (!ret) { + for (i = 0; i < dev->ocount; i++) { + int tmpret; + + tmpret = usb_bulk_msg(dev->usb_dev, + usb_rcvbulkpipe(dev->usb_dev, + DIOLAN_IN_EP), + dev->ibuffer, + sizeof(dev->ibuffer), &actual, + DIOLAN_USB_TIMEOUT); + /* + * Stop command processing if a previous command + * returned an error. + * Note that we still need to retrieve all messages. + */ + if (ret < 0) + continue; + ret = tmpret; + if (ret == 0 && actual > 0) { + switch (dev->ibuffer[actual - 1]) { + case RESP_NACK: + /* + * Return ENXIO if NACK was received as + * response to the address phase, + * EIO otherwise + */ + ret = i == 1 ? -ENXIO : -EIO; + break; + case RESP_TIMEOUT: + ret = -ETIMEDOUT; + break; + case RESP_OK: + /* strip off return code */ + ret = actual - 1; + break; + default: + ret = -EIO; + break; + } + } + } + } + dev->olen = 0; + dev->ocount = 0; + return ret; +} + +static int diolan_write_cmd(struct i2c_diolan_u2c *dev, bool flush) +{ + if (flush || dev->olen >= DIOLAN_FLUSH_LEN) + return diolan_usb_transfer(dev); + return 0; +} + +/* Send command (no data) */ +static int diolan_usb_cmd(struct i2c_diolan_u2c *dev, u8 command, bool flush) +{ + dev->obuffer[dev->olen++] = command; + dev->ocount++; + return diolan_write_cmd(dev, flush); +} + +/* Send command with one byte of data */ +static int diolan_usb_cmd_data(struct i2c_diolan_u2c *dev, u8 command, u8 data, + bool flush) +{ + dev->obuffer[dev->olen++] = command; + dev->obuffer[dev->olen++] = data; + dev->ocount++; + return diolan_write_cmd(dev, flush); +} + +/* Send command with two bytes of data */ +static int diolan_usb_cmd_data2(struct i2c_diolan_u2c *dev, u8 command, u8 d1, + u8 d2, bool flush) +{ + dev->obuffer[dev->olen++] = command; + dev->obuffer[dev->olen++] = d1; + dev->obuffer[dev->olen++] = d2; + dev->ocount++; + return diolan_write_cmd(dev, flush); +} + +/* + * Flush input queue. + * If we don't do this at startup and the controller has queued up + * messages which were not retrieved, it will stop responding + * at some point. + */ +static void diolan_flush_input(struct i2c_diolan_u2c *dev) +{ + int i; + + for (i = 0; i < 10; i++) { + int actual = 0; + int ret; + + ret = usb_bulk_msg(dev->usb_dev, + usb_rcvbulkpipe(dev->usb_dev, DIOLAN_IN_EP), + dev->ibuffer, sizeof(dev->ibuffer), &actual, + DIOLAN_USB_TIMEOUT); + if (ret < 0 || actual == 0) + break; + } + if (i == 10) + dev_err(&dev->interface->dev, "Failed to flush input buffer\n"); +} + +static int diolan_i2c_start(struct i2c_diolan_u2c *dev) +{ + return diolan_usb_cmd(dev, CMD_I2C_START, false); +} + +static int diolan_i2c_repeated_start(struct i2c_diolan_u2c *dev) +{ + return diolan_usb_cmd(dev, CMD_I2C_REPEATED_START, false); +} + +static int diolan_i2c_stop(struct i2c_diolan_u2c *dev) +{ + return diolan_usb_cmd(dev, CMD_I2C_STOP, true); +} + +static int diolan_i2c_get_byte_ack(struct i2c_diolan_u2c *dev, bool ack, + u8 *byte) +{ + int ret; + + ret = diolan_usb_cmd_data(dev, CMD_I2C_GET_BYTE_ACK, ack, true); + if (ret > 0) + *byte = dev->ibuffer[0]; + else if (ret == 0) + ret = -EIO; + + return ret; +} + +static int diolan_i2c_put_byte_ack(struct i2c_diolan_u2c *dev, u8 byte) +{ + return diolan_usb_cmd_data(dev, CMD_I2C_PUT_BYTE_ACK, byte, false); +} + +static int diolan_set_speed(struct i2c_diolan_u2c *dev, u8 speed) +{ + return diolan_usb_cmd_data(dev, CMD_I2C_SET_SPEED, speed, true); +} + +/* Enable or disable clock synchronization (stretching) */ +static int diolan_set_clock_synch(struct i2c_diolan_u2c *dev, bool enable) +{ + return diolan_usb_cmd_data(dev, CMD_I2C_SET_CLK_SYNC, enable, true); +} + +/* Set clock synchronization timeout in ms */ +static int diolan_set_clock_synch_timeout(struct i2c_diolan_u2c *dev, int ms) +{ + int to_val = ms * 10; + + return diolan_usb_cmd_data2(dev, CMD_I2C_SET_CLK_SYNC_TO, + to_val & 0xff, (to_val >> 8) & 0xff, true); +} + +static void diolan_fw_version(struct i2c_diolan_u2c *dev) +{ + int ret; + + ret = diolan_usb_cmd(dev, CMD_GET_FW_VERSION, true); + if (ret >= 2) + dev_info(&dev->interface->dev, + "Diolan U2C firmware version %u.%u\n", + (unsigned int)dev->ibuffer[0], + (unsigned int)dev->ibuffer[1]); +} + +static void diolan_get_serial(struct i2c_diolan_u2c *dev) +{ + int ret; + u32 serial; + + ret = diolan_usb_cmd(dev, CMD_GET_SERIAL, true); + if (ret >= 4) { + serial = le32_to_cpu(*(u32 *)dev->ibuffer); + dev_info(&dev->interface->dev, + "Diolan U2C serial number %u\n", serial); + } +} + +static int diolan_init(struct i2c_diolan_u2c *dev) +{ + int speed, ret; + + if (frequency >= 200000) { + speed = U2C_I2C_SPEED_FAST; + frequency = U2C_I2C_FREQ_FAST; + } else if (frequency >= 100000 || frequency == 0) { + speed = U2C_I2C_SPEED_STD; + frequency = U2C_I2C_FREQ_STD; + } else { + speed = U2C_I2C_SPEED(frequency); + if (speed > U2C_I2C_SPEED_2KHZ) + speed = U2C_I2C_SPEED_2KHZ; + frequency = U2C_I2C_FREQ(speed); + } + + dev_info(&dev->interface->dev, + "Diolan U2C at USB bus %03d address %03d speed %d Hz\n", + dev->usb_dev->bus->busnum, dev->usb_dev->devnum, frequency); + + diolan_flush_input(dev); + diolan_fw_version(dev); + diolan_get_serial(dev); + + /* Set I2C speed */ + ret = diolan_set_speed(dev, speed); + if (ret < 0) + return ret; + + /* Configure I2C clock synchronization */ + ret = diolan_set_clock_synch(dev, speed != U2C_I2C_SPEED_FAST); + if (ret < 0) + return ret; + + if (speed != U2C_I2C_SPEED_FAST) + ret = diolan_set_clock_synch_timeout(dev, DIOLAN_SYNC_TIMEOUT); + + return ret; +} + +/* i2c layer */ + +static int diolan_usb_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, + int num) +{ + struct i2c_diolan_u2c *dev = i2c_get_adapdata(adapter); + struct i2c_msg *pmsg; + int i, j; + int ret, sret; + + ret = diolan_i2c_start(dev); + if (ret < 0) + return ret; + + for (i = 0; i < num; i++) { + pmsg = &msgs[i]; + if (i) { + ret = diolan_i2c_repeated_start(dev); + if (ret < 0) + goto abort; + } + if (pmsg->flags & I2C_M_RD) { + ret = + diolan_i2c_put_byte_ack(dev, (pmsg->addr << 1) | 1); + if (ret < 0) + goto abort; + for (j = 0; j < pmsg->len; j++) { + u8 byte; + bool ack = j < pmsg->len - 1; + + /* + * Don't send NACK if this is the first byte + * of a SMBUS_BLOCK message. + */ + if (j == 0 && (pmsg->flags & I2C_M_RECV_LEN)) + ack = true; + + ret = diolan_i2c_get_byte_ack(dev, ack, &byte); + if (ret < 0) + goto abort; + /* + * Adjust count if first received byte is length + */ + if (j == 0 && (pmsg->flags & I2C_M_RECV_LEN)) { + if (byte == 0 + || byte > I2C_SMBUS_BLOCK_MAX) { + ret = -EPROTO; + goto abort; + } + pmsg->len += byte; + } + pmsg->buf[j] = byte; + } + } else { + ret = diolan_i2c_put_byte_ack(dev, pmsg->addr << 1); + if (ret < 0) + goto abort; + for (j = 0; j < pmsg->len; j++) { + ret = diolan_i2c_put_byte_ack(dev, + pmsg->buf[j]); + if (ret < 0) + goto abort; + } + } + } +abort: + sret = diolan_i2c_stop(dev); + if (sret < 0 && ret >= 0) + ret = sret; + return ret; +} + +/* + * Return list of supported functionality. + */ +static u32 diolan_usb_func(struct i2c_adapter *a) +{ + return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | + I2C_FUNC_SMBUS_READ_BLOCK_DATA | I2C_FUNC_SMBUS_BLOCK_PROC_CALL; +} + +static const struct i2c_algorithm diolan_usb_algorithm = { + .master_xfer = diolan_usb_xfer, + .functionality = diolan_usb_func, +}; + +/* device layer */ + +static const struct usb_device_id diolan_u2c_table[] = { + { USB_DEVICE(USB_VENDOR_ID_DIOLAN, USB_DEVICE_ID_DIOLAN_U2C) }, + { } +}; + +MODULE_DEVICE_TABLE(usb, diolan_u2c_table); + +static void diolan_u2c_free(struct i2c_diolan_u2c *dev) +{ + usb_put_dev(dev->usb_dev); + kfree(dev); +} + +static int diolan_u2c_probe(struct usb_interface *interface, + const struct usb_device_id *id) +{ + struct i2c_diolan_u2c *dev; + int ret; + + /* allocate memory for our device state and initialize it */ + dev = kzalloc(sizeof(*dev), GFP_KERNEL); + if (dev == NULL) { + dev_err(&interface->dev, "no memory for device state\n"); + ret = -ENOMEM; + goto error; + } + + dev->usb_dev = usb_get_dev(interface_to_usbdev(interface)); + dev->interface = interface; + + /* save our data pointer in this interface device */ + usb_set_intfdata(interface, dev); + + /* setup i2c adapter description */ + dev->adapter.owner = THIS_MODULE; + dev->adapter.class = I2C_CLASS_HWMON; + dev->adapter.algo = &diolan_usb_algorithm; + i2c_set_adapdata(&dev->adapter, dev); + snprintf(dev->adapter.name, sizeof(dev->adapter.name), + DRIVER_NAME " at bus %03d device %03d", + dev->usb_dev->bus->busnum, dev->usb_dev->devnum); + + dev->adapter.dev.parent = &dev->interface->dev; + + /* initialize diolan i2c interface */ + ret = diolan_init(dev); + if (ret < 0) { + dev_err(&interface->dev, "failed to initialize adapter\n"); + goto error_free; + } + + /* and finally attach to i2c layer */ + ret = i2c_add_adapter(&dev->adapter); + if (ret < 0) { + dev_err(&interface->dev, "failed to add I2C adapter\n"); + goto error_free; + } + + dev_dbg(&interface->dev, "connected " DRIVER_NAME "\n"); + + return 0; + +error_free: + usb_set_intfdata(interface, NULL); + diolan_u2c_free(dev); +error: + return ret; +} + +static void diolan_u2c_disconnect(struct usb_interface *interface) +{ + struct i2c_diolan_u2c *dev = usb_get_intfdata(interface); + + i2c_del_adapter(&dev->adapter); + usb_set_intfdata(interface, NULL); + diolan_u2c_free(dev); + + dev_dbg(&interface->dev, "disconnected\n"); +} + +static struct usb_driver diolan_u2c_driver = { + .name = DRIVER_NAME, + .probe = diolan_u2c_probe, + .disconnect = diolan_u2c_disconnect, + .id_table = diolan_u2c_table, +}; + +static int __init diolan_u2c_init(void) +{ + /* register this driver with the USB subsystem */ + return usb_register(&diolan_u2c_driver); +} + +static void __exit diolan_u2c_exit(void) +{ + /* deregister this driver with the USB subsystem */ + usb_deregister(&diolan_u2c_driver); +} + +module_init(diolan_u2c_init); +module_exit(diolan_u2c_exit); + +MODULE_AUTHOR("Guenter Roeck "); +MODULE_DESCRIPTION(DRIVER_NAME " driver"); +MODULE_LICENSE("GPL"); -- GitLab From 087809fce28f50098d9c3ef1a6865c722f23afd2 Mon Sep 17 00:00:00 2001 From: Jamie Iles Date: Fri, 21 Jan 2011 14:11:52 +0000 Subject: [PATCH 0020/2822] dmaengine/dw_dmac: don't scan descriptors if no xfers in progress Some hardware (picoChip picoXCell in particular) sometimes has the block transfer complete bit being set for a channel after the whole transfer has completed. If we don't have any transfers in the active list then don't bother to scan the descriptors. This often happens in normal operation and doesn't require the channel to be reset. v2: cleanup whitespace Signed-off-by: Jamie Iles Signed-off-by: Dan Williams --- drivers/dma/dw_dmac.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/dma/dw_dmac.c b/drivers/dma/dw_dmac.c index a3991ab0d67e0..db22754be35d0 100644 --- a/drivers/dma/dw_dmac.c +++ b/drivers/dma/dw_dmac.c @@ -291,6 +291,9 @@ static void dwc_scan_descriptors(struct dw_dma *dw, struct dw_dma_chan *dwc) return; } + if (list_empty(&dwc->active_list)) + return; + dev_vdbg(chan2dev(&dwc->chan), "scan_descriptors: llp=0x%x\n", llp); list_for_each_entry_safe(desc, _desc, &dwc->active_list, desc_node) { -- GitLab From f301c062dcdd113bc977ae1ebc8c12232f8531a9 Mon Sep 17 00:00:00 2001 From: Jamie Iles Date: Fri, 21 Jan 2011 14:11:53 +0000 Subject: [PATCH 0021/2822] dmaengine/dw_dmac: allow src/dst masters to be configured at runtime Some platforms have flexible mastering capabilities and this needs to be selected at runtime. If the platform has specified private data in the form of the dw_dma_slave then fetch the source and destination masters from here. If this isn't present, default to the previous of 0 and 1. v2: cleanup whitespace Acked-by: Hans-Christian Egtvedt Signed-off-by: Jamie Iles Signed-off-by: Dan Williams --- drivers/dma/dw_dmac.c | 31 +++++++++++++++++-------------- include/linux/dw_dmac.h | 2 ++ 2 files changed, 19 insertions(+), 14 deletions(-) diff --git a/drivers/dma/dw_dmac.c b/drivers/dma/dw_dmac.c index db22754be35d0..a4cf2614085a3 100644 --- a/drivers/dma/dw_dmac.c +++ b/drivers/dma/dw_dmac.c @@ -32,15 +32,18 @@ * which does not support descriptor writeback. */ -/* NOTE: DMS+SMS is system-specific. We should get this information - * from the platform code somehow. - */ -#define DWC_DEFAULT_CTLLO (DWC_CTLL_DST_MSIZE(0) \ - | DWC_CTLL_SRC_MSIZE(0) \ - | DWC_CTLL_DMS(0) \ - | DWC_CTLL_SMS(1) \ - | DWC_CTLL_LLP_D_EN \ - | DWC_CTLL_LLP_S_EN) +#define DWC_DEFAULT_CTLLO(private) ({ \ + struct dw_dma_slave *__slave = (private); \ + int dms = __slave ? __slave->dst_master : 0; \ + int sms = __slave ? __slave->src_master : 1; \ + \ + (DWC_CTLL_DST_MSIZE(0) \ + | DWC_CTLL_SRC_MSIZE(0) \ + | DWC_CTLL_LLP_D_EN \ + | DWC_CTLL_LLP_S_EN \ + | DWC_CTLL_DMS(dms) \ + | DWC_CTLL_SMS(sms)); \ + }) /* * This is configuration-dependent and usually a funny size like 4095. @@ -591,7 +594,7 @@ dwc_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dest, dma_addr_t src, else src_width = dst_width = 0; - ctllo = DWC_DEFAULT_CTLLO + ctllo = DWC_DEFAULT_CTLLO(chan->private) | DWC_CTLL_DST_WIDTH(dst_width) | DWC_CTLL_SRC_WIDTH(src_width) | DWC_CTLL_DST_INC @@ -672,7 +675,7 @@ dwc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, switch (direction) { case DMA_TO_DEVICE: - ctllo = (DWC_DEFAULT_CTLLO + ctllo = (DWC_DEFAULT_CTLLO(chan->private) | DWC_CTLL_DST_WIDTH(reg_width) | DWC_CTLL_DST_FIX | DWC_CTLL_SRC_INC @@ -717,7 +720,7 @@ dwc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, } break; case DMA_FROM_DEVICE: - ctllo = (DWC_DEFAULT_CTLLO + ctllo = (DWC_DEFAULT_CTLLO(chan->private) | DWC_CTLL_SRC_WIDTH(reg_width) | DWC_CTLL_DST_INC | DWC_CTLL_SRC_FIX @@ -1129,7 +1132,7 @@ struct dw_cyclic_desc *dw_dma_cyclic_prep(struct dma_chan *chan, case DMA_TO_DEVICE: desc->lli.dar = dws->tx_reg; desc->lli.sar = buf_addr + (period_len * i); - desc->lli.ctllo = (DWC_DEFAULT_CTLLO + desc->lli.ctllo = (DWC_DEFAULT_CTLLO(chan->private) | DWC_CTLL_DST_WIDTH(reg_width) | DWC_CTLL_SRC_WIDTH(reg_width) | DWC_CTLL_DST_FIX @@ -1140,7 +1143,7 @@ struct dw_cyclic_desc *dw_dma_cyclic_prep(struct dma_chan *chan, case DMA_FROM_DEVICE: desc->lli.dar = buf_addr + (period_len * i); desc->lli.sar = dws->rx_reg; - desc->lli.ctllo = (DWC_DEFAULT_CTLLO + desc->lli.ctllo = (DWC_DEFAULT_CTLLO(chan->private) | DWC_CTLL_SRC_WIDTH(reg_width) | DWC_CTLL_DST_WIDTH(reg_width) | DWC_CTLL_DST_INC diff --git a/include/linux/dw_dmac.h b/include/linux/dw_dmac.h index c8aad713a0460..8014eb81054db 100644 --- a/include/linux/dw_dmac.h +++ b/include/linux/dw_dmac.h @@ -52,6 +52,8 @@ struct dw_dma_slave { enum dw_dma_slave_width reg_width; u32 cfg_hi; u32 cfg_lo; + int src_master; + int dst_master; }; /* Platform-configurable bits in CFG_HI */ -- GitLab From 95ea759e9e116dade3e7386be2a3db76c90f4675 Mon Sep 17 00:00:00 2001 From: Jamie Iles Date: Fri, 21 Jan 2011 14:11:54 +0000 Subject: [PATCH 0022/2822] dmaengine/dw_dmac: provide a mechanism to indicate private devices Some platforms (e.g. Picochip PC3XX) have multiple DMA controllers where some may be used for slave transfers and others for general purpose memcpy type transfers. Add a .is_private boolean to the platform data structure so that controllers can be marked as private so that the DMA_PRIVATE capability will be set for that controller. Signed-off-by: Jamie Iles Signed-off-by: Dan Williams --- drivers/dma/dw_dmac.c | 2 ++ include/linux/dw_dmac.h | 3 +++ 2 files changed, 5 insertions(+) diff --git a/drivers/dma/dw_dmac.c b/drivers/dma/dw_dmac.c index a4cf2614085a3..08dab3badad2d 100644 --- a/drivers/dma/dw_dmac.c +++ b/drivers/dma/dw_dmac.c @@ -1341,6 +1341,8 @@ static int __init dw_probe(struct platform_device *pdev) dma_cap_set(DMA_MEMCPY, dw->dma.cap_mask); dma_cap_set(DMA_SLAVE, dw->dma.cap_mask); + if (pdata->is_private) + dma_cap_set(DMA_PRIVATE, dw->dma.cap_mask); dw->dma.dev = &pdev->dev; dw->dma.device_alloc_chan_resources = dwc_alloc_chan_resources; dw->dma.device_free_chan_resources = dwc_free_chan_resources; diff --git a/include/linux/dw_dmac.h b/include/linux/dw_dmac.h index 8014eb81054db..deec66b37180c 100644 --- a/include/linux/dw_dmac.h +++ b/include/linux/dw_dmac.h @@ -16,9 +16,12 @@ /** * struct dw_dma_platform_data - Controller configuration parameters * @nr_channels: Number of channels supported by hardware (max 8) + * @is_private: The device channels should be marked as private and not for + * by the general purpose DMA channel allocator. */ struct dw_dma_platform_data { unsigned int nr_channels; + bool is_private; }; /** -- GitLab From 4aa5f366431fef0afca0df348ca9782c63ac9911 Mon Sep 17 00:00:00 2001 From: Jamie Iles Date: Fri, 21 Jan 2011 14:11:55 +0000 Subject: [PATCH 0023/2822] avr32: at32ap700x: specify DMA src and dst masters Now that the dw_dmac DMA driver supports configurable source and destination masters we need to specify which ones to use. This was previously hardcoded to 0 and 1 respectively in the driver. Acked-by: Hans-Christian Egtvedt Signed-off-by: Jamie Iles Signed-off-by: Dan Williams --- arch/avr32/mach-at32ap/at32ap700x.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/arch/avr32/mach-at32ap/at32ap700x.c b/arch/avr32/mach-at32ap/at32ap700x.c index e67c999454284..2747cde8c9a71 100644 --- a/arch/avr32/mach-at32ap/at32ap700x.c +++ b/arch/avr32/mach-at32ap/at32ap700x.c @@ -2048,6 +2048,8 @@ at32_add_device_ac97c(unsigned int id, struct ac97c_platform_data *data, rx_dws->reg_width = DW_DMA_SLAVE_WIDTH_16BIT; rx_dws->cfg_hi = DWC_CFGH_SRC_PER(3); rx_dws->cfg_lo &= ~(DWC_CFGL_HS_DST_POL | DWC_CFGL_HS_SRC_POL); + rx_dws->src_master = 0; + rx_dws->dst_master = 1; } /* Check if DMA slave interface for playback should be configured. */ @@ -2056,6 +2058,8 @@ at32_add_device_ac97c(unsigned int id, struct ac97c_platform_data *data, tx_dws->reg_width = DW_DMA_SLAVE_WIDTH_16BIT; tx_dws->cfg_hi = DWC_CFGH_DST_PER(4); tx_dws->cfg_lo &= ~(DWC_CFGL_HS_DST_POL | DWC_CFGL_HS_SRC_POL); + rx_dws->src_master = 0; + rx_dws->dst_master = 1; } if (platform_device_add_data(pdev, data, @@ -2128,6 +2132,8 @@ at32_add_device_abdac(unsigned int id, struct atmel_abdac_pdata *data) dws->reg_width = DW_DMA_SLAVE_WIDTH_32BIT; dws->cfg_hi = DWC_CFGH_DST_PER(2); dws->cfg_lo &= ~(DWC_CFGL_HS_DST_POL | DWC_CFGL_HS_SRC_POL); + dws->src_master = 0; + dws->dst_master = 1; if (platform_device_add_data(pdev, data, sizeof(struct atmel_abdac_pdata))) -- GitLab From 00cfa730db0d8378685148e6365b9cec7384b275 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Sun, 30 Jan 2011 12:31:30 -0800 Subject: [PATCH 0024/2822] Input: wm831x - add driver for Wolfson WM831x PMIC touchscreen controllers Some of the WM831x series of PMICs from Wolfson Microelectronics include a resistive touchscreen controller. Implement support for these controllers within the input API. Platform data is supported to allow configuration of system parameters such as selection between four and five wire touchscreens and for specification of optional direct to CPU IRQs for sample availability and for pen down. Use of this feature for at least the data IRQ is strongly recommended. Thanks to Julien Boibessot for extensive testing and detailed feedback. Signed-off-by: Mark Brown Tested-by: Julien Boibessot Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/Kconfig | 10 + drivers/input/touchscreen/Makefile | 1 + drivers/input/touchscreen/wm831x-ts.c | 355 ++++++++++++++++++++++++++ include/linux/mfd/wm831x/pdata.h | 3 +- 4 files changed, 368 insertions(+), 1 deletion(-) create mode 100644 drivers/input/touchscreen/wm831x-ts.c diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig index 07ac77d393a4f..ec5ee98fa6f63 100644 --- a/drivers/input/touchscreen/Kconfig +++ b/drivers/input/touchscreen/Kconfig @@ -423,6 +423,16 @@ config TOUCHSCREEN_UCB1400 To compile this driver as a module, choose M here: the module will be called ucb1400_ts. +config TOUCHSCREEN_WM831X + tristate "Support for WM831x touchscreen controllers" + depends on MFD_WM831X + help + This enables support for the touchscreen controller on the WM831x + series of PMICs. + + To compile this driver as a module, choose M here: the + module will be called wm831x-ts. + config TOUCHSCREEN_WM97XX tristate "Support for WM97xx AC97 touchscreen controllers" depends on AC97_BUS diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile index 718bcc814952c..e8dcfab7c2dc0 100644 --- a/drivers/input/touchscreen/Makefile +++ b/drivers/input/touchscreen/Makefile @@ -48,6 +48,7 @@ obj-$(CONFIG_TOUCHSCREEN_TOUCHWIN) += touchwin.o obj-$(CONFIG_TOUCHSCREEN_TSC2007) += tsc2007.o obj-$(CONFIG_TOUCHSCREEN_UCB1400) += ucb1400_ts.o obj-$(CONFIG_TOUCHSCREEN_WACOM_W8001) += wacom_w8001.o +obj-$(CONFIG_TOUCHSCREEN_WM831X) += wm831x-ts.o obj-$(CONFIG_TOUCHSCREEN_WM97XX) += wm97xx-ts.o wm97xx-ts-$(CONFIG_TOUCHSCREEN_WM9705) += wm9705.o wm97xx-ts-$(CONFIG_TOUCHSCREEN_WM9712) += wm9712.o diff --git a/drivers/input/touchscreen/wm831x-ts.c b/drivers/input/touchscreen/wm831x-ts.c new file mode 100644 index 0000000000000..a6121bdb635df --- /dev/null +++ b/drivers/input/touchscreen/wm831x-ts.c @@ -0,0 +1,355 @@ +/* + * Touchscreen driver for WM831x PMICs + * + * Copyright 2011 Wolfson Microelectronics plc. + * Author: Mark Brown + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * R16424 (0x4028) - Touch Control 1 + */ +#define WM831X_TCH_ENA 0x8000 /* TCH_ENA */ +#define WM831X_TCH_CVT_ENA 0x4000 /* TCH_CVT_ENA */ +#define WM831X_TCH_SLPENA 0x1000 /* TCH_SLPENA */ +#define WM831X_TCH_Z_ENA 0x0400 /* TCH_Z_ENA */ +#define WM831X_TCH_Y_ENA 0x0200 /* TCH_Y_ENA */ +#define WM831X_TCH_X_ENA 0x0100 /* TCH_X_ENA */ +#define WM831X_TCH_DELAY_MASK 0x00E0 /* TCH_DELAY - [7:5] */ +#define WM831X_TCH_DELAY_SHIFT 5 /* TCH_DELAY - [7:5] */ +#define WM831X_TCH_DELAY_WIDTH 3 /* TCH_DELAY - [7:5] */ +#define WM831X_TCH_RATE_MASK 0x001F /* TCH_RATE - [4:0] */ +#define WM831X_TCH_RATE_SHIFT 0 /* TCH_RATE - [4:0] */ +#define WM831X_TCH_RATE_WIDTH 5 /* TCH_RATE - [4:0] */ + +/* + * R16425 (0x4029) - Touch Control 2 + */ +#define WM831X_TCH_PD_WK 0x2000 /* TCH_PD_WK */ +#define WM831X_TCH_5WIRE 0x1000 /* TCH_5WIRE */ +#define WM831X_TCH_PDONLY 0x0800 /* TCH_PDONLY */ +#define WM831X_TCH_ISEL 0x0100 /* TCH_ISEL */ +#define WM831X_TCH_RPU_MASK 0x000F /* TCH_RPU - [3:0] */ +#define WM831X_TCH_RPU_SHIFT 0 /* TCH_RPU - [3:0] */ +#define WM831X_TCH_RPU_WIDTH 4 /* TCH_RPU - [3:0] */ + +/* + * R16426-8 (0x402A-C) - Touch Data X/Y/X + */ +#define WM831X_TCH_PD 0x8000 /* TCH_PD1 */ +#define WM831X_TCH_DATA_MASK 0x0FFF /* TCH_DATA - [11:0] */ +#define WM831X_TCH_DATA_SHIFT 0 /* TCH_DATA - [11:0] */ +#define WM831X_TCH_DATA_WIDTH 12 /* TCH_DATA - [11:0] */ + +struct wm831x_ts { + struct input_dev *input_dev; + struct wm831x *wm831x; + unsigned int data_irq; + unsigned int pd_irq; + bool pressure; + bool pen_down; +}; + +static irqreturn_t wm831x_ts_data_irq(int irq, void *irq_data) +{ + struct wm831x_ts *wm831x_ts = irq_data; + struct wm831x *wm831x = wm831x_ts->wm831x; + static int data_types[] = { ABS_X, ABS_Y, ABS_PRESSURE }; + u16 data[3]; + int count = wm831x_ts->pressure ? 3 : 2; + int i, ret; + + wm831x_set_bits(wm831x, WM831X_INTERRUPT_STATUS_1, + WM831X_TCHDATA_EINT, WM831X_TCHDATA_EINT); + + ret = wm831x_bulk_read(wm831x, WM831X_TOUCH_DATA_X, count, + data); + if (ret != 0) { + dev_err(wm831x->dev, "Failed to read touch data: %d\n", + ret); + return IRQ_NONE; + } + + /* + * We get a pen down reading on every reading, report pen up if any + * individual reading does so. + */ + wm831x_ts->pen_down = true; + for (i = 0; i < count; i++) { + if (!(data[i] & WM831X_TCH_PD)) { + wm831x_ts->pen_down = false; + continue; + } + input_report_abs(wm831x_ts->input_dev, data_types[i], + data[i] & WM831X_TCH_DATA_MASK); + } + + if (!wm831x_ts->pen_down) { + disable_irq_nosync(wm831x_ts->data_irq); + + /* Don't need data any more */ + wm831x_set_bits(wm831x, WM831X_TOUCH_CONTROL_1, + WM831X_TCH_X_ENA | WM831X_TCH_Y_ENA | + WM831X_TCH_Z_ENA, 0); + + /* Flush any final samples that arrived while reading */ + wm831x_set_bits(wm831x, WM831X_INTERRUPT_STATUS_1, + WM831X_TCHDATA_EINT, WM831X_TCHDATA_EINT); + + wm831x_bulk_read(wm831x, WM831X_TOUCH_DATA_X, count, data); + + if (wm831x_ts->pressure) + input_report_abs(wm831x_ts->input_dev, + ABS_PRESSURE, 0); + + input_report_key(wm831x_ts->input_dev, BTN_TOUCH, 0); + } + + input_sync(wm831x_ts->input_dev); + + return IRQ_HANDLED; +} + +static irqreturn_t wm831x_ts_pen_down_irq(int irq, void *irq_data) +{ + struct wm831x_ts *wm831x_ts = irq_data; + struct wm831x *wm831x = wm831x_ts->wm831x; + int ena; + + /* Start collecting data */ + ena = wm831x_ts->pressure ? WM831X_TCH_Z_ENA : 0; + + wm831x_set_bits(wm831x, WM831X_TOUCH_CONTROL_1, + WM831X_TCH_X_ENA | WM831X_TCH_Y_ENA | WM831X_TCH_Z_ENA, + WM831X_TCH_X_ENA | WM831X_TCH_Y_ENA | ena); + + input_report_key(wm831x_ts->input_dev, BTN_TOUCH, 1); + input_sync(wm831x_ts->input_dev); + + wm831x_set_bits(wm831x, WM831X_INTERRUPT_STATUS_1, + WM831X_TCHPD_EINT, WM831X_TCHPD_EINT); + + wm831x_ts->pen_down = true; + enable_irq(wm831x_ts->data_irq); + + return IRQ_HANDLED; +} + +static int wm831x_ts_input_open(struct input_dev *idev) +{ + struct wm831x_ts *wm831x_ts = input_get_drvdata(idev); + struct wm831x *wm831x = wm831x_ts->wm831x; + + wm831x_set_bits(wm831x, WM831X_TOUCH_CONTROL_1, + WM831X_TCH_ENA, WM831X_TCH_ENA); + + wm831x_set_bits(wm831x, WM831X_TOUCH_CONTROL_1, + WM831X_TCH_CVT_ENA, WM831X_TCH_CVT_ENA); + + return 0; +} + +static void wm831x_ts_input_close(struct input_dev *idev) +{ + struct wm831x_ts *wm831x_ts = input_get_drvdata(idev); + struct wm831x *wm831x = wm831x_ts->wm831x; + + wm831x_set_bits(wm831x, WM831X_TOUCH_CONTROL_1, + WM831X_TCH_ENA | WM831X_TCH_CVT_ENA | + WM831X_TCH_X_ENA | WM831X_TCH_Y_ENA | + WM831X_TCH_Z_ENA, 0); + + if (wm831x_ts->pen_down) + disable_irq(wm831x_ts->data_irq); +} + +static __devinit int wm831x_ts_probe(struct platform_device *pdev) +{ + struct wm831x_ts *wm831x_ts; + struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent); + struct wm831x_pdata *core_pdata = dev_get_platdata(pdev->dev.parent); + struct wm831x_touch_pdata *pdata = + core_pdata ? core_pdata->touch : NULL; + struct input_dev *input_dev; + int error; + + wm831x_ts = kzalloc(sizeof(struct wm831x_ts), GFP_KERNEL); + input_dev = input_allocate_device(); + if (!wm831x_ts || !input_dev) { + error = -ENOMEM; + goto err_alloc; + } + + wm831x_ts->wm831x = wm831x; + wm831x_ts->input_dev = input_dev; + + /* + * If we have a direct IRQ use it, otherwise use the interrupt + * from the WM831x IRQ controller. + */ + if (pdata && pdata->data_irq) + wm831x_ts->data_irq = pdata->data_irq; + else + wm831x_ts->data_irq = platform_get_irq_byname(pdev, "TCHDATA"); + + if (pdata && pdata->pd_irq) + wm831x_ts->pd_irq = pdata->pd_irq; + else + wm831x_ts->pd_irq = platform_get_irq_byname(pdev, "TCHPD"); + + wm831x_ts->pressure = pdata && pdata->pressure; + + /* Five wire touchscreens can't report pressure */ + if (pdata && pdata->fivewire) { + wm831x_set_bits(wm831x, WM831X_TOUCH_CONTROL_2, + WM831X_TCH_5WIRE, WM831X_TCH_5WIRE); + + /* Pressure measurements are not possible for five wire mode */ + WARN_ON(pdata->pressure && pdata->fivewire); + wm831x_ts->pressure = false; + } else { + wm831x_set_bits(wm831x, WM831X_TOUCH_CONTROL_2, + WM831X_TCH_5WIRE, 0); + } + + if (pdata) { + switch (pdata->isel) { + default: + dev_err(&pdev->dev, "Unsupported ISEL setting: %d\n", + pdata->isel); + /* Fall through */ + case 200: + case 0: + wm831x_set_bits(wm831x, WM831X_TOUCH_CONTROL_2, + WM831X_TCH_ISEL, 0); + break; + case 400: + wm831x_set_bits(wm831x, WM831X_TOUCH_CONTROL_2, + WM831X_TCH_ISEL, WM831X_TCH_ISEL); + break; + } + } + + wm831x_set_bits(wm831x, WM831X_TOUCH_CONTROL_2, + WM831X_TCH_PDONLY, 0); + + /* Default to 96 samples/sec */ + wm831x_set_bits(wm831x, WM831X_TOUCH_CONTROL_1, + WM831X_TCH_RATE_MASK, 6); + + error = request_threaded_irq(wm831x_ts->data_irq, + NULL, wm831x_ts_data_irq, + IRQF_ONESHOT, + "Touchscreen data", wm831x_ts); + if (error) { + dev_err(&pdev->dev, "Failed to request data IRQ %d: %d\n", + wm831x_ts->data_irq, error); + goto err_alloc; + } + disable_irq(wm831x_ts->data_irq); + + error = request_threaded_irq(wm831x_ts->pd_irq, + NULL, wm831x_ts_pen_down_irq, + IRQF_ONESHOT, + "Touchscreen pen down", wm831x_ts); + if (error) { + dev_err(&pdev->dev, "Failed to request pen down IRQ %d: %d\n", + wm831x_ts->pd_irq, error); + goto err_data_irq; + } + + /* set up touch configuration */ + input_dev->name = "WM831x touchscreen"; + input_dev->phys = "wm831x"; + input_dev->open = wm831x_ts_input_open; + input_dev->close = wm831x_ts_input_close; + + __set_bit(EV_ABS, input_dev->evbit); + __set_bit(EV_KEY, input_dev->evbit); + __set_bit(BTN_TOUCH, input_dev->keybit); + + input_set_abs_params(input_dev, ABS_X, 0, 4095, 5, 0); + input_set_abs_params(input_dev, ABS_Y, 0, 4095, 5, 0); + if (wm831x_ts->pressure) + input_set_abs_params(input_dev, ABS_PRESSURE, 0, 4095, 5, 0); + + input_set_drvdata(input_dev, wm831x_ts); + input_dev->dev.parent = &pdev->dev; + + error = input_register_device(input_dev); + if (error) + goto err_pd_irq; + + platform_set_drvdata(pdev, wm831x_ts); + return 0; + +err_pd_irq: + free_irq(wm831x_ts->pd_irq, wm831x_ts); +err_data_irq: + free_irq(wm831x_ts->data_irq, wm831x_ts); +err_alloc: + input_free_device(input_dev); + kfree(wm831x_ts); + + return error; +} + +static __devexit int wm831x_ts_remove(struct platform_device *pdev) +{ + struct wm831x_ts *wm831x_ts = platform_get_drvdata(pdev); + + free_irq(wm831x_ts->pd_irq, wm831x_ts); + free_irq(wm831x_ts->data_irq, wm831x_ts); + input_unregister_device(wm831x_ts->input_dev); + kfree(wm831x_ts); + + platform_set_drvdata(pdev, NULL); + return 0; +} + +static struct platform_driver wm831x_ts_driver = { + .driver = { + .name = "wm831x-touch", + .owner = THIS_MODULE, + }, + .probe = wm831x_ts_probe, + .remove = __devexit_p(wm831x_ts_remove), +}; + +static int __init wm831x_ts_init(void) +{ + return platform_driver_register(&wm831x_ts_driver); +} +module_init(wm831x_ts_init); + +static void __exit wm831x_ts_exit(void) +{ + platform_driver_unregister(&wm831x_ts_driver); +} +module_exit(wm831x_ts_exit); + +/* Module information */ +MODULE_AUTHOR("Mark Brown "); +MODULE_DESCRIPTION("WM831x PMIC touchscreen driver"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:wm831x-touch"); diff --git a/include/linux/mfd/wm831x/pdata.h b/include/linux/mfd/wm831x/pdata.h index fd322aca33ba8..173086d42af4d 100644 --- a/include/linux/mfd/wm831x/pdata.h +++ b/include/linux/mfd/wm831x/pdata.h @@ -80,7 +80,8 @@ struct wm831x_touch_pdata { int isel; /** Current for pen down (uA) */ int rpu; /** Pen down sensitivity resistor divider */ int pressure; /** Report pressure (boolean) */ - int data_irq; /** Touch data ready IRQ */ + unsigned int data_irq; /** Touch data ready IRQ */ + unsigned int pd_irq; /** Touch pendown detect IRQ */ }; enum wm831x_watchdog_action { -- GitLab From cb9ab2d8e4661c811d5e9a8e687b6f736690c90e Mon Sep 17 00:00:00 2001 From: Rabin Vincent Date: Tue, 25 Jan 2011 11:18:04 +0100 Subject: [PATCH 0025/2822] dma40: make init function static Acked-by: Per Forlin Acked-by: Jonas Aaberg Signed-off-by: Rabin Vincent Signed-off-by: Linus Walleij Signed-off-by: Dan Williams --- drivers/dma/ste_dma40.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/dma/ste_dma40.c b/drivers/dma/ste_dma40.c index 6e1d46a65d0ee..52013ed4b4425 100644 --- a/drivers/dma/ste_dma40.c +++ b/drivers/dma/ste_dma40.c @@ -3060,7 +3060,7 @@ static struct platform_driver d40_driver = { }, }; -int __init stedma40_init(void) +static int __init stedma40_init(void) { return platform_driver_probe(&d40_driver, d40_probe); } -- GitLab From 262d2915d4f11e5e78e432ab68f0ee034ef3f75f Mon Sep 17 00:00:00 2001 From: Rabin Vincent Date: Tue, 25 Jan 2011 11:18:05 +0100 Subject: [PATCH 0026/2822] dma40: ensure event lines get enabled The controller sometimes fails to register the enable of the event line when both src and dst event lines are used on the same logical channel. Implement the recommended software workaround, which is to retry the write until it works. Acked-by: Per Forlin Acked-by: Jonas Aaberg Signed-off-by: Rabin Vincent Signed-off-by: Linus Walleij Signed-off-by: Dan Williams --- drivers/dma/ste_dma40.c | 63 ++++++++++++++++++++++++++++++----------- 1 file changed, 46 insertions(+), 17 deletions(-) diff --git a/drivers/dma/ste_dma40.c b/drivers/dma/ste_dma40.c index 52013ed4b4425..42c88fc28815c 100644 --- a/drivers/dma/ste_dma40.c +++ b/drivers/dma/ste_dma40.c @@ -303,6 +303,11 @@ struct d40_reg_val { unsigned int val; }; +static struct device *chan2dev(struct d40_chan *d40c) +{ + return &d40c->chan.dev->device; +} + static int d40_pool_lli_alloc(struct d40_desc *d40d, int lli_len, bool is_log) { @@ -701,17 +706,46 @@ static void d40_term_all(struct d40_chan *d40c) d40c->busy = false; } +static void __d40_config_set_event(struct d40_chan *d40c, bool enable, + u32 event, int reg) +{ + void __iomem *addr = d40c->base->virtbase + D40_DREG_PCBASE + + d40c->phy_chan->num * D40_DREG_PCDELTA + reg; + int tries; + + if (!enable) { + writel((D40_DEACTIVATE_EVENTLINE << D40_EVENTLINE_POS(event)) + | ~D40_EVENTLINE_MASK(event), addr); + return; + } + + /* + * The hardware sometimes doesn't register the enable when src and dst + * event lines are active on the same logical channel. Retry to ensure + * it does. Usually only one retry is sufficient. + */ + tries = 100; + while (--tries) { + writel((D40_ACTIVATE_EVENTLINE << D40_EVENTLINE_POS(event)) + | ~D40_EVENTLINE_MASK(event), addr); + + if (readl(addr) & D40_EVENTLINE_MASK(event)) + break; + } + + if (tries != 99) + dev_dbg(chan2dev(d40c), + "[%s] workaround enable S%cLNK (%d tries)\n", + __func__, reg == D40_CHAN_REG_SSLNK ? 'S' : 'D', + 100 - tries); + + WARN_ON(!tries); +} + static void d40_config_set_event(struct d40_chan *d40c, bool do_enable) { - u32 val; unsigned long flags; - /* Notice, that disable requires the physical channel to be stopped */ - if (do_enable) - val = D40_ACTIVATE_EVENTLINE; - else - val = D40_DEACTIVATE_EVENTLINE; - spin_lock_irqsave(&d40c->phy_chan->lock, flags); /* Enable event line connected to device (or memcpy) */ @@ -719,20 +753,15 @@ static void d40_config_set_event(struct d40_chan *d40c, bool do_enable) (d40c->dma_cfg.dir == STEDMA40_PERIPH_TO_PERIPH)) { u32 event = D40_TYPE_TO_EVENT(d40c->dma_cfg.src_dev_type); - writel((val << D40_EVENTLINE_POS(event)) | - ~D40_EVENTLINE_MASK(event), - d40c->base->virtbase + D40_DREG_PCBASE + - d40c->phy_chan->num * D40_DREG_PCDELTA + - D40_CHAN_REG_SSLNK); + __d40_config_set_event(d40c, do_enable, event, + D40_CHAN_REG_SSLNK); } + if (d40c->dma_cfg.dir != STEDMA40_PERIPH_TO_MEM) { u32 event = D40_TYPE_TO_EVENT(d40c->dma_cfg.dst_dev_type); - writel((val << D40_EVENTLINE_POS(event)) | - ~D40_EVENTLINE_MASK(event), - d40c->base->virtbase + D40_DREG_PCBASE + - d40c->phy_chan->num * D40_DREG_PCDELTA + - D40_CHAN_REG_SDLNK); + __d40_config_set_event(d40c, do_enable, event, + D40_CHAN_REG_SDLNK); } spin_unlock_irqrestore(&d40c->phy_chan->lock, flags); -- GitLab From 7d83a854a1a44a8f6a699503441403a36c42f66c Mon Sep 17 00:00:00 2001 From: Rabin Vincent Date: Tue, 25 Jan 2011 11:18:06 +0100 Subject: [PATCH 0027/2822] dma40: remove "hardware link with previous jobs" code This link in hardware with previous jobs code is: - unused, no clients using or requiring this feature - incomplete, being implemented only for physical channels - broken, only working to perform one link Remove it. This also allows us to get rid of the channel pause in the submit_tx() routine. Acked-by: Per Forlin Acked-by: Jonas Aaberg Signed-off-by: Rabin Vincent Signed-off-by: Linus Walleij Signed-off-by: Dan Williams --- drivers/dma/ste_dma40.c | 113 +++------------------------------------- 1 file changed, 6 insertions(+), 107 deletions(-) diff --git a/drivers/dma/ste_dma40.c b/drivers/dma/ste_dma40.c index 42c88fc28815c..ed2a3ebcd86c6 100644 --- a/drivers/dma/ste_dma40.c +++ b/drivers/dma/ste_dma40.c @@ -94,7 +94,6 @@ struct d40_lli_pool { * during a transfer. * @node: List entry. * @is_in_client_list: true if the client owns this descriptor. - * @is_hw_linked: true if this job will automatically be continued for * the previous one. * * This descriptor is used for both logical and physical transfers. @@ -114,7 +113,6 @@ struct d40_desc { struct list_head node; bool is_in_client_list; - bool is_hw_linked; }; /** @@ -548,18 +546,6 @@ static struct d40_desc *d40_first_queued(struct d40_chan *d40c) return d; } -static struct d40_desc *d40_last_queued(struct d40_chan *d40c) -{ - struct d40_desc *d; - - if (list_empty(&d40c->queue)) - return NULL; - list_for_each_entry(d, &d40c->queue, node) - if (list_is_last(&d->node, &d40c->queue)) - break; - return d; -} - static int d40_psize_2_burst_size(bool is_log, int psize) { if (is_log) { @@ -940,77 +926,6 @@ no_suspend: return res; } -static void d40_tx_submit_log(struct d40_chan *d40c, struct d40_desc *d40d) -{ - /* TODO: Write */ -} - -static void d40_tx_submit_phy(struct d40_chan *d40c, struct d40_desc *d40d) -{ - struct d40_desc *d40d_prev = NULL; - int i; - u32 val; - - if (!list_empty(&d40c->queue)) - d40d_prev = d40_last_queued(d40c); - else if (!list_empty(&d40c->active)) - d40d_prev = d40_first_active_get(d40c); - - if (!d40d_prev) - return; - - /* Here we try to join this job with previous jobs */ - val = readl(d40c->base->virtbase + D40_DREG_PCBASE + - d40c->phy_chan->num * D40_DREG_PCDELTA + - D40_CHAN_REG_SSLNK); - - /* Figure out which link we're currently transmitting */ - for (i = 0; i < d40d_prev->lli_len; i++) - if (val == d40d_prev->lli_phy.src[i].reg_lnk) - break; - - val = readl(d40c->base->virtbase + D40_DREG_PCBASE + - d40c->phy_chan->num * D40_DREG_PCDELTA + - D40_CHAN_REG_SSELT) >> D40_SREG_ELEM_LOG_ECNT_POS; - - if (i == (d40d_prev->lli_len - 1) && val > 0) { - /* Change the current one */ - writel(virt_to_phys(d40d->lli_phy.src), - d40c->base->virtbase + D40_DREG_PCBASE + - d40c->phy_chan->num * D40_DREG_PCDELTA + - D40_CHAN_REG_SSLNK); - writel(virt_to_phys(d40d->lli_phy.dst), - d40c->base->virtbase + D40_DREG_PCBASE + - d40c->phy_chan->num * D40_DREG_PCDELTA + - D40_CHAN_REG_SDLNK); - - d40d->is_hw_linked = true; - - } else if (i < d40d_prev->lli_len) { - (void) dma_unmap_single(d40c->base->dev, - virt_to_phys(d40d_prev->lli_phy.src), - d40d_prev->lli_pool.size, - DMA_TO_DEVICE); - - /* Keep the settings */ - val = d40d_prev->lli_phy.src[d40d_prev->lli_len - 1].reg_lnk & - ~D40_SREG_LNK_PHYS_LNK_MASK; - d40d_prev->lli_phy.src[d40d_prev->lli_len - 1].reg_lnk = - val | virt_to_phys(d40d->lli_phy.src); - - val = d40d_prev->lli_phy.dst[d40d_prev->lli_len - 1].reg_lnk & - ~D40_SREG_LNK_PHYS_LNK_MASK; - d40d_prev->lli_phy.dst[d40d_prev->lli_len - 1].reg_lnk = - val | virt_to_phys(d40d->lli_phy.dst); - - (void) dma_map_single(d40c->base->dev, - d40d_prev->lli_phy.src, - d40d_prev->lli_pool.size, - DMA_TO_DEVICE); - d40d->is_hw_linked = true; - } -} - static dma_cookie_t d40_tx_submit(struct dma_async_tx_descriptor *tx) { struct d40_chan *d40c = container_of(tx->chan, @@ -1019,8 +934,6 @@ static dma_cookie_t d40_tx_submit(struct dma_async_tx_descriptor *tx) struct d40_desc *d40d = container_of(tx, struct d40_desc, txd); unsigned long flags; - (void) d40_pause(&d40c->chan); - spin_lock_irqsave(&d40c->lock, flags); d40c->chan.cookie++; @@ -1030,17 +943,10 @@ static dma_cookie_t d40_tx_submit(struct dma_async_tx_descriptor *tx) d40d->txd.cookie = d40c->chan.cookie; - if (d40c->log_num == D40_PHY_CHAN) - d40_tx_submit_phy(d40c, d40d); - else - d40_tx_submit_log(d40c, d40d); - d40_desc_queue(d40c, d40d); spin_unlock_irqrestore(&d40c->lock, flags); - (void) d40_resume(&d40c->chan); - return tx->cookie; } @@ -1080,21 +986,14 @@ static struct d40_desc *d40_queue_start(struct d40_chan *d40c) /* Add to active queue */ d40_desc_submit(d40c, d40d); - /* - * If this job is already linked in hw, - * do not submit it. - */ - - if (!d40d->is_hw_linked) { - /* Initiate DMA job */ - d40_desc_load(d40c, d40d); + /* Initiate DMA job */ + d40_desc_load(d40c, d40d); - /* Start dma job */ - err = d40_start(d40c); + /* Start dma job */ + err = d40_start(d40c); - if (err) - return NULL; - } + if (err) + return NULL; } return d40d; -- GitLab From 8ca84687b91322b9eafeaf4da43a21684cd0316e Mon Sep 17 00:00:00 2001 From: Rabin Vincent Date: Tue, 25 Jan 2011 11:18:07 +0100 Subject: [PATCH 0028/2822] dma40: use helper for channel registers base The register offset computation for accessing channel registers is copy/pasted in several places. Create a helper function to do it. Acked-by: Per Forlin Acked-by: Jonas Aaberg Signed-off-by: Rabin Vincent Signed-off-by: Linus Walleij Signed-off-by: Dan Williams --- drivers/dma/ste_dma40.c | 74 +++++++++++++++++------------------------ 1 file changed, 30 insertions(+), 44 deletions(-) diff --git a/drivers/dma/ste_dma40.c b/drivers/dma/ste_dma40.c index ed2a3ebcd86c6..3d4cea3cff35f 100644 --- a/drivers/dma/ste_dma40.c +++ b/drivers/dma/ste_dma40.c @@ -306,6 +306,12 @@ static struct device *chan2dev(struct d40_chan *d40c) return &d40c->chan.dev->device; } +static void __iomem *chan_base(struct d40_chan *chan) +{ + return chan->base->virtbase + D40_DREG_PCBASE + + chan->phy_chan->num * D40_DREG_PCDELTA; +} + static int d40_pool_lli_alloc(struct d40_desc *d40d, int lli_len, bool is_log) { @@ -695,8 +701,7 @@ static void d40_term_all(struct d40_chan *d40c) static void __d40_config_set_event(struct d40_chan *d40c, bool enable, u32 event, int reg) { - void __iomem *addr = d40c->base->virtbase + D40_DREG_PCBASE - + d40c->phy_chan->num * D40_DREG_PCDELTA + reg; + void __iomem *addr = chan_base(d40c) + reg; int tries; if (!enable) { @@ -755,15 +760,12 @@ static void d40_config_set_event(struct d40_chan *d40c, bool do_enable) static u32 d40_chan_has_events(struct d40_chan *d40c) { + void __iomem *chanbase = chan_base(d40c); u32 val; - val = readl(d40c->base->virtbase + D40_DREG_PCBASE + - d40c->phy_chan->num * D40_DREG_PCDELTA + - D40_CHAN_REG_SSLNK); + val = readl(chanbase + D40_CHAN_REG_SSLNK); + val |= readl(chanbase + D40_CHAN_REG_SDLNK); - val |= readl(d40c->base->virtbase + D40_DREG_PCBASE + - d40c->phy_chan->num * D40_DREG_PCDELTA + - D40_CHAN_REG_SDLNK); return val; } @@ -810,29 +812,17 @@ static void d40_config_write(struct d40_chan *d40c) writel(var, d40c->base->virtbase + D40_DREG_PRMOE + addr_base); if (d40c->log_num != D40_PHY_CHAN) { + int lidx = (d40c->phy_chan->num << D40_SREG_ELEM_LOG_LIDX_POS) + & D40_SREG_ELEM_LOG_LIDX_MASK; + void __iomem *chanbase = chan_base(d40c); + /* Set default config for CFG reg */ - writel(d40c->src_def_cfg, - d40c->base->virtbase + D40_DREG_PCBASE + - d40c->phy_chan->num * D40_DREG_PCDELTA + - D40_CHAN_REG_SSCFG); - writel(d40c->dst_def_cfg, - d40c->base->virtbase + D40_DREG_PCBASE + - d40c->phy_chan->num * D40_DREG_PCDELTA + - D40_CHAN_REG_SDCFG); + writel(d40c->src_def_cfg, chanbase + D40_CHAN_REG_SSCFG); + writel(d40c->dst_def_cfg, chanbase + D40_CHAN_REG_SDCFG); /* Set LIDX for lcla */ - writel((d40c->phy_chan->num << D40_SREG_ELEM_LOG_LIDX_POS) & - D40_SREG_ELEM_LOG_LIDX_MASK, - d40c->base->virtbase + D40_DREG_PCBASE + - d40c->phy_chan->num * D40_DREG_PCDELTA + - D40_CHAN_REG_SDELT); - - writel((d40c->phy_chan->num << D40_SREG_ELEM_LOG_LIDX_POS) & - D40_SREG_ELEM_LOG_LIDX_MASK, - d40c->base->virtbase + D40_DREG_PCBASE + - d40c->phy_chan->num * D40_DREG_PCDELTA + - D40_CHAN_REG_SSELT); - + writel(lidx, chanbase + D40_CHAN_REG_SSELT); + writel(lidx, chanbase + D40_CHAN_REG_SDELT); } } @@ -843,12 +833,12 @@ static u32 d40_residue(struct d40_chan *d40c) if (d40c->log_num != D40_PHY_CHAN) num_elt = (readl(&d40c->lcpa->lcsp2) & D40_MEM_LCSP2_ECNT_MASK) >> D40_MEM_LCSP2_ECNT_POS; - else - num_elt = (readl(d40c->base->virtbase + D40_DREG_PCBASE + - d40c->phy_chan->num * D40_DREG_PCDELTA + - D40_CHAN_REG_SDELT) & - D40_SREG_ELEM_PHY_ECNT_MASK) >> - D40_SREG_ELEM_PHY_ECNT_POS; + else { + u32 val = readl(chan_base(d40c) + D40_CHAN_REG_SDELT); + num_elt = (val & D40_SREG_ELEM_PHY_ECNT_MASK) + >> D40_SREG_ELEM_PHY_ECNT_POS; + } + return num_elt * (1 << d40c->dma_cfg.dst_info.data_width); } @@ -859,10 +849,9 @@ static bool d40_tx_is_linked(struct d40_chan *d40c) if (d40c->log_num != D40_PHY_CHAN) is_link = readl(&d40c->lcpa->lcsp3) & D40_MEM_LCSP3_DLOS_MASK; else - is_link = readl(d40c->base->virtbase + D40_DREG_PCBASE + - d40c->phy_chan->num * D40_DREG_PCDELTA + - D40_CHAN_REG_SDLNK) & - D40_SREG_LNK_PHYS_LNK_MASK; + is_link = readl(chan_base(d40c) + D40_CHAN_REG_SDLNK) + & D40_SREG_LNK_PHYS_LNK_MASK; + return is_link; } @@ -1550,6 +1539,7 @@ static int d40_free_dma(struct d40_chan *d40c) static bool d40_is_paused(struct d40_chan *d40c) { + void __iomem *chanbase = chan_base(d40c); bool is_paused = false; unsigned long flags; void __iomem *active_reg; @@ -1576,14 +1566,10 @@ static bool d40_is_paused(struct d40_chan *d40c) if (d40c->dma_cfg.dir == STEDMA40_MEM_TO_PERIPH || d40c->dma_cfg.dir == STEDMA40_MEM_TO_MEM) { event = D40_TYPE_TO_EVENT(d40c->dma_cfg.dst_dev_type); - status = readl(d40c->base->virtbase + D40_DREG_PCBASE + - d40c->phy_chan->num * D40_DREG_PCDELTA + - D40_CHAN_REG_SDLNK); + status = readl(chanbase + D40_CHAN_REG_SDLNK); } else if (d40c->dma_cfg.dir == STEDMA40_PERIPH_TO_MEM) { event = D40_TYPE_TO_EVENT(d40c->dma_cfg.src_dev_type); - status = readl(d40c->base->virtbase + D40_DREG_PCBASE + - d40c->phy_chan->num * D40_DREG_PCDELTA + - D40_CHAN_REG_SSLNK); + status = readl(chanbase + D40_CHAN_REG_SSLNK); } else { dev_err(&d40c->chan.dev->device, "[%s] Unknown direction\n", __func__); -- GitLab From 724a8577d80c6f8e9ac680be1cf419eddbd6f2a1 Mon Sep 17 00:00:00 2001 From: Rabin Vincent Date: Tue, 25 Jan 2011 11:18:08 +0100 Subject: [PATCH 0029/2822] dma40: use helpers for channel type check The somewhat confusing check d40c->log_num == D40_PHY_CHAN and its variants are used in several places to check if a channel is logical or physical. Use appropriately named helpers to do this to make the code more readable. Acked-by: Per Forlin Acked-by: Jonas Aaberg Signed-off-by: Rabin Vincent Signed-off-by: Linus Walleij Signed-off-by: Dan Williams --- drivers/dma/ste_dma40.c | 54 ++++++++++++++++++++++++----------------- 1 file changed, 32 insertions(+), 22 deletions(-) diff --git a/drivers/dma/ste_dma40.c b/drivers/dma/ste_dma40.c index 3d4cea3cff35f..0073988cdaf61 100644 --- a/drivers/dma/ste_dma40.c +++ b/drivers/dma/ste_dma40.c @@ -306,6 +306,16 @@ static struct device *chan2dev(struct d40_chan *d40c) return &d40c->chan.dev->device; } +static bool chan_is_physical(struct d40_chan *chan) +{ + return chan->log_num == D40_PHY_CHAN; +} + +static bool chan_is_logical(struct d40_chan *chan) +{ + return !chan_is_physical(chan); +} + static void __iomem *chan_base(struct d40_chan *chan) { return chan->base->virtbase + D40_DREG_PCBASE + @@ -400,7 +410,7 @@ static int d40_lcla_free_all(struct d40_chan *d40c, int i; int ret = -EINVAL; - if (d40c->log_num == D40_PHY_CHAN) + if (chan_is_physical(d40c)) return 0; spin_lock_irqsave(&d40c->base->lcla_pool.lock, flags); @@ -472,7 +482,7 @@ static void d40_desc_load(struct d40_chan *d40c, struct d40_desc *d40d) { int curr_lcla = -EINVAL, next_lcla; - if (d40c->log_num == D40_PHY_CHAN) { + if (chan_is_physical(d40c)) { d40_phy_lli_write(d40c->base->virtbase, d40c->phy_chan->num, d40d->lli_phy.dst, @@ -788,7 +798,7 @@ static u32 d40_get_prmo(struct d40_chan *d40c) = D40_DREG_PRMO_LCHAN_SRC_LOG_DST_LOG, }; - if (d40c->log_num == D40_PHY_CHAN) + if (chan_is_physical(d40c)) return phy_map[d40c->dma_cfg.mode_opt]; else return log_map[d40c->dma_cfg.mode_opt]; @@ -802,7 +812,7 @@ static void d40_config_write(struct d40_chan *d40c) /* Odd addresses are even addresses + 4 */ addr_base = (d40c->phy_chan->num % 2) * 4; /* Setup channel mode to logical or physical */ - var = ((u32)(d40c->log_num != D40_PHY_CHAN) + 1) << + var = ((u32)(chan_is_logical(d40c)) + 1) << D40_CHAN_POS(d40c->phy_chan->num); writel(var, d40c->base->virtbase + D40_DREG_PRMSE + addr_base); @@ -811,7 +821,7 @@ static void d40_config_write(struct d40_chan *d40c) writel(var, d40c->base->virtbase + D40_DREG_PRMOE + addr_base); - if (d40c->log_num != D40_PHY_CHAN) { + if (chan_is_logical(d40c)) { int lidx = (d40c->phy_chan->num << D40_SREG_ELEM_LOG_LIDX_POS) & D40_SREG_ELEM_LOG_LIDX_MASK; void __iomem *chanbase = chan_base(d40c); @@ -830,7 +840,7 @@ static u32 d40_residue(struct d40_chan *d40c) { u32 num_elt; - if (d40c->log_num != D40_PHY_CHAN) + if (chan_is_logical(d40c)) num_elt = (readl(&d40c->lcpa->lcsp2) & D40_MEM_LCSP2_ECNT_MASK) >> D40_MEM_LCSP2_ECNT_POS; else { @@ -846,7 +856,7 @@ static bool d40_tx_is_linked(struct d40_chan *d40c) { bool is_link; - if (d40c->log_num != D40_PHY_CHAN) + if (chan_is_logical(d40c)) is_link = readl(&d40c->lcpa->lcsp3) & D40_MEM_LCSP3_DLOS_MASK; else is_link = readl(chan_base(d40c) + D40_CHAN_REG_SDLNK) @@ -869,7 +879,7 @@ static int d40_pause(struct dma_chan *chan) res = d40_channel_execute_command(d40c, D40_DMA_SUSPEND_REQ); if (res == 0) { - if (d40c->log_num != D40_PHY_CHAN) { + if (chan_is_logical(d40c)) { d40_config_set_event(d40c, false); /* Resume the other logical channels if any */ if (d40_chan_has_events(d40c)) @@ -895,7 +905,7 @@ static int d40_resume(struct dma_chan *chan) spin_lock_irqsave(&d40c->lock, flags); if (d40c->base->rev == 0) - if (d40c->log_num != D40_PHY_CHAN) { + if (chan_is_logical(d40c)) { res = d40_channel_execute_command(d40c, D40_DMA_SUSPEND_REQ); goto no_suspend; @@ -904,7 +914,7 @@ static int d40_resume(struct dma_chan *chan) /* If bytes left to transfer or linked tx resume job */ if (d40_residue(d40c) || d40_tx_is_linked(d40c)) { - if (d40c->log_num != D40_PHY_CHAN) + if (chan_is_logical(d40c)) d40_config_set_event(d40c, true); res = d40_channel_execute_command(d40c, D40_DMA_RUN); @@ -944,7 +954,7 @@ static int d40_start(struct d40_chan *d40c) if (d40c->base->rev == 0) { int err; - if (d40c->log_num != D40_PHY_CHAN) { + if (chan_is_logical(d40c)) { err = d40_channel_execute_command(d40c, D40_DMA_SUSPEND_REQ); if (err) @@ -952,7 +962,7 @@ static int d40_start(struct d40_chan *d40c) } } - if (d40c->log_num != D40_PHY_CHAN) + if (chan_is_logical(d40c)) d40_config_set_event(d40c, true); return d40_channel_execute_command(d40c, D40_DMA_RUN); @@ -1495,7 +1505,7 @@ static int d40_free_dma(struct d40_chan *d40c) return res; } - if (d40c->log_num != D40_PHY_CHAN) { + if (chan_is_logical(d40c)) { /* Release logical channel, deactivate the event line */ d40_config_set_event(d40c, false); @@ -1548,7 +1558,7 @@ static bool d40_is_paused(struct d40_chan *d40c) spin_lock_irqsave(&d40c->lock, flags); - if (d40c->log_num == D40_PHY_CHAN) { + if (chan_is_physical(d40c)) { if (d40c->phy_chan->num % 2 == 0) active_reg = d40c->base->virtbase + D40_DREG_ACTIVE; else @@ -1638,7 +1648,7 @@ struct dma_async_tx_descriptor *stedma40_memcpy_sg(struct dma_chan *chan, d40d->lli_current = 0; d40d->txd.flags = dma_flags; - if (d40c->log_num != D40_PHY_CHAN) { + if (chan_is_logical(d40c)) { if (d40_pool_lli_alloc(d40d, d40d->lli_len, true) < 0) { dev_err(&d40c->chan.dev->device, @@ -1765,9 +1775,9 @@ static int d40_alloc_chan_resources(struct dma_chan *chan) /* Fill in basic CFG register values */ d40_phy_cfg(&d40c->dma_cfg, &d40c->src_def_cfg, - &d40c->dst_def_cfg, d40c->log_num != D40_PHY_CHAN); + &d40c->dst_def_cfg, chan_is_logical(d40c)); - if (d40c->log_num != D40_PHY_CHAN) { + if (chan_is_logical(d40c)) { d40_log_cfg(&d40c->dma_cfg, &d40c->log_def.lcsp1, &d40c->log_def.lcsp3); @@ -1857,7 +1867,7 @@ static struct dma_async_tx_descriptor *d40_prep_memcpy(struct dma_chan *chan, d40d->txd.tx_submit = d40_tx_submit; - if (d40c->log_num != D40_PHY_CHAN) { + if (chan_is_logical(d40c)) { if (d40_pool_lli_alloc(d40d, d40d->lli_len, true) < 0) { dev_err(&d40c->chan.dev->device, @@ -2093,7 +2103,7 @@ static struct dma_async_tx_descriptor *d40_prep_slave_sg(struct dma_chan *chan, if (d40d == NULL) goto err; - if (d40c->log_num != D40_PHY_CHAN) + if (chan_is_logical(d40c)) err = d40_prep_slave_sg_log(d40d, d40c, sgl, sg_len, direction, dma_flags); else @@ -2103,7 +2113,7 @@ static struct dma_async_tx_descriptor *d40_prep_slave_sg(struct dma_chan *chan, dev_err(&d40c->chan.dev->device, "[%s] Failed to prepare %s slave sg job: %d\n", __func__, - d40c->log_num != D40_PHY_CHAN ? "log" : "phy", err); + chan_is_logical(d40c) ? "log" : "phy", err); goto err; } @@ -2253,7 +2263,7 @@ static void d40_set_runtime_config(struct dma_chan *chan, return; } - if (d40c->log_num != D40_PHY_CHAN) { + if (chan_is_logical(d40c)) { if (config_maxburst >= 16) psize = STEDMA40_PSIZE_LOG_16; else if (config_maxburst >= 8) @@ -2286,7 +2296,7 @@ static void d40_set_runtime_config(struct dma_chan *chan, cfg->dst_info.flow_ctrl = STEDMA40_NO_FLOW_CTRL; /* Fill in register values */ - if (d40c->log_num != D40_PHY_CHAN) + if (chan_is_logical(d40c)) d40_log_cfg(cfg, &d40c->log_def.lcsp1, &d40c->log_def.lcsp3); else d40_phy_cfg(cfg, &d40c->src_def_cfg, -- GitLab From 6db5a8ba11bf23d1618e392518f1684cbf2fe031 Mon Sep 17 00:00:00 2001 From: Rabin Vincent Date: Tue, 25 Jan 2011 11:18:09 +0100 Subject: [PATCH 0030/2822] dma40: use helpers for error functions Almost every use of dev_err in this driver prints the function name. Abstract out wrappers to help with this and reduce code duplication. Acked-by: Per Forlin Acked-by: Jonas Aaberg Signed-off-by: Rabin Vincent Signed-off-by: Linus Walleij Signed-off-by: Dan Williams --- drivers/dma/ste_dma40.c | 201 +++++++++++++++------------------------- 1 file changed, 74 insertions(+), 127 deletions(-) diff --git a/drivers/dma/ste_dma40.c b/drivers/dma/ste_dma40.c index 0073988cdaf61..ab3ca6af7dbd3 100644 --- a/drivers/dma/ste_dma40.c +++ b/drivers/dma/ste_dma40.c @@ -322,6 +322,12 @@ static void __iomem *chan_base(struct d40_chan *chan) chan->phy_chan->num * D40_DREG_PCDELTA; } +#define d40_err(dev, format, arg...) \ + dev_err(dev, "[%s] " format, __func__, ## arg) + +#define chan_err(d40c, format, arg...) \ + d40_err(chan2dev(d40c), format, ## arg) + static int d40_pool_lli_alloc(struct d40_desc *d40d, int lli_len, bool is_log) { @@ -673,9 +679,9 @@ static int d40_channel_execute_command(struct d40_chan *d40c, } if (i == D40_SUSPEND_MAX_IT) { - dev_err(&d40c->chan.dev->device, - "[%s]: unable to suspend the chl %d (log: %d) status %x\n", - __func__, d40c->phy_chan->num, d40c->log_num, + chan_err(d40c, + "unable to suspend the chl %d (log: %d) status %x\n", + d40c->phy_chan->num, d40c->log_num, status); dump_stack(); ret = -EBUSY; @@ -1143,9 +1149,8 @@ static irqreturn_t d40_handle_interrupt(int irq, void *data) if (!il[row].is_error) dma_tc_handle(d40c); else - dev_err(base->dev, - "[%s] IRQ chan: %ld offset %d idx %d\n", - __func__, chan, il[row].offset, idx); + d40_err(base->dev, "IRQ chan: %ld offset %d idx %d\n", + chan, il[row].offset, idx); spin_unlock(&d40c->lock); } @@ -1164,8 +1169,7 @@ static int d40_validate_conf(struct d40_chan *d40c, bool is_log = conf->mode == STEDMA40_MODE_LOGICAL; if (!conf->dir) { - dev_err(&d40c->chan.dev->device, "[%s] Invalid direction.\n", - __func__); + chan_err(d40c, "Invalid direction.\n"); res = -EINVAL; } @@ -1173,46 +1177,40 @@ static int d40_validate_conf(struct d40_chan *d40c, d40c->base->plat_data->dev_tx[conf->dst_dev_type] == 0 && d40c->runtime_addr == 0) { - dev_err(&d40c->chan.dev->device, - "[%s] Invalid TX channel address (%d)\n", - __func__, conf->dst_dev_type); + chan_err(d40c, "Invalid TX channel address (%d)\n", + conf->dst_dev_type); res = -EINVAL; } if (conf->src_dev_type != STEDMA40_DEV_SRC_MEMORY && d40c->base->plat_data->dev_rx[conf->src_dev_type] == 0 && d40c->runtime_addr == 0) { - dev_err(&d40c->chan.dev->device, - "[%s] Invalid RX channel address (%d)\n", - __func__, conf->src_dev_type); + chan_err(d40c, "Invalid RX channel address (%d)\n", + conf->src_dev_type); res = -EINVAL; } if (conf->dir == STEDMA40_MEM_TO_PERIPH && dst_event_group == STEDMA40_DEV_DST_MEMORY) { - dev_err(&d40c->chan.dev->device, "[%s] Invalid dst\n", - __func__); + chan_err(d40c, "Invalid dst\n"); res = -EINVAL; } if (conf->dir == STEDMA40_PERIPH_TO_MEM && src_event_group == STEDMA40_DEV_SRC_MEMORY) { - dev_err(&d40c->chan.dev->device, "[%s] Invalid src\n", - __func__); + chan_err(d40c, "Invalid src\n"); res = -EINVAL; } if (src_event_group == STEDMA40_DEV_SRC_MEMORY && dst_event_group == STEDMA40_DEV_DST_MEMORY && is_log) { - dev_err(&d40c->chan.dev->device, - "[%s] No event line\n", __func__); + chan_err(d40c, "No event line\n"); res = -EINVAL; } if (conf->dir == STEDMA40_PERIPH_TO_PERIPH && (src_event_group != dst_event_group)) { - dev_err(&d40c->chan.dev->device, - "[%s] Invalid event group\n", __func__); + chan_err(d40c, "Invalid event group\n"); res = -EINVAL; } @@ -1221,9 +1219,7 @@ static int d40_validate_conf(struct d40_chan *d40c, * DMAC HW supports it. Will be added to this driver, * in case any dma client requires it. */ - dev_err(&d40c->chan.dev->device, - "[%s] periph to periph not supported\n", - __func__); + chan_err(d40c, "periph to periph not supported\n"); res = -EINVAL; } @@ -1236,9 +1232,7 @@ static int d40_validate_conf(struct d40_chan *d40c, * src (burst x width) == dst (burst x width) */ - dev_err(&d40c->chan.dev->device, - "[%s] src (burst x width) != dst (burst x width)\n", - __func__); + chan_err(d40c, "src (burst x width) != dst (burst x width)\n"); res = -EINVAL; } @@ -1441,8 +1435,7 @@ static int d40_config_memcpy(struct d40_chan *d40c) dma_has_cap(DMA_SLAVE, cap)) { d40c->dma_cfg = *d40c->base->plat_data->memcpy_conf_phy; } else { - dev_err(&d40c->chan.dev->device, "[%s] No memcpy\n", - __func__); + chan_err(d40c, "No memcpy\n"); return -EINVAL; } @@ -1473,15 +1466,13 @@ static int d40_free_dma(struct d40_chan *d40c) } if (phy == NULL) { - dev_err(&d40c->chan.dev->device, "[%s] phy == null\n", - __func__); + chan_err(d40c, "phy == null\n"); return -EINVAL; } if (phy->allocated_src == D40_ALLOC_FREE && phy->allocated_dst == D40_ALLOC_FREE) { - dev_err(&d40c->chan.dev->device, "[%s] channel already free\n", - __func__); + chan_err(d40c, "channel already free\n"); return -EINVAL; } @@ -1493,15 +1484,13 @@ static int d40_free_dma(struct d40_chan *d40c) event = D40_TYPE_TO_EVENT(d40c->dma_cfg.src_dev_type); is_src = true; } else { - dev_err(&d40c->chan.dev->device, - "[%s] Unknown direction\n", __func__); + chan_err(d40c, "Unknown direction\n"); return -EINVAL; } res = d40_channel_execute_command(d40c, D40_DMA_SUSPEND_REQ); if (res) { - dev_err(&d40c->chan.dev->device, "[%s] suspend failed\n", - __func__); + chan_err(d40c, "suspend failed\n"); return res; } @@ -1521,9 +1510,8 @@ static int d40_free_dma(struct d40_chan *d40c) res = d40_channel_execute_command(d40c, D40_DMA_RUN); if (res) { - dev_err(&d40c->chan.dev->device, - "[%s] Executing RUN command\n", - __func__); + chan_err(d40c, + "Executing RUN command\n"); return res; } } @@ -1536,8 +1524,7 @@ static int d40_free_dma(struct d40_chan *d40c) /* Release physical channel */ res = d40_channel_execute_command(d40c, D40_DMA_STOP); if (res) { - dev_err(&d40c->chan.dev->device, - "[%s] Failed to stop channel\n", __func__); + chan_err(d40c, "Failed to stop channel\n"); return res; } d40c->phy_chan = NULL; @@ -1581,8 +1568,7 @@ static bool d40_is_paused(struct d40_chan *d40c) event = D40_TYPE_TO_EVENT(d40c->dma_cfg.src_dev_type); status = readl(chanbase + D40_CHAN_REG_SSLNK); } else { - dev_err(&d40c->chan.dev->device, - "[%s] Unknown direction\n", __func__); + chan_err(d40c, "Unknown direction\n"); goto _exit; } @@ -1625,8 +1611,7 @@ struct dma_async_tx_descriptor *stedma40_memcpy_sg(struct dma_chan *chan, unsigned long flags; if (d40c->phy_chan == NULL) { - dev_err(&d40c->chan.dev->device, - "[%s] Unallocated channel.\n", __func__); + chan_err(d40c, "Unallocated channel.\n"); return ERR_PTR(-EINVAL); } @@ -1640,8 +1625,7 @@ struct dma_async_tx_descriptor *stedma40_memcpy_sg(struct dma_chan *chan, d40c->dma_cfg.src_info.data_width, d40c->dma_cfg.dst_info.data_width); if (d40d->lli_len < 0) { - dev_err(&d40c->chan.dev->device, - "[%s] Unaligned size\n", __func__); + chan_err(d40c, "Unaligned size\n"); goto err; } @@ -1651,8 +1635,7 @@ struct dma_async_tx_descriptor *stedma40_memcpy_sg(struct dma_chan *chan, if (chan_is_logical(d40c)) { if (d40_pool_lli_alloc(d40d, d40d->lli_len, true) < 0) { - dev_err(&d40c->chan.dev->device, - "[%s] Out of memory\n", __func__); + chan_err(d40c, "Out of memory\n"); goto err; } @@ -1671,8 +1654,7 @@ struct dma_async_tx_descriptor *stedma40_memcpy_sg(struct dma_chan *chan, d40c->dma_cfg.src_info.data_width); } else { if (d40_pool_lli_alloc(d40d, d40d->lli_len, false) < 0) { - dev_err(&d40c->chan.dev->device, - "[%s] Out of memory\n", __func__); + chan_err(d40c, "Out of memory\n"); goto err; } @@ -1758,9 +1740,7 @@ static int d40_alloc_chan_resources(struct dma_chan *chan) if (!d40c->configured) { err = d40_config_memcpy(d40c); if (err) { - dev_err(&d40c->chan.dev->device, - "[%s] Failed to configure memcpy channel\n", - __func__); + chan_err(d40c, "Failed to configure memcpy channel\n"); goto fail; } } @@ -1768,8 +1748,7 @@ static int d40_alloc_chan_resources(struct dma_chan *chan) err = d40_allocate_channel(d40c); if (err) { - dev_err(&d40c->chan.dev->device, - "[%s] Failed to allocate channel\n", __func__); + chan_err(d40c, "Failed to allocate channel\n"); goto fail; } @@ -1810,8 +1789,7 @@ static void d40_free_chan_resources(struct dma_chan *chan) unsigned long flags; if (d40c->phy_chan == NULL) { - dev_err(&d40c->chan.dev->device, - "[%s] Cannot free unallocated channel\n", __func__); + chan_err(d40c, "Cannot free unallocated channel\n"); return; } @@ -1821,8 +1799,7 @@ static void d40_free_chan_resources(struct dma_chan *chan) err = d40_free_dma(d40c); if (err) - dev_err(&d40c->chan.dev->device, - "[%s] Failed to free channel\n", __func__); + chan_err(d40c, "Failed to free channel\n"); spin_unlock_irqrestore(&d40c->lock, flags); } @@ -1838,8 +1815,7 @@ static struct dma_async_tx_descriptor *d40_prep_memcpy(struct dma_chan *chan, unsigned long flags; if (d40c->phy_chan == NULL) { - dev_err(&d40c->chan.dev->device, - "[%s] Channel is not allocated.\n", __func__); + chan_err(d40c, "Channel is not allocated.\n"); return ERR_PTR(-EINVAL); } @@ -1847,8 +1823,7 @@ static struct dma_async_tx_descriptor *d40_prep_memcpy(struct dma_chan *chan, d40d = d40_desc_get(d40c); if (d40d == NULL) { - dev_err(&d40c->chan.dev->device, - "[%s] Descriptor is NULL\n", __func__); + chan_err(d40c, "Descriptor is NULL\n"); goto err; } @@ -1857,8 +1832,7 @@ static struct dma_async_tx_descriptor *d40_prep_memcpy(struct dma_chan *chan, d40c->dma_cfg.src_info.data_width, d40c->dma_cfg.dst_info.data_width); if (d40d->lli_len < 0) { - dev_err(&d40c->chan.dev->device, - "[%s] Unaligned size\n", __func__); + chan_err(d40c, "Unaligned size\n"); goto err; } @@ -1870,8 +1844,7 @@ static struct dma_async_tx_descriptor *d40_prep_memcpy(struct dma_chan *chan, if (chan_is_logical(d40c)) { if (d40_pool_lli_alloc(d40d, d40d->lli_len, true) < 0) { - dev_err(&d40c->chan.dev->device, - "[%s] Out of memory\n", __func__); + chan_err(d40c, "Out of memory\n"); goto err; } d40d->lli_current = 0; @@ -1897,8 +1870,7 @@ static struct dma_async_tx_descriptor *d40_prep_memcpy(struct dma_chan *chan, } else { if (d40_pool_lli_alloc(d40d, d40d->lli_len, false) < 0) { - dev_err(&d40c->chan.dev->device, - "[%s] Out of memory\n", __func__); + chan_err(d40c, "Out of memory\n"); goto err; } @@ -1966,14 +1938,12 @@ static int d40_prep_slave_sg_log(struct d40_desc *d40d, d40c->dma_cfg.src_info.data_width, d40c->dma_cfg.dst_info.data_width); if (d40d->lli_len < 0) { - dev_err(&d40c->chan.dev->device, - "[%s] Unaligned size\n", __func__); + chan_err(d40c, "Unaligned size\n"); return -EINVAL; } if (d40_pool_lli_alloc(d40d, d40d->lli_len, true) < 0) { - dev_err(&d40c->chan.dev->device, - "[%s] Out of memory\n", __func__); + chan_err(d40c, "Out of memory\n"); return -ENOMEM; } @@ -2022,14 +1992,12 @@ static int d40_prep_slave_sg_phy(struct d40_desc *d40d, d40c->dma_cfg.src_info.data_width, d40c->dma_cfg.dst_info.data_width); if (d40d->lli_len < 0) { - dev_err(&d40c->chan.dev->device, - "[%s] Unaligned size\n", __func__); + chan_err(d40c, "Unaligned size\n"); return -EINVAL; } if (d40_pool_lli_alloc(d40d, d40d->lli_len, false) < 0) { - dev_err(&d40c->chan.dev->device, - "[%s] Out of memory\n", __func__); + chan_err(d40c, "Out of memory\n"); return -ENOMEM; } @@ -2092,8 +2060,7 @@ static struct dma_async_tx_descriptor *d40_prep_slave_sg(struct dma_chan *chan, int err; if (d40c->phy_chan == NULL) { - dev_err(&d40c->chan.dev->device, - "[%s] Cannot prepare unallocated channel\n", __func__); + chan_err(d40c, "Cannot prepare unallocated channel\n"); return ERR_PTR(-EINVAL); } @@ -2110,9 +2077,7 @@ static struct dma_async_tx_descriptor *d40_prep_slave_sg(struct dma_chan *chan, err = d40_prep_slave_sg_phy(d40d, d40c, sgl, sg_len, direction, dma_flags); if (err) { - dev_err(&d40c->chan.dev->device, - "[%s] Failed to prepare %s slave sg job: %d\n", - __func__, + chan_err(d40c, "Failed to prepare %s slave sg job: %d\n", chan_is_logical(d40c) ? "log" : "phy", err); goto err; } @@ -2143,9 +2108,7 @@ static enum dma_status d40_tx_status(struct dma_chan *chan, int ret; if (d40c->phy_chan == NULL) { - dev_err(&d40c->chan.dev->device, - "[%s] Cannot read status of unallocated channel\n", - __func__); + chan_err(d40c, "Cannot read status of unallocated channel\n"); return -EINVAL; } @@ -2169,8 +2132,7 @@ static void d40_issue_pending(struct dma_chan *chan) unsigned long flags; if (d40c->phy_chan == NULL) { - dev_err(&d40c->chan.dev->device, - "[%s] Channel is not allocated!\n", __func__); + chan_err(d40c, "Channel is not allocated!\n"); return; } @@ -2321,8 +2283,7 @@ static int d40_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd, struct d40_chan *d40c = container_of(chan, struct d40_chan, chan); if (d40c->phy_chan == NULL) { - dev_err(&d40c->chan.dev->device, - "[%s] Channel is not allocated!\n", __func__); + chan_err(d40c, "Channel is not allocated!\n"); return -EINVAL; } @@ -2404,9 +2365,7 @@ static int __init d40_dmaengine_init(struct d40_base *base, err = dma_async_device_register(&base->dma_slave); if (err) { - dev_err(base->dev, - "[%s] Failed to register slave channels\n", - __func__); + d40_err(base->dev, "Failed to register slave channels\n"); goto failure1; } @@ -2435,9 +2394,8 @@ static int __init d40_dmaengine_init(struct d40_base *base, err = dma_async_device_register(&base->dma_memcpy); if (err) { - dev_err(base->dev, - "[%s] Failed to regsiter memcpy only channels\n", - __func__); + d40_err(base->dev, + "Failed to regsiter memcpy only channels\n"); goto failure2; } @@ -2462,9 +2420,8 @@ static int __init d40_dmaengine_init(struct d40_base *base, err = dma_async_device_register(&base->dma_both); if (err) { - dev_err(base->dev, - "[%s] Failed to register logical and physical capable channels\n", - __func__); + d40_err(base->dev, + "Failed to register logical and physical capable channels\n"); goto failure3; } return 0; @@ -2566,8 +2523,7 @@ static struct d40_base * __init d40_hw_detect_init(struct platform_device *pdev) clk = clk_get(&pdev->dev, NULL); if (IS_ERR(clk)) { - dev_err(&pdev->dev, "[%s] No matching clock found\n", - __func__); + d40_err(&pdev->dev, "No matching clock found\n"); goto failure; } @@ -2590,9 +2546,8 @@ static struct d40_base * __init d40_hw_detect_init(struct platform_device *pdev) for (i = 0; i < ARRAY_SIZE(dma_id_regs); i++) { if (dma_id_regs[i].val != readl(virtbase + dma_id_regs[i].reg)) { - dev_err(&pdev->dev, - "[%s] Unknown hardware! Expected 0x%x at 0x%x but got 0x%x\n", - __func__, + d40_err(&pdev->dev, + "Unknown hardware! Expected 0x%x at 0x%x but got 0x%x\n", dma_id_regs[i].val, dma_id_regs[i].reg, readl(virtbase + dma_id_regs[i].reg)); @@ -2605,9 +2560,8 @@ static struct d40_base * __init d40_hw_detect_init(struct platform_device *pdev) if ((val & D40_DREG_PERIPHID2_DESIGNER_MASK) != D40_HW_DESIGNER) { - dev_err(&pdev->dev, - "[%s] Unknown designer! Got %x wanted %x\n", - __func__, val & D40_DREG_PERIPHID2_DESIGNER_MASK, + d40_err(&pdev->dev, "Unknown designer! Got %x wanted %x\n", + val & D40_DREG_PERIPHID2_DESIGNER_MASK, D40_HW_DESIGNER); goto failure; } @@ -2637,7 +2591,7 @@ static struct d40_base * __init d40_hw_detect_init(struct platform_device *pdev) sizeof(struct d40_chan), GFP_KERNEL); if (base == NULL) { - dev_err(&pdev->dev, "[%s] Out of memory\n", __func__); + d40_err(&pdev->dev, "Out of memory\n"); goto failure; } @@ -2809,9 +2763,8 @@ static int __init d40_lcla_allocate(struct d40_base *base) base->lcla_pool.pages); if (!page_list[i]) { - dev_err(base->dev, - "[%s] Failed to allocate %d pages.\n", - __func__, base->lcla_pool.pages); + d40_err(base->dev, "Failed to allocate %d pages.\n", + base->lcla_pool.pages); for (j = 0; j < i; j++) free_pages(page_list[j], base->lcla_pool.pages); @@ -2881,9 +2834,7 @@ static int __init d40_probe(struct platform_device *pdev) res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "lcpa"); if (!res) { ret = -ENOENT; - dev_err(&pdev->dev, - "[%s] No \"lcpa\" memory resource\n", - __func__); + d40_err(&pdev->dev, "No \"lcpa\" memory resource\n"); goto failure; } base->lcpa_size = resource_size(res); @@ -2892,9 +2843,9 @@ static int __init d40_probe(struct platform_device *pdev) if (request_mem_region(res->start, resource_size(res), D40_NAME " I/O lcpa") == NULL) { ret = -EBUSY; - dev_err(&pdev->dev, - "[%s] Failed to request LCPA region 0x%x-0x%x\n", - __func__, res->start, res->end); + d40_err(&pdev->dev, + "Failed to request LCPA region 0x%x-0x%x\n", + res->start, res->end); goto failure; } @@ -2910,16 +2861,13 @@ static int __init d40_probe(struct platform_device *pdev) base->lcpa_base = ioremap(res->start, resource_size(res)); if (!base->lcpa_base) { ret = -ENOMEM; - dev_err(&pdev->dev, - "[%s] Failed to ioremap LCPA region\n", - __func__); + d40_err(&pdev->dev, "Failed to ioremap LCPA region\n"); goto failure; } ret = d40_lcla_allocate(base); if (ret) { - dev_err(&pdev->dev, "[%s] Failed to allocate LCLA area\n", - __func__); + d40_err(&pdev->dev, "Failed to allocate LCLA area\n"); goto failure; } @@ -2928,9 +2876,8 @@ static int __init d40_probe(struct platform_device *pdev) base->irq = platform_get_irq(pdev, 0); ret = request_irq(base->irq, d40_handle_interrupt, 0, D40_NAME, base); - if (ret) { - dev_err(&pdev->dev, "[%s] No IRQ defined\n", __func__); + d40_err(&pdev->dev, "No IRQ defined\n"); goto failure; } @@ -2973,7 +2920,7 @@ failure: kfree(base); } - dev_err(&pdev->dev, "[%s] probe failed\n", __func__); + d40_err(&pdev->dev, "probe failed\n"); return ret; } -- GitLab From 4d5949009e585b2bcf09dc4de625351f987a1e6d Mon Sep 17 00:00:00 2001 From: Rabin Vincent Date: Tue, 25 Jan 2011 11:18:10 +0100 Subject: [PATCH 0031/2822] dma40: fix comment to refer to SOCs rather than boards And add DB8500v2 information. Acked-by: Per Forlin Acked-by: Jonas Aaberg Signed-off-by: Rabin Vincent Signed-off-by: Linus Walleij Signed-off-by: Dan Williams --- drivers/dma/ste_dma40.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/dma/ste_dma40.c b/drivers/dma/ste_dma40.c index ab3ca6af7dbd3..0faae662ad15a 100644 --- a/drivers/dma/ste_dma40.c +++ b/drivers/dma/ste_dma40.c @@ -2497,9 +2497,10 @@ static struct d40_base * __init d40_hw_detect_init(struct platform_device *pdev) { .reg = D40_DREG_PERIPHID1, .val = 0x0000}, /* * D40_DREG_PERIPHID2 Depends on HW revision: - * MOP500/HREF ED has 0x0008, + * DB8500ed has 0x0008, * ? has 0x0018, - * HREF V1 has 0x0028 + * DB8500v1 has 0x0028 + * DB8500v2 has 0x0038 */ { .reg = D40_DREG_PERIPHID3, .val = 0x0000}, -- GitLab From ac2c0a387194f45c759572b3462d1bf92ec92f00 Mon Sep 17 00:00:00 2001 From: Rabin Vincent Date: Tue, 25 Jan 2011 11:18:11 +0100 Subject: [PATCH 0032/2822] dma40: allow realtime and priority for event lines DB8500v2's DMA40 (revision 3) allows setting event lines as high priority and real time. Acked-by: Per Forlin Acked-by: Jonas Aaberg Signed-off-by: Rabin Vincent Signed-off-by: Linus Walleij Signed-off-by: Dan Williams --- .../arm/plat-nomadik/include/plat/ste_dma40.h | 3 ++ drivers/dma/ste_dma40.c | 34 +++++++++++++++++++ drivers/dma/ste_dma40_ll.h | 16 +++++++++ 3 files changed, 53 insertions(+) diff --git a/arch/arm/plat-nomadik/include/plat/ste_dma40.h b/arch/arm/plat-nomadik/include/plat/ste_dma40.h index 4d6dd4c39b750..8358f857a29ed 100644 --- a/arch/arm/plat-nomadik/include/plat/ste_dma40.h +++ b/arch/arm/plat-nomadik/include/plat/ste_dma40.h @@ -104,6 +104,8 @@ struct stedma40_half_channel_info { * * @dir: MEM 2 MEM, PERIPH 2 MEM , MEM 2 PERIPH, PERIPH 2 PERIPH * @high_priority: true if high-priority + * @realtime: true if realtime mode is to be enabled. Only available on DMA40 + * version 3+, i.e DB8500v2+ * @mode: channel mode: physical, logical, or operation * @mode_opt: options for the chosen channel mode * @src_dev_type: Src device type @@ -119,6 +121,7 @@ struct stedma40_half_channel_info { struct stedma40_chan_cfg { enum stedma40_xfer_dir dir; bool high_priority; + bool realtime; enum stedma40_mode mode; enum stedma40_mode_opt mode_opt; int src_dev_type; diff --git a/drivers/dma/ste_dma40.c b/drivers/dma/ste_dma40.c index 0faae662ad15a..ce55162215812 100644 --- a/drivers/dma/ste_dma40.c +++ b/drivers/dma/ste_dma40.c @@ -1724,6 +1724,38 @@ bool stedma40_filter(struct dma_chan *chan, void *data) } EXPORT_SYMBOL(stedma40_filter); +static void __d40_set_prio_rt(struct d40_chan *d40c, int dev_type, bool src) +{ + bool realtime = d40c->dma_cfg.realtime; + bool highprio = d40c->dma_cfg.high_priority; + u32 prioreg = highprio ? D40_DREG_PSEG1 : D40_DREG_PCEG1; + u32 rtreg = realtime ? D40_DREG_RSEG1 : D40_DREG_RCEG1; + u32 event = D40_TYPE_TO_EVENT(dev_type); + u32 group = D40_TYPE_TO_GROUP(dev_type); + u32 bit = 1 << event; + + /* Destination event lines are stored in the upper halfword */ + if (!src) + bit <<= 16; + + writel(bit, d40c->base->virtbase + prioreg + group * 4); + writel(bit, d40c->base->virtbase + rtreg + group * 4); +} + +static void d40_set_prio_realtime(struct d40_chan *d40c) +{ + if (d40c->base->rev < 3) + return; + + if ((d40c->dma_cfg.dir == STEDMA40_PERIPH_TO_MEM) || + (d40c->dma_cfg.dir == STEDMA40_PERIPH_TO_PERIPH)) + __d40_set_prio_rt(d40c, d40c->dma_cfg.src_dev_type, true); + + if ((d40c->dma_cfg.dir == STEDMA40_MEM_TO_PERIPH) || + (d40c->dma_cfg.dir == STEDMA40_PERIPH_TO_PERIPH)) + __d40_set_prio_rt(d40c, d40c->dma_cfg.dst_dev_type, false); +} + /* DMA ENGINE functions */ static int d40_alloc_chan_resources(struct dma_chan *chan) { @@ -1756,6 +1788,8 @@ static int d40_alloc_chan_resources(struct dma_chan *chan) d40_phy_cfg(&d40c->dma_cfg, &d40c->src_def_cfg, &d40c->dst_def_cfg, chan_is_logical(d40c)); + d40_set_prio_realtime(d40c); + if (chan_is_logical(d40c)) { d40_log_cfg(&d40c->dma_cfg, &d40c->log_def.lcsp1, &d40c->log_def.lcsp3); diff --git a/drivers/dma/ste_dma40_ll.h b/drivers/dma/ste_dma40_ll.h index 9cc43495bea20..e93f394187a37 100644 --- a/drivers/dma/ste_dma40_ll.h +++ b/drivers/dma/ste_dma40_ll.h @@ -163,6 +163,22 @@ #define D40_DREG_LCEIS1 0x0B4 #define D40_DREG_LCEIS2 0x0B8 #define D40_DREG_LCEIS3 0x0BC +#define D40_DREG_PSEG1 0x110 +#define D40_DREG_PSEG2 0x114 +#define D40_DREG_PSEG3 0x118 +#define D40_DREG_PSEG4 0x11C +#define D40_DREG_PCEG1 0x120 +#define D40_DREG_PCEG2 0x124 +#define D40_DREG_PCEG3 0x128 +#define D40_DREG_PCEG4 0x12C +#define D40_DREG_RSEG1 0x130 +#define D40_DREG_RSEG2 0x134 +#define D40_DREG_RSEG3 0x138 +#define D40_DREG_RSEG4 0x13C +#define D40_DREG_RCEG1 0x140 +#define D40_DREG_RCEG2 0x144 +#define D40_DREG_RCEG3 0x148 +#define D40_DREG_RCEG4 0x14C #define D40_DREG_STFU 0xFC8 #define D40_DREG_ICFG 0xFCC #define D40_DREG_PERIPHID0 0xFE0 -- GitLab From 594ece4dc0e8ac222945ef2048430600ad3c7644 Mon Sep 17 00:00:00 2001 From: Rabin Vincent Date: Tue, 25 Jan 2011 11:18:12 +0100 Subject: [PATCH 0033/2822] dma40: remove unnecessary ALIGN()s ALIGN(x * y, y) == x * y ALIGN(aligned + x * y, y) == aligned + x * y Acked-by: Per Forlin Acked-by: Jonas Aaberg Signed-off-by: Rabin Vincent Signed-off-by: Linus Walleij Signed-off-by: Dan Williams --- drivers/dma/ste_dma40.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/drivers/dma/ste_dma40.c b/drivers/dma/ste_dma40.c index ce55162215812..d32a9ac86084a 100644 --- a/drivers/dma/ste_dma40.c +++ b/drivers/dma/ste_dma40.c @@ -344,7 +344,7 @@ static int d40_pool_lli_alloc(struct d40_desc *d40d, d40d->lli_pool.size = sizeof(d40d->lli_pool.pre_alloc_lli); d40d->lli_pool.base = NULL; } else { - d40d->lli_pool.size = ALIGN(lli_len * 2 * align, align); + d40d->lli_pool.size = lli_len * 2 * align; base = kmalloc(d40d->lli_pool.size + align, GFP_NOWAIT); d40d->lli_pool.base = base; @@ -356,13 +356,11 @@ static int d40_pool_lli_alloc(struct d40_desc *d40d, if (is_log) { d40d->lli_log.src = PTR_ALIGN((struct d40_log_lli *) base, align); - d40d->lli_log.dst = PTR_ALIGN(d40d->lli_log.src + lli_len, - align); + d40d->lli_log.dst = d40d->lli_log.src + lli_len; } else { d40d->lli_phy.src = PTR_ALIGN((struct d40_phy_lli *)base, align); - d40d->lli_phy.dst = PTR_ALIGN(d40d->lli_phy.src + lli_len, - align); + d40d->lli_phy.dst = d40d->lli_phy.src + lli_len; } return 0; -- GitLab From 7fe8be5a74eb058b0b48970caef83e0215f55944 Mon Sep 17 00:00:00 2001 From: Rabin Vincent Date: Tue, 25 Jan 2011 11:18:13 +0100 Subject: [PATCH 0034/2822] dma40: use sg_dma_address() instead of sg_phys() The address to use for DMA should be taken from sg_dma_address() and not sg_phys(). Acked-by: Per Forlin Acked-by: Jonas Aaberg Signed-off-by: Rabin Vincent Signed-off-by: Linus Walleij Signed-off-by: Dan Williams --- drivers/dma/ste_dma40_ll.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/dma/ste_dma40_ll.c b/drivers/dma/ste_dma40_ll.c index 0b096a38322dd..6f03f580c4926 100644 --- a/drivers/dma/ste_dma40_ll.c +++ b/drivers/dma/ste_dma40_ll.c @@ -272,7 +272,7 @@ int d40_phy_sg_to_lli(struct scatterlist *sg, if (target) dst = target; else - dst = sg_phys(current_sg); + dst = sg_dma_address(current_sg); l_phys = ALIGN(lli_phys + (lli - lli_sg) * sizeof(struct d40_phy_lli), D40_LLI_ALIGN); @@ -416,7 +416,7 @@ int d40_log_sg_to_dev(struct scatterlist *sg, if (direction == DMA_TO_DEVICE) { lli_src = d40_log_buf_to_lli(lli_src, - sg_phys(current_sg), + sg_dma_address(current_sg), sg_dma_len(current_sg), lcsp->lcsp1, src_data_width, dst_data_width, @@ -431,7 +431,7 @@ int d40_log_sg_to_dev(struct scatterlist *sg, } else { lli_dst = d40_log_buf_to_lli(lli_dst, - sg_phys(current_sg), + sg_dma_address(current_sg), sg_dma_len(current_sg), lcsp->lcsp3, dst_data_width, src_data_width, @@ -491,7 +491,7 @@ int d40_log_sg_to_lli(struct scatterlist *sg, for_each_sg(sg, current_sg, sg_len, i) { total_size += sg_dma_len(current_sg); lli = d40_log_buf_to_lli(lli, - sg_phys(current_sg), + sg_dma_address(current_sg), sg_dma_len(current_sg), lcsp13, data_width1, data_width2, true); -- GitLab From 026cbc424a162e495ad29e91d354fb8fc2da2657 Mon Sep 17 00:00:00 2001 From: Rabin Vincent Date: Tue, 25 Jan 2011 11:18:14 +0100 Subject: [PATCH 0035/2822] dma40: fix DMA API usage for LCLA Map the buffer once and use dma_sync*() appropriately instead of mapping the buffer over and over without unmapping it. Acked-by: Per Forlin Acked-by: Jonas Aaberg Signed-off-by: Rabin Vincent Signed-off-by: Linus Walleij Signed-off-by: Dan Williams --- drivers/dma/ste_dma40.c | 33 +++++++++++++++++++++++++-------- 1 file changed, 25 insertions(+), 8 deletions(-) diff --git a/drivers/dma/ste_dma40.c b/drivers/dma/ste_dma40.c index d32a9ac86084a..f08e5c49c5d2b 100644 --- a/drivers/dma/ste_dma40.c +++ b/drivers/dma/ste_dma40.c @@ -128,6 +128,7 @@ struct d40_desc { */ struct d40_lcla_pool { void *base; + dma_addr_t dma_addr; void *base_unaligned; int pages; spinlock_t lock; @@ -504,25 +505,25 @@ static void d40_desc_load(struct d40_chan *d40c, struct d40_desc *d40d) d40d->lli_current++; for (; d40d->lli_current < d40d->lli_len; d40d->lli_current++) { - struct d40_log_lli *lcla; + unsigned int lcla_offset = d40c->phy_chan->num * 1024 + + 8 * curr_lcla * 2; + struct d40_lcla_pool *pool = &d40c->base->lcla_pool; + struct d40_log_lli *lcla = pool->base + lcla_offset; if (d40d->lli_current + 1 < d40d->lli_len) next_lcla = d40_lcla_alloc_one(d40c, d40d); else next_lcla = -EINVAL; - lcla = d40c->base->lcla_pool.base + - d40c->phy_chan->num * 1024 + - 8 * curr_lcla * 2; - d40_log_lli_lcla_write(lcla, &d40d->lli_log.dst[d40d->lli_current], &d40d->lli_log.src[d40d->lli_current], next_lcla); - (void) dma_map_single(d40c->base->dev, lcla, - 2 * sizeof(struct d40_log_lli), - DMA_TO_DEVICE); + dma_sync_single_range_for_device(d40c->base->dev, + pool->dma_addr, lcla_offset, + 2 * sizeof(struct d40_log_lli), + DMA_TO_DEVICE); curr_lcla = next_lcla; @@ -2771,6 +2772,7 @@ static void __init d40_hw_init(struct d40_base *base) static int __init d40_lcla_allocate(struct d40_base *base) { + struct d40_lcla_pool *pool = &base->lcla_pool; unsigned long *page_list; int i, j; int ret = 0; @@ -2835,6 +2837,15 @@ static int __init d40_lcla_allocate(struct d40_base *base) LCLA_ALIGNMENT); } + pool->dma_addr = dma_map_single(base->dev, pool->base, + SZ_1K * base->num_phy_chans, + DMA_TO_DEVICE); + if (dma_mapping_error(base->dev, pool->dma_addr)) { + pool->dma_addr = 0; + ret = -ENOMEM; + goto failure; + } + writel(virt_to_phys(base->lcla_pool.base), base->virtbase + D40_DREG_LCLA); failure: @@ -2929,6 +2940,12 @@ failure: kmem_cache_destroy(base->desc_slab); if (base->virtbase) iounmap(base->virtbase); + + if (base->lcla_pool.dma_addr) + dma_unmap_single(base->dev, base->lcla_pool.dma_addr, + SZ_1K * base->num_phy_chans, + DMA_TO_DEVICE); + if (!base->lcla_pool.base_unaligned && base->lcla_pool.base) free_pages((unsigned long)base->lcla_pool.base, base->lcla_pool.pages); -- GitLab From b00f938c8cf5ba8e7a692519548a256aa3ea1203 Mon Sep 17 00:00:00 2001 From: Rabin Vincent Date: Tue, 25 Jan 2011 11:18:15 +0100 Subject: [PATCH 0036/2822] dma40: fix DMA API usage for LLIs Map and unmap the LLIs and use dma_sync_single_for_device() appropriately instead of mapping and never unmapping them. Acked-by: Per Forlin Acked-by: Jonas Aaberg Signed-off-by: Rabin Vincent Signed-off-by: Linus Walleij Signed-off-by: Dan Williams --- drivers/dma/ste_dma40.c | 58 +++++++++++++++++++++++++++++------------ 1 file changed, 41 insertions(+), 17 deletions(-) diff --git a/drivers/dma/ste_dma40.c b/drivers/dma/ste_dma40.c index f08e5c49c5d2b..b5856864d48dc 100644 --- a/drivers/dma/ste_dma40.c +++ b/drivers/dma/ste_dma40.c @@ -68,6 +68,7 @@ enum d40_command { * @base: Pointer to memory area when the pre_alloc_lli's are not large * enough, IE bigger than the most common case, 1 dst and 1 src. NULL if * pre_alloc_lli is used. + * @dma_addr: DMA address, if mapped * @size: The size in bytes of the memory at base or the size of pre_alloc_lli. * @pre_alloc_lli: Pre allocated area for the most common case of transfers, * one buffer to one buffer. @@ -75,6 +76,7 @@ enum d40_command { struct d40_lli_pool { void *base; int size; + dma_addr_t dma_addr; /* Space for dst and src, plus an extra for padding */ u8 pre_alloc_lli[3 * sizeof(struct d40_phy_lli)]; }; @@ -329,7 +331,7 @@ static void __iomem *chan_base(struct d40_chan *chan) #define chan_err(d40c, format, arg...) \ d40_err(chan2dev(d40c), format, ## arg) -static int d40_pool_lli_alloc(struct d40_desc *d40d, +static int d40_pool_lli_alloc(struct d40_chan *d40c, struct d40_desc *d40d, int lli_len, bool is_log) { u32 align; @@ -358,17 +360,36 @@ static int d40_pool_lli_alloc(struct d40_desc *d40d, d40d->lli_log.src = PTR_ALIGN((struct d40_log_lli *) base, align); d40d->lli_log.dst = d40d->lli_log.src + lli_len; + + d40d->lli_pool.dma_addr = 0; } else { d40d->lli_phy.src = PTR_ALIGN((struct d40_phy_lli *)base, align); d40d->lli_phy.dst = d40d->lli_phy.src + lli_len; + + d40d->lli_pool.dma_addr = dma_map_single(d40c->base->dev, + d40d->lli_phy.src, + d40d->lli_pool.size, + DMA_TO_DEVICE); + + if (dma_mapping_error(d40c->base->dev, + d40d->lli_pool.dma_addr)) { + kfree(d40d->lli_pool.base); + d40d->lli_pool.base = NULL; + d40d->lli_pool.dma_addr = 0; + return -ENOMEM; + } } return 0; } -static void d40_pool_lli_free(struct d40_desc *d40d) +static void d40_pool_lli_free(struct d40_chan *d40c, struct d40_desc *d40d) { + if (d40d->lli_pool.dma_addr) + dma_unmap_single(d40c->base->dev, d40d->lli_pool.dma_addr, + d40d->lli_pool.size, DMA_TO_DEVICE); + kfree(d40d->lli_pool.base); d40d->lli_pool.base = NULL; d40d->lli_pool.size = 0; @@ -454,7 +475,7 @@ static struct d40_desc *d40_desc_get(struct d40_chan *d40c) list_for_each_entry_safe(d, _d, &d40c->client, node) if (async_tx_test_ack(&d->txd)) { - d40_pool_lli_free(d); + d40_pool_lli_free(d40c, d); d40_desc_remove(d); desc = d; memset(desc, 0, sizeof(*desc)); @@ -474,6 +495,7 @@ static struct d40_desc *d40_desc_get(struct d40_chan *d40c) static void d40_desc_free(struct d40_chan *d40c, struct d40_desc *d40d) { + d40_pool_lli_free(d40c, d40d); d40_lcla_free_all(d40c, d40d); kmem_cache_free(d40c->base->desc_slab, d40d); } @@ -1063,7 +1085,7 @@ static void dma_tasklet(unsigned long data) callback_param = d40d->txd.callback_param; if (async_tx_test_ack(&d40d->txd)) { - d40_pool_lli_free(d40d); + d40_pool_lli_free(d40c, d40d); d40_desc_remove(d40d); d40_desc_free(d40c, d40d); } else { @@ -1459,7 +1481,7 @@ static int d40_free_dma(struct d40_chan *d40c) /* Release client owned descriptors */ if (!list_empty(&d40c->client)) list_for_each_entry_safe(d, _d, &d40c->client, node) { - d40_pool_lli_free(d); + d40_pool_lli_free(d40c, d); d40_desc_remove(d); d40_desc_free(d40c, d); } @@ -1633,7 +1655,7 @@ struct dma_async_tx_descriptor *stedma40_memcpy_sg(struct dma_chan *chan, if (chan_is_logical(d40c)) { - if (d40_pool_lli_alloc(d40d, d40d->lli_len, true) < 0) { + if (d40_pool_lli_alloc(d40c, d40d, d40d->lli_len, true) < 0) { chan_err(d40c, "Out of memory\n"); goto err; } @@ -1652,7 +1674,7 @@ struct dma_async_tx_descriptor *stedma40_memcpy_sg(struct dma_chan *chan, d40c->dma_cfg.dst_info.data_width, d40c->dma_cfg.src_info.data_width); } else { - if (d40_pool_lli_alloc(d40d, d40d->lli_len, false) < 0) { + if (d40_pool_lli_alloc(d40c, d40d, d40d->lli_len, false) < 0) { chan_err(d40c, "Out of memory\n"); goto err; } @@ -1683,8 +1705,9 @@ struct dma_async_tx_descriptor *stedma40_memcpy_sg(struct dma_chan *chan, if (res < 0) goto err; - (void) dma_map_single(d40c->base->dev, d40d->lli_phy.src, - d40d->lli_pool.size, DMA_TO_DEVICE); + dma_sync_single_for_device(d40c->base->dev, + d40d->lli_pool.dma_addr, + d40d->lli_pool.size, DMA_TO_DEVICE); } dma_async_tx_descriptor_init(&d40d->txd, chan); @@ -1876,7 +1899,7 @@ static struct dma_async_tx_descriptor *d40_prep_memcpy(struct dma_chan *chan, if (chan_is_logical(d40c)) { - if (d40_pool_lli_alloc(d40d, d40d->lli_len, true) < 0) { + if (d40_pool_lli_alloc(d40c,d40d, d40d->lli_len, true) < 0) { chan_err(d40c, "Out of memory\n"); goto err; } @@ -1902,7 +1925,7 @@ static struct dma_async_tx_descriptor *d40_prep_memcpy(struct dma_chan *chan, } else { - if (d40_pool_lli_alloc(d40d, d40d->lli_len, false) < 0) { + if (d40_pool_lli_alloc(d40c, d40d, d40d->lli_len, false) < 0) { chan_err(d40c, "Out of memory\n"); goto err; } @@ -1931,8 +1954,9 @@ static struct dma_async_tx_descriptor *d40_prep_memcpy(struct dma_chan *chan, false) == NULL) goto err; - (void) dma_map_single(d40c->base->dev, d40d->lli_phy.src, - d40d->lli_pool.size, DMA_TO_DEVICE); + dma_sync_single_for_device(d40c->base->dev, + d40d->lli_pool.dma_addr, + d40d->lli_pool.size, DMA_TO_DEVICE); } spin_unlock_irqrestore(&d40c->lock, flags); @@ -1975,7 +1999,7 @@ static int d40_prep_slave_sg_log(struct d40_desc *d40d, return -EINVAL; } - if (d40_pool_lli_alloc(d40d, d40d->lli_len, true) < 0) { + if (d40_pool_lli_alloc(d40c, d40d, d40d->lli_len, true) < 0) { chan_err(d40c, "Out of memory\n"); return -ENOMEM; } @@ -2029,7 +2053,7 @@ static int d40_prep_slave_sg_phy(struct d40_desc *d40d, return -EINVAL; } - if (d40_pool_lli_alloc(d40d, d40d->lli_len, false) < 0) { + if (d40_pool_lli_alloc(d40c, d40d, d40d->lli_len, false) < 0) { chan_err(d40c, "Out of memory\n"); return -ENOMEM; } @@ -2075,8 +2099,8 @@ static int d40_prep_slave_sg_phy(struct d40_desc *d40d, if (res < 0) return res; - (void) dma_map_single(d40c->base->dev, d40d->lli_phy.src, - d40d->lli_pool.size, DMA_TO_DEVICE); + dma_sync_single_for_device(d40c->base->dev, d40d->lli_pool.dma_addr, + d40d->lli_pool.size, DMA_TO_DEVICE); return 0; } -- GitLab From d924abad7fa9a78d70b20552bf27fe4f7a19a2fb Mon Sep 17 00:00:00 2001 From: Rabin Vincent Date: Tue, 25 Jan 2011 11:18:16 +0100 Subject: [PATCH 0037/2822] dma40: remove unnecessary casts Acked-by: Per Forlin Acked-by: Jonas Aaberg Signed-off-by: Rabin Vincent Signed-off-by: Linus Walleij Signed-off-by: Dan Williams --- drivers/dma/ste_dma40.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/dma/ste_dma40.c b/drivers/dma/ste_dma40.c index b5856864d48dc..bd72269dac084 100644 --- a/drivers/dma/ste_dma40.c +++ b/drivers/dma/ste_dma40.c @@ -357,14 +357,12 @@ static int d40_pool_lli_alloc(struct d40_chan *d40c, struct d40_desc *d40d, } if (is_log) { - d40d->lli_log.src = PTR_ALIGN((struct d40_log_lli *) base, - align); + d40d->lli_log.src = PTR_ALIGN(base, align); d40d->lli_log.dst = d40d->lli_log.src + lli_len; d40d->lli_pool.dma_addr = 0; } else { - d40d->lli_phy.src = PTR_ALIGN((struct d40_phy_lli *)base, - align); + d40d->lli_phy.src = PTR_ALIGN(base, align); d40d->lli_phy.dst = d40d->lli_phy.src + lli_len; d40d->lli_pool.dma_addr = dma_map_single(d40c->base->dev, -- GitLab From 95944c6ef5b5214508273992416adb836b63c73f Mon Sep 17 00:00:00 2001 From: Rabin Vincent Date: Tue, 25 Jan 2011 11:18:17 +0100 Subject: [PATCH 0038/2822] dma40: implement prep_memcpy as a wrapper around memcpy_sg To simplify the code. Acked-by: Per Forlin Acked-by: Jonas Aaberg Signed-off-by: Rabin Vincent Signed-off-by: Linus Walleij Signed-off-by: Dan Williams --- drivers/dma/ste_dma40.c | 107 ++++--------------------------------- drivers/dma/ste_dma40_ll.c | 2 +- drivers/dma/ste_dma40_ll.h | 11 ---- 3 files changed, 10 insertions(+), 110 deletions(-) diff --git a/drivers/dma/ste_dma40.c b/drivers/dma/ste_dma40.c index bd72269dac084..0a20179349b06 100644 --- a/drivers/dma/ste_dma40.c +++ b/drivers/dma/ste_dma40.c @@ -1863,108 +1863,19 @@ static struct dma_async_tx_descriptor *d40_prep_memcpy(struct dma_chan *chan, size_t size, unsigned long dma_flags) { - struct d40_desc *d40d; - struct d40_chan *d40c = container_of(chan, struct d40_chan, - chan); - unsigned long flags; - - if (d40c->phy_chan == NULL) { - chan_err(d40c, "Channel is not allocated.\n"); - return ERR_PTR(-EINVAL); - } - - spin_lock_irqsave(&d40c->lock, flags); - d40d = d40_desc_get(d40c); - - if (d40d == NULL) { - chan_err(d40c, "Descriptor is NULL\n"); - goto err; - } - - d40d->txd.flags = dma_flags; - d40d->lli_len = d40_size_2_dmalen(size, - d40c->dma_cfg.src_info.data_width, - d40c->dma_cfg.dst_info.data_width); - if (d40d->lli_len < 0) { - chan_err(d40c, "Unaligned size\n"); - goto err; - } - - - dma_async_tx_descriptor_init(&d40d->txd, chan); - - d40d->txd.tx_submit = d40_tx_submit; - - if (chan_is_logical(d40c)) { - - if (d40_pool_lli_alloc(d40c,d40d, d40d->lli_len, true) < 0) { - chan_err(d40c, "Out of memory\n"); - goto err; - } - d40d->lli_current = 0; - - if (d40_log_buf_to_lli(d40d->lli_log.src, - src, - size, - d40c->log_def.lcsp1, - d40c->dma_cfg.src_info.data_width, - d40c->dma_cfg.dst_info.data_width, - true) == NULL) - goto err; - - if (d40_log_buf_to_lli(d40d->lli_log.dst, - dst, - size, - d40c->log_def.lcsp3, - d40c->dma_cfg.dst_info.data_width, - d40c->dma_cfg.src_info.data_width, - true) == NULL) - goto err; - - } else { - - if (d40_pool_lli_alloc(d40c, d40d, d40d->lli_len, false) < 0) { - chan_err(d40c, "Out of memory\n"); - goto err; - } - - if (d40_phy_buf_to_lli(d40d->lli_phy.src, - src, - size, - d40c->dma_cfg.src_info.psize, - 0, - d40c->src_def_cfg, - true, - d40c->dma_cfg.src_info.data_width, - d40c->dma_cfg.dst_info.data_width, - false) == NULL) - goto err; + struct scatterlist dst_sg; + struct scatterlist src_sg; - if (d40_phy_buf_to_lli(d40d->lli_phy.dst, - dst, - size, - d40c->dma_cfg.dst_info.psize, - 0, - d40c->dst_def_cfg, - true, - d40c->dma_cfg.dst_info.data_width, - d40c->dma_cfg.src_info.data_width, - false) == NULL) - goto err; + sg_init_table(&dst_sg, 1); + sg_init_table(&src_sg, 1); - dma_sync_single_for_device(d40c->base->dev, - d40d->lli_pool.dma_addr, - d40d->lli_pool.size, DMA_TO_DEVICE); - } + sg_dma_address(&dst_sg) = dst; + sg_dma_address(&src_sg) = src; - spin_unlock_irqrestore(&d40c->lock, flags); - return &d40d->txd; + sg_dma_len(&dst_sg) = size; + sg_dma_len(&src_sg) = size; -err: - if (d40d) - d40_desc_free(d40c, d40d); - spin_unlock_irqrestore(&d40c->lock, flags); - return NULL; + return stedma40_memcpy_sg(chan, &dst_sg, &src_sg, 1, dma_flags); } static struct dma_async_tx_descriptor * diff --git a/drivers/dma/ste_dma40_ll.c b/drivers/dma/ste_dma40_ll.c index 6f03f580c4926..552c5972c75ed 100644 --- a/drivers/dma/ste_dma40_ll.c +++ b/drivers/dma/ste_dma40_ll.c @@ -198,7 +198,7 @@ static int d40_seg_size(int size, int data_width1, int data_width2) return seg_max; } -struct d40_phy_lli *d40_phy_buf_to_lli(struct d40_phy_lli *lli, +static struct d40_phy_lli *d40_phy_buf_to_lli(struct d40_phy_lli *lli, dma_addr_t addr, u32 size, int psize, diff --git a/drivers/dma/ste_dma40_ll.h b/drivers/dma/ste_dma40_ll.h index e93f394187a37..a5d71714ebf70 100644 --- a/drivers/dma/ste_dma40_ll.h +++ b/drivers/dma/ste_dma40_ll.h @@ -312,17 +312,6 @@ int d40_phy_sg_to_lli(struct scatterlist *sg, u32 data_width2, int psize); -struct d40_phy_lli *d40_phy_buf_to_lli(struct d40_phy_lli *lli, - dma_addr_t data, - u32 data_size, - int psize, - dma_addr_t next_lli, - u32 reg_cfg, - bool term_int, - u32 data_width1, - u32 data_width2, - bool is_device); - void d40_phy_lli_write(void __iomem *virtbase, u32 phy_chan_num, struct d40_phy_lli *lli_dst, -- GitLab From 5f81158f90db4bc8a79e91736aa3afce8e590e46 Mon Sep 17 00:00:00 2001 From: Rabin Vincent Date: Tue, 25 Jan 2011 11:18:18 +0100 Subject: [PATCH 0039/2822] dma40: combine desc init functions The desc init code can be shared between the mem and slave prep routines. Acked-by: Per Forlin Acked-by: Jonas Aaberg Signed-off-by: Rabin Vincent Signed-off-by: Linus Walleij Signed-off-by: Dan Williams --- drivers/dma/ste_dma40.c | 76 +++++++++++++++++------------------------ 1 file changed, 32 insertions(+), 44 deletions(-) diff --git a/drivers/dma/ste_dma40.c b/drivers/dma/ste_dma40.c index 0a20179349b06..5259a98324359 100644 --- a/drivers/dma/ste_dma40.c +++ b/drivers/dma/ste_dma40.c @@ -1617,6 +1617,35 @@ static u32 stedma40_residue(struct dma_chan *chan) return bytes_left; } +static struct d40_desc * +d40_prep_desc(struct d40_chan *chan, struct scatterlist *sg, + unsigned int sg_len, unsigned long dma_flags) +{ + struct stedma40_chan_cfg *cfg = &chan->dma_cfg; + struct d40_desc *desc; + + desc = d40_desc_get(chan); + if (!desc) + return NULL; + + desc->lli_len = d40_sg_2_dmalen(sg, sg_len, cfg->src_info.data_width, + cfg->dst_info.data_width); + if (desc->lli_len < 0) { + chan_err(chan, "Unaligned size\n"); + d40_desc_free(chan, desc); + + return NULL; + } + + desc->lli_current = 0; + desc->txd.flags = dma_flags; + desc->txd.tx_submit = d40_tx_submit; + + dma_async_tx_descriptor_init(&desc->txd, &chan->chan); + + return desc; +} + struct dma_async_tx_descriptor *stedma40_memcpy_sg(struct dma_chan *chan, struct scatterlist *sgl_dst, struct scatterlist *sgl_src, @@ -1635,22 +1664,11 @@ struct dma_async_tx_descriptor *stedma40_memcpy_sg(struct dma_chan *chan, } spin_lock_irqsave(&d40c->lock, flags); - d40d = d40_desc_get(d40c); - if (d40d == NULL) + d40d = d40_prep_desc(d40c, sgl_dst, sgl_len, dma_flags); + if (!d40d) goto err; - d40d->lli_len = d40_sg_2_dmalen(sgl_dst, sgl_len, - d40c->dma_cfg.src_info.data_width, - d40c->dma_cfg.dst_info.data_width); - if (d40d->lli_len < 0) { - chan_err(d40c, "Unaligned size\n"); - goto err; - } - - d40d->lli_current = 0; - d40d->txd.flags = dma_flags; - if (chan_is_logical(d40c)) { if (d40_pool_lli_alloc(d40c, d40d, d40d->lli_len, true) < 0) { @@ -1708,10 +1726,6 @@ struct dma_async_tx_descriptor *stedma40_memcpy_sg(struct dma_chan *chan, d40d->lli_pool.size, DMA_TO_DEVICE); } - dma_async_tx_descriptor_init(&d40d->txd, chan); - - d40d->txd.tx_submit = d40_tx_submit; - spin_unlock_irqrestore(&d40c->lock, flags); return &d40d->txd; @@ -1900,21 +1914,11 @@ static int d40_prep_slave_sg_log(struct d40_desc *d40d, dma_addr_t dev_addr = 0; int total_size; - d40d->lli_len = d40_sg_2_dmalen(sgl, sg_len, - d40c->dma_cfg.src_info.data_width, - d40c->dma_cfg.dst_info.data_width); - if (d40d->lli_len < 0) { - chan_err(d40c, "Unaligned size\n"); - return -EINVAL; - } - if (d40_pool_lli_alloc(d40c, d40d, d40d->lli_len, true) < 0) { chan_err(d40c, "Out of memory\n"); return -ENOMEM; } - d40d->lli_current = 0; - if (direction == DMA_FROM_DEVICE) if (d40c->runtime_addr) dev_addr = d40c->runtime_addr; @@ -1954,21 +1958,11 @@ static int d40_prep_slave_sg_phy(struct d40_desc *d40d, dma_addr_t dst_dev_addr; int res; - d40d->lli_len = d40_sg_2_dmalen(sgl, sgl_len, - d40c->dma_cfg.src_info.data_width, - d40c->dma_cfg.dst_info.data_width); - if (d40d->lli_len < 0) { - chan_err(d40c, "Unaligned size\n"); - return -EINVAL; - } - if (d40_pool_lli_alloc(d40c, d40d, d40d->lli_len, false) < 0) { chan_err(d40c, "Out of memory\n"); return -ENOMEM; } - d40d->lli_current = 0; - if (direction == DMA_FROM_DEVICE) { dst_dev_addr = 0; if (d40c->runtime_addr) @@ -2031,8 +2025,8 @@ static struct dma_async_tx_descriptor *d40_prep_slave_sg(struct dma_chan *chan, } spin_lock_irqsave(&d40c->lock, flags); - d40d = d40_desc_get(d40c); + d40d = d40_prep_desc(d40c, sgl, sg_len, dma_flags); if (d40d == NULL) goto err; @@ -2048,12 +2042,6 @@ static struct dma_async_tx_descriptor *d40_prep_slave_sg(struct dma_chan *chan, goto err; } - d40d->txd.flags = dma_flags; - - dma_async_tx_descriptor_init(&d40d->txd, chan); - - d40d->txd.tx_submit = d40_tx_submit; - spin_unlock_irqrestore(&d40c->lock, flags); return &d40d->txd; -- GitLab From dbd887880320b6a56811bb38ff4ad888728c3a91 Mon Sep 17 00:00:00 2001 From: Rabin Vincent Date: Tue, 25 Jan 2011 11:18:19 +0100 Subject: [PATCH 0040/2822] dma40: combine duplicated d40_pool_lli_alloc() calls Acked-by: Per Forlin Acked-by: Jonas Aaberg Signed-off-by: Rabin Vincent Signed-off-by: Linus Walleij Signed-off-by: Dan Williams --- drivers/dma/ste_dma40.c | 38 ++++++++++++++------------------------ 1 file changed, 14 insertions(+), 24 deletions(-) diff --git a/drivers/dma/ste_dma40.c b/drivers/dma/ste_dma40.c index 5259a98324359..495f9eb0a4b6e 100644 --- a/drivers/dma/ste_dma40.c +++ b/drivers/dma/ste_dma40.c @@ -332,8 +332,9 @@ static void __iomem *chan_base(struct d40_chan *chan) d40_err(chan2dev(d40c), format, ## arg) static int d40_pool_lli_alloc(struct d40_chan *d40c, struct d40_desc *d40d, - int lli_len, bool is_log) + int lli_len) { + bool is_log = chan_is_logical(d40c); u32 align; void *base; @@ -1623,6 +1624,7 @@ d40_prep_desc(struct d40_chan *chan, struct scatterlist *sg, { struct stedma40_chan_cfg *cfg = &chan->dma_cfg; struct d40_desc *desc; + int ret; desc = d40_desc_get(chan); if (!desc) @@ -1632,11 +1634,16 @@ d40_prep_desc(struct d40_chan *chan, struct scatterlist *sg, cfg->dst_info.data_width); if (desc->lli_len < 0) { chan_err(chan, "Unaligned size\n"); - d40_desc_free(chan, desc); + goto err; + } - return NULL; + ret = d40_pool_lli_alloc(chan, desc, desc->lli_len); + if (ret < 0) { + chan_err(chan, "Could not allocate lli\n"); + goto err; } + desc->lli_current = 0; desc->txd.flags = dma_flags; desc->txd.tx_submit = d40_tx_submit; @@ -1644,6 +1651,10 @@ d40_prep_desc(struct d40_chan *chan, struct scatterlist *sg, dma_async_tx_descriptor_init(&desc->txd, &chan->chan); return desc; + +err: + d40_desc_free(chan, desc); + return NULL; } struct dma_async_tx_descriptor *stedma40_memcpy_sg(struct dma_chan *chan, @@ -1670,12 +1681,6 @@ struct dma_async_tx_descriptor *stedma40_memcpy_sg(struct dma_chan *chan, goto err; if (chan_is_logical(d40c)) { - - if (d40_pool_lli_alloc(d40c, d40d, d40d->lli_len, true) < 0) { - chan_err(d40c, "Out of memory\n"); - goto err; - } - (void) d40_log_sg_to_lli(sgl_src, sgl_len, d40d->lli_log.src, @@ -1690,11 +1695,6 @@ struct dma_async_tx_descriptor *stedma40_memcpy_sg(struct dma_chan *chan, d40c->dma_cfg.dst_info.data_width, d40c->dma_cfg.src_info.data_width); } else { - if (d40_pool_lli_alloc(d40c, d40d, d40d->lli_len, false) < 0) { - chan_err(d40c, "Out of memory\n"); - goto err; - } - res = d40_phy_sg_to_lli(sgl_src, sgl_len, 0, @@ -1914,11 +1914,6 @@ static int d40_prep_slave_sg_log(struct d40_desc *d40d, dma_addr_t dev_addr = 0; int total_size; - if (d40_pool_lli_alloc(d40c, d40d, d40d->lli_len, true) < 0) { - chan_err(d40c, "Out of memory\n"); - return -ENOMEM; - } - if (direction == DMA_FROM_DEVICE) if (d40c->runtime_addr) dev_addr = d40c->runtime_addr; @@ -1958,11 +1953,6 @@ static int d40_prep_slave_sg_phy(struct d40_desc *d40d, dma_addr_t dst_dev_addr; int res; - if (d40_pool_lli_alloc(d40c, d40d, d40d->lli_len, false) < 0) { - chan_err(d40c, "Out of memory\n"); - return -ENOMEM; - } - if (direction == DMA_FROM_DEVICE) { dst_dev_addr = 0; if (d40c->runtime_addr) -- GitLab From 00ac0341486ffe212f45ff1fe0780d12a36fffde Mon Sep 17 00:00:00 2001 From: Rabin Vincent Date: Tue, 25 Jan 2011 11:18:20 +0100 Subject: [PATCH 0041/2822] dma40: remove duplicated dev addr code Acked-by: Per Forlin Acked-by: Jonas Aaberg Signed-off-by: Rabin Vincent Signed-off-by: Linus Walleij Signed-off-by: Dan Williams --- drivers/dma/ste_dma40.c | 66 +++++++++++++++++++---------------------- 1 file changed, 30 insertions(+), 36 deletions(-) diff --git a/drivers/dma/ste_dma40.c b/drivers/dma/ste_dma40.c index 495f9eb0a4b6e..65b5aad1fc4c6 100644 --- a/drivers/dma/ste_dma40.c +++ b/drivers/dma/ste_dma40.c @@ -1909,25 +1909,10 @@ static int d40_prep_slave_sg_log(struct d40_desc *d40d, struct scatterlist *sgl, unsigned int sg_len, enum dma_data_direction direction, - unsigned long dma_flags) + dma_addr_t dev_addr) { - dma_addr_t dev_addr = 0; int total_size; - if (direction == DMA_FROM_DEVICE) - if (d40c->runtime_addr) - dev_addr = d40c->runtime_addr; - else - dev_addr = d40c->base->plat_data->dev_rx[d40c->dma_cfg.src_dev_type]; - else if (direction == DMA_TO_DEVICE) - if (d40c->runtime_addr) - dev_addr = d40c->runtime_addr; - else - dev_addr = d40c->base->plat_data->dev_tx[d40c->dma_cfg.dst_dev_type]; - - else - return -EINVAL; - total_size = d40_log_sg_to_dev(sgl, sg_len, &d40d->lli_log, &d40c->log_def, @@ -1947,27 +1932,12 @@ static int d40_prep_slave_sg_phy(struct d40_desc *d40d, struct scatterlist *sgl, unsigned int sgl_len, enum dma_data_direction direction, - unsigned long dma_flags) + dma_addr_t dev_addr) { - dma_addr_t src_dev_addr; - dma_addr_t dst_dev_addr; + dma_addr_t src_dev_addr = direction == DMA_FROM_DEVICE ? dev_addr : 0; + dma_addr_t dst_dev_addr = direction == DMA_TO_DEVICE ? dev_addr : 0; int res; - if (direction == DMA_FROM_DEVICE) { - dst_dev_addr = 0; - if (d40c->runtime_addr) - src_dev_addr = d40c->runtime_addr; - else - src_dev_addr = d40c->base->plat_data->dev_rx[d40c->dma_cfg.src_dev_type]; - } else if (direction == DMA_TO_DEVICE) { - if (d40c->runtime_addr) - dst_dev_addr = d40c->runtime_addr; - else - dst_dev_addr = d40c->base->plat_data->dev_tx[d40c->dma_cfg.dst_dev_type]; - src_dev_addr = 0; - } else - return -EINVAL; - res = d40_phy_sg_to_lli(sgl, sgl_len, src_dev_addr, @@ -1997,6 +1967,24 @@ static int d40_prep_slave_sg_phy(struct d40_desc *d40d, return 0; } +static dma_addr_t +d40_get_dev_addr(struct d40_chan *chan, enum dma_data_direction direction) +{ + struct stedma40_platform_data *plat = chan->base->plat_data; + struct stedma40_chan_cfg *cfg = &chan->dma_cfg; + dma_addr_t addr; + + if (chan->runtime_addr) + return chan->runtime_addr; + + if (direction == DMA_FROM_DEVICE) + addr = plat->dev_rx[cfg->src_dev_type]; + else if (direction == DMA_TO_DEVICE) + addr = plat->dev_tx[cfg->dst_dev_type]; + + return addr; +} + static struct dma_async_tx_descriptor *d40_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, unsigned int sg_len, @@ -2006,6 +1994,7 @@ static struct dma_async_tx_descriptor *d40_prep_slave_sg(struct dma_chan *chan, struct d40_desc *d40d; struct d40_chan *d40c = container_of(chan, struct d40_chan, chan); + dma_addr_t dev_addr; unsigned long flags; int err; @@ -2014,18 +2003,23 @@ static struct dma_async_tx_descriptor *d40_prep_slave_sg(struct dma_chan *chan, return ERR_PTR(-EINVAL); } + if (direction != DMA_FROM_DEVICE && direction != DMA_TO_DEVICE) + return NULL; + spin_lock_irqsave(&d40c->lock, flags); d40d = d40_prep_desc(d40c, sgl, sg_len, dma_flags); if (d40d == NULL) goto err; + dev_addr = d40_get_dev_addr(d40c, direction); + if (chan_is_logical(d40c)) err = d40_prep_slave_sg_log(d40d, d40c, sgl, sg_len, - direction, dma_flags); + direction, dev_addr); else err = d40_prep_slave_sg_phy(d40d, d40c, sgl, sg_len, - direction, dma_flags); + direction, dev_addr); if (err) { chan_err(d40c, "Failed to prepare %s slave sg job: %d\n", chan_is_logical(d40c) ? "log" : "phy", err); -- GitLab From 3e3a0763e78b520dac5fde569c42664863336d94 Mon Sep 17 00:00:00 2001 From: Rabin Vincent Date: Tue, 25 Jan 2011 11:18:21 +0100 Subject: [PATCH 0042/2822] dma40: combine mem and slave sg-to-lli functions Acked-by: Per Forlin Acked-by: Jonas Aaberg Signed-off-by: Rabin Vincent Signed-off-by: Linus Walleij Signed-off-by: Dan Williams --- drivers/dma/ste_dma40.c | 194 +++++++++++++++++----------------------- 1 file changed, 84 insertions(+), 110 deletions(-) diff --git a/drivers/dma/ste_dma40.c b/drivers/dma/ste_dma40.c index 65b5aad1fc4c6..8c6abc23db801 100644 --- a/drivers/dma/ste_dma40.c +++ b/drivers/dma/ste_dma40.c @@ -1618,6 +1618,81 @@ static u32 stedma40_residue(struct dma_chan *chan) return bytes_left; } +static int +d40_prep_sg_log(struct d40_chan *chan, struct d40_desc *desc, + struct scatterlist *sg_src, struct scatterlist *sg_dst, + unsigned int sg_len, enum dma_data_direction direction, + dma_addr_t dev_addr) +{ + struct stedma40_chan_cfg *cfg = &chan->dma_cfg; + struct stedma40_half_channel_info *src_info = &cfg->src_info; + struct stedma40_half_channel_info *dst_info = &cfg->dst_info; + + if (direction == DMA_NONE) { + /* memcpy */ + (void) d40_log_sg_to_lli(sg_src, sg_len, + desc->lli_log.src, + chan->log_def.lcsp1, + src_info->data_width, + dst_info->data_width); + + (void) d40_log_sg_to_lli(sg_dst, sg_len, + desc->lli_log.dst, + chan->log_def.lcsp3, + dst_info->data_width, + src_info->data_width); + } else { + unsigned int total_size; + + total_size = d40_log_sg_to_dev(sg_src, sg_len, + &desc->lli_log, + &chan->log_def, + src_info->data_width, + dst_info->data_width, + direction, dev_addr); + if (total_size < 0) + return -EINVAL; + } + + return 0; +} + +static int +d40_prep_sg_phy(struct d40_chan *chan, struct d40_desc *desc, + struct scatterlist *sg_src, struct scatterlist *sg_dst, + unsigned int sg_len, enum dma_data_direction direction, + dma_addr_t dev_addr) +{ + dma_addr_t src_dev_addr = direction == DMA_FROM_DEVICE ? dev_addr : 0; + dma_addr_t dst_dev_addr = direction == DMA_TO_DEVICE ? dev_addr : 0; + struct stedma40_chan_cfg *cfg = &chan->dma_cfg; + struct stedma40_half_channel_info *src_info = &cfg->src_info; + struct stedma40_half_channel_info *dst_info = &cfg->dst_info; + int ret; + + ret = d40_phy_sg_to_lli(sg_src, sg_len, src_dev_addr, + desc->lli_phy.src, + virt_to_phys(desc->lli_phy.src), + chan->src_def_cfg, + src_info->data_width, + dst_info->data_width, + src_info->psize); + + ret = d40_phy_sg_to_lli(sg_dst, sg_len, dst_dev_addr, + desc->lli_phy.dst, + virt_to_phys(desc->lli_phy.dst), + chan->dst_def_cfg, + dst_info->data_width, + src_info->data_width, + dst_info->psize); + + dma_sync_single_for_device(chan->base->dev, desc->lli_pool.dma_addr, + desc->lli_pool.size, DMA_TO_DEVICE); + + return ret < 0 ? ret : 0; +} + + static struct d40_desc * d40_prep_desc(struct d40_chan *chan, struct scatterlist *sg, unsigned int sg_len, unsigned long dma_flags) @@ -1663,7 +1738,6 @@ struct dma_async_tx_descriptor *stedma40_memcpy_sg(struct dma_chan *chan, unsigned int sgl_len, unsigned long dma_flags) { - int res; struct d40_desc *d40d; struct d40_chan *d40c = container_of(chan, struct d40_chan, chan); @@ -1681,49 +1755,11 @@ struct dma_async_tx_descriptor *stedma40_memcpy_sg(struct dma_chan *chan, goto err; if (chan_is_logical(d40c)) { - (void) d40_log_sg_to_lli(sgl_src, - sgl_len, - d40d->lli_log.src, - d40c->log_def.lcsp1, - d40c->dma_cfg.src_info.data_width, - d40c->dma_cfg.dst_info.data_width); - - (void) d40_log_sg_to_lli(sgl_dst, - sgl_len, - d40d->lli_log.dst, - d40c->log_def.lcsp3, - d40c->dma_cfg.dst_info.data_width, - d40c->dma_cfg.src_info.data_width); + d40_prep_sg_log(d40c, d40d, sgl_src, sgl_dst, + sgl_len, DMA_NONE, 0); } else { - res = d40_phy_sg_to_lli(sgl_src, - sgl_len, - 0, - d40d->lli_phy.src, - virt_to_phys(d40d->lli_phy.src), - d40c->src_def_cfg, - d40c->dma_cfg.src_info.data_width, - d40c->dma_cfg.dst_info.data_width, - d40c->dma_cfg.src_info.psize); - - if (res < 0) - goto err; - - res = d40_phy_sg_to_lli(sgl_dst, - sgl_len, - 0, - d40d->lli_phy.dst, - virt_to_phys(d40d->lli_phy.dst), - d40c->dst_def_cfg, - d40c->dma_cfg.dst_info.data_width, - d40c->dma_cfg.src_info.data_width, - d40c->dma_cfg.dst_info.psize); - - if (res < 0) - goto err; - - dma_sync_single_for_device(d40c->base->dev, - d40d->lli_pool.dma_addr, - d40d->lli_pool.size, DMA_TO_DEVICE); + d40_prep_sg_phy(d40c, d40d, sgl_src, sgl_dst, + sgl_len, DMA_NONE, 0); } spin_unlock_irqrestore(&d40c->lock, flags); @@ -1904,69 +1940,6 @@ d40_prep_sg(struct dma_chan *chan, return stedma40_memcpy_sg(chan, dst_sg, src_sg, dst_nents, dma_flags); } -static int d40_prep_slave_sg_log(struct d40_desc *d40d, - struct d40_chan *d40c, - struct scatterlist *sgl, - unsigned int sg_len, - enum dma_data_direction direction, - dma_addr_t dev_addr) -{ - int total_size; - - total_size = d40_log_sg_to_dev(sgl, sg_len, - &d40d->lli_log, - &d40c->log_def, - d40c->dma_cfg.src_info.data_width, - d40c->dma_cfg.dst_info.data_width, - direction, - dev_addr); - - if (total_size < 0) - return -EINVAL; - - return 0; -} - -static int d40_prep_slave_sg_phy(struct d40_desc *d40d, - struct d40_chan *d40c, - struct scatterlist *sgl, - unsigned int sgl_len, - enum dma_data_direction direction, - dma_addr_t dev_addr) -{ - dma_addr_t src_dev_addr = direction == DMA_FROM_DEVICE ? dev_addr : 0; - dma_addr_t dst_dev_addr = direction == DMA_TO_DEVICE ? dev_addr : 0; - int res; - - res = d40_phy_sg_to_lli(sgl, - sgl_len, - src_dev_addr, - d40d->lli_phy.src, - virt_to_phys(d40d->lli_phy.src), - d40c->src_def_cfg, - d40c->dma_cfg.src_info.data_width, - d40c->dma_cfg.dst_info.data_width, - d40c->dma_cfg.src_info.psize); - if (res < 0) - return res; - - res = d40_phy_sg_to_lli(sgl, - sgl_len, - dst_dev_addr, - d40d->lli_phy.dst, - virt_to_phys(d40d->lli_phy.dst), - d40c->dst_def_cfg, - d40c->dma_cfg.dst_info.data_width, - d40c->dma_cfg.src_info.data_width, - d40c->dma_cfg.dst_info.psize); - if (res < 0) - return res; - - dma_sync_single_for_device(d40c->base->dev, d40d->lli_pool.dma_addr, - d40d->lli_pool.size, DMA_TO_DEVICE); - return 0; -} - static dma_addr_t d40_get_dev_addr(struct d40_chan *chan, enum dma_data_direction direction) { @@ -2015,11 +1988,12 @@ static struct dma_async_tx_descriptor *d40_prep_slave_sg(struct dma_chan *chan, dev_addr = d40_get_dev_addr(d40c, direction); if (chan_is_logical(d40c)) - err = d40_prep_slave_sg_log(d40d, d40c, sgl, sg_len, - direction, dev_addr); + err = d40_prep_sg_log(d40c, d40d, sgl, NULL, + sg_len, direction, dev_addr); else - err = d40_prep_slave_sg_phy(d40d, d40c, sgl, sg_len, - direction, dev_addr); + err = d40_prep_sg_phy(d40c, d40d, sgl, NULL, + sg_len, direction, dev_addr); + if (err) { chan_err(d40c, "Failed to prepare %s slave sg job: %d\n", chan_is_logical(d40c) ? "log" : "phy", err); -- GitLab From 10a946b3a4e1ad665a81981cbe33c3d3903cd7da Mon Sep 17 00:00:00 2001 From: Rabin Vincent Date: Tue, 25 Jan 2011 11:18:22 +0100 Subject: [PATCH 0043/2822] dma40: remove export of stedma40_memcpy_sg The dmaengine framework has the API for this now. Acked-by: Per Forlin Acked-by: Jonas Aaberg Signed-off-by: Rabin Vincent Signed-off-by: Linus Walleij Signed-off-by: Dan Williams --- .../arm/plat-nomadik/include/plat/ste_dma40.h | 19 ------------------- drivers/dma/ste_dma40.c | 2 +- 2 files changed, 1 insertion(+), 20 deletions(-) diff --git a/arch/arm/plat-nomadik/include/plat/ste_dma40.h b/arch/arm/plat-nomadik/include/plat/ste_dma40.h index 8358f857a29ed..c44886062f8ed 100644 --- a/arch/arm/plat-nomadik/include/plat/ste_dma40.h +++ b/arch/arm/plat-nomadik/include/plat/ste_dma40.h @@ -171,25 +171,6 @@ struct stedma40_platform_data { bool stedma40_filter(struct dma_chan *chan, void *data); -/** - * stedma40_memcpy_sg() - extension of the dma framework, memcpy to/from - * scattergatter lists. - * - * @chan: dmaengine handle - * @sgl_dst: Destination scatter list - * @sgl_src: Source scatter list - * @sgl_len: The length of each scatterlist. Both lists must be of equal length - * and each element must match the corresponding element in the other scatter - * list. - * @flags: is actually enum dma_ctrl_flags. See dmaengine.h - */ - -struct dma_async_tx_descriptor *stedma40_memcpy_sg(struct dma_chan *chan, - struct scatterlist *sgl_dst, - struct scatterlist *sgl_src, - unsigned int sgl_len, - unsigned long flags); - /** * stedma40_slave_mem() - Transfers a raw data buffer to or from a slave * (=device) diff --git a/drivers/dma/ste_dma40.c b/drivers/dma/ste_dma40.c index 8c6abc23db801..0f5d61720ab80 100644 --- a/drivers/dma/ste_dma40.c +++ b/drivers/dma/ste_dma40.c @@ -1733,6 +1733,7 @@ err: } struct dma_async_tx_descriptor *stedma40_memcpy_sg(struct dma_chan *chan, +static struct dma_async_tx_descriptor *stedma40_memcpy_sg(struct dma_chan *chan, struct scatterlist *sgl_dst, struct scatterlist *sgl_src, unsigned int sgl_len, @@ -1771,7 +1772,6 @@ err: spin_unlock_irqrestore(&d40c->lock, flags); return NULL; } -EXPORT_SYMBOL(stedma40_memcpy_sg); bool stedma40_filter(struct dma_chan *chan, void *data) { -- GitLab From cade1d30b2e071a687011c2a38c03ed7187ec501 Mon Sep 17 00:00:00 2001 From: Rabin Vincent Date: Tue, 25 Jan 2011 11:18:23 +0100 Subject: [PATCH 0044/2822] dma40: combine mem and slave prep_sg functions Acked-by: Per Forlin Acked-by: Jonas Aaberg Signed-off-by: Rabin Vincent Signed-off-by: Linus Walleij Signed-off-by: Dan Williams --- drivers/dma/ste_dma40.c | 156 ++++++++++++++++------------------------ 1 file changed, 62 insertions(+), 94 deletions(-) diff --git a/drivers/dma/ste_dma40.c b/drivers/dma/ste_dma40.c index 0f5d61720ab80..4e9d6c5a71343 100644 --- a/drivers/dma/ste_dma40.c +++ b/drivers/dma/ste_dma40.c @@ -1732,44 +1732,70 @@ err: return NULL; } -struct dma_async_tx_descriptor *stedma40_memcpy_sg(struct dma_chan *chan, -static struct dma_async_tx_descriptor *stedma40_memcpy_sg(struct dma_chan *chan, - struct scatterlist *sgl_dst, - struct scatterlist *sgl_src, - unsigned int sgl_len, - unsigned long dma_flags) +static dma_addr_t +d40_get_dev_addr(struct d40_chan *chan, enum dma_data_direction direction) { - struct d40_desc *d40d; - struct d40_chan *d40c = container_of(chan, struct d40_chan, - chan); + struct stedma40_platform_data *plat = chan->base->plat_data; + struct stedma40_chan_cfg *cfg = &chan->dma_cfg; + dma_addr_t addr; + + if (chan->runtime_addr) + return chan->runtime_addr; + + if (direction == DMA_FROM_DEVICE) + addr = plat->dev_rx[cfg->src_dev_type]; + else if (direction == DMA_TO_DEVICE) + addr = plat->dev_tx[cfg->dst_dev_type]; + + return addr; +} + +static struct dma_async_tx_descriptor * +d40_prep_sg(struct dma_chan *dchan, struct scatterlist *sg_src, + struct scatterlist *sg_dst, unsigned int sg_len, + enum dma_data_direction direction, unsigned long dma_flags) +{ + struct d40_chan *chan = container_of(dchan, struct d40_chan, chan); + dma_addr_t dev_addr = 0; + struct d40_desc *desc; unsigned long flags; + int ret; - if (d40c->phy_chan == NULL) { - chan_err(d40c, "Unallocated channel.\n"); - return ERR_PTR(-EINVAL); + if (!chan->phy_chan) { + chan_err(chan, "Cannot prepare unallocated channel\n"); + return NULL; } - spin_lock_irqsave(&d40c->lock, flags); + spin_lock_irqsave(&chan->lock, flags); - d40d = d40_prep_desc(d40c, sgl_dst, sgl_len, dma_flags); - if (!d40d) + desc = d40_prep_desc(chan, sg_src, sg_len, dma_flags); + if (desc == NULL) goto err; - if (chan_is_logical(d40c)) { - d40_prep_sg_log(d40c, d40d, sgl_src, sgl_dst, - sgl_len, DMA_NONE, 0); - } else { - d40_prep_sg_phy(d40c, d40d, sgl_src, sgl_dst, - sgl_len, DMA_NONE, 0); + if (direction != DMA_NONE) + dev_addr = d40_get_dev_addr(chan, direction); + + if (chan_is_logical(chan)) + ret = d40_prep_sg_log(chan, desc, sg_src, sg_dst, + sg_len, direction, dev_addr); + else + ret = d40_prep_sg_phy(chan, desc, sg_src, sg_dst, + sg_len, direction, dev_addr); + + if (ret) { + chan_err(chan, "Failed to prepare %s sg job: %d\n", + chan_is_logical(chan) ? "log" : "phy", ret); + goto err; } - spin_unlock_irqrestore(&d40c->lock, flags); + spin_unlock_irqrestore(&chan->lock, flags); + + return &desc->txd; - return &d40d->txd; err: - if (d40d) - d40_desc_free(d40c, d40d); - spin_unlock_irqrestore(&d40c->lock, flags); + if (desc) + d40_desc_free(chan, desc); + spin_unlock_irqrestore(&chan->lock, flags); return NULL; } @@ -1925,37 +1951,19 @@ static struct dma_async_tx_descriptor *d40_prep_memcpy(struct dma_chan *chan, sg_dma_len(&dst_sg) = size; sg_dma_len(&src_sg) = size; - return stedma40_memcpy_sg(chan, &dst_sg, &src_sg, 1, dma_flags); + return d40_prep_sg(chan, &src_sg, &dst_sg, 1, DMA_NONE, dma_flags); } static struct dma_async_tx_descriptor * -d40_prep_sg(struct dma_chan *chan, - struct scatterlist *dst_sg, unsigned int dst_nents, - struct scatterlist *src_sg, unsigned int src_nents, - unsigned long dma_flags) +d40_prep_memcpy_sg(struct dma_chan *chan, + struct scatterlist *dst_sg, unsigned int dst_nents, + struct scatterlist *src_sg, unsigned int src_nents, + unsigned long dma_flags) { if (dst_nents != src_nents) return NULL; - return stedma40_memcpy_sg(chan, dst_sg, src_sg, dst_nents, dma_flags); -} - -static dma_addr_t -d40_get_dev_addr(struct d40_chan *chan, enum dma_data_direction direction) -{ - struct stedma40_platform_data *plat = chan->base->plat_data; - struct stedma40_chan_cfg *cfg = &chan->dma_cfg; - dma_addr_t addr; - - if (chan->runtime_addr) - return chan->runtime_addr; - - if (direction == DMA_FROM_DEVICE) - addr = plat->dev_rx[cfg->src_dev_type]; - else if (direction == DMA_TO_DEVICE) - addr = plat->dev_tx[cfg->dst_dev_type]; - - return addr; + return d40_prep_sg(chan, src_sg, dst_sg, src_nents, DMA_NONE, dma_flags); } static struct dma_async_tx_descriptor *d40_prep_slave_sg(struct dma_chan *chan, @@ -1964,50 +1972,10 @@ static struct dma_async_tx_descriptor *d40_prep_slave_sg(struct dma_chan *chan, enum dma_data_direction direction, unsigned long dma_flags) { - struct d40_desc *d40d; - struct d40_chan *d40c = container_of(chan, struct d40_chan, - chan); - dma_addr_t dev_addr; - unsigned long flags; - int err; - - if (d40c->phy_chan == NULL) { - chan_err(d40c, "Cannot prepare unallocated channel\n"); - return ERR_PTR(-EINVAL); - } - if (direction != DMA_FROM_DEVICE && direction != DMA_TO_DEVICE) return NULL; - spin_lock_irqsave(&d40c->lock, flags); - - d40d = d40_prep_desc(d40c, sgl, sg_len, dma_flags); - if (d40d == NULL) - goto err; - - dev_addr = d40_get_dev_addr(d40c, direction); - - if (chan_is_logical(d40c)) - err = d40_prep_sg_log(d40c, d40d, sgl, NULL, - sg_len, direction, dev_addr); - else - err = d40_prep_sg_phy(d40c, d40d, sgl, NULL, - sg_len, direction, dev_addr); - - if (err) { - chan_err(d40c, "Failed to prepare %s slave sg job: %d\n", - chan_is_logical(d40c) ? "log" : "phy", err); - goto err; - } - - spin_unlock_irqrestore(&d40c->lock, flags); - return &d40d->txd; - -err: - if (d40d) - d40_desc_free(d40c, d40d); - spin_unlock_irqrestore(&d40c->lock, flags); - return NULL; + return d40_prep_sg(chan, sgl, sgl, sg_len, direction, dma_flags); } static enum dma_status d40_tx_status(struct dma_chan *chan, @@ -2267,7 +2235,7 @@ static int __init d40_dmaengine_init(struct d40_base *base, base->dma_slave.device_alloc_chan_resources = d40_alloc_chan_resources; base->dma_slave.device_free_chan_resources = d40_free_chan_resources; base->dma_slave.device_prep_dma_memcpy = d40_prep_memcpy; - base->dma_slave.device_prep_dma_sg = d40_prep_sg; + base->dma_slave.device_prep_dma_sg = d40_prep_memcpy_sg; base->dma_slave.device_prep_slave_sg = d40_prep_slave_sg; base->dma_slave.device_tx_status = d40_tx_status; base->dma_slave.device_issue_pending = d40_issue_pending; @@ -2291,7 +2259,7 @@ static int __init d40_dmaengine_init(struct d40_base *base, base->dma_memcpy.device_alloc_chan_resources = d40_alloc_chan_resources; base->dma_memcpy.device_free_chan_resources = d40_free_chan_resources; base->dma_memcpy.device_prep_dma_memcpy = d40_prep_memcpy; - base->dma_slave.device_prep_dma_sg = d40_prep_sg; + base->dma_slave.device_prep_dma_sg = d40_prep_memcpy_sg; base->dma_memcpy.device_prep_slave_sg = d40_prep_slave_sg; base->dma_memcpy.device_tx_status = d40_tx_status; base->dma_memcpy.device_issue_pending = d40_issue_pending; @@ -2322,7 +2290,7 @@ static int __init d40_dmaengine_init(struct d40_base *base, base->dma_both.device_alloc_chan_resources = d40_alloc_chan_resources; base->dma_both.device_free_chan_resources = d40_free_chan_resources; base->dma_both.device_prep_dma_memcpy = d40_prep_memcpy; - base->dma_slave.device_prep_dma_sg = d40_prep_sg; + base->dma_slave.device_prep_dma_sg = d40_prep_memcpy_sg; base->dma_both.device_prep_slave_sg = d40_prep_slave_sg; base->dma_both.device_tx_status = d40_tx_status; base->dma_both.device_issue_pending = d40_issue_pending; -- GitLab From 1c4b0927feab41346b0be971e0287aaf46eba8e0 Mon Sep 17 00:00:00 2001 From: Rabin Vincent Date: Tue, 25 Jan 2011 11:18:24 +0100 Subject: [PATCH 0045/2822] dma40: move lli_load to main source file These register writes are better placed in the main source file rather than ll.c. Acked-by: Per Forlin Acked-by: Jonas Aaberg Signed-off-by: Rabin Vincent Signed-off-by: Linus Walleij Signed-off-by: Dan Williams --- drivers/dma/ste_dma40.c | 22 ++++++++++++++++++---- drivers/dma/ste_dma40_ll.c | 26 -------------------------- drivers/dma/ste_dma40_ll.h | 5 ----- 3 files changed, 18 insertions(+), 35 deletions(-) diff --git a/drivers/dma/ste_dma40.c b/drivers/dma/ste_dma40.c index 4e9d6c5a71343..6a7a00d5d682a 100644 --- a/drivers/dma/ste_dma40.c +++ b/drivers/dma/ste_dma40.c @@ -504,15 +504,29 @@ static void d40_desc_submit(struct d40_chan *d40c, struct d40_desc *desc) list_add_tail(&desc->node, &d40c->active); } +static void d40_phy_lli_load(struct d40_chan *chan, struct d40_desc *desc) +{ + struct d40_phy_lli *lli_dst = desc->lli_phy.dst; + struct d40_phy_lli *lli_src = desc->lli_phy.src; + void __iomem *base = chan_base(chan); + + writel(lli_src->reg_cfg, base + D40_CHAN_REG_SSCFG); + writel(lli_src->reg_elt, base + D40_CHAN_REG_SSELT); + writel(lli_src->reg_ptr, base + D40_CHAN_REG_SSPTR); + writel(lli_src->reg_lnk, base + D40_CHAN_REG_SSLNK); + + writel(lli_dst->reg_cfg, base + D40_CHAN_REG_SDCFG); + writel(lli_dst->reg_elt, base + D40_CHAN_REG_SDELT); + writel(lli_dst->reg_ptr, base + D40_CHAN_REG_SDPTR); + writel(lli_dst->reg_lnk, base + D40_CHAN_REG_SDLNK); +} + static void d40_desc_load(struct d40_chan *d40c, struct d40_desc *d40d) { int curr_lcla = -EINVAL, next_lcla; if (chan_is_physical(d40c)) { - d40_phy_lli_write(d40c->base->virtbase, - d40c->phy_chan->num, - d40d->lli_phy.dst, - d40d->lli_phy.src); + d40_phy_lli_load(d40c, d40d); d40d->lli_current = d40d->lli_len; } else { diff --git a/drivers/dma/ste_dma40_ll.c b/drivers/dma/ste_dma40_ll.c index 552c5972c75ed..fd7525162596b 100644 --- a/drivers/dma/ste_dma40_ll.c +++ b/drivers/dma/ste_dma40_ll.c @@ -295,32 +295,6 @@ int d40_phy_sg_to_lli(struct scatterlist *sg, } -void d40_phy_lli_write(void __iomem *virtbase, - u32 phy_chan_num, - struct d40_phy_lli *lli_dst, - struct d40_phy_lli *lli_src) -{ - - writel(lli_src->reg_cfg, virtbase + D40_DREG_PCBASE + - phy_chan_num * D40_DREG_PCDELTA + D40_CHAN_REG_SSCFG); - writel(lli_src->reg_elt, virtbase + D40_DREG_PCBASE + - phy_chan_num * D40_DREG_PCDELTA + D40_CHAN_REG_SSELT); - writel(lli_src->reg_ptr, virtbase + D40_DREG_PCBASE + - phy_chan_num * D40_DREG_PCDELTA + D40_CHAN_REG_SSPTR); - writel(lli_src->reg_lnk, virtbase + D40_DREG_PCBASE + - phy_chan_num * D40_DREG_PCDELTA + D40_CHAN_REG_SSLNK); - - writel(lli_dst->reg_cfg, virtbase + D40_DREG_PCBASE + - phy_chan_num * D40_DREG_PCDELTA + D40_CHAN_REG_SDCFG); - writel(lli_dst->reg_elt, virtbase + D40_DREG_PCBASE + - phy_chan_num * D40_DREG_PCDELTA + D40_CHAN_REG_SDELT); - writel(lli_dst->reg_ptr, virtbase + D40_DREG_PCBASE + - phy_chan_num * D40_DREG_PCDELTA + D40_CHAN_REG_SDPTR); - writel(lli_dst->reg_lnk, virtbase + D40_DREG_PCBASE + - phy_chan_num * D40_DREG_PCDELTA + D40_CHAN_REG_SDLNK); - -} - /* DMA logical lli operations */ static void d40_log_lli_link(struct d40_log_lli *lli_dst, diff --git a/drivers/dma/ste_dma40_ll.h b/drivers/dma/ste_dma40_ll.h index a5d71714ebf70..46578a661b282 100644 --- a/drivers/dma/ste_dma40_ll.h +++ b/drivers/dma/ste_dma40_ll.h @@ -312,11 +312,6 @@ int d40_phy_sg_to_lli(struct scatterlist *sg, u32 data_width2, int psize); -void d40_phy_lli_write(void __iomem *virtbase, - u32 phy_chan_num, - struct d40_phy_lli *lli_dst, - struct d40_phy_lli *lli_src); - /* Logical channels */ struct d40_log_lli *d40_log_buf_to_lli(struct d40_log_lli *lli_sg, -- GitLab From e24b36bdf873b4a64545fd66da13877214d235cf Mon Sep 17 00:00:00 2001 From: Rabin Vincent Date: Tue, 25 Jan 2011 11:18:25 +0100 Subject: [PATCH 0046/2822] dma40: combine duplicated code in log_sg_to_dev Acked-by: Per Forlin Acked-by: Jonas Aaberg Signed-off-by: Rabin Vincent Signed-off-by: Linus Walleij Signed-off-by: Dan Williams --- drivers/dma/ste_dma40_ll.c | 52 +++++++++++++++++--------------------- 1 file changed, 23 insertions(+), 29 deletions(-) diff --git a/drivers/dma/ste_dma40_ll.c b/drivers/dma/ste_dma40_ll.c index fd7525162596b..fa6c3ab93faed 100644 --- a/drivers/dma/ste_dma40_ll.c +++ b/drivers/dma/ste_dma40_ll.c @@ -385,40 +385,34 @@ int d40_log_sg_to_dev(struct scatterlist *sg, struct d40_log_lli *lli_dst = lli->dst; for_each_sg(sg, current_sg, sg_len, i) { - total_size += sg_dma_len(current_sg); + dma_addr_t sg_addr = sg_dma_address(current_sg); + unsigned int len = sg_dma_len(current_sg); + dma_addr_t src; + dma_addr_t dst; + + total_size += len; if (direction == DMA_TO_DEVICE) { - lli_src = - d40_log_buf_to_lli(lli_src, - sg_dma_address(current_sg), - sg_dma_len(current_sg), - lcsp->lcsp1, src_data_width, - dst_data_width, - true); - lli_dst = - d40_log_buf_to_lli(lli_dst, - dev_addr, - sg_dma_len(current_sg), - lcsp->lcsp3, dst_data_width, - src_data_width, - false); + src = sg_addr; + dst = dev_addr; } else { - lli_dst = - d40_log_buf_to_lli(lli_dst, - sg_dma_address(current_sg), - sg_dma_len(current_sg), - lcsp->lcsp3, dst_data_width, - src_data_width, - true); - lli_src = - d40_log_buf_to_lli(lli_src, - dev_addr, - sg_dma_len(current_sg), - lcsp->lcsp1, src_data_width, - dst_data_width, - false); + src = dev_addr; + dst = sg_addr; } + + lli_src = d40_log_buf_to_lli(lli_src, src, len, + lcsp->lcsp1, + src_data_width, + dst_data_width, + src == sg_addr); + + lli_dst = d40_log_buf_to_lli(lli_dst, dst, len, + lcsp->lcsp3, + dst_data_width, + src_data_width, + dst == sg_addr); } + return total_size; } -- GitLab From 5ed04b8575cb22920b1333aeb55121339449048f Mon Sep 17 00:00:00 2001 From: Rabin Vincent Date: Tue, 25 Jan 2011 11:18:26 +0100 Subject: [PATCH 0047/2822] dma40: unify d40_log_sg_to_lli funcs for mem and slave Acked-by: Per Forlin Acked-by: Jonas Aaberg Signed-off-by: Rabin Vincent Signed-off-by: Linus Walleij Signed-off-by: Dan Williams --- drivers/dma/ste_dma40.c | 41 ++++++++++--------------- drivers/dma/ste_dma40_ll.c | 63 ++++++++------------------------------ drivers/dma/ste_dma40_ll.h | 10 +----- 3 files changed, 29 insertions(+), 85 deletions(-) diff --git a/drivers/dma/ste_dma40.c b/drivers/dma/ste_dma40.c index 6a7a00d5d682a..c597dba713b00 100644 --- a/drivers/dma/ste_dma40.c +++ b/drivers/dma/ste_dma40.c @@ -1638,37 +1638,28 @@ d40_prep_sg_log(struct d40_chan *chan, struct d40_desc *desc, unsigned int sg_len, enum dma_data_direction direction, dma_addr_t dev_addr) { + dma_addr_t src_dev_addr = direction == DMA_FROM_DEVICE ? dev_addr : 0; + dma_addr_t dst_dev_addr = direction == DMA_TO_DEVICE ? dev_addr : 0; struct stedma40_chan_cfg *cfg = &chan->dma_cfg; struct stedma40_half_channel_info *src_info = &cfg->src_info; struct stedma40_half_channel_info *dst_info = &cfg->dst_info; + int ret; - if (direction == DMA_NONE) { - /* memcpy */ - (void) d40_log_sg_to_lli(sg_src, sg_len, - desc->lli_log.src, - chan->log_def.lcsp1, - src_info->data_width, - dst_info->data_width); - - (void) d40_log_sg_to_lli(sg_dst, sg_len, - desc->lli_log.dst, - chan->log_def.lcsp3, - dst_info->data_width, - src_info->data_width); - } else { - unsigned int total_size; + ret = d40_log_sg_to_lli(sg_src, sg_len, + src_dev_addr, + desc->lli_log.src, + chan->log_def.lcsp1, + src_info->data_width, + dst_info->data_width); - total_size = d40_log_sg_to_dev(sg_src, sg_len, - &desc->lli_log, - &chan->log_def, - src_info->data_width, - dst_info->data_width, - direction, dev_addr); - if (total_size < 0) - return -EINVAL; - } + ret = d40_log_sg_to_lli(sg_dst, sg_len, + dst_dev_addr, + desc->lli_log.dst, + chan->log_def.lcsp3, + dst_info->data_width, + src_info->data_width); - return 0; + return ret < 0 ? ret : 0; } static int diff --git a/drivers/dma/ste_dma40_ll.c b/drivers/dma/ste_dma40_ll.c index fa6c3ab93faed..9935c6dbcfe0e 100644 --- a/drivers/dma/ste_dma40_ll.c +++ b/drivers/dma/ste_dma40_ll.c @@ -369,53 +369,6 @@ static void d40_log_fill_lli(struct d40_log_lli *lli, } -int d40_log_sg_to_dev(struct scatterlist *sg, - int sg_len, - struct d40_log_lli_bidir *lli, - struct d40_def_lcsp *lcsp, - u32 src_data_width, - u32 dst_data_width, - enum dma_data_direction direction, - dma_addr_t dev_addr) -{ - int total_size = 0; - struct scatterlist *current_sg = sg; - int i; - struct d40_log_lli *lli_src = lli->src; - struct d40_log_lli *lli_dst = lli->dst; - - for_each_sg(sg, current_sg, sg_len, i) { - dma_addr_t sg_addr = sg_dma_address(current_sg); - unsigned int len = sg_dma_len(current_sg); - dma_addr_t src; - dma_addr_t dst; - - total_size += len; - - if (direction == DMA_TO_DEVICE) { - src = sg_addr; - dst = dev_addr; - } else { - src = dev_addr; - dst = sg_addr; - } - - lli_src = d40_log_buf_to_lli(lli_src, src, len, - lcsp->lcsp1, - src_data_width, - dst_data_width, - src == sg_addr); - - lli_dst = d40_log_buf_to_lli(lli_dst, dst, len, - lcsp->lcsp3, - dst_data_width, - src_data_width, - dst == sg_addr); - } - - return total_size; -} - struct d40_log_lli *d40_log_buf_to_lli(struct d40_log_lli *lli_sg, dma_addr_t addr, int size, @@ -447,6 +400,7 @@ struct d40_log_lli *d40_log_buf_to_lli(struct d40_log_lli *lli_sg, int d40_log_sg_to_lli(struct scatterlist *sg, int sg_len, + dma_addr_t dev_addr, struct d40_log_lli *lli_sg, u32 lcsp13, /* src or dst*/ u32 data_width1, u32 data_width2) @@ -455,14 +409,21 @@ int d40_log_sg_to_lli(struct scatterlist *sg, struct scatterlist *current_sg = sg; int i; struct d40_log_lli *lli = lli_sg; + bool autoinc = !dev_addr; for_each_sg(sg, current_sg, sg_len, i) { + dma_addr_t sg_addr = sg_dma_address(current_sg); + unsigned int len = sg_dma_len(current_sg); + dma_addr_t addr = dev_addr ?: sg_addr; + total_size += sg_dma_len(current_sg); - lli = d40_log_buf_to_lli(lli, - sg_dma_address(current_sg), - sg_dma_len(current_sg), + + lli = d40_log_buf_to_lli(lli, addr, len, lcsp13, - data_width1, data_width2, true); + data_width1, + data_width2, + autoinc); } + return total_size; } diff --git a/drivers/dma/ste_dma40_ll.h b/drivers/dma/ste_dma40_ll.h index 46578a661b282..867f23f6e0986 100644 --- a/drivers/dma/ste_dma40_ll.h +++ b/drivers/dma/ste_dma40_ll.h @@ -321,17 +321,9 @@ struct d40_log_lli *d40_log_buf_to_lli(struct d40_log_lli *lli_sg, u32 data_width1, u32 data_width2, bool addr_inc); -int d40_log_sg_to_dev(struct scatterlist *sg, - int sg_len, - struct d40_log_lli_bidir *lli, - struct d40_def_lcsp *lcsp, - u32 src_data_width, - u32 dst_data_width, - enum dma_data_direction direction, - dma_addr_t dev_addr); - int d40_log_sg_to_lli(struct scatterlist *sg, int sg_len, + dma_addr_t dev_addr, struct d40_log_lli *lli_sg, u32 lcsp13, /* src or dst*/ u32 data_width1, u32 data_width2); -- GitLab From cc31b6f7949efd46c5f13d0758cf7b0bcb71fae2 Mon Sep 17 00:00:00 2001 From: Rabin Vincent Date: Tue, 25 Jan 2011 11:18:27 +0100 Subject: [PATCH 0048/2822] dma40: pass the info pointer all the way to reduce argument count Acked-by: Per Forlin Acked-by: Jonas Aaberg Signed-off-by: Rabin Vincent Signed-off-by: Linus Walleij Signed-off-by: Dan Williams --- drivers/dma/ste_dma40.c | 8 ++------ drivers/dma/ste_dma40_ll.c | 42 ++++++++++++++++---------------------- drivers/dma/ste_dma40_ll.h | 5 ++--- 3 files changed, 22 insertions(+), 33 deletions(-) diff --git a/drivers/dma/ste_dma40.c b/drivers/dma/ste_dma40.c index c597dba713b00..3c61c582303d8 100644 --- a/drivers/dma/ste_dma40.c +++ b/drivers/dma/ste_dma40.c @@ -1679,17 +1679,13 @@ d40_prep_sg_phy(struct d40_chan *chan, struct d40_desc *desc, desc->lli_phy.src, virt_to_phys(desc->lli_phy.src), chan->src_def_cfg, - src_info->data_width, - dst_info->data_width, - src_info->psize); + src_info, dst_info); ret = d40_phy_sg_to_lli(sg_dst, sg_len, dst_dev_addr, desc->lli_phy.dst, virt_to_phys(desc->lli_phy.dst), chan->dst_def_cfg, - dst_info->data_width, - src_info->data_width, - dst_info->psize); + dst_info, src_info); dma_sync_single_for_device(chan->base->dev, desc->lli_pool.dma_addr, desc->lli_pool.size, DMA_TO_DEVICE); diff --git a/drivers/dma/ste_dma40_ll.c b/drivers/dma/ste_dma40_ll.c index 9935c6dbcfe0e..509a13049d7e0 100644 --- a/drivers/dma/ste_dma40_ll.c +++ b/drivers/dma/ste_dma40_ll.c @@ -125,13 +125,14 @@ void d40_phy_cfg(struct stedma40_chan_cfg *cfg, static int d40_phy_fill_lli(struct d40_phy_lli *lli, dma_addr_t data, u32 data_size, - int psize, dma_addr_t next_lli, u32 reg_cfg, bool term_int, - u32 data_width, - bool is_device) + bool is_device, + struct stedma40_half_channel_info *info) { + unsigned int data_width = info->data_width; + int psize = info->psize; int num_elems; if (psize == STEDMA40_PSIZE_PHY_1) @@ -198,16 +199,11 @@ static int d40_seg_size(int size, int data_width1, int data_width2) return seg_max; } -static struct d40_phy_lli *d40_phy_buf_to_lli(struct d40_phy_lli *lli, - dma_addr_t addr, - u32 size, - int psize, - dma_addr_t lli_phys, - u32 reg_cfg, - bool term_int, - u32 data_width1, - u32 data_width2, - bool is_device) +static struct d40_phy_lli * +d40_phy_buf_to_lli(struct d40_phy_lli *lli, dma_addr_t addr, u32 size, + dma_addr_t lli_phys, u32 reg_cfg, bool term_int, + bool is_device, struct stedma40_half_channel_info *info, + struct stedma40_half_channel_info *otherinfo) { int err; dma_addr_t next = lli_phys; @@ -215,7 +211,8 @@ static struct d40_phy_lli *d40_phy_buf_to_lli(struct d40_phy_lli *lli, int size_seg = 0; do { - size_seg = d40_seg_size(size_rest, data_width1, data_width2); + size_seg = d40_seg_size(size_rest, info->data_width, + otherinfo->data_width); size_rest -= size_seg; if (term_int && size_rest == 0) @@ -227,12 +224,11 @@ static struct d40_phy_lli *d40_phy_buf_to_lli(struct d40_phy_lli *lli, err = d40_phy_fill_lli(lli, addr, size_seg, - psize, next, reg_cfg, !next, - data_width1, - is_device); + is_device, + info); if (err) goto err; @@ -254,9 +250,8 @@ int d40_phy_sg_to_lli(struct scatterlist *sg, struct d40_phy_lli *lli_sg, dma_addr_t lli_phys, u32 reg_cfg, - u32 data_width1, - u32 data_width2, - int psize) + struct stedma40_half_channel_info *info, + struct stedma40_half_channel_info *otherinfo) { int total_size = 0; int i; @@ -280,13 +275,12 @@ int d40_phy_sg_to_lli(struct scatterlist *sg, lli = d40_phy_buf_to_lli(lli, dst, sg_dma_len(current_sg), - psize, l_phys, reg_cfg, sg_len - 1 == i, - data_width1, - data_width2, - target == dst); + target == dst, + info, + otherinfo); if (lli == NULL) return -EINVAL; } diff --git a/drivers/dma/ste_dma40_ll.h b/drivers/dma/ste_dma40_ll.h index 867f23f6e0986..cd94afd9c2f24 100644 --- a/drivers/dma/ste_dma40_ll.h +++ b/drivers/dma/ste_dma40_ll.h @@ -308,9 +308,8 @@ int d40_phy_sg_to_lli(struct scatterlist *sg, struct d40_phy_lli *lli, dma_addr_t lli_phys, u32 reg_cfg, - u32 data_width1, - u32 data_width2, - int psize); + struct stedma40_half_channel_info *info, + struct stedma40_half_channel_info *otherinfo); /* Logical channels */ -- GitLab From 822c567639971628ceba2c53531670d595e3164d Mon Sep 17 00:00:00 2001 From: Rabin Vincent Date: Tue, 25 Jan 2011 11:18:28 +0100 Subject: [PATCH 0049/2822] dma40: unify src/dst addr check Acked-by: Per Forlin Acked-by: Jonas Aaberg Signed-off-by: Rabin Vincent Signed-off-by: Linus Walleij Signed-off-by: Dan Williams --- drivers/dma/ste_dma40.c | 29 ++++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/drivers/dma/ste_dma40.c b/drivers/dma/ste_dma40.c index 3c61c582303d8..d9dfda2c65b5f 100644 --- a/drivers/dma/ste_dma40.c +++ b/drivers/dma/ste_dma40.c @@ -1635,11 +1635,9 @@ static u32 stedma40_residue(struct dma_chan *chan) static int d40_prep_sg_log(struct d40_chan *chan, struct d40_desc *desc, struct scatterlist *sg_src, struct scatterlist *sg_dst, - unsigned int sg_len, enum dma_data_direction direction, - dma_addr_t dev_addr) + unsigned int sg_len, dma_addr_t src_dev_addr, + dma_addr_t dst_dev_addr) { - dma_addr_t src_dev_addr = direction == DMA_FROM_DEVICE ? dev_addr : 0; - dma_addr_t dst_dev_addr = direction == DMA_TO_DEVICE ? dev_addr : 0; struct stedma40_chan_cfg *cfg = &chan->dma_cfg; struct stedma40_half_channel_info *src_info = &cfg->src_info; struct stedma40_half_channel_info *dst_info = &cfg->dst_info; @@ -1665,11 +1663,9 @@ d40_prep_sg_log(struct d40_chan *chan, struct d40_desc *desc, static int d40_prep_sg_phy(struct d40_chan *chan, struct d40_desc *desc, struct scatterlist *sg_src, struct scatterlist *sg_dst, - unsigned int sg_len, enum dma_data_direction direction, - dma_addr_t dev_addr) + unsigned int sg_len, dma_addr_t src_dev_addr, + dma_addr_t dst_dev_addr) { - dma_addr_t src_dev_addr = direction == DMA_FROM_DEVICE ? dev_addr : 0; - dma_addr_t dst_dev_addr = direction == DMA_TO_DEVICE ? dev_addr : 0; struct stedma40_chan_cfg *cfg = &chan->dma_cfg; struct stedma40_half_channel_info *src_info = &cfg->src_info; struct stedma40_half_channel_info *dst_info = &cfg->dst_info; @@ -1757,7 +1753,8 @@ d40_prep_sg(struct dma_chan *dchan, struct scatterlist *sg_src, enum dma_data_direction direction, unsigned long dma_flags) { struct d40_chan *chan = container_of(dchan, struct d40_chan, chan); - dma_addr_t dev_addr = 0; + dma_addr_t src_dev_addr = 0; + dma_addr_t dst_dev_addr = 0; struct d40_desc *desc; unsigned long flags; int ret; @@ -1773,15 +1770,21 @@ d40_prep_sg(struct dma_chan *dchan, struct scatterlist *sg_src, if (desc == NULL) goto err; - if (direction != DMA_NONE) - dev_addr = d40_get_dev_addr(chan, direction); + if (direction != DMA_NONE) { + dma_addr_t dev_addr = d40_get_dev_addr(chan, direction); + + if (direction == DMA_FROM_DEVICE) + src_dev_addr = dev_addr; + else if (direction == DMA_TO_DEVICE) + dst_dev_addr = dev_addr; + } if (chan_is_logical(chan)) ret = d40_prep_sg_log(chan, desc, sg_src, sg_dst, - sg_len, direction, dev_addr); + sg_len, src_dev_addr, dst_dev_addr); else ret = d40_prep_sg_phy(chan, desc, sg_src, sg_dst, - sg_len, direction, dev_addr); + sg_len, src_dev_addr, dst_dev_addr); if (ret) { chan_err(chan, "Failed to prepare %s sg job: %d\n", -- GitLab From 1f7622ca55b1f5875e32140b4781759f800aded3 Mon Sep 17 00:00:00 2001 From: Rabin Vincent Date: Tue, 25 Jan 2011 11:18:29 +0100 Subject: [PATCH 0050/2822] dma40: make d40_log_buf_to_lli static Acked-by: Per Forlin Acked-by: Jonas Aaberg Signed-off-by: Rabin Vincent Signed-off-by: Linus Walleij Signed-off-by: Dan Williams --- drivers/dma/ste_dma40_ll.c | 2 +- drivers/dma/ste_dma40_ll.h | 7 ------- 2 files changed, 1 insertion(+), 8 deletions(-) diff --git a/drivers/dma/ste_dma40_ll.c b/drivers/dma/ste_dma40_ll.c index 509a13049d7e0..876aad2c838a9 100644 --- a/drivers/dma/ste_dma40_ll.c +++ b/drivers/dma/ste_dma40_ll.c @@ -363,7 +363,7 @@ static void d40_log_fill_lli(struct d40_log_lli *lli, } -struct d40_log_lli *d40_log_buf_to_lli(struct d40_log_lli *lli_sg, +static struct d40_log_lli *d40_log_buf_to_lli(struct d40_log_lli *lli_sg, dma_addr_t addr, int size, u32 lcsp13, /* src or dst*/ diff --git a/drivers/dma/ste_dma40_ll.h b/drivers/dma/ste_dma40_ll.h index cd94afd9c2f24..4626c8874374d 100644 --- a/drivers/dma/ste_dma40_ll.h +++ b/drivers/dma/ste_dma40_ll.h @@ -313,13 +313,6 @@ int d40_phy_sg_to_lli(struct scatterlist *sg, /* Logical channels */ -struct d40_log_lli *d40_log_buf_to_lli(struct d40_log_lli *lli_sg, - dma_addr_t addr, - int size, - u32 lcsp13, /* src or dst*/ - u32 data_width1, u32 data_width2, - bool addr_inc); - int d40_log_sg_to_lli(struct scatterlist *sg, int sg_len, dma_addr_t dev_addr, -- GitLab From 7f933bed96e9872131014ea2bdd5b012e43fc316 Mon Sep 17 00:00:00 2001 From: Rabin Vincent Date: Tue, 25 Jan 2011 11:18:30 +0100 Subject: [PATCH 0051/2822] dma40: use flags to reduce parameter count Acked-by: Per Forlin Acked-by: Jonas Aaberg Signed-off-by: Rabin Vincent Signed-off-by: Linus Walleij Signed-off-by: Dan Williams --- drivers/dma/ste_dma40_ll.c | 84 +++++++++++++++++++++----------------- drivers/dma/ste_dma40_ll.h | 5 +++ 2 files changed, 52 insertions(+), 37 deletions(-) diff --git a/drivers/dma/ste_dma40_ll.c b/drivers/dma/ste_dma40_ll.c index 876aad2c838a9..88b9e371be2f0 100644 --- a/drivers/dma/ste_dma40_ll.c +++ b/drivers/dma/ste_dma40_ll.c @@ -127,10 +127,11 @@ static int d40_phy_fill_lli(struct d40_phy_lli *lli, u32 data_size, dma_addr_t next_lli, u32 reg_cfg, - bool term_int, - bool is_device, - struct stedma40_half_channel_info *info) + struct stedma40_half_channel_info *info, + unsigned int flags) { + bool addr_inc = flags & LLI_ADDR_INC; + bool term_int = flags & LLI_TERM_INT; unsigned int data_width = info->data_width; int psize = info->psize; int num_elems; @@ -155,7 +156,7 @@ static int d40_phy_fill_lli(struct d40_phy_lli *lli, * Distance to next element sized entry. * Usually the size of the element unless you want gaps. */ - if (!is_device) + if (addr_inc) lli->reg_elt |= (0x1 << data_width) << D40_SREG_ELEM_PHY_EIDX_POS; @@ -201,40 +202,45 @@ static int d40_seg_size(int size, int data_width1, int data_width2) static struct d40_phy_lli * d40_phy_buf_to_lli(struct d40_phy_lli *lli, dma_addr_t addr, u32 size, - dma_addr_t lli_phys, u32 reg_cfg, bool term_int, - bool is_device, struct stedma40_half_channel_info *info, - struct stedma40_half_channel_info *otherinfo) + dma_addr_t lli_phys, u32 reg_cfg, + struct stedma40_half_channel_info *info, + struct stedma40_half_channel_info *otherinfo, + unsigned long flags) { + bool addr_inc = flags & LLI_ADDR_INC; + bool term_int = flags & LLI_TERM_INT; int err; dma_addr_t next = lli_phys; int size_rest = size; int size_seg = 0; + /* + * This piece may be split up based on d40_seg_size(); we only want the + * term int on the last part. + */ + if (term_int) + flags &= ~LLI_TERM_INT; + do { size_seg = d40_seg_size(size_rest, info->data_width, otherinfo->data_width); size_rest -= size_seg; - if (term_int && size_rest == 0) + if (term_int && size_rest == 0) { next = 0; - else + flags |= LLI_TERM_INT; + } else next = ALIGN(next + sizeof(struct d40_phy_lli), D40_LLI_ALIGN); - err = d40_phy_fill_lli(lli, - addr, - size_seg, - next, - reg_cfg, - !next, - is_device, - info); + err = d40_phy_fill_lli(lli, addr, size_seg, next, + reg_cfg, info, flags); if (err) goto err; lli++; - if (!is_device) + if (addr_inc) addr += size_seg; } while (size_rest); @@ -256,31 +262,29 @@ int d40_phy_sg_to_lli(struct scatterlist *sg, int total_size = 0; int i; struct scatterlist *current_sg = sg; - dma_addr_t dst; struct d40_phy_lli *lli = lli_sg; dma_addr_t l_phys = lli_phys; + unsigned long flags = 0; + + if (!target) + flags |= LLI_ADDR_INC; for_each_sg(sg, current_sg, sg_len, i) { + dma_addr_t sg_addr = sg_dma_address(current_sg); + unsigned int len = sg_dma_len(current_sg); + dma_addr_t dst = target ?: sg_addr; total_size += sg_dma_len(current_sg); - if (target) - dst = target; - else - dst = sg_dma_address(current_sg); + if (i == sg_len - 1) + flags |= LLI_TERM_INT; l_phys = ALIGN(lli_phys + (lli - lli_sg) * sizeof(struct d40_phy_lli), D40_LLI_ALIGN); - lli = d40_phy_buf_to_lli(lli, - dst, - sg_dma_len(current_sg), - l_phys, - reg_cfg, - sg_len - 1 == i, - target == dst, - info, - otherinfo); + lli = d40_phy_buf_to_lli(lli, dst, len, l_phys, + reg_cfg, info, otherinfo, flags); + if (lli == NULL) return -EINVAL; } @@ -343,8 +347,10 @@ static void d40_log_fill_lli(struct d40_log_lli *lli, dma_addr_t data, u32 data_size, u32 reg_cfg, u32 data_width, - bool addr_inc) + unsigned int flags) { + bool addr_inc = flags & LLI_ADDR_INC; + lli->lcsp13 = reg_cfg; /* The number of elements to transfer */ @@ -369,8 +375,9 @@ static struct d40_log_lli *d40_log_buf_to_lli(struct d40_log_lli *lli_sg, u32 lcsp13, /* src or dst*/ u32 data_width1, u32 data_width2, - bool addr_inc) + unsigned int flags) { + bool addr_inc = flags & LLI_ADDR_INC; struct d40_log_lli *lli = lli_sg; int size_rest = size; int size_seg = 0; @@ -383,7 +390,7 @@ static struct d40_log_lli *d40_log_buf_to_lli(struct d40_log_lli *lli_sg, addr, size_seg, lcsp13, data_width1, - addr_inc); + flags); if (addr_inc) addr += size_seg; lli++; @@ -403,7 +410,10 @@ int d40_log_sg_to_lli(struct scatterlist *sg, struct scatterlist *current_sg = sg; int i; struct d40_log_lli *lli = lli_sg; - bool autoinc = !dev_addr; + unsigned long flags = 0; + + if (!dev_addr) + flags |= LLI_ADDR_INC; for_each_sg(sg, current_sg, sg_len, i) { dma_addr_t sg_addr = sg_dma_address(current_sg); @@ -416,7 +426,7 @@ int d40_log_sg_to_lli(struct scatterlist *sg, lcsp13, data_width1, data_width2, - autoinc); + flags); } return total_size; diff --git a/drivers/dma/ste_dma40_ll.h b/drivers/dma/ste_dma40_ll.h index 4626c8874374d..59e72f0cc901f 100644 --- a/drivers/dma/ste_dma40_ll.h +++ b/drivers/dma/ste_dma40_ll.h @@ -293,6 +293,11 @@ struct d40_def_lcsp { /* Physical channels */ +enum d40_lli_flags { + LLI_ADDR_INC = 1 << 0, + LLI_TERM_INT = 1 << 1, +}; + void d40_phy_cfg(struct stedma40_chan_cfg *cfg, u32 *src_cfg, u32 *dst_cfg, -- GitLab From e65889c75ccb5b64dfb60f32e2d9448446cabcc7 Mon Sep 17 00:00:00 2001 From: Rabin Vincent Date: Tue, 25 Jan 2011 11:18:31 +0100 Subject: [PATCH 0052/2822] dma40: extract lcla code into separate function Acked-by: Per Forlin Acked-by: Jonas Aaberg Signed-off-by: Rabin Vincent Signed-off-by: Linus Walleij Signed-off-by: Dan Williams --- drivers/dma/ste_dma40.c | 92 ++++++++++++++++++++++------------------- 1 file changed, 50 insertions(+), 42 deletions(-) diff --git a/drivers/dma/ste_dma40.c b/drivers/dma/ste_dma40.c index d9dfda2c65b5f..4ec96ac1e41a8 100644 --- a/drivers/dma/ste_dma40.c +++ b/drivers/dma/ste_dma40.c @@ -521,54 +521,62 @@ static void d40_phy_lli_load(struct d40_chan *chan, struct d40_desc *desc) writel(lli_dst->reg_lnk, base + D40_CHAN_REG_SDLNK); } -static void d40_desc_load(struct d40_chan *d40c, struct d40_desc *d40d) -{ - int curr_lcla = -EINVAL, next_lcla; - - if (chan_is_physical(d40c)) { - d40_phy_lli_load(d40c, d40d); - d40d->lli_current = d40d->lli_len; - } else { - - if ((d40d->lli_len - d40d->lli_current) > 1) - curr_lcla = d40_lcla_alloc_one(d40c, d40d); - - d40_log_lli_lcpa_write(d40c->lcpa, - &d40d->lli_log.dst[d40d->lli_current], - &d40d->lli_log.src[d40d->lli_current], - curr_lcla); - - d40d->lli_current++; - for (; d40d->lli_current < d40d->lli_len; d40d->lli_current++) { - unsigned int lcla_offset = d40c->phy_chan->num * 1024 + - 8 * curr_lcla * 2; - struct d40_lcla_pool *pool = &d40c->base->lcla_pool; - struct d40_log_lli *lcla = pool->base + lcla_offset; - - if (d40d->lli_current + 1 < d40d->lli_len) - next_lcla = d40_lcla_alloc_one(d40c, d40d); - else - next_lcla = -EINVAL; - - d40_log_lli_lcla_write(lcla, - &d40d->lli_log.dst[d40d->lli_current], - &d40d->lli_log.src[d40d->lli_current], - next_lcla); +static void d40_log_lli_to_lcxa(struct d40_chan *chan, struct d40_desc *desc) +{ + struct d40_lcla_pool *pool = &chan->base->lcla_pool; + struct d40_log_lli_bidir *lli = &desc->lli_log; + int lli_current = desc->lli_current; + int lli_len = desc->lli_len; + int curr_lcla = -EINVAL; + + if (lli_len - lli_current > 1) + curr_lcla = d40_lcla_alloc_one(chan, desc); + + d40_log_lli_lcpa_write(chan->lcpa, + &lli->dst[lli_current], + &lli->src[lli_current], + curr_lcla); + + lli_current++; + for (; lli_current < lli_len; lli_current++) { + unsigned int lcla_offset = chan->phy_chan->num * 1024 + + 8 * curr_lcla * 2; + struct d40_log_lli *lcla = pool->base + lcla_offset; + int next_lcla; + + if (lli_current + 1 < lli_len) + next_lcla = d40_lcla_alloc_one(chan, desc); + else + next_lcla = -EINVAL; - dma_sync_single_range_for_device(d40c->base->dev, - pool->dma_addr, lcla_offset, - 2 * sizeof(struct d40_log_lli), - DMA_TO_DEVICE); + d40_log_lli_lcla_write(lcla, + &lli->dst[lli_current], + &lli->src[lli_current], + next_lcla); - curr_lcla = next_lcla; + dma_sync_single_range_for_device(chan->base->dev, + pool->dma_addr, lcla_offset, + 2 * sizeof(struct d40_log_lli), + DMA_TO_DEVICE); - if (curr_lcla == -EINVAL) { - d40d->lli_current++; - break; - } + curr_lcla = next_lcla; + if (curr_lcla == -EINVAL) { + lli_current++; + break; } } + + desc->lli_current = lli_current; +} + +static void d40_desc_load(struct d40_chan *d40c, struct d40_desc *d40d) +{ + if (chan_is_physical(d40c)) { + d40_phy_lli_load(d40c, d40d); + d40d->lli_current = d40d->lli_len; + } else + d40_log_lli_to_lcxa(d40c, d40d); } static struct d40_desc *d40_first_active_get(struct d40_chan *d40c) -- GitLab From 6045f0bb2818393a44e835454db96709cb5b3d80 Mon Sep 17 00:00:00 2001 From: Rabin Vincent Date: Tue, 25 Jan 2011 11:18:32 +0100 Subject: [PATCH 0053/2822] dma40: handle failure to allocate first LCLA Acked-by: Per Forlin Acked-by: Jonas Aaberg Signed-off-by: Rabin Vincent Signed-off-by: Linus Walleij Signed-off-by: Dan Williams --- drivers/dma/ste_dma40.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/dma/ste_dma40.c b/drivers/dma/ste_dma40.c index 4ec96ac1e41a8..b8cce85a95583 100644 --- a/drivers/dma/ste_dma40.c +++ b/drivers/dma/ste_dma40.c @@ -538,6 +538,10 @@ static void d40_log_lli_to_lcxa(struct d40_chan *chan, struct d40_desc *desc) curr_lcla); lli_current++; + + if (curr_lcla < 0) + goto out; + for (; lli_current < lli_len; lli_current++) { unsigned int lcla_offset = chan->phy_chan->num * 1024 + 8 * curr_lcla * 2; @@ -567,6 +571,7 @@ static void d40_log_lli_to_lcxa(struct d40_chan *chan, struct d40_desc *desc) } } +out: desc->lli_current = lli_current; } -- GitLab From 7ad74a7cf6f6355fd3f4c15afe63460fc4ec3f57 Mon Sep 17 00:00:00 2001 From: Rabin Vincent Date: Tue, 25 Jan 2011 11:18:33 +0100 Subject: [PATCH 0054/2822] dma40: fix DMA_SG capability and channels The DMA_SG cap is enabled on the wrong channel, and the pointers are repeatedly set incorrectly. Fix it and combine the ops settings to a common function. Acked-by: Per Forlin Acked-by: Jonas Aaberg Signed-off-by: Rabin Vincent Signed-off-by: Linus Walleij Signed-off-by: Dan Williams --- drivers/dma/ste_dma40.c | 71 ++++++++++++++++++++--------------------- 1 file changed, 34 insertions(+), 37 deletions(-) diff --git a/drivers/dma/ste_dma40.c b/drivers/dma/ste_dma40.c index b8cce85a95583..929fd8f45a2da 100644 --- a/drivers/dma/ste_dma40.c +++ b/drivers/dma/ste_dma40.c @@ -2238,6 +2238,32 @@ static void __init d40_chan_init(struct d40_base *base, struct dma_device *dma, } } +static void d40_ops_init(struct d40_base *base, struct dma_device *dev) +{ + if (dma_has_cap(DMA_SLAVE, dev->cap_mask)) + dev->device_prep_slave_sg = d40_prep_slave_sg; + + if (dma_has_cap(DMA_MEMCPY, dev->cap_mask)) { + dev->device_prep_dma_memcpy = d40_prep_memcpy; + + /* + * This controller can only access address at even + * 32bit boundaries, i.e. 2^2 + */ + dev->copy_align = 2; + } + + if (dma_has_cap(DMA_SG, dev->cap_mask)) + dev->device_prep_dma_sg = d40_prep_memcpy_sg; + + dev->device_alloc_chan_resources = d40_alloc_chan_resources; + dev->device_free_chan_resources = d40_free_chan_resources; + dev->device_issue_pending = d40_issue_pending; + dev->device_tx_status = d40_tx_status; + dev->device_control = d40_control; + dev->dev = base->dev; +} + static int __init d40_dmaengine_init(struct d40_base *base, int num_reserved_chans) { @@ -2249,15 +2275,7 @@ static int __init d40_dmaengine_init(struct d40_base *base, dma_cap_zero(base->dma_slave.cap_mask); dma_cap_set(DMA_SLAVE, base->dma_slave.cap_mask); - base->dma_slave.device_alloc_chan_resources = d40_alloc_chan_resources; - base->dma_slave.device_free_chan_resources = d40_free_chan_resources; - base->dma_slave.device_prep_dma_memcpy = d40_prep_memcpy; - base->dma_slave.device_prep_dma_sg = d40_prep_memcpy_sg; - base->dma_slave.device_prep_slave_sg = d40_prep_slave_sg; - base->dma_slave.device_tx_status = d40_tx_status; - base->dma_slave.device_issue_pending = d40_issue_pending; - base->dma_slave.device_control = d40_control; - base->dma_slave.dev = base->dev; + d40_ops_init(base, &base->dma_slave); err = dma_async_device_register(&base->dma_slave); @@ -2271,22 +2289,9 @@ static int __init d40_dmaengine_init(struct d40_base *base, dma_cap_zero(base->dma_memcpy.cap_mask); dma_cap_set(DMA_MEMCPY, base->dma_memcpy.cap_mask); - dma_cap_set(DMA_SG, base->dma_slave.cap_mask); - - base->dma_memcpy.device_alloc_chan_resources = d40_alloc_chan_resources; - base->dma_memcpy.device_free_chan_resources = d40_free_chan_resources; - base->dma_memcpy.device_prep_dma_memcpy = d40_prep_memcpy; - base->dma_slave.device_prep_dma_sg = d40_prep_memcpy_sg; - base->dma_memcpy.device_prep_slave_sg = d40_prep_slave_sg; - base->dma_memcpy.device_tx_status = d40_tx_status; - base->dma_memcpy.device_issue_pending = d40_issue_pending; - base->dma_memcpy.device_control = d40_control; - base->dma_memcpy.dev = base->dev; - /* - * This controller can only access address at even - * 32bit boundaries, i.e. 2^2 - */ - base->dma_memcpy.copy_align = 2; + dma_cap_set(DMA_SG, base->dma_memcpy.cap_mask); + + d40_ops_init(base, &base->dma_memcpy); err = dma_async_device_register(&base->dma_memcpy); @@ -2302,18 +2307,10 @@ static int __init d40_dmaengine_init(struct d40_base *base, dma_cap_zero(base->dma_both.cap_mask); dma_cap_set(DMA_SLAVE, base->dma_both.cap_mask); dma_cap_set(DMA_MEMCPY, base->dma_both.cap_mask); - dma_cap_set(DMA_SG, base->dma_slave.cap_mask); - - base->dma_both.device_alloc_chan_resources = d40_alloc_chan_resources; - base->dma_both.device_free_chan_resources = d40_free_chan_resources; - base->dma_both.device_prep_dma_memcpy = d40_prep_memcpy; - base->dma_slave.device_prep_dma_sg = d40_prep_memcpy_sg; - base->dma_both.device_prep_slave_sg = d40_prep_slave_sg; - base->dma_both.device_tx_status = d40_tx_status; - base->dma_both.device_issue_pending = d40_issue_pending; - base->dma_both.device_control = d40_control; - base->dma_both.dev = base->dev; - base->dma_both.copy_align = 2; + dma_cap_set(DMA_SG, base->dma_both.cap_mask); + + d40_ops_init(base, &base->dma_both); + err = dma_async_device_register(&base->dma_both); if (err) { -- GitLab From 86eb5fb61125e4646c9447a1f2ce130817dab34e Mon Sep 17 00:00:00 2001 From: Rabin Vincent Date: Tue, 25 Jan 2011 11:18:34 +0100 Subject: [PATCH 0055/2822] dma40: stop ongoing transfers in DMA_TERMINATE_ALL The current implementation of DMA_TERMINATE_ALL leaves ongoing transfers running. Fix it. Acked-by: Per Forlin Acked-by: Jonas Aaberg Signed-off-by: Rabin Vincent Signed-off-by: Linus Walleij Signed-off-by: Dan Williams --- drivers/dma/ste_dma40.c | 34 +++++++++++++++++++++------------- 1 file changed, 21 insertions(+), 13 deletions(-) diff --git a/drivers/dma/ste_dma40.c b/drivers/dma/ste_dma40.c index 929fd8f45a2da..8fd0bb94e777b 100644 --- a/drivers/dma/ste_dma40.c +++ b/drivers/dma/ste_dma40.c @@ -918,10 +918,8 @@ static bool d40_tx_is_linked(struct d40_chan *d40c) return is_link; } -static int d40_pause(struct dma_chan *chan) +static int d40_pause(struct d40_chan *d40c) { - struct d40_chan *d40c = - container_of(chan, struct d40_chan, chan); int res = 0; unsigned long flags; @@ -945,10 +943,8 @@ static int d40_pause(struct dma_chan *chan) return res; } -static int d40_resume(struct dma_chan *chan) +static int d40_resume(struct d40_chan *d40c) { - struct d40_chan *d40c = - container_of(chan, struct d40_chan, chan); int res = 0; unsigned long flags; @@ -978,6 +974,22 @@ no_suspend: return res; } +static int d40_terminate_all(struct d40_chan *chan) +{ + unsigned long flags; + int ret = 0; + + ret = d40_pause(chan); + if (!ret && chan_is_physical(chan)) + ret = d40_channel_execute_command(chan, D40_DMA_STOP); + + spin_lock_irqsave(&chan->lock, flags); + d40_term_all(chan); + spin_unlock_irqrestore(&chan->lock, flags); + + return ret; +} + static dma_cookie_t d40_tx_submit(struct dma_async_tx_descriptor *tx) { struct d40_chan *d40c = container_of(tx->chan, @@ -2176,7 +2188,6 @@ static void d40_set_runtime_config(struct dma_chan *chan, static int d40_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd, unsigned long arg) { - unsigned long flags; struct d40_chan *d40c = container_of(chan, struct d40_chan, chan); if (d40c->phy_chan == NULL) { @@ -2186,14 +2197,11 @@ static int d40_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd, switch (cmd) { case DMA_TERMINATE_ALL: - spin_lock_irqsave(&d40c->lock, flags); - d40_term_all(d40c); - spin_unlock_irqrestore(&d40c->lock, flags); - return 0; + return d40_terminate_all(d40c); case DMA_PAUSE: - return d40_pause(chan); + return d40_pause(d40c); case DMA_RESUME: - return d40_resume(chan); + return d40_resume(d40c); case DMA_SLAVE_CONFIG: d40_set_runtime_config(chan, (struct dma_slave_config *) arg); -- GitLab From 0c842b551063c5f7382ac9b457992f3b34972801 Mon Sep 17 00:00:00 2001 From: Rabin Vincent Date: Tue, 25 Jan 2011 11:18:35 +0100 Subject: [PATCH 0056/2822] dma40: cyclic xfer support Support cyclic transfers, which are useful for ALSA drivers. Acked-by: Per Forlin Acked-by: Jonas Aaberg Signed-off-by: Rabin Vincent Signed-off-by: Linus Walleij Signed-off-by: Dan Williams --- drivers/dma/ste_dma40.c | 172 ++++++++++++++++++++++++++++++------- drivers/dma/ste_dma40_ll.c | 35 +++++--- drivers/dma/ste_dma40_ll.h | 9 +- 3 files changed, 167 insertions(+), 49 deletions(-) diff --git a/drivers/dma/ste_dma40.c b/drivers/dma/ste_dma40.c index 8fd0bb94e777b..af955de035f42 100644 --- a/drivers/dma/ste_dma40.c +++ b/drivers/dma/ste_dma40.c @@ -115,6 +115,7 @@ struct d40_desc { struct list_head node; bool is_in_client_list; + bool cyclic; }; /** @@ -527,17 +528,45 @@ static void d40_log_lli_to_lcxa(struct d40_chan *chan, struct d40_desc *desc) struct d40_log_lli_bidir *lli = &desc->lli_log; int lli_current = desc->lli_current; int lli_len = desc->lli_len; + bool cyclic = desc->cyclic; int curr_lcla = -EINVAL; + int first_lcla = 0; + bool linkback; - if (lli_len - lli_current > 1) + /* + * We may have partially running cyclic transfers, in case we did't get + * enough LCLA entries. + */ + linkback = cyclic && lli_current == 0; + + /* + * For linkback, we need one LCLA even with only one link, because we + * can't link back to the one in LCPA space + */ + if (linkback || (lli_len - lli_current > 1)) { curr_lcla = d40_lcla_alloc_one(chan, desc); + first_lcla = curr_lcla; + } + + /* + * For linkback, we normally load the LCPA in the loop since we need to + * link it to the second LCLA and not the first. However, if we + * couldn't even get a first LCLA, then we have to run in LCPA and + * reload manually. + */ + if (!linkback || curr_lcla == -EINVAL) { + unsigned int flags = 0; - d40_log_lli_lcpa_write(chan->lcpa, - &lli->dst[lli_current], - &lli->src[lli_current], - curr_lcla); + if (curr_lcla == -EINVAL) + flags |= LLI_TERM_INT; - lli_current++; + d40_log_lli_lcpa_write(chan->lcpa, + &lli->dst[lli_current], + &lli->src[lli_current], + curr_lcla, + flags); + lli_current++; + } if (curr_lcla < 0) goto out; @@ -546,17 +575,33 @@ static void d40_log_lli_to_lcxa(struct d40_chan *chan, struct d40_desc *desc) unsigned int lcla_offset = chan->phy_chan->num * 1024 + 8 * curr_lcla * 2; struct d40_log_lli *lcla = pool->base + lcla_offset; + unsigned int flags = 0; int next_lcla; if (lli_current + 1 < lli_len) next_lcla = d40_lcla_alloc_one(chan, desc); else - next_lcla = -EINVAL; + next_lcla = linkback ? first_lcla : -EINVAL; + + if (cyclic || next_lcla == -EINVAL) + flags |= LLI_TERM_INT; + if (linkback && curr_lcla == first_lcla) { + /* First link goes in both LCPA and LCLA */ + d40_log_lli_lcpa_write(chan->lcpa, + &lli->dst[lli_current], + &lli->src[lli_current], + next_lcla, flags); + } + + /* + * One unused LCLA in the cyclic case if the very first + * next_lcla fails... + */ d40_log_lli_lcla_write(lcla, &lli->dst[lli_current], &lli->src[lli_current], - next_lcla); + next_lcla, flags); dma_sync_single_range_for_device(chan->base->dev, pool->dma_addr, lcla_offset, @@ -565,7 +610,7 @@ static void d40_log_lli_to_lcxa(struct d40_chan *chan, struct d40_desc *desc) curr_lcla = next_lcla; - if (curr_lcla == -EINVAL) { + if (curr_lcla == -EINVAL || curr_lcla == first_lcla) { lli_current++; break; } @@ -1074,17 +1119,36 @@ static void dma_tc_handle(struct d40_chan *d40c) if (d40d == NULL) return; - d40_lcla_free_all(d40c, d40d); + if (d40d->cyclic) { + /* + * If this was a paritially loaded list, we need to reloaded + * it, and only when the list is completed. We need to check + * for done because the interrupt will hit for every link, and + * not just the last one. + */ + if (d40d->lli_current < d40d->lli_len + && !d40_tx_is_linked(d40c) + && !d40_residue(d40c)) { + d40_lcla_free_all(d40c, d40d); + d40_desc_load(d40c, d40d); + (void) d40_start(d40c); - if (d40d->lli_current < d40d->lli_len) { - d40_desc_load(d40c, d40d); - /* Start dma job */ - (void) d40_start(d40c); - return; - } + if (d40d->lli_current == d40d->lli_len) + d40d->lli_current = 0; + } + } else { + d40_lcla_free_all(d40c, d40d); - if (d40_queue_start(d40c) == NULL) - d40c->busy = false; + if (d40d->lli_current < d40d->lli_len) { + d40_desc_load(d40c, d40d); + /* Start dma job */ + (void) d40_start(d40c); + return; + } + + if (d40_queue_start(d40c) == NULL) + d40c->busy = false; + } d40c->pending_tx++; tasklet_schedule(&d40c->tasklet); @@ -1103,11 +1167,11 @@ static void dma_tasklet(unsigned long data) /* Get first active entry from list */ d40d = d40_first_active_get(d40c); - if (d40d == NULL) goto err; - d40c->completed = d40d->txd.cookie; + if (!d40d->cyclic) + d40c->completed = d40d->txd.cookie; /* * If terminating a channel pending_tx is set to zero. @@ -1122,16 +1186,18 @@ static void dma_tasklet(unsigned long data) callback = d40d->txd.callback; callback_param = d40d->txd.callback_param; - if (async_tx_test_ack(&d40d->txd)) { - d40_pool_lli_free(d40c, d40d); - d40_desc_remove(d40d); - d40_desc_free(d40c, d40d); - } else { - if (!d40d->is_in_client_list) { + if (!d40d->cyclic) { + if (async_tx_test_ack(&d40d->txd)) { + d40_pool_lli_free(d40c, d40d); d40_desc_remove(d40d); - d40_lcla_free_all(d40c, d40d); - list_add_tail(&d40d->node, &d40c->client); - d40d->is_in_client_list = true; + d40_desc_free(d40c, d40d); + } else { + if (!d40d->is_in_client_list) { + d40_desc_remove(d40d); + d40_lcla_free_all(d40c, d40d); + list_add_tail(&d40d->node, &d40c->client); + d40d->is_in_client_list = true; + } } } @@ -1694,19 +1760,23 @@ d40_prep_sg_phy(struct d40_chan *chan, struct d40_desc *desc, struct stedma40_chan_cfg *cfg = &chan->dma_cfg; struct stedma40_half_channel_info *src_info = &cfg->src_info; struct stedma40_half_channel_info *dst_info = &cfg->dst_info; + unsigned long flags = 0; int ret; + if (desc->cyclic) + flags |= LLI_CYCLIC | LLI_TERM_INT; + ret = d40_phy_sg_to_lli(sg_src, sg_len, src_dev_addr, desc->lli_phy.src, virt_to_phys(desc->lli_phy.src), chan->src_def_cfg, - src_info, dst_info); + src_info, dst_info, flags); ret = d40_phy_sg_to_lli(sg_dst, sg_len, dst_dev_addr, desc->lli_phy.dst, virt_to_phys(desc->lli_phy.dst), chan->dst_def_cfg, - dst_info, src_info); + dst_info, src_info, flags); dma_sync_single_for_device(chan->base->dev, desc->lli_pool.dma_addr, desc->lli_pool.size, DMA_TO_DEVICE); @@ -1789,12 +1859,16 @@ d40_prep_sg(struct dma_chan *dchan, struct scatterlist *sg_src, return NULL; } + spin_lock_irqsave(&chan->lock, flags); desc = d40_prep_desc(chan, sg_src, sg_len, dma_flags); if (desc == NULL) goto err; + if (sg_next(&sg_src[sg_len - 1]) == sg_src) + desc->cyclic = true; + if (direction != DMA_NONE) { dma_addr_t dev_addr = d40_get_dev_addr(chan, direction); @@ -2007,6 +2081,36 @@ static struct dma_async_tx_descriptor *d40_prep_slave_sg(struct dma_chan *chan, return d40_prep_sg(chan, sgl, sgl, sg_len, direction, dma_flags); } +static struct dma_async_tx_descriptor * +dma40_prep_dma_cyclic(struct dma_chan *chan, dma_addr_t dma_addr, + size_t buf_len, size_t period_len, + enum dma_data_direction direction) +{ + unsigned int periods = buf_len / period_len; + struct dma_async_tx_descriptor *txd; + struct scatterlist *sg; + int i; + + sg = kcalloc(periods + 1, sizeof(struct scatterlist), GFP_KERNEL); + for (i = 0; i < periods; i++) { + sg_dma_address(&sg[i]) = dma_addr; + sg_dma_len(&sg[i]) = period_len; + dma_addr += period_len; + } + + sg[periods].offset = 0; + sg[periods].length = 0; + sg[periods].page_link = + ((unsigned long)sg | 0x01) & ~0x02; + + txd = d40_prep_sg(chan, sg, sg, periods, direction, + DMA_PREP_INTERRUPT); + + kfree(sg); + + return txd; +} + static enum dma_status d40_tx_status(struct dma_chan *chan, dma_cookie_t cookie, struct dma_tx_state *txstate) @@ -2264,6 +2368,9 @@ static void d40_ops_init(struct d40_base *base, struct dma_device *dev) if (dma_has_cap(DMA_SG, dev->cap_mask)) dev->device_prep_dma_sg = d40_prep_memcpy_sg; + if (dma_has_cap(DMA_CYCLIC, dev->cap_mask)) + dev->device_prep_dma_cyclic = dma40_prep_dma_cyclic; + dev->device_alloc_chan_resources = d40_alloc_chan_resources; dev->device_free_chan_resources = d40_free_chan_resources; dev->device_issue_pending = d40_issue_pending; @@ -2282,6 +2389,7 @@ static int __init d40_dmaengine_init(struct d40_base *base, dma_cap_zero(base->dma_slave.cap_mask); dma_cap_set(DMA_SLAVE, base->dma_slave.cap_mask); + dma_cap_set(DMA_CYCLIC, base->dma_slave.cap_mask); d40_ops_init(base, &base->dma_slave); @@ -2316,9 +2424,9 @@ static int __init d40_dmaengine_init(struct d40_base *base, dma_cap_set(DMA_SLAVE, base->dma_both.cap_mask); dma_cap_set(DMA_MEMCPY, base->dma_both.cap_mask); dma_cap_set(DMA_SG, base->dma_both.cap_mask); + dma_cap_set(DMA_CYCLIC, base->dma_slave.cap_mask); d40_ops_init(base, &base->dma_both); - err = dma_async_device_register(&base->dma_both); if (err) { diff --git a/drivers/dma/ste_dma40_ll.c b/drivers/dma/ste_dma40_ll.c index 88b9e371be2f0..cad9e1daedff4 100644 --- a/drivers/dma/ste_dma40_ll.c +++ b/drivers/dma/ste_dma40_ll.c @@ -202,13 +202,15 @@ static int d40_seg_size(int size, int data_width1, int data_width2) static struct d40_phy_lli * d40_phy_buf_to_lli(struct d40_phy_lli *lli, dma_addr_t addr, u32 size, - dma_addr_t lli_phys, u32 reg_cfg, + dma_addr_t lli_phys, dma_addr_t first_phys, u32 reg_cfg, struct stedma40_half_channel_info *info, struct stedma40_half_channel_info *otherinfo, unsigned long flags) { + bool lastlink = flags & LLI_LAST_LINK; bool addr_inc = flags & LLI_ADDR_INC; bool term_int = flags & LLI_TERM_INT; + bool cyclic = flags & LLI_CYCLIC; int err; dma_addr_t next = lli_phys; int size_rest = size; @@ -226,10 +228,12 @@ d40_phy_buf_to_lli(struct d40_phy_lli *lli, dma_addr_t addr, u32 size, otherinfo->data_width); size_rest -= size_seg; - if (term_int && size_rest == 0) { - next = 0; + if (size_rest == 0 && term_int) flags |= LLI_TERM_INT; - } else + + if (size_rest == 0 && lastlink) + next = cyclic ? first_phys : 0; + else next = ALIGN(next + sizeof(struct d40_phy_lli), D40_LLI_ALIGN); @@ -257,14 +261,14 @@ int d40_phy_sg_to_lli(struct scatterlist *sg, dma_addr_t lli_phys, u32 reg_cfg, struct stedma40_half_channel_info *info, - struct stedma40_half_channel_info *otherinfo) + struct stedma40_half_channel_info *otherinfo, + unsigned long flags) { int total_size = 0; int i; struct scatterlist *current_sg = sg; struct d40_phy_lli *lli = lli_sg; dma_addr_t l_phys = lli_phys; - unsigned long flags = 0; if (!target) flags |= LLI_ADDR_INC; @@ -277,12 +281,12 @@ int d40_phy_sg_to_lli(struct scatterlist *sg, total_size += sg_dma_len(current_sg); if (i == sg_len - 1) - flags |= LLI_TERM_INT; + flags |= LLI_TERM_INT | LLI_LAST_LINK; l_phys = ALIGN(lli_phys + (lli - lli_sg) * sizeof(struct d40_phy_lli), D40_LLI_ALIGN); - lli = d40_phy_buf_to_lli(lli, dst, len, l_phys, + lli = d40_phy_buf_to_lli(lli, dst, len, l_phys, lli_phys, reg_cfg, info, otherinfo, flags); if (lli == NULL) @@ -297,15 +301,18 @@ int d40_phy_sg_to_lli(struct scatterlist *sg, static void d40_log_lli_link(struct d40_log_lli *lli_dst, struct d40_log_lli *lli_src, - int next) + int next, unsigned int flags) { + bool interrupt = flags & LLI_TERM_INT; u32 slos = 0; u32 dlos = 0; if (next != -EINVAL) { slos = next * 2; dlos = next * 2 + 1; - } else { + } + + if (interrupt) { lli_dst->lcsp13 |= D40_MEM_LCSP1_SCFG_TIM_MASK; lli_dst->lcsp13 |= D40_MEM_LCSP3_DTCP_MASK; } @@ -320,9 +327,9 @@ static void d40_log_lli_link(struct d40_log_lli *lli_dst, void d40_log_lli_lcpa_write(struct d40_log_lli_full *lcpa, struct d40_log_lli *lli_dst, struct d40_log_lli *lli_src, - int next) + int next, unsigned int flags) { - d40_log_lli_link(lli_dst, lli_src, next); + d40_log_lli_link(lli_dst, lli_src, next, flags); writel(lli_src->lcsp02, &lcpa[0].lcsp0); writel(lli_src->lcsp13, &lcpa[0].lcsp1); @@ -333,9 +340,9 @@ void d40_log_lli_lcpa_write(struct d40_log_lli_full *lcpa, void d40_log_lli_lcla_write(struct d40_log_lli *lcla, struct d40_log_lli *lli_dst, struct d40_log_lli *lli_src, - int next) + int next, unsigned int flags) { - d40_log_lli_link(lli_dst, lli_src, next); + d40_log_lli_link(lli_dst, lli_src, next, flags); writel(lli_src->lcsp02, &lcla[0].lcsp02); writel(lli_src->lcsp13, &lcla[0].lcsp13); diff --git a/drivers/dma/ste_dma40_ll.h b/drivers/dma/ste_dma40_ll.h index 59e72f0cc901f..195ee65ee7f35 100644 --- a/drivers/dma/ste_dma40_ll.h +++ b/drivers/dma/ste_dma40_ll.h @@ -296,6 +296,8 @@ struct d40_def_lcsp { enum d40_lli_flags { LLI_ADDR_INC = 1 << 0, LLI_TERM_INT = 1 << 1, + LLI_CYCLIC = 1 << 2, + LLI_LAST_LINK = 1 << 3, }; void d40_phy_cfg(struct stedma40_chan_cfg *cfg, @@ -314,7 +316,8 @@ int d40_phy_sg_to_lli(struct scatterlist *sg, dma_addr_t lli_phys, u32 reg_cfg, struct stedma40_half_channel_info *info, - struct stedma40_half_channel_info *otherinfo); + struct stedma40_half_channel_info *otherinfo, + unsigned long flags); /* Logical channels */ @@ -328,11 +331,11 @@ int d40_log_sg_to_lli(struct scatterlist *sg, void d40_log_lli_lcpa_write(struct d40_log_lli_full *lcpa, struct d40_log_lli *lli_dst, struct d40_log_lli *lli_src, - int next); + int next, unsigned int flags); void d40_log_lli_lcla_write(struct d40_log_lli *lcla, struct d40_log_lli *lli_dst, struct d40_log_lli *lli_src, - int next); + int next, unsigned int flags); #endif /* STE_DMA40_LLI_H */ -- GitLab From 51d07566045787b99219d809639c8724506fc78a Mon Sep 17 00:00:00 2001 From: Rhyland Klein Date: Tue, 25 Jan 2011 11:10:06 -0800 Subject: [PATCH 0057/2822] bq20z75: Add support for charge properties Adding support for charge properties for gas gauge. Also ensuring that battery mode is correct now for energy as well as charge properties by setting it on the fly. I also added 2 functions to power_supply.h to help identify the units for specific properties more easily by power supplies. Signed-off-by: Rhyland Klein Signed-off-by: Anton Vorontsov --- drivers/power/bq20z75.c | 98 ++++++++++++++++++++++++++++++++---- include/linux/power_supply.h | 44 ++++++++++++++++ 2 files changed, 131 insertions(+), 11 deletions(-) diff --git a/drivers/power/bq20z75.c b/drivers/power/bq20z75.c index 492da27e1a47e..4141775e5ff60 100644 --- a/drivers/power/bq20z75.c +++ b/drivers/power/bq20z75.c @@ -38,11 +38,22 @@ enum { REG_CYCLE_COUNT, REG_SERIAL_NUMBER, REG_REMAINING_CAPACITY, + REG_REMAINING_CAPACITY_CHARGE, REG_FULL_CHARGE_CAPACITY, + REG_FULL_CHARGE_CAPACITY_CHARGE, REG_DESIGN_CAPACITY, + REG_DESIGN_CAPACITY_CHARGE, REG_DESIGN_VOLTAGE, }; +/* Battery Mode defines */ +#define BATTERY_MODE_OFFSET 0x03 +#define BATTERY_MODE_MASK 0x8000 +enum bq20z75_battery_mode { + BATTERY_MODE_AMPS, + BATTERY_MODE_WATTS +}; + /* manufacturer access defines */ #define MANUFACTURER_ACCESS_STATUS 0x0006 #define MANUFACTURER_ACCESS_SLEEP 0x0011 @@ -78,8 +89,12 @@ static const struct bq20z75_device_data { BQ20Z75_DATA(POWER_SUPPLY_PROP_CAPACITY, 0x0E, 0, 100), [REG_REMAINING_CAPACITY] = BQ20Z75_DATA(POWER_SUPPLY_PROP_ENERGY_NOW, 0x0F, 0, 65535), + [REG_REMAINING_CAPACITY_CHARGE] = + BQ20Z75_DATA(POWER_SUPPLY_PROP_CHARGE_NOW, 0x0F, 0, 65535), [REG_FULL_CHARGE_CAPACITY] = BQ20Z75_DATA(POWER_SUPPLY_PROP_ENERGY_FULL, 0x10, 0, 65535), + [REG_FULL_CHARGE_CAPACITY_CHARGE] = + BQ20Z75_DATA(POWER_SUPPLY_PROP_CHARGE_FULL, 0x10, 0, 65535), [REG_TIME_TO_EMPTY] = BQ20Z75_DATA(POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG, 0x12, 0, 65535), @@ -93,6 +108,9 @@ static const struct bq20z75_device_data { [REG_DESIGN_CAPACITY] = BQ20Z75_DATA(POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN, 0x18, 0, 65535), + [REG_DESIGN_CAPACITY_CHARGE] = + BQ20Z75_DATA(POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN, 0x18, 0, + 65535), [REG_DESIGN_VOLTAGE] = BQ20Z75_DATA(POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN, 0x19, 0, 65535), @@ -117,6 +135,9 @@ static enum power_supply_property bq20z75_properties[] = { POWER_SUPPLY_PROP_ENERGY_NOW, POWER_SUPPLY_PROP_ENERGY_FULL, POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN, + POWER_SUPPLY_PROP_CHARGE_NOW, + POWER_SUPPLY_PROP_CHARGE_FULL, + POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN, }; struct bq20z75_info { @@ -260,6 +281,9 @@ static void bq20z75_unit_adjustment(struct i2c_client *client, case POWER_SUPPLY_PROP_VOLTAGE_NOW: case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN: case POWER_SUPPLY_PROP_CURRENT_NOW: + case POWER_SUPPLY_PROP_CHARGE_NOW: + case POWER_SUPPLY_PROP_CHARGE_FULL: + case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN: val->intval *= BASE_UNIT_CONVERSION; break; @@ -281,11 +305,44 @@ static void bq20z75_unit_adjustment(struct i2c_client *client, } } +static enum bq20z75_battery_mode +bq20z75_set_battery_mode(struct i2c_client *client, + enum bq20z75_battery_mode mode) +{ + int ret, original_val; + + original_val = bq20z75_read_word_data(client, BATTERY_MODE_OFFSET); + if (original_val < 0) + return original_val; + + if ((original_val & BATTERY_MODE_MASK) == mode) + return mode; + + if (mode == BATTERY_MODE_AMPS) + ret = original_val & ~BATTERY_MODE_MASK; + else + ret = original_val | BATTERY_MODE_MASK; + + ret = bq20z75_write_word_data(client, BATTERY_MODE_OFFSET, ret); + if (ret < 0) + return ret; + + return original_val & BATTERY_MODE_MASK; +} + static int bq20z75_get_battery_capacity(struct i2c_client *client, int reg_offset, enum power_supply_property psp, union power_supply_propval *val) { s32 ret; + enum bq20z75_battery_mode mode = BATTERY_MODE_WATTS; + + if (power_supply_is_amp_property(psp)) + mode = BATTERY_MODE_AMPS; + + mode = bq20z75_set_battery_mode(client, mode); + if (mode < 0) + return mode; ret = bq20z75_read_word_data(client, bq20z75_data[reg_offset].addr); if (ret < 0) @@ -298,6 +355,10 @@ static int bq20z75_get_battery_capacity(struct i2c_client *client, } else val->intval = ret; + ret = bq20z75_set_battery_mode(client, mode); + if (ret < 0) + return ret; + return 0; } @@ -318,11 +379,25 @@ static int bq20z75_get_battery_serial_number(struct i2c_client *client, return 0; } +static int bq20z75_get_property_index(struct i2c_client *client, + enum power_supply_property psp) +{ + int count; + for (count = 0; count < ARRAY_SIZE(bq20z75_data); count++) + if (psp == bq20z75_data[count].psp) + return count; + + dev_warn(&client->dev, + "%s: Invalid Property - %d\n", __func__, psp); + + return -EINVAL; +} + static int bq20z75_get_property(struct power_supply *psy, enum power_supply_property psp, union power_supply_propval *val) { - int count; + int ps_index; int ret; struct bq20z75_info *bq20z75_device = container_of(psy, struct bq20z75_info, power_supply); @@ -343,13 +418,15 @@ static int bq20z75_get_property(struct power_supply *psy, case POWER_SUPPLY_PROP_ENERGY_NOW: case POWER_SUPPLY_PROP_ENERGY_FULL: case POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN: + case POWER_SUPPLY_PROP_CHARGE_NOW: + case POWER_SUPPLY_PROP_CHARGE_FULL: + case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN: case POWER_SUPPLY_PROP_CAPACITY: - for (count = 0; count < ARRAY_SIZE(bq20z75_data); count++) { - if (psp == bq20z75_data[count].psp) - break; - } + ps_index = bq20z75_get_property_index(client, psp); + if (ps_index < 0) + return ps_index; - ret = bq20z75_get_battery_capacity(client, count, psp, val); + ret = bq20z75_get_battery_capacity(client, ps_index, psp, val); if (ret) return ret; @@ -369,12 +446,11 @@ static int bq20z75_get_property(struct power_supply *psy, case POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG: case POWER_SUPPLY_PROP_TIME_TO_FULL_AVG: case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN: - for (count = 0; count < ARRAY_SIZE(bq20z75_data); count++) { - if (psp == bq20z75_data[count].psp) - break; - } + ps_index = bq20z75_get_property_index(client, psp); + if (ps_index < 0) + return ps_index; - ret = bq20z75_get_battery_property(client, count, psp, val); + ret = bq20z75_get_battery_property(client, ps_index, psp, val); if (ret) return ret; diff --git a/include/linux/power_supply.h b/include/linux/power_supply.h index 7d7325685c421..e3419fc5541e0 100644 --- a/include/linux/power_supply.h +++ b/include/linux/power_supply.h @@ -213,4 +213,48 @@ extern void power_supply_unregister(struct power_supply *psy); /* For APM emulation, think legacy userspace. */ extern struct class *power_supply_class; +static inline bool power_supply_is_amp_property(enum power_supply_property psp) +{ + switch (psp) { + case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN: + case POWER_SUPPLY_PROP_CHARGE_EMPTY_DESIGN: + case POWER_SUPPLY_PROP_CHARGE_FULL: + case POWER_SUPPLY_PROP_CHARGE_EMPTY: + case POWER_SUPPLY_PROP_CHARGE_NOW: + case POWER_SUPPLY_PROP_CHARGE_AVG: + case POWER_SUPPLY_PROP_CHARGE_COUNTER: + case POWER_SUPPLY_PROP_CURRENT_MAX: + case POWER_SUPPLY_PROP_CURRENT_NOW: + case POWER_SUPPLY_PROP_CURRENT_AVG: + return 1; + default: + break; + } + + return 0; +} + +static inline bool power_supply_is_watt_property(enum power_supply_property psp) +{ + switch (psp) { + case POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN: + case POWER_SUPPLY_PROP_ENERGY_EMPTY_DESIGN: + case POWER_SUPPLY_PROP_ENERGY_FULL: + case POWER_SUPPLY_PROP_ENERGY_EMPTY: + case POWER_SUPPLY_PROP_ENERGY_NOW: + case POWER_SUPPLY_PROP_ENERGY_AVG: + case POWER_SUPPLY_PROP_VOLTAGE_MAX: + case POWER_SUPPLY_PROP_VOLTAGE_MIN: + case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN: + case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN: + case POWER_SUPPLY_PROP_VOLTAGE_NOW: + case POWER_SUPPLY_PROP_VOLTAGE_AVG: + return 1; + default: + break; + } + + return 0; +} + #endif /* __LINUX_POWER_SUPPLY_H__ */ -- GitLab From 0b9536c957095eb1497828aa51b34ac695f67eae Mon Sep 17 00:00:00 2001 From: Vasily Khoruzhick Date: Fri, 7 Jan 2011 16:28:16 +0000 Subject: [PATCH 0058/2822] leds: Add ability to blink via simple trigger As blink API is now available, it's possible to add ability to blink via simple trigger. Signed-off-by: Vasily Khoruzhick Signed-off-by: Anton Vorontsov --- drivers/leds/led-triggers.c | 20 ++++++++++++++++++++ include/linux/leds.h | 3 +++ 2 files changed, 23 insertions(+) diff --git a/drivers/leds/led-triggers.c b/drivers/leds/led-triggers.c index c41eb6180c9c2..4bebae733349b 100644 --- a/drivers/leds/led-triggers.c +++ b/drivers/leds/led-triggers.c @@ -231,6 +231,26 @@ void led_trigger_event(struct led_trigger *trigger, } EXPORT_SYMBOL_GPL(led_trigger_event); +void led_trigger_blink(struct led_trigger *trigger, + unsigned long *delay_on, + unsigned long *delay_off) +{ + struct list_head *entry; + + if (!trigger) + return; + + read_lock(&trigger->leddev_list_lock); + list_for_each(entry, &trigger->led_cdevs) { + struct led_classdev *led_cdev; + + led_cdev = list_entry(entry, struct led_classdev, trig_list); + led_blink_set(led_cdev, delay_on, delay_off); + } + read_unlock(&trigger->leddev_list_lock); +} +EXPORT_SYMBOL_GPL(led_trigger_blink); + void led_trigger_register_simple(const char *name, struct led_trigger **tp) { struct led_trigger *trigger; diff --git a/include/linux/leds.h b/include/linux/leds.h index 0f19df9e37b0f..ffd5c3d911933 100644 --- a/include/linux/leds.h +++ b/include/linux/leds.h @@ -145,6 +145,9 @@ extern void led_trigger_register_simple(const char *name, extern void led_trigger_unregister_simple(struct led_trigger *trigger); extern void led_trigger_event(struct led_trigger *trigger, enum led_brightness event); +extern void led_trigger_blink(struct led_trigger *trigger, + unsigned long *delay_on, + unsigned long *delay_off); #else -- GitLab From 6501f728c56f831626d52b236023e556bca37f51 Mon Sep 17 00:00:00 2001 From: Vasily Khoruzhick Date: Fri, 7 Jan 2011 18:28:17 +0200 Subject: [PATCH 0059/2822] power_supply: Add new LED trigger charging-blink-solid-full Add new trigger to power_supply LEDs. It will blink when battery is charging, and stay solid when battery is charged. It's usefull to indicate battery state when there's only one LED available. Signed-off-by: Vasily Khoruzhick Signed-off-by: Anton Vorontsov --- drivers/power/power_supply_leds.c | 19 +++++++++++++++++++ include/linux/power_supply.h | 2 ++ 2 files changed, 21 insertions(+) diff --git a/drivers/power/power_supply_leds.c b/drivers/power/power_supply_leds.c index 031a554837f78..da25eb94e5c64 100644 --- a/drivers/power/power_supply_leds.c +++ b/drivers/power/power_supply_leds.c @@ -21,6 +21,8 @@ static void power_supply_update_bat_leds(struct power_supply *psy) { union power_supply_propval status; + unsigned long delay_on = 0; + unsigned long delay_off = 0; if (psy->get_property(psy, POWER_SUPPLY_PROP_STATUS, &status)) return; @@ -32,16 +34,22 @@ static void power_supply_update_bat_leds(struct power_supply *psy) led_trigger_event(psy->charging_full_trig, LED_FULL); led_trigger_event(psy->charging_trig, LED_OFF); led_trigger_event(psy->full_trig, LED_FULL); + led_trigger_event(psy->charging_blink_full_solid_trig, + LED_FULL); break; case POWER_SUPPLY_STATUS_CHARGING: led_trigger_event(psy->charging_full_trig, LED_FULL); led_trigger_event(psy->charging_trig, LED_FULL); led_trigger_event(psy->full_trig, LED_OFF); + led_trigger_blink(psy->charging_blink_full_solid_trig, + &delay_on, &delay_off); break; default: led_trigger_event(psy->charging_full_trig, LED_OFF); led_trigger_event(psy->charging_trig, LED_OFF); led_trigger_event(psy->full_trig, LED_OFF); + led_trigger_event(psy->charging_blink_full_solid_trig, + LED_OFF); break; } } @@ -64,15 +72,24 @@ static int power_supply_create_bat_triggers(struct power_supply *psy) if (!psy->full_trig_name) goto full_failed; + psy->charging_blink_full_solid_trig_name = kasprintf(GFP_KERNEL, + "%s-charging-blink-full-solid", psy->name); + if (!psy->charging_blink_full_solid_trig_name) + goto charging_blink_full_solid_failed; + led_trigger_register_simple(psy->charging_full_trig_name, &psy->charging_full_trig); led_trigger_register_simple(psy->charging_trig_name, &psy->charging_trig); led_trigger_register_simple(psy->full_trig_name, &psy->full_trig); + led_trigger_register_simple(psy->charging_blink_full_solid_trig_name, + &psy->charging_blink_full_solid_trig); goto success; +charging_blink_full_solid_failed: + kfree(psy->full_trig_name); full_failed: kfree(psy->charging_trig_name); charging_failed: @@ -88,6 +105,8 @@ static void power_supply_remove_bat_triggers(struct power_supply *psy) led_trigger_unregister_simple(psy->charging_full_trig); led_trigger_unregister_simple(psy->charging_trig); led_trigger_unregister_simple(psy->full_trig); + led_trigger_unregister_simple(psy->charging_blink_full_solid_trig); + kfree(psy->charging_blink_full_solid_trig_name); kfree(psy->full_trig_name); kfree(psy->charging_trig_name); kfree(psy->charging_full_trig_name); diff --git a/include/linux/power_supply.h b/include/linux/power_supply.h index e3419fc5541e0..20f23fef63cce 100644 --- a/include/linux/power_supply.h +++ b/include/linux/power_supply.h @@ -173,6 +173,8 @@ struct power_supply { char *full_trig_name; struct led_trigger *online_trig; char *online_trig_name; + struct led_trigger *charging_blink_full_solid_trig; + char *charging_blink_full_solid_trig_name; #endif }; -- GitLab From 723d928417bffff6467da155d8ebbbe016464012 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Mon, 31 Jan 2011 21:09:25 -0800 Subject: [PATCH 0060/2822] Input: wm831x-ts - remove use of ternary operator While being applied the driver was modified to add use of the ternary operator. Write the conditionals out longhand as I find it terribly unhelpful for legibility. Signed-off-by: Mark Brown Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/wm831x-ts.c | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/drivers/input/touchscreen/wm831x-ts.c b/drivers/input/touchscreen/wm831x-ts.c index a6121bdb635df..1022f715d3c25 100644 --- a/drivers/input/touchscreen/wm831x-ts.c +++ b/drivers/input/touchscreen/wm831x-ts.c @@ -76,9 +76,14 @@ static irqreturn_t wm831x_ts_data_irq(int irq, void *irq_data) struct wm831x *wm831x = wm831x_ts->wm831x; static int data_types[] = { ABS_X, ABS_Y, ABS_PRESSURE }; u16 data[3]; - int count = wm831x_ts->pressure ? 3 : 2; + int count; int i, ret; + if (wm831x_ts->pressure) + count = 3; + else + count = 2; + wm831x_set_bits(wm831x, WM831X_INTERRUPT_STATUS_1, WM831X_TCHDATA_EINT, WM831X_TCHDATA_EINT); @@ -134,10 +139,11 @@ static irqreturn_t wm831x_ts_pen_down_irq(int irq, void *irq_data) { struct wm831x_ts *wm831x_ts = irq_data; struct wm831x *wm831x = wm831x_ts->wm831x; - int ena; + int ena = 0; /* Start collecting data */ - ena = wm831x_ts->pressure ? WM831X_TCH_Z_ENA : 0; + if (wm831x_ts->pressure) + ena |= WM831X_TCH_Z_ENA; wm831x_set_bits(wm831x, WM831X_TOUCH_CONTROL_1, WM831X_TCH_X_ENA | WM831X_TCH_Y_ENA | WM831X_TCH_Z_ENA, @@ -188,11 +194,13 @@ static __devinit int wm831x_ts_probe(struct platform_device *pdev) struct wm831x_ts *wm831x_ts; struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent); struct wm831x_pdata *core_pdata = dev_get_platdata(pdev->dev.parent); - struct wm831x_touch_pdata *pdata = - core_pdata ? core_pdata->touch : NULL; + struct wm831x_touch_pdata *pdata = NULL; struct input_dev *input_dev; int error; + if (core_pdata) + pdata = core_pdata->touch; + wm831x_ts = kzalloc(sizeof(struct wm831x_ts), GFP_KERNEL); input_dev = input_allocate_device(); if (!wm831x_ts || !input_dev) { -- GitLab From f06e6a52ca3dbe927f58653b1e90cbb53f5ceb55 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Mon, 31 Jan 2011 21:06:39 -0800 Subject: [PATCH 0061/2822] Input: dvb-usb-remote - convert to new style of get/setkeycode Acked-by: Mauro Carvalho Chehab Signed-off-by: Dmitry Torokhov --- drivers/media/dvb/dvb-usb/dvb-usb-remote.c | 113 +++++++++++++-------- 1 file changed, 70 insertions(+), 43 deletions(-) diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-remote.c b/drivers/media/dvb/dvb-usb/dvb-usb-remote.c index 23005b3cf30be..347fbd4e2d561 100644 --- a/drivers/media/dvb/dvb-usb/dvb-usb-remote.c +++ b/drivers/media/dvb/dvb-usb/dvb-usb-remote.c @@ -8,60 +8,71 @@ #include "dvb-usb-common.h" #include +static unsigned int +legacy_dvb_usb_get_keymap_index(const struct input_keymap_entry *ke, + struct rc_map_table *keymap, + unsigned int keymap_size) +{ + unsigned int index; + unsigned int scancode; + + if (ke->flags & INPUT_KEYMAP_BY_INDEX) { + index = ke->index; + } else { + if (input_scancode_to_scalar(ke, &scancode)) + return keymap_size; + + /* See if we can match the raw key code. */ + for (index = 0; index < keymap_size; index++) + if (keymap[index].scancode == scancode) + break; + + /* See if there is an unused hole in the map */ + if (index >= keymap_size) { + for (index = 0; index < keymap_size; index++) { + if (keymap[index].keycode == KEY_RESERVED || + keymap[index].keycode == KEY_UNKNOWN) { + break; + } + } + } + } + + return index; +} + static int legacy_dvb_usb_getkeycode(struct input_dev *dev, - unsigned int scancode, unsigned int *keycode) + struct input_keymap_entry *ke) { struct dvb_usb_device *d = input_get_drvdata(dev); - struct rc_map_table *keymap = d->props.rc.legacy.rc_map_table; - int i; + unsigned int keymap_size = d->props.rc.legacy.rc_map_size; + unsigned int index; - /* See if we can match the raw key code. */ - for (i = 0; i < d->props.rc.legacy.rc_map_size; i++) - if (keymap[i].scancode == scancode) { - *keycode = keymap[i].keycode; - return 0; - } + index = legacy_dvb_usb_get_keymap_index(ke, keymap, keymap_size); + if (index >= keymap_size) + return -EINVAL; - /* - * If is there extra space, returns KEY_RESERVED, - * otherwise, input core won't let legacy_dvb_usb_setkeycode - * to work - */ - for (i = 0; i < d->props.rc.legacy.rc_map_size; i++) - if (keymap[i].keycode == KEY_RESERVED || - keymap[i].keycode == KEY_UNKNOWN) { - *keycode = KEY_RESERVED; - return 0; - } + ke->keycode = keymap[index].keycode; + if (ke->keycode == KEY_UNKNOWN) + ke->keycode = KEY_RESERVED; + ke->len = sizeof(keymap[index].scancode); + memcpy(&ke->scancode, &keymap[index].scancode, ke->len); + ke->index = index; - return -EINVAL; + return 0; } static int legacy_dvb_usb_setkeycode(struct input_dev *dev, - unsigned int scancode, unsigned int keycode) + const struct input_keymap_entry *ke, + unsigned int *old_keycode) { struct dvb_usb_device *d = input_get_drvdata(dev); - struct rc_map_table *keymap = d->props.rc.legacy.rc_map_table; - int i; - - /* Search if it is replacing an existing keycode */ - for (i = 0; i < d->props.rc.legacy.rc_map_size; i++) - if (keymap[i].scancode == scancode) { - keymap[i].keycode = keycode; - return 0; - } - - /* Search if is there a clean entry. If so, use it */ - for (i = 0; i < d->props.rc.legacy.rc_map_size; i++) - if (keymap[i].keycode == KEY_RESERVED || - keymap[i].keycode == KEY_UNKNOWN) { - keymap[i].scancode = scancode; - keymap[i].keycode = keycode; - return 0; - } + unsigned int keymap_size = d->props.rc.legacy.rc_map_size; + unsigned int index; + index = legacy_dvb_usb_get_keymap_index(ke, keymap, keymap_size); /* * FIXME: Currently, it is not possible to increase the size of * scancode table. For it to happen, one possibility @@ -69,8 +80,24 @@ static int legacy_dvb_usb_setkeycode(struct input_dev *dev, * copying data, appending the new key on it, and freeing * the old one - or maybe just allocating some spare space */ + if (index >= keymap_size) + return -EINVAL; + + *old_keycode = keymap[index].keycode; + keymap->keycode = ke->keycode; + __set_bit(ke->keycode, dev->keybit); + + if (*old_keycode != KEY_RESERVED) { + __clear_bit(*old_keycode, dev->keybit); + for (index = 0; index < keymap_size; index++) { + if (keymap[index].keycode == *old_keycode) { + __set_bit(*old_keycode, dev->keybit); + break; + } + } + } - return -EINVAL; + return 0; } /* Remote-control poll function - called every dib->rc_query_interval ms to see @@ -171,8 +198,8 @@ static int legacy_dvb_usb_remote_init(struct dvb_usb_device *d) d->input_dev = input_dev; d->rc_dev = NULL; - input_dev->getkeycode = legacy_dvb_usb_getkeycode; - input_dev->setkeycode = legacy_dvb_usb_setkeycode; + input_dev->getkeycode_new = legacy_dvb_usb_getkeycode; + input_dev->setkeycode_new = legacy_dvb_usb_setkeycode; /* set the bits for the keys */ deb_rc("key map size: %d\n", d->props.rc.legacy.rc_map_size); -- GitLab From aebd636bd60e2dda0ebc907dd5f7f4a45174411c Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Mon, 31 Jan 2011 21:06:39 -0800 Subject: [PATCH 0062/2822] Input: switch completely over to the new versions of get/setkeycode All users of old style get/setkeycode methids have been converted so it is time to retire them. Acked-by: Mauro Carvalho Chehab Acked-by: Jiri Kosina Signed-off-by: Dmitry Torokhov --- drivers/hid/hid-input.c | 4 +- drivers/input/input.c | 55 +++------------------- drivers/input/misc/ati_remote2.c | 4 +- drivers/input/sparse-keymap.c | 4 +- drivers/media/dvb/dvb-usb/dvb-usb-remote.c | 4 +- drivers/media/rc/rc-main.c | 4 +- include/linux/input.h | 12 ++--- 7 files changed, 20 insertions(+), 67 deletions(-) diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c index 7f552bfad32c0..ba2aeea2cbf99 100644 --- a/drivers/hid/hid-input.c +++ b/drivers/hid/hid-input.c @@ -888,8 +888,8 @@ int hidinput_connect(struct hid_device *hid, unsigned int force) hid->ll_driver->hidinput_input_event; input_dev->open = hidinput_open; input_dev->close = hidinput_close; - input_dev->setkeycode_new = hidinput_setkeycode; - input_dev->getkeycode_new = hidinput_getkeycode; + input_dev->setkeycode = hidinput_setkeycode; + input_dev->getkeycode = hidinput_getkeycode; input_dev->name = hid->name; input_dev->phys = hid->phys; diff --git a/drivers/input/input.c b/drivers/input/input.c index 7985114beac72..ee2959bd322c5 100644 --- a/drivers/input/input.c +++ b/drivers/input/input.c @@ -806,22 +806,9 @@ int input_get_keycode(struct input_dev *dev, struct input_keymap_entry *ke) int retval; spin_lock_irqsave(&dev->event_lock, flags); - - if (dev->getkeycode) { - /* - * Support for legacy drivers, that don't implement the new - * ioctls - */ - u32 scancode = ke->index; - - memcpy(ke->scancode, &scancode, sizeof(scancode)); - ke->len = sizeof(scancode); - retval = dev->getkeycode(dev, scancode, &ke->keycode); - } else { - retval = dev->getkeycode_new(dev, ke); - } - + retval = dev->getkeycode(dev, ke); spin_unlock_irqrestore(&dev->event_lock, flags); + return retval; } EXPORT_SYMBOL(input_get_keycode); @@ -846,35 +833,7 @@ int input_set_keycode(struct input_dev *dev, spin_lock_irqsave(&dev->event_lock, flags); - if (dev->setkeycode) { - /* - * Support for legacy drivers, that don't implement the new - * ioctls - */ - unsigned int scancode; - - retval = input_scancode_to_scalar(ke, &scancode); - if (retval) - goto out; - - /* - * We need to know the old scancode, in order to generate a - * keyup effect, if the set operation happens successfully - */ - if (!dev->getkeycode) { - retval = -EINVAL; - goto out; - } - - retval = dev->getkeycode(dev, scancode, &old_keycode); - if (retval) - goto out; - - retval = dev->setkeycode(dev, scancode, ke->keycode); - } else { - retval = dev->setkeycode_new(dev, ke, &old_keycode); - } - + retval = dev->setkeycode(dev, ke, &old_keycode); if (retval) goto out; @@ -1861,11 +1820,11 @@ int input_register_device(struct input_dev *dev) dev->rep[REP_PERIOD] = 33; } - if (!dev->getkeycode && !dev->getkeycode_new) - dev->getkeycode_new = input_default_getkeycode; + if (!dev->getkeycode) + dev->getkeycode = input_default_getkeycode; - if (!dev->setkeycode && !dev->setkeycode_new) - dev->setkeycode_new = input_default_setkeycode; + if (!dev->setkeycode) + dev->setkeycode = input_default_setkeycode; dev_set_name(&dev->dev, "input%ld", (unsigned long) atomic_inc_return(&input_no) - 1); diff --git a/drivers/input/misc/ati_remote2.c b/drivers/input/misc/ati_remote2.c index 0b0e9be635421..9ccdb82d869a0 100644 --- a/drivers/input/misc/ati_remote2.c +++ b/drivers/input/misc/ati_remote2.c @@ -612,8 +612,8 @@ static int ati_remote2_input_init(struct ati_remote2 *ar2) idev->open = ati_remote2_open; idev->close = ati_remote2_close; - idev->getkeycode_new = ati_remote2_getkeycode; - idev->setkeycode_new = ati_remote2_setkeycode; + idev->getkeycode = ati_remote2_getkeycode; + idev->setkeycode = ati_remote2_setkeycode; idev->name = ar2->name; idev->phys = ar2->phys; diff --git a/drivers/input/sparse-keymap.c b/drivers/input/sparse-keymap.c index 7729e547ba65d..337bf51bc9842 100644 --- a/drivers/input/sparse-keymap.c +++ b/drivers/input/sparse-keymap.c @@ -210,8 +210,8 @@ int sparse_keymap_setup(struct input_dev *dev, dev->keycode = map; dev->keycodemax = map_size; - dev->getkeycode_new = sparse_keymap_getkeycode; - dev->setkeycode_new = sparse_keymap_setkeycode; + dev->getkeycode = sparse_keymap_getkeycode; + dev->setkeycode = sparse_keymap_setkeycode; return 0; diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-remote.c b/drivers/media/dvb/dvb-usb/dvb-usb-remote.c index 347fbd4e2d561..b2b9415d874d0 100644 --- a/drivers/media/dvb/dvb-usb/dvb-usb-remote.c +++ b/drivers/media/dvb/dvb-usb/dvb-usb-remote.c @@ -198,8 +198,8 @@ static int legacy_dvb_usb_remote_init(struct dvb_usb_device *d) d->input_dev = input_dev; d->rc_dev = NULL; - input_dev->getkeycode_new = legacy_dvb_usb_getkeycode; - input_dev->setkeycode_new = legacy_dvb_usb_setkeycode; + input_dev->getkeycode = legacy_dvb_usb_getkeycode; + input_dev->setkeycode = legacy_dvb_usb_setkeycode; /* set the bits for the keys */ deb_rc("key map size: %d\n", d->props.rc.legacy.rc_map_size); diff --git a/drivers/media/rc/rc-main.c b/drivers/media/rc/rc-main.c index 512a2f4ada0e1..c3769283936ff 100644 --- a/drivers/media/rc/rc-main.c +++ b/drivers/media/rc/rc-main.c @@ -966,8 +966,8 @@ struct rc_dev *rc_allocate_device(void) return NULL; } - dev->input_dev->getkeycode_new = ir_getkeycode; - dev->input_dev->setkeycode_new = ir_setkeycode; + dev->input_dev->getkeycode = ir_getkeycode; + dev->input_dev->setkeycode = ir_setkeycode; input_set_drvdata(dev->input_dev, dev); spin_lock_init(&dev->rc_map.lock); diff --git a/include/linux/input.h b/include/linux/input.h index e428382ca28a5..056ae8a5bd9b8 100644 --- a/include/linux/input.h +++ b/include/linux/input.h @@ -1154,8 +1154,6 @@ struct ff_effect { * sparse keymaps. If not supplied default mechanism will be used. * The method is being called while holding event_lock and thus must * not sleep - * @getkeycode_new: transition method - * @setkeycode_new: transition method * @ff: force feedback structure associated with the device if device * supports force feedback effects * @repeat_key: stores key code of the last key pressed; used to implement @@ -1234,14 +1232,10 @@ struct input_dev { void *keycode; int (*setkeycode)(struct input_dev *dev, - unsigned int scancode, unsigned int keycode); + const struct input_keymap_entry *ke, + unsigned int *old_keycode); int (*getkeycode)(struct input_dev *dev, - unsigned int scancode, unsigned int *keycode); - int (*setkeycode_new)(struct input_dev *dev, - const struct input_keymap_entry *ke, - unsigned int *old_keycode); - int (*getkeycode_new)(struct input_dev *dev, - struct input_keymap_entry *ke); + struct input_keymap_entry *ke); struct ff_device *ff; -- GitLab From 2546bcc2d64c3bd0e7cb802cb8fc6cf757c6be0b Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Mon, 31 Jan 2011 21:06:34 -0800 Subject: [PATCH 0063/2822] Input: input-polldev - fix a couple of typos Signed-off-by: Dmitry Torokhov --- drivers/input/input-polldev.c | 4 ++-- include/linux/input-polldev.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/input/input-polldev.c b/drivers/input/input-polldev.c index 0559e309bac9a..3037842a60d8a 100644 --- a/drivers/input/input-polldev.c +++ b/drivers/input/input-polldev.c @@ -192,7 +192,7 @@ static struct attribute_group input_polldev_attribute_group = { }; /** - * input_allocate_polled_device - allocated memory polled device + * input_allocate_polled_device - allocate memory for polled device * * The function allocates memory for a polled device and also * for an input device associated with this polled device. @@ -239,7 +239,7 @@ EXPORT_SYMBOL(input_free_polled_device); * with input layer. The device should be allocated with call to * input_allocate_polled_device(). Callers should also set up poll() * method and set up capabilities (id, name, phys, bits) of the - * corresponing input_dev structure. + * corresponding input_dev structure. */ int input_register_polled_device(struct input_polled_dev *dev) { diff --git a/include/linux/input-polldev.h b/include/linux/input-polldev.h index 5e3dddf8f5626..ce0b72464eb81 100644 --- a/include/linux/input-polldev.h +++ b/include/linux/input-polldev.h @@ -22,12 +22,12 @@ * @poll: driver-supplied method that polls the device and posts * input events (mandatory). * @poll_interval: specifies how often the poll() method should be called. - * Defaults to 500 msec unless overriden when registering the device. + * Defaults to 500 msec unless overridden when registering the device. * @poll_interval_max: specifies upper bound for the poll interval. * Defaults to the initial value of @poll_interval. * @poll_interval_min: specifies lower bound for the poll interval. * Defaults to 0. - * @input: input device structire associated with the polled device. + * @input: input device structure associated with the polled device. * Must be properly initialized by the driver (id, name, phys, bits). * * Polled input device provides a skeleton for supporting simple input -- GitLab From 04e99455ea5bb17ea7c2e7bb0970168efb736242 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Tue, 25 Jan 2011 09:06:19 +0000 Subject: [PATCH 0064/2822] xfs: only lock the rt bitmap inode once per allocation Currently both xfs_rtpick_extent and xfs_rtallocate_extent call xfs_trans_iget to grab and lock the rt bitmap inode, which results in a deadlock since the removal of the lock recursion counters in commit "xfs: simplify inode to transaction joining" Fix this by acquiring and locking the inode in xfs_bmap_rtalloc before calling into xfs_rtpick_extent and xfs_rtallocate_extent. Signed-off-by: Christoph Hellwig Signed-off-by: Alex Elder --- fs/xfs/xfs_bmap.c | 11 +++++++++++ fs/xfs/xfs_rtalloc.c | 34 +++++++++++++--------------------- 2 files changed, 24 insertions(+), 21 deletions(-) diff --git a/fs/xfs/xfs_bmap.c b/fs/xfs/xfs_bmap.c index dc3afd7739ff4..2f89af25996f5 100644 --- a/fs/xfs/xfs_bmap.c +++ b/fs/xfs/xfs_bmap.c @@ -2333,6 +2333,7 @@ xfs_bmap_rtalloc( xfs_extlen_t prod = 0; /* product factor for allocators */ xfs_extlen_t ralen = 0; /* realtime allocation length */ xfs_extlen_t align; /* minimum allocation alignment */ + xfs_inode_t *ip; /* bitmap incore inode */ xfs_rtblock_t rtb; mp = ap->ip->i_mount; @@ -2365,6 +2366,16 @@ xfs_bmap_rtalloc( */ if (ralen * mp->m_sb.sb_rextsize >= MAXEXTLEN) ralen = MAXEXTLEN / mp->m_sb.sb_rextsize; + + /* + * Lock out other modifications to the RT bitmap inode. + */ + error = xfs_trans_iget(mp, ap->tp, mp->m_sb.sb_rbmino, 0, + XFS_ILOCK_EXCL, &ip); + if (error) + return error; + ASSERT(ip == mp->m_rbmip); + /* * If it's an allocation to an empty file at offset 0, * pick an extent that will space things out in the rt area. diff --git a/fs/xfs/xfs_rtalloc.c b/fs/xfs/xfs_rtalloc.c index 12a1913853104..037fab1402427 100644 --- a/fs/xfs/xfs_rtalloc.c +++ b/fs/xfs/xfs_rtalloc.c @@ -2075,15 +2075,15 @@ xfs_rtallocate_extent( xfs_extlen_t prod, /* extent product factor */ xfs_rtblock_t *rtblock) /* out: start block allocated */ { + xfs_mount_t *mp = tp->t_mountp; int error; /* error value */ - xfs_inode_t *ip; /* inode for bitmap file */ - xfs_mount_t *mp; /* file system mount structure */ xfs_rtblock_t r; /* result allocated block */ xfs_fsblock_t sb; /* summary file block number */ xfs_buf_t *sumbp; /* summary file block buffer */ + ASSERT(xfs_isilocked(mp->m_rbmip, XFS_ILOCK_EXCL)); ASSERT(minlen > 0 && minlen <= maxlen); - mp = tp->t_mountp; + /* * If prod is set then figure out what to do to minlen and maxlen. */ @@ -2099,12 +2099,7 @@ xfs_rtallocate_extent( return 0; } } - /* - * Lock out other callers by grabbing the bitmap inode lock. - */ - if ((error = xfs_trans_iget(mp, tp, mp->m_sb.sb_rbmino, 0, - XFS_ILOCK_EXCL, &ip))) - return error; + sumbp = NULL; /* * Allocate by size, or near another block, or exactly at some block. @@ -2123,11 +2118,12 @@ xfs_rtallocate_extent( len, &sumbp, &sb, prod, &r); break; default: + error = EIO; ASSERT(0); } - if (error) { + if (error) return error; - } + /* * If it worked, update the superblock. */ @@ -2306,20 +2302,16 @@ xfs_rtpick_extent( xfs_rtblock_t *pick) /* result rt extent */ { xfs_rtblock_t b; /* result block */ - int error; /* error return value */ - xfs_inode_t *ip; /* bitmap incore inode */ int log2; /* log of sequence number */ __uint64_t resid; /* residual after log removed */ __uint64_t seq; /* sequence number of file creation */ __uint64_t *seqp; /* pointer to seqno in inode */ - if ((error = xfs_trans_iget(mp, tp, mp->m_sb.sb_rbmino, 0, - XFS_ILOCK_EXCL, &ip))) - return error; - ASSERT(ip == mp->m_rbmip); - seqp = (__uint64_t *)&ip->i_d.di_atime; - if (!(ip->i_d.di_flags & XFS_DIFLAG_NEWRTBM)) { - ip->i_d.di_flags |= XFS_DIFLAG_NEWRTBM; + ASSERT(xfs_isilocked(mp->m_rbmip, XFS_ILOCK_EXCL)); + + seqp = (__uint64_t *)&mp->m_rbmip->i_d.di_atime; + if (!(mp->m_rbmip->i_d.di_flags & XFS_DIFLAG_NEWRTBM)) { + mp->m_rbmip->i_d.di_flags |= XFS_DIFLAG_NEWRTBM; *seqp = 0; } seq = *seqp; @@ -2335,7 +2327,7 @@ xfs_rtpick_extent( b = mp->m_sb.sb_rextents - len; } *seqp = seq + 1; - xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); + xfs_trans_log_inode(tp, mp->m_rbmip, XFS_ILOG_CORE); *pick = b; return 0; } -- GitLab From 0d8b30ad19bf13197cbcd786e2cd5a2ecef72e68 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Tue, 25 Jan 2011 09:06:20 +0000 Subject: [PATCH 0065/2822] xfs: fix xfs_get_extsz_hint for a zero extent size hint We can easily set the extsize flag without setting an extent size hint, or one that evaluates to zero. Historically the di_extsize field was only used when it was non-zero, but the commit "Cleanup inode extent size hint extraction" broke this. Restore the old behaviour, thus fixing xfsqa 090 with a debug kernel. Signed-off-by: Christoph Hellwig Signed-off-by: Alex Elder --- fs/xfs/xfs_rw.c | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) diff --git a/fs/xfs/xfs_rw.c b/fs/xfs/xfs_rw.c index 56861d5daaef5..ccd3adf640ee3 100644 --- a/fs/xfs/xfs_rw.c +++ b/fs/xfs/xfs_rw.c @@ -173,17 +173,9 @@ xfs_extlen_t xfs_get_extsz_hint( struct xfs_inode *ip) { - xfs_extlen_t extsz; - - if (unlikely(XFS_IS_REALTIME_INODE(ip))) { - extsz = (ip->i_d.di_flags & XFS_DIFLAG_EXTSIZE) - ? ip->i_d.di_extsize - : ip->i_mount->m_sb.sb_rextsize; - ASSERT(extsz); - } else { - extsz = (ip->i_d.di_flags & XFS_DIFLAG_EXTSIZE) - ? ip->i_d.di_extsize : 0; - } - - return extsz; + if ((ip->i_d.di_flags & XFS_DIFLAG_EXTSIZE) && ip->i_d.di_extsize) + return ip->i_d.di_extsize; + if (XFS_IS_REALTIME_INODE(ip)) + return ip->i_mount->m_sb.sb_rextsize; + return 0; } -- GitLab From 9681153b460006923bb1e9d39b05b80ec09d6b4e Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Tue, 25 Jan 2011 09:06:21 +0000 Subject: [PATCH 0066/2822] xfs: add lockdep annotations for the rt inodes The rt bitmap and summary inodes do not participate in the normal inode locking protocol. Instead the rt bitmap inode can be locked in any transaction involving rt allocations, and the both of the rt inodes can be locked at the same time. Add specific lockdep subclasses for the rt inodes to prevent lockdep from blowing up. Signed-off-by: Christoph Hellwig Signed-off-by: Alex Elder --- fs/xfs/xfs_bmap.c | 2 +- fs/xfs/xfs_inode.h | 23 +++++++++++++++-------- fs/xfs/xfs_rtalloc.c | 16 ++++++++++------ 3 files changed, 26 insertions(+), 15 deletions(-) diff --git a/fs/xfs/xfs_bmap.c b/fs/xfs/xfs_bmap.c index 2f89af25996f5..d8d0906652830 100644 --- a/fs/xfs/xfs_bmap.c +++ b/fs/xfs/xfs_bmap.c @@ -2371,7 +2371,7 @@ xfs_bmap_rtalloc( * Lock out other modifications to the RT bitmap inode. */ error = xfs_trans_iget(mp, ap->tp, mp->m_sb.sb_rbmino, 0, - XFS_ILOCK_EXCL, &ip); + XFS_ILOCK_EXCL | XFS_ILOCK_RTBITMAP, &ip); if (error) return error; ASSERT(ip == mp->m_rbmip); diff --git a/fs/xfs/xfs_inode.h b/fs/xfs/xfs_inode.h index 5c95fa8ec11da..f753200cef8d3 100644 --- a/fs/xfs/xfs_inode.h +++ b/fs/xfs/xfs_inode.h @@ -409,28 +409,35 @@ static inline void xfs_ifunlock(xfs_inode_t *ip) /* * Flags for lockdep annotations. * - * XFS_I[O]LOCK_PARENT - for operations that require locking two inodes - * (ie directory operations that require locking a directory inode and - * an entry inode). The first inode gets locked with this flag so it - * gets a lockdep subclass of 1 and the second lock will have a lockdep - * subclass of 0. + * XFS_LOCK_PARENT - for directory operations that require locking a + * parent directory inode and a child entry inode. The parent gets locked + * with this flag so it gets a lockdep subclass of 1 and the child entry + * lock will have a lockdep subclass of 0. + * + * XFS_LOCK_RTBITMAP/XFS_LOCK_RTSUM - the realtime device bitmap and summary + * inodes do not participate in the normal lock order, and thus have their + * own subclasses. * * XFS_LOCK_INUMORDER - for locking several inodes at the some time * with xfs_lock_inodes(). This flag is used as the starting subclass * and each subsequent lock acquired will increment the subclass by one. - * So the first lock acquired will have a lockdep subclass of 2, the - * second lock will have a lockdep subclass of 3, and so on. It is + * So the first lock acquired will have a lockdep subclass of 4, the + * second lock will have a lockdep subclass of 5, and so on. It is * the responsibility of the class builder to shift this to the correct * portion of the lock_mode lockdep mask. */ #define XFS_LOCK_PARENT 1 -#define XFS_LOCK_INUMORDER 2 +#define XFS_LOCK_RTBITMAP 2 +#define XFS_LOCK_RTSUM 3 +#define XFS_LOCK_INUMORDER 4 #define XFS_IOLOCK_SHIFT 16 #define XFS_IOLOCK_PARENT (XFS_LOCK_PARENT << XFS_IOLOCK_SHIFT) #define XFS_ILOCK_SHIFT 24 #define XFS_ILOCK_PARENT (XFS_LOCK_PARENT << XFS_ILOCK_SHIFT) +#define XFS_ILOCK_RTBITMAP (XFS_LOCK_RTBITMAP << XFS_ILOCK_SHIFT) +#define XFS_ILOCK_RTSUM (XFS_LOCK_RTSUM << XFS_ILOCK_SHIFT) #define XFS_IOLOCK_DEP_MASK 0x00ff0000 #define XFS_ILOCK_DEP_MASK 0xff000000 diff --git a/fs/xfs/xfs_rtalloc.c b/fs/xfs/xfs_rtalloc.c index 037fab1402427..f592ac978186a 100644 --- a/fs/xfs/xfs_rtalloc.c +++ b/fs/xfs/xfs_rtalloc.c @@ -1972,8 +1972,10 @@ xfs_growfs_rt( /* * Lock out other callers by grabbing the bitmap inode lock. */ - if ((error = xfs_trans_iget(mp, tp, mp->m_sb.sb_rbmino, 0, - XFS_ILOCK_EXCL, &ip))) + error = xfs_trans_iget(mp, tp, mp->m_sb.sb_rbmino, 0, + XFS_ILOCK_EXCL | XFS_ILOCK_RTBITMAP, + &ip); + if (error) goto error_cancel; ASSERT(ip == mp->m_rbmip); /* @@ -1986,8 +1988,9 @@ xfs_growfs_rt( /* * Get the summary inode into the transaction. */ - if ((error = xfs_trans_iget(mp, tp, mp->m_sb.sb_rsumino, 0, - XFS_ILOCK_EXCL, &ip))) + error = xfs_trans_iget(mp, tp, mp->m_sb.sb_rsumino, 0, + XFS_ILOCK_EXCL | XFS_ILOCK_RTSUM, &ip); + if (error) goto error_cancel; ASSERT(ip == mp->m_rsumip); /* @@ -2160,8 +2163,9 @@ xfs_rtfree_extent( /* * Synchronize by locking the bitmap inode. */ - if ((error = xfs_trans_iget(mp, tp, mp->m_sb.sb_rbmino, 0, - XFS_ILOCK_EXCL, &ip))) + error = xfs_trans_iget(mp, tp, mp->m_sb.sb_rbmino, 0, + XFS_ILOCK_EXCL | XFS_ILOCK_RTBITMAP, &ip); + if (error) return error; #if defined(__KERNEL__) && defined(DEBUG) /* -- GitLab From 8e1964a98920100f113ad26f78220ea706dbfa2b Mon Sep 17 00:00:00 2001 From: James Bottomley Date: Thu, 20 Jan 2011 12:54:18 -0600 Subject: [PATCH 0067/2822] [PARISC] fix vmap flush/invalidate On parisc, we never implemented invalidate_kernel_vmap_range() because it was unnecessary for the xfs use case. However, we do need to implement an invalidate for the opposite use case (which occurred in a recent NFS change) where the user wants to read through the vmap range and write via the kernel address. There's an additional complexity to this in that if the page has no userspace mappings, it might have dirty cache lines in the kernel (indicated by the PG_dcache_dirty bit). In order to get full coherency, we need to flush these pages through the kernel mapping before invalidating the vmap range. Signed-off-by: James Bottomley --- arch/parisc/include/asm/cacheflush.h | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/arch/parisc/include/asm/cacheflush.h b/arch/parisc/include/asm/cacheflush.h index f388a85bba113..7344e1d304af0 100644 --- a/arch/parisc/include/asm/cacheflush.h +++ b/arch/parisc/include/asm/cacheflush.h @@ -37,6 +37,13 @@ void flush_cache_all_local(void); void flush_cache_all(void); void flush_cache_mm(struct mm_struct *mm); +#define ARCH_HAS_FLUSH_KERNEL_DCACHE_PAGE +void flush_kernel_dcache_page_addr(void *addr); +static inline void flush_kernel_dcache_page(struct page *page) +{ + flush_kernel_dcache_page_addr(page_address(page)); +} + #define flush_kernel_dcache_range(start,size) \ flush_kernel_dcache_range_asm((start), (start)+(size)); /* vmap range flushes and invalidates. Architecturally, we don't need @@ -50,6 +57,16 @@ static inline void flush_kernel_vmap_range(void *vaddr, int size) } static inline void invalidate_kernel_vmap_range(void *vaddr, int size) { + unsigned long start = (unsigned long)vaddr; + void *cursor = vaddr; + + for ( ; cursor < vaddr + size; cursor += PAGE_SIZE) { + struct page *page = vmalloc_to_page(cursor); + + if (test_and_clear_bit(PG_dcache_dirty, &page->flags)) + flush_kernel_dcache_page(page); + } + flush_kernel_dcache_range_asm(start, start + size); } #define flush_cache_vmap(start, end) flush_cache_all() @@ -98,13 +115,6 @@ flush_anon_page(struct vm_area_struct *vma, struct page *page, unsigned long vma flush_user_dcache_page(vmaddr); } -#define ARCH_HAS_FLUSH_KERNEL_DCACHE_PAGE -void flush_kernel_dcache_page_addr(void *addr); -static inline void flush_kernel_dcache_page(struct page *page) -{ - flush_kernel_dcache_page_addr(page_address(page)); -} - #ifdef CONFIG_DEBUG_RODATA void mark_rodata_ro(void); #endif -- GitLab From 9804c9eaeacfe78651052c5ddff31099f60ef78c Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Mon, 7 Feb 2011 19:28:01 +0100 Subject: [PATCH 0068/2822] [PARISC] fix per-cpu flag problem in the cpu affinity checkers The CHECK_IRQ_PER_CPU is wrong, it should be checking irq_to_desc(irq)->status not just irq. Signed-off-by: Thomas Gleixner Cc: stable@kernel.org Signed-off-by: James Bottomley --- arch/parisc/kernel/irq.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/parisc/kernel/irq.c b/arch/parisc/kernel/irq.c index d7d94b845dc2c..3948f1dd455aa 100644 --- a/arch/parisc/kernel/irq.c +++ b/arch/parisc/kernel/irq.c @@ -108,7 +108,7 @@ int cpu_check_affinity(unsigned int irq, const struct cpumask *dest) int cpu_dest; /* timer and ipi have to always be received on all CPUs */ - if (CHECK_IRQ_PER_CPU(irq)) { + if (CHECK_IRQ_PER_CPU(irq_to_desc(irq)->status)) { /* Bad linux design decision. The mask has already * been set; we must reset it */ cpumask_setall(irq_desc[irq].affinity); -- GitLab From ab94e4666d5cee0e393367671eeab4111105bffb Mon Sep 17 00:00:00 2001 From: Dick Streefland Date: Mon, 24 Jan 2011 00:44:57 +0100 Subject: [PATCH 0069/2822] scripts/extract-ikconfig: add xz compression support Add support for kernels compressed with xz to the extract-ikconfig script. Signed-off-by: Dick Streefland Acked-by: WANG Cong Signed-off-by: Michal Marek --- scripts/extract-ikconfig | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/scripts/extract-ikconfig b/scripts/extract-ikconfig index 1512c0a755ace..e1862429ccda5 100755 --- a/scripts/extract-ikconfig +++ b/scripts/extract-ikconfig @@ -56,10 +56,11 @@ trap "rm -f $tmp1 $tmp2" 0 dump_config "$img" # That didn't work, so retry after decompression. -try_decompress '\037\213\010' xy gunzip -try_decompress 'BZh' xy bunzip2 -try_decompress '\135\0\0\0' xxx unlzma -try_decompress '\211\114\132' xy 'lzop -d' +try_decompress '\037\213\010' xy gunzip +try_decompress '\3757zXZ\000' abcde unxz +try_decompress 'BZh' xy bunzip2 +try_decompress '\135\0\0\0' xxx unlzma +try_decompress '\211\114\132' xy 'lzop -d' # Bail out: echo "$me: Cannot find kernel config." >&2 -- GitLab From 4c4231ea2f794d73bbb50b8d84e00c66a012a607 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Sun, 6 Feb 2011 20:45:52 +0000 Subject: [PATCH 0070/2822] [PARISC] Convert to new irq_chip functions Convert all the parisc driver interrupt handlers (dino, eisa, gsc, iosapic and superio) as well as the cpu interrupts. Prepare show_interrupts for GENERIC_HARDIRQS_NO_DEPRECATED and finally selects that Kconfig option [jejb: compile and testing fixes] Signed-off-by: Thomas Gleixner Signed-off-by: James Bottomley --- arch/parisc/Kconfig | 1 + arch/parisc/include/asm/irq.h | 13 +++---- arch/parisc/kernel/irq.c | 64 ++++++++++++++++++++--------------- drivers/parisc/dino.c | 22 ++++++------ drivers/parisc/eisa.c | 12 ++++--- drivers/parisc/gsc.c | 22 ++++++------ drivers/parisc/iosapic.c | 40 +++++++++++----------- drivers/parisc/superio.c | 12 ++++--- 8 files changed, 98 insertions(+), 88 deletions(-) diff --git a/arch/parisc/Kconfig b/arch/parisc/Kconfig index fed2946f73352..fafdf30bea9e5 100644 --- a/arch/parisc/Kconfig +++ b/arch/parisc/Kconfig @@ -15,6 +15,7 @@ config PARISC select HAVE_GENERIC_HARDIRQS select GENERIC_IRQ_PROBE select IRQ_PER_CPU + select GENERIC_HARDIRQS_NO_DEPRECATED help The PA-RISC microprocessor is designed by Hewlett-Packard and used diff --git a/arch/parisc/include/asm/irq.h b/arch/parisc/include/asm/irq.h index c67dccf2e31f8..1073599a7be93 100644 --- a/arch/parisc/include/asm/irq.h +++ b/arch/parisc/include/asm/irq.h @@ -32,15 +32,10 @@ static __inline__ int irq_canonicalize(int irq) } struct irq_chip; +struct irq_data; -/* - * Some useful "we don't have to do anything here" handlers. Should - * probably be provided by the generic code. - */ -void no_ack_irq(unsigned int irq); -void no_end_irq(unsigned int irq); -void cpu_ack_irq(unsigned int irq); -void cpu_eoi_irq(unsigned int irq); +void cpu_ack_irq(struct irq_data *d); +void cpu_eoi_irq(struct irq_data *d); extern int txn_alloc_irq(unsigned int nbits); extern int txn_claim_irq(int); @@ -49,7 +44,7 @@ extern unsigned long txn_alloc_addr(unsigned int); extern unsigned long txn_affinity_addr(unsigned int irq, int cpu); extern int cpu_claim_irq(unsigned int irq, struct irq_chip *, void *); -extern int cpu_check_affinity(unsigned int irq, const struct cpumask *dest); +extern int cpu_check_affinity(struct irq_data *d, const struct cpumask *dest); /* soft power switch support (power.c) */ extern struct tasklet_struct power_tasklet; diff --git a/arch/parisc/kernel/irq.c b/arch/parisc/kernel/irq.c index 3948f1dd455aa..cb450e1e79b32 100644 --- a/arch/parisc/kernel/irq.c +++ b/arch/parisc/kernel/irq.c @@ -52,9 +52,9 @@ static volatile unsigned long cpu_eiem = 0; */ static DEFINE_PER_CPU(unsigned long, local_ack_eiem) = ~0UL; -static void cpu_mask_irq(unsigned int irq) +static void cpu_mask_irq(struct irq_data *d) { - unsigned long eirr_bit = EIEM_MASK(irq); + unsigned long eirr_bit = EIEM_MASK(d->irq); cpu_eiem &= ~eirr_bit; /* Do nothing on the other CPUs. If they get this interrupt, @@ -63,7 +63,7 @@ static void cpu_mask_irq(unsigned int irq) * then gets disabled */ } -static void cpu_unmask_irq(unsigned int irq) +static void __cpu_unmask_irq(unsigned int irq) { unsigned long eirr_bit = EIEM_MASK(irq); @@ -75,9 +75,14 @@ static void cpu_unmask_irq(unsigned int irq) smp_send_all_nop(); } -void cpu_ack_irq(unsigned int irq) +static void cpu_unmask_irq(struct irq_data *d) +{ + __cpu_unmask_irq(d->irq); +} + +void cpu_ack_irq(struct irq_data *d) { - unsigned long mask = EIEM_MASK(irq); + unsigned long mask = EIEM_MASK(d->irq); int cpu = smp_processor_id(); /* Clear in EIEM so we can no longer process */ @@ -90,9 +95,9 @@ void cpu_ack_irq(unsigned int irq) mtctl(mask, 23); } -void cpu_eoi_irq(unsigned int irq) +void cpu_eoi_irq(struct irq_data *d) { - unsigned long mask = EIEM_MASK(irq); + unsigned long mask = EIEM_MASK(d->irq); int cpu = smp_processor_id(); /* set it in the eiems---it's no longer in process */ @@ -103,15 +108,16 @@ void cpu_eoi_irq(unsigned int irq) } #ifdef CONFIG_SMP -int cpu_check_affinity(unsigned int irq, const struct cpumask *dest) +int cpu_check_affinity(struct irq_data *d, const struct cpumask *dest) { int cpu_dest; /* timer and ipi have to always be received on all CPUs */ - if (CHECK_IRQ_PER_CPU(irq_to_desc(irq)->status)) { + if (CHECK_IRQ_PER_CPU(irq_to_desc(d->irq)->status)) { /* Bad linux design decision. The mask has already - * been set; we must reset it */ - cpumask_setall(irq_desc[irq].affinity); + * been set; we must reset it. Will fix - tglx + */ + cpumask_setall(d->affinity); return -EINVAL; } @@ -121,33 +127,34 @@ int cpu_check_affinity(unsigned int irq, const struct cpumask *dest) return cpu_dest; } -static int cpu_set_affinity_irq(unsigned int irq, const struct cpumask *dest) +static int cpu_set_affinity_irq(struct irq_data *d, const struct cpumask *dest, + bool force) { int cpu_dest; - cpu_dest = cpu_check_affinity(irq, dest); + cpu_dest = cpu_check_affinity(d, dest); if (cpu_dest < 0) return -1; - cpumask_copy(irq_desc[irq].affinity, dest); + cpumask_copy(d->affinity, dest); return 0; } #endif static struct irq_chip cpu_interrupt_type = { - .name = "CPU", - .mask = cpu_mask_irq, - .unmask = cpu_unmask_irq, - .ack = cpu_ack_irq, - .eoi = cpu_eoi_irq, + .name = "CPU", + .irq_mask = cpu_mask_irq, + .irq_unmask = cpu_unmask_irq, + .irq_ack = cpu_ack_irq, + .irq_eoi = cpu_eoi_irq, #ifdef CONFIG_SMP - .set_affinity = cpu_set_affinity_irq, + .irq_set_affinity = cpu_set_affinity_irq, #endif /* XXX: Needs to be written. We managed without it so far, but * we really ought to write it. */ - .retrigger = NULL, + .irq_retrigger = NULL, }; int show_interrupts(struct seq_file *p, void *v) @@ -181,7 +188,7 @@ int show_interrupts(struct seq_file *p, void *v) seq_printf(p, "%10u ", kstat_irqs(i)); #endif - seq_printf(p, " %14s", irq_desc[i].chip->name); + seq_printf(p, " %14s", irq_desc[i].irq_data.chip->name); #ifndef PARISC_IRQ_CR16_COUNTS seq_printf(p, " %s", action->name); @@ -233,14 +240,14 @@ int cpu_claim_irq(unsigned int irq, struct irq_chip *type, void *data) { if (irq_desc[irq].action) return -EBUSY; - if (irq_desc[irq].chip != &cpu_interrupt_type) + if (get_irq_chip(irq) != &cpu_interrupt_type) return -EBUSY; /* for iosapic interrupts */ if (type) { set_irq_chip_and_handler(irq, type, handle_percpu_irq); set_irq_chip_data(irq, data); - cpu_unmask_irq(irq); + __cpu_unmask_irq(irq); } return 0; } @@ -289,7 +296,8 @@ int txn_alloc_irq(unsigned int bits_wide) unsigned long txn_affinity_addr(unsigned int irq, int cpu) { #ifdef CONFIG_SMP - cpumask_copy(irq_desc[irq].affinity, cpumask_of(cpu)); + struct irq_data *d = irq_get_irq_data(irq); + cpumask_copy(d->affinity, cpumask_of(cpu)); #endif return per_cpu(cpu_data, cpu).txn_addr; @@ -333,6 +341,7 @@ void do_cpu_irq_mask(struct pt_regs *regs) unsigned long eirr_val; int irq, cpu = smp_processor_id(); #ifdef CONFIG_SMP + struct irq_desc *desc; cpumask_t dest; #endif @@ -346,8 +355,9 @@ void do_cpu_irq_mask(struct pt_regs *regs) irq = eirr_to_irq(eirr_val); #ifdef CONFIG_SMP - cpumask_copy(&dest, irq_desc[irq].affinity); - if (CHECK_IRQ_PER_CPU(irq_desc[irq].status) && + desc = irq_to_desc(irq); + cpumask_copy(&dest, desc->irq_data.affinity); + if (CHECK_IRQ_PER_CPU(desc->status) && !cpu_isset(smp_processor_id(), dest)) { int cpu = first_cpu(dest); diff --git a/drivers/parisc/dino.c b/drivers/parisc/dino.c index 9383063d2b168..bcd5d54b7d4d2 100644 --- a/drivers/parisc/dino.c +++ b/drivers/parisc/dino.c @@ -296,25 +296,25 @@ static struct pci_port_ops dino_port_ops = { .outl = dino_out32 }; -static void dino_mask_irq(unsigned int irq) +static void dino_mask_irq(struct irq_data *d) { - struct dino_device *dino_dev = get_irq_chip_data(irq); - int local_irq = gsc_find_local_irq(irq, dino_dev->global_irq, DINO_LOCAL_IRQS); + struct dino_device *dino_dev = irq_data_get_irq_chip_data(d); + int local_irq = gsc_find_local_irq(d->irq, dino_dev->global_irq, DINO_LOCAL_IRQS); - DBG(KERN_WARNING "%s(0x%p, %d)\n", __func__, dino_dev, irq); + DBG(KERN_WARNING "%s(0x%p, %d)\n", __func__, dino_dev, d->irq); /* Clear the matching bit in the IMR register */ dino_dev->imr &= ~(DINO_MASK_IRQ(local_irq)); __raw_writel(dino_dev->imr, dino_dev->hba.base_addr+DINO_IMR); } -static void dino_unmask_irq(unsigned int irq) +static void dino_unmask_irq(struct irq_data *d) { - struct dino_device *dino_dev = get_irq_chip_data(irq); - int local_irq = gsc_find_local_irq(irq, dino_dev->global_irq, DINO_LOCAL_IRQS); + struct dino_device *dino_dev = irq_data_get_irq_chip_data(d); + int local_irq = gsc_find_local_irq(d->irq, dino_dev->global_irq, DINO_LOCAL_IRQS); u32 tmp; - DBG(KERN_WARNING "%s(0x%p, %d)\n", __func__, dino_dev, irq); + DBG(KERN_WARNING "%s(0x%p, %d)\n", __func__, dino_dev, d->irq); /* ** clear pending IRQ bits @@ -346,9 +346,9 @@ static void dino_unmask_irq(unsigned int irq) } static struct irq_chip dino_interrupt_type = { - .name = "GSC-PCI", - .unmask = dino_unmask_irq, - .mask = dino_mask_irq, + .name = "GSC-PCI", + .irq_unmask = dino_unmask_irq, + .irq_mask = dino_mask_irq, }; diff --git a/drivers/parisc/eisa.c b/drivers/parisc/eisa.c index e860038b0b841..deeec32a5803c 100644 --- a/drivers/parisc/eisa.c +++ b/drivers/parisc/eisa.c @@ -144,8 +144,9 @@ static unsigned int eisa_irq_level __read_mostly; /* default to edge triggered * /* called by free irq */ -static void eisa_mask_irq(unsigned int irq) +static void eisa_mask_irq(struct irq_data *d) { + unsigned int irq = d->irq; unsigned long flags; EISA_DBG("disable irq %d\n", irq); @@ -164,8 +165,9 @@ static void eisa_mask_irq(unsigned int irq) } /* called by request irq */ -static void eisa_unmask_irq(unsigned int irq) +static void eisa_unmask_irq(struct irq_data *d) { + unsigned int irq = d->irq; unsigned long flags; EISA_DBG("enable irq %d\n", irq); @@ -183,9 +185,9 @@ static void eisa_unmask_irq(unsigned int irq) } static struct irq_chip eisa_interrupt_type = { - .name = "EISA", - .unmask = eisa_unmask_irq, - .mask = eisa_mask_irq, + .name = "EISA", + .irq_unmask = eisa_unmask_irq, + .irq_mask = eisa_mask_irq, }; static irqreturn_t eisa_irq(int wax_irq, void *intr_dev) diff --git a/drivers/parisc/gsc.c b/drivers/parisc/gsc.c index 772b1939ac218..ef31080cf5912 100644 --- a/drivers/parisc/gsc.c +++ b/drivers/parisc/gsc.c @@ -105,13 +105,13 @@ int gsc_find_local_irq(unsigned int irq, int *global_irqs, int limit) return NO_IRQ; } -static void gsc_asic_mask_irq(unsigned int irq) +static void gsc_asic_mask_irq(struct irq_data *d) { - struct gsc_asic *irq_dev = get_irq_chip_data(irq); - int local_irq = gsc_find_local_irq(irq, irq_dev->global_irq, 32); + struct gsc_asic *irq_dev = irq_data_get_irq_chip_data(d); + int local_irq = gsc_find_local_irq(d->irq, irq_dev->global_irq, 32); u32 imr; - DEBPRINTK(KERN_DEBUG "%s(%d) %s: IMR 0x%x\n", __func__, irq, + DEBPRINTK(KERN_DEBUG "%s(%d) %s: IMR 0x%x\n", __func__, d->irq, irq_dev->name, imr); /* Disable the IRQ line by clearing the bit in the IMR */ @@ -120,13 +120,13 @@ static void gsc_asic_mask_irq(unsigned int irq) gsc_writel(imr, irq_dev->hpa + OFFSET_IMR); } -static void gsc_asic_unmask_irq(unsigned int irq) +static void gsc_asic_unmask_irq(struct irq_data *d) { - struct gsc_asic *irq_dev = get_irq_chip_data(irq); - int local_irq = gsc_find_local_irq(irq, irq_dev->global_irq, 32); + struct gsc_asic *irq_dev = irq_data_get_irq_chip_data(d); + int local_irq = gsc_find_local_irq(d->irq, irq_dev->global_irq, 32); u32 imr; - DEBPRINTK(KERN_DEBUG "%s(%d) %s: IMR 0x%x\n", __func__, irq, + DEBPRINTK(KERN_DEBUG "%s(%d) %s: IMR 0x%x\n", __func__, d->irq, irq_dev->name, imr); /* Enable the IRQ line by setting the bit in the IMR */ @@ -140,9 +140,9 @@ static void gsc_asic_unmask_irq(unsigned int irq) } static struct irq_chip gsc_asic_interrupt_type = { - .name = "GSC-ASIC", - .unmask = gsc_asic_unmask_irq, - .mask = gsc_asic_mask_irq, + .name = "GSC-ASIC", + .irq_unmask = gsc_asic_unmask_irq, + .irq_mask = gsc_asic_mask_irq, }; int gsc_assign_irq(struct irq_chip *type, void *data) diff --git a/drivers/parisc/iosapic.c b/drivers/parisc/iosapic.c index 0327894bf2355..95930d016235a 100644 --- a/drivers/parisc/iosapic.c +++ b/drivers/parisc/iosapic.c @@ -615,10 +615,10 @@ iosapic_set_irt_data( struct vector_info *vi, u32 *dp0, u32 *dp1) } -static void iosapic_mask_irq(unsigned int irq) +static void iosapic_mask_irq(struct irq_data *d) { unsigned long flags; - struct vector_info *vi = get_irq_chip_data(irq); + struct vector_info *vi = irq_data_get_irq_chip_data(d); u32 d0, d1; spin_lock_irqsave(&iosapic_lock, flags); @@ -628,9 +628,9 @@ static void iosapic_mask_irq(unsigned int irq) spin_unlock_irqrestore(&iosapic_lock, flags); } -static void iosapic_unmask_irq(unsigned int irq) +static void iosapic_unmask_irq(struct irq_data *d) { - struct vector_info *vi = get_irq_chip_data(irq); + struct vector_info *vi = irq_data_get_irq_chip_data(d); u32 d0, d1; /* data is initialized by fixup_irq */ @@ -666,34 +666,34 @@ printk("\n"); * enables their IRQ. It can lead to "interesting" race conditions * in the driver initialization sequence. */ - DBG(KERN_DEBUG "enable_irq(%d): eoi(%p, 0x%x)\n", irq, + DBG(KERN_DEBUG "enable_irq(%d): eoi(%p, 0x%x)\n", d->irq, vi->eoi_addr, vi->eoi_data); iosapic_eoi(vi->eoi_addr, vi->eoi_data); } -static void iosapic_eoi_irq(unsigned int irq) +static void iosapic_eoi_irq(struct irq_data *d) { - struct vector_info *vi = get_irq_chip_data(irq); + struct vector_info *vi = irq_data_get_irq_chip_data(d); iosapic_eoi(vi->eoi_addr, vi->eoi_data); - cpu_eoi_irq(irq); + cpu_eoi_irq(d); } #ifdef CONFIG_SMP -static int iosapic_set_affinity_irq(unsigned int irq, - const struct cpumask *dest) +static int iosapic_set_affinity_irq(struct irq_data *d, + const struct cpumask *dest, bool force) { - struct vector_info *vi = get_irq_chip_data(irq); + struct vector_info *vi = irq_data_get_irq_chip_data(d); u32 d0, d1, dummy_d0; unsigned long flags; int dest_cpu; - dest_cpu = cpu_check_affinity(irq, dest); + dest_cpu = cpu_check_affinity(d, dest); if (dest_cpu < 0) return -1; - cpumask_copy(irq_desc[irq].affinity, cpumask_of(dest_cpu)); - vi->txn_addr = txn_affinity_addr(irq, dest_cpu); + cpumask_copy(d->affinity, cpumask_of(dest_cpu)); + vi->txn_addr = txn_affinity_addr(d->irq, dest_cpu); spin_lock_irqsave(&iosapic_lock, flags); /* d1 contains the destination CPU, so only want to set that @@ -708,13 +708,13 @@ static int iosapic_set_affinity_irq(unsigned int irq, #endif static struct irq_chip iosapic_interrupt_type = { - .name = "IO-SAPIC-level", - .unmask = iosapic_unmask_irq, - .mask = iosapic_mask_irq, - .ack = cpu_ack_irq, - .eoi = iosapic_eoi_irq, + .name = "IO-SAPIC-level", + .irq_unmask = iosapic_unmask_irq, + .irq_mask = iosapic_mask_irq, + .irq_ack = cpu_ack_irq, + .irq_eoi = iosapic_eoi_irq, #ifdef CONFIG_SMP - .set_affinity = iosapic_set_affinity_irq, + .irq_set_affinity = iosapic_set_affinity_irq, #endif }; diff --git a/drivers/parisc/superio.c b/drivers/parisc/superio.c index 28241532c0fd1..a4d8ff66a6390 100644 --- a/drivers/parisc/superio.c +++ b/drivers/parisc/superio.c @@ -286,8 +286,9 @@ superio_init(struct pci_dev *pcidev) } DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_87560_LIO, superio_init); -static void superio_mask_irq(unsigned int irq) +static void superio_mask_irq(struct irq_data *d) { + unsigned int irq = d->irq; u8 r8; if ((irq < 1) || (irq == 2) || (irq > 7)) { @@ -303,8 +304,9 @@ static void superio_mask_irq(unsigned int irq) outb (r8,IC_PIC1+1); } -static void superio_unmask_irq(unsigned int irq) +static void superio_unmask_irq(struct irq_data *d) { + unsigned int irq = d->irq; u8 r8; if ((irq < 1) || (irq == 2) || (irq > 7)) { @@ -320,9 +322,9 @@ static void superio_unmask_irq(unsigned int irq) } static struct irq_chip superio_interrupt_type = { - .name = SUPERIO, - .unmask = superio_unmask_irq, - .mask = superio_mask_irq, + .name = SUPERIO, + .irq_unmask = superio_unmask_irq, + .irq_mask = superio_mask_irq, }; #ifdef DEBUG_SUPERIO_INIT -- GitLab From 9d5a4e946ce5352f19400b6370f4cd8e72806278 Mon Sep 17 00:00:00 2001 From: Mike Snitzer Date: Fri, 11 Feb 2011 11:05:46 +0100 Subject: [PATCH 0071/2822] block: skip elevator data initialization for flush requests Skip elevator initialization for flush requests by passing priv=0 to blk_alloc_request() in get_request(). As such elv_set_request() is never called for flush requests. Signed-off-by: Mike Snitzer Signed-off-by: Jens Axboe --- block/blk-core.c | 29 +++++++++++++++++++++++++---- 1 file changed, 25 insertions(+), 4 deletions(-) diff --git a/block/blk-core.c b/block/blk-core.c index 05746093b45e8..ab4a7696956d9 100644 --- a/block/blk-core.c +++ b/block/blk-core.c @@ -737,6 +737,25 @@ static void freed_request(struct request_queue *q, int sync, int priv) __freed_request(q, sync ^ 1); } +/* + * Determine if elevator data should be initialized when allocating the + * request associated with @bio. + */ +static bool blk_rq_should_init_elevator(struct bio *bio) +{ + if (!bio) + return true; + + /* + * Flush requests do not use the elevator so skip initialization. + * This allows a request to share the flush and elevator data. + */ + if (bio->bi_rw & (REQ_FLUSH | REQ_FUA)) + return false; + + return true; +} + /* * Get a free request, queue_lock must be held. * Returns NULL on failure, with queue_lock held. @@ -749,7 +768,7 @@ static struct request *get_request(struct request_queue *q, int rw_flags, struct request_list *rl = &q->rq; struct io_context *ioc = NULL; const bool is_sync = rw_is_sync(rw_flags) != 0; - int may_queue, priv; + int may_queue, priv = 0; may_queue = elv_may_queue(q, rw_flags); if (may_queue == ELV_MQUEUE_NO) @@ -793,9 +812,11 @@ static struct request *get_request(struct request_queue *q, int rw_flags, rl->count[is_sync]++; rl->starved[is_sync] = 0; - priv = !test_bit(QUEUE_FLAG_ELVSWITCH, &q->queue_flags); - if (priv) - rl->elvpriv++; + if (blk_rq_should_init_elevator(bio)) { + priv = !test_bit(QUEUE_FLAG_ELVSWITCH, &q->queue_flags); + if (priv) + rl->elvpriv++; + } if (blk_queue_io_stat(q)) rw_flags |= REQ_IO_STAT; -- GitLab From c186794dbb466b45cf40f942f2d09d6d5b4b0e42 Mon Sep 17 00:00:00 2001 From: Mike Snitzer Date: Fri, 11 Feb 2011 11:08:00 +0100 Subject: [PATCH 0072/2822] block: share request flush fields with elevator_private Flush requests are never put on the IO scheduler. Convert request structure's elevator_private* into an array and have the flush fields share a union with it. Reclaim the space lost in 'struct request' by moving 'completion_data' back in the union with 'rb_node'. Signed-off-by: Mike Snitzer Acked-by: Vivek Goyal Acked-by: Tejun Heo Signed-off-by: Jens Axboe --- block/cfq-iosched.c | 18 +++++++++--------- block/elevator.c | 2 +- include/linux/blkdev.h | 23 ++++++++++++----------- 3 files changed, 22 insertions(+), 21 deletions(-) diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c index 4cd59b0d7c15b..968455c57e1a1 100644 --- a/block/cfq-iosched.c +++ b/block/cfq-iosched.c @@ -54,9 +54,9 @@ static const int cfq_hist_divisor = 4; #define CFQQ_SEEKY(cfqq) (hweight32(cfqq->seek_history) > 32/8) #define RQ_CIC(rq) \ - ((struct cfq_io_context *) (rq)->elevator_private) -#define RQ_CFQQ(rq) (struct cfq_queue *) ((rq)->elevator_private2) -#define RQ_CFQG(rq) (struct cfq_group *) ((rq)->elevator_private3) + ((struct cfq_io_context *) (rq)->elevator_private[0]) +#define RQ_CFQQ(rq) (struct cfq_queue *) ((rq)->elevator_private[1]) +#define RQ_CFQG(rq) (struct cfq_group *) ((rq)->elevator_private[2]) static struct kmem_cache *cfq_pool; static struct kmem_cache *cfq_ioc_pool; @@ -3589,12 +3589,12 @@ static void cfq_put_request(struct request *rq) put_io_context(RQ_CIC(rq)->ioc); - rq->elevator_private = NULL; - rq->elevator_private2 = NULL; + rq->elevator_private[0] = NULL; + rq->elevator_private[1] = NULL; /* Put down rq reference on cfqg */ cfq_put_cfqg(RQ_CFQG(rq)); - rq->elevator_private3 = NULL; + rq->elevator_private[2] = NULL; cfq_put_queue(cfqq); } @@ -3685,9 +3685,9 @@ new_queue: spin_unlock_irqrestore(q->queue_lock, flags); - rq->elevator_private = cic; - rq->elevator_private2 = cfqq; - rq->elevator_private3 = cfq_ref_get_cfqg(cfqq->cfqg); + rq->elevator_private[0] = cic; + rq->elevator_private[1] = cfqq; + rq->elevator_private[2] = cfq_ref_get_cfqg(cfqq->cfqg); return 0; queue_fail: diff --git a/block/elevator.c b/block/elevator.c index 270e0972eb9f1..f98e92edc9378 100644 --- a/block/elevator.c +++ b/block/elevator.c @@ -764,7 +764,7 @@ int elv_set_request(struct request_queue *q, struct request *rq, gfp_t gfp_mask) if (e->ops->elevator_set_req_fn) return e->ops->elevator_set_req_fn(q, rq, gfp_mask); - rq->elevator_private = NULL; + rq->elevator_private[0] = NULL; return 0; } diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index 6d7e9afd08c38..12bb426949e9f 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -99,25 +99,26 @@ struct request { /* * The rb_node is only used inside the io scheduler, requests * are pruned when moved to the dispatch queue. So let the - * flush fields share space with the rb_node. + * completion_data share space with the rb_node. */ union { struct rb_node rb_node; /* sort/lookup */ - struct { - unsigned int seq; - struct list_head list; - } flush; + void *completion_data; }; - void *completion_data; - /* * Three pointers are available for the IO schedulers, if they need - * more they have to dynamically allocate it. + * more they have to dynamically allocate it. Flush requests are + * never put on the IO scheduler. So let the flush fields share + * space with the three elevator_private pointers. */ - void *elevator_private; - void *elevator_private2; - void *elevator_private3; + union { + void *elevator_private[3]; + struct { + unsigned int seq; + struct list_head list; + } flush; + }; struct gendisk *rq_disk; unsigned long start_time; -- GitLab From 3ff84a7f36554b257cd57325b1a7c1fa4b49fbe3 Mon Sep 17 00:00:00 2001 From: Pekka Enberg Date: Mon, 14 Feb 2011 17:46:21 +0200 Subject: [PATCH 0073/2822] Revert "slab: Fix missing DEBUG_SLAB last user" This reverts commit 5c5e3b33b7cb959a401f823707bee006caadd76e. The commit breaks ARM thusly: | Mount-cache hash table entries: 512 | slab error in verify_redzone_free(): cache `idr_layer_cache': memory outside object was overwritten | Backtrace: | [] (dump_backtrace+0x0/0x110) from [] (dump_stack+0x18/0x1c) | [] (dump_stack+0x0/0x1c) from [] (__slab_error+0x28/0x30) | [] (__slab_error+0x0/0x30) from [] (cache_free_debugcheck+0x1c0/0x2b8) | [] (cache_free_debugcheck+0x0/0x2b8) from [] (kmem_cache_free+0x3c/0xc0) | [] (kmem_cache_free+0x0/0xc0) from [] (ida_get_new_above+0x19c/0x1c0) | [] (ida_get_new_above+0x0/0x1c0) from [] (alloc_vfsmnt+0x54/0x144) | [] (alloc_vfsmnt+0x0/0x144) from [] (vfs_kern_mount+0x30/0xec) | [] (vfs_kern_mount+0x0/0xec) from [] (kern_mount_data+0x1c/0x20) | [] (kern_mount_data+0x0/0x20) from [] (sysfs_init+0x68/0xc8) | [] (sysfs_init+0x0/0xc8) from [] (mnt_init+0x90/0x1b0) | [] (mnt_init+0x0/0x1b0) from [] (vfs_caches_init+0x100/0x140) | [] (vfs_caches_init+0x0/0x140) from [] (start_kernel+0x2e8/0x368) | [] (start_kernel+0x0/0x368) from [] (__enable_mmu+0x0/0x2c) | c0113268: redzone 1:0xd84156c5c032b3ac, redzone 2:0xd84156c5635688c0. | slab error in cache_alloc_debugcheck_after(): cache `idr_layer_cache': double free, or memory outside object was overwritten | ... | c011307c: redzone 1:0x9f91102ffffffff, redzone 2:0x9f911029d74e35b | slab: Internal list corruption detected in cache 'idr_layer_cache'(24), slabp c0113000(16). Hexdump: | | 000: 20 4f 10 c0 20 4f 10 c0 7c 00 00 00 7c 30 11 c0 | 010: 10 00 00 00 10 00 00 00 00 00 c9 17 fe ff ff ff | 020: fe ff ff ff fe ff ff ff fe ff ff ff fe ff ff ff | 030: fe ff ff ff fe ff ff ff fe ff ff ff fe ff ff ff | 040: fe ff ff ff fe ff ff ff fe ff ff ff fe ff ff ff | 050: fe ff ff ff fe ff ff ff fe ff ff ff 11 00 00 00 | 060: 12 00 00 00 13 00 00 00 14 00 00 00 15 00 00 00 | 070: 16 00 00 00 17 00 00 00 c0 88 56 63 | kernel BUG at /home/rmk/git/linux-2.6-rmk/mm/slab.c:2928! Reference: https://lkml.org/lkml/2011/2/7/238 Cc: # 2.6.35.y and later Reported-and-analyzed-by: Russell King Signed-off-by: Pekka Enberg --- mm/slab.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/mm/slab.c b/mm/slab.c index 37961d1f584fe..4c6e2e31ced05 100644 --- a/mm/slab.c +++ b/mm/slab.c @@ -2288,8 +2288,8 @@ kmem_cache_create (const char *name, size_t size, size_t align, if (ralign < align) { ralign = align; } - /* disable debug if not aligning with REDZONE_ALIGN */ - if (ralign & (__alignof__(unsigned long long) - 1)) + /* disable debug if necessary */ + if (ralign > __alignof__(unsigned long long)) flags &= ~(SLAB_RED_ZONE | SLAB_STORE_USER); /* * 4) Store it. @@ -2315,8 +2315,8 @@ kmem_cache_create (const char *name, size_t size, size_t align, */ if (flags & SLAB_RED_ZONE) { /* add space for red zone words */ - cachep->obj_offset += align; - size += align + sizeof(unsigned long long); + cachep->obj_offset += sizeof(unsigned long long); + size += 2 * sizeof(unsigned long long); } if (flags & SLAB_STORE_USER) { /* user store requires one word storage behind the end of -- GitLab From 410f14837a92177242a403c20d0a0906fe357019 Mon Sep 17 00:00:00 2001 From: Catalin Marinas Date: Mon, 14 Feb 2011 12:58:04 +0100 Subject: [PATCH 0074/2822] ARM: 6667/1: Fix early_pte_alloc() assumption about the Linux PTE With LPAE we no longer have software bits in a separate Linux PTE and the early_pte_alloc() function should pass PTE_HWTABLE_OFF + PTE_HWTABLE_SIZE to early_alloc() to avoid allocating extra memory. Signed-off-by: Catalin Marinas Signed-off-by: Russell King --- arch/arm/mm/mmu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c index 546e44734db02..7515d4718645a 100644 --- a/arch/arm/mm/mmu.c +++ b/arch/arm/mm/mmu.c @@ -532,7 +532,7 @@ static void __init *early_alloc(unsigned long sz) static pte_t * __init early_pte_alloc(pmd_t *pmd, unsigned long addr, unsigned long prot) { if (pmd_none(*pmd)) { - pte_t *pte = early_alloc(2 * PTRS_PER_PTE * sizeof(pte_t)); + pte_t *pte = early_alloc(PTE_HWTABLE_OFF + PTE_HWTABLE_SIZE); __pmd_populate(pmd, __pa(pte), prot); } BUG_ON(pmd_bad(*pmd)); -- GitLab From 29a38193c15bd72ba96c57a805443ef46ea6a6ac Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Tue, 15 Feb 2011 14:31:37 +0100 Subject: [PATCH 0075/2822] ARM: 6674/1: LPAE: use long long format when printing physical addresses and ptes For the Kernel to support 2 level and 3 level page tables, physical addresses (and also page table entries) need to be 32 or 64-bits depending upon the configuration. This patch uses the %08llx conversion specifier for physical addresses and page table entries, ensuring that they are cast to (long long) so that common code can be used regardless of the datatype widths. Acked-by: Catalin Marinas Signed-off-by: Will Deacon Signed-off-by: Russell King --- arch/arm/kernel/setup.c | 2 +- arch/arm/kernel/traps.c | 6 +++--- arch/arm/mm/fault.c | 10 ++++++---- arch/arm/mm/mmu.c | 26 +++++++++++++------------- 4 files changed, 23 insertions(+), 21 deletions(-) diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c index 336f14e0e5c21..77af580953e62 100644 --- a/arch/arm/kernel/setup.c +++ b/arch/arm/kernel/setup.c @@ -448,7 +448,7 @@ static int __init arm_add_memory(unsigned long start, unsigned long size) if (meminfo.nr_banks >= NR_BANKS) { printk(KERN_CRIT "NR_BANKS too low, " - "ignoring memory at %#lx\n", start); + "ignoring memory at 0x%08llx\n", (long long)start); return -EINVAL; } diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c index 354cd4ce400a2..10f5b8926ee69 100644 --- a/arch/arm/kernel/traps.c +++ b/arch/arm/kernel/traps.c @@ -710,17 +710,17 @@ EXPORT_SYMBOL(__readwrite_bug); void __pte_error(const char *file, int line, pte_t pte) { - printk("%s:%d: bad pte %08lx.\n", file, line, pte_val(pte)); + printk("%s:%d: bad pte %08llx.\n", file, line, (long long)pte_val(pte)); } void __pmd_error(const char *file, int line, pmd_t pmd) { - printk("%s:%d: bad pmd %08lx.\n", file, line, pmd_val(pmd)); + printk("%s:%d: bad pmd %08llx.\n", file, line, (long long)pmd_val(pmd)); } void __pgd_error(const char *file, int line, pgd_t pgd) { - printk("%s:%d: bad pgd %08lx.\n", file, line, pgd_val(pgd)); + printk("%s:%d: bad pgd %08llx.\n", file, line, (long long)pgd_val(pgd)); } asmlinkage void __div0(void) diff --git a/arch/arm/mm/fault.c b/arch/arm/mm/fault.c index f10f9bac22069..ef0e24f578ef2 100644 --- a/arch/arm/mm/fault.c +++ b/arch/arm/mm/fault.c @@ -76,7 +76,8 @@ void show_pte(struct mm_struct *mm, unsigned long addr) printk(KERN_ALERT "pgd = %p\n", mm->pgd); pgd = pgd_offset(mm, addr); - printk(KERN_ALERT "[%08lx] *pgd=%08lx", addr, pgd_val(*pgd)); + printk(KERN_ALERT "[%08lx] *pgd=%08llx", + addr, (long long)pgd_val(*pgd)); do { pmd_t *pmd; @@ -92,7 +93,7 @@ void show_pte(struct mm_struct *mm, unsigned long addr) pmd = pmd_offset(pgd, addr); if (PTRS_PER_PMD != 1) - printk(", *pmd=%08lx", pmd_val(*pmd)); + printk(", *pmd=%08llx", (long long)pmd_val(*pmd)); if (pmd_none(*pmd)) break; @@ -107,8 +108,9 @@ void show_pte(struct mm_struct *mm, unsigned long addr) break; pte = pte_offset_map(pmd, addr); - printk(", *pte=%08lx", pte_val(*pte)); - printk(", *ppte=%08lx", pte_val(pte[PTE_HWTABLE_PTRS])); + printk(", *pte=%08llx", (long long)pte_val(*pte)); + printk(", *ppte=%08llx", + (long long)pte_val(pte[PTE_HWTABLE_PTRS])); pte_unmap(pte); } while(0); diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c index 7515d4718645a..f512ad97dafe0 100644 --- a/arch/arm/mm/mmu.c +++ b/arch/arm/mm/mmu.c @@ -597,7 +597,7 @@ static void __init create_36bit_mapping(struct map_desc *md, if (!(cpu_architecture() >= CPU_ARCH_ARMv6 || cpu_is_xsc3())) { printk(KERN_ERR "MM: CPU does not support supersection " "mapping for 0x%08llx at 0x%08lx\n", - __pfn_to_phys((u64)md->pfn), addr); + (long long)__pfn_to_phys((u64)md->pfn), addr); return; } @@ -610,14 +610,14 @@ static void __init create_36bit_mapping(struct map_desc *md, if (type->domain) { printk(KERN_ERR "MM: invalid domain in supersection " "mapping for 0x%08llx at 0x%08lx\n", - __pfn_to_phys((u64)md->pfn), addr); + (long long)__pfn_to_phys((u64)md->pfn), addr); return; } if ((addr | length | __pfn_to_phys(md->pfn)) & ~SUPERSECTION_MASK) { - printk(KERN_ERR "MM: cannot create mapping for " - "0x%08llx at 0x%08lx invalid alignment\n", - __pfn_to_phys((u64)md->pfn), addr); + printk(KERN_ERR "MM: cannot create mapping for 0x%08llx" + " at 0x%08lx invalid alignment\n", + (long long)__pfn_to_phys((u64)md->pfn), addr); return; } @@ -656,17 +656,17 @@ static void __init create_mapping(struct map_desc *md) pgd_t *pgd; if (md->virtual != vectors_base() && md->virtual < TASK_SIZE) { - printk(KERN_WARNING "BUG: not creating mapping for " - "0x%08llx at 0x%08lx in user region\n", - __pfn_to_phys((u64)md->pfn), md->virtual); + printk(KERN_WARNING "BUG: not creating mapping for 0x%08llx" + " at 0x%08lx in user region\n", + (long long)__pfn_to_phys((u64)md->pfn), md->virtual); return; } if ((md->type == MT_DEVICE || md->type == MT_ROM) && md->virtual >= PAGE_OFFSET && md->virtual < VMALLOC_END) { - printk(KERN_WARNING "BUG: mapping for 0x%08llx at 0x%08lx " - "overlaps vmalloc space\n", - __pfn_to_phys((u64)md->pfn), md->virtual); + printk(KERN_WARNING "BUG: mapping for 0x%08llx" + " at 0x%08lx overlaps vmalloc space\n", + (long long)__pfn_to_phys((u64)md->pfn), md->virtual); } type = &mem_types[md->type]; @@ -684,9 +684,9 @@ static void __init create_mapping(struct map_desc *md) length = PAGE_ALIGN(md->length + (md->virtual & ~PAGE_MASK)); if (type->prot_l1 == 0 && ((addr | phys | length) & ~SECTION_MASK)) { - printk(KERN_WARNING "BUG: map for 0x%08lx at 0x%08lx can not " + printk(KERN_WARNING "BUG: map for 0x%08llx at 0x%08lx can not " "be mapped using pages, ignoring.\n", - __pfn_to_phys(md->pfn), addr); + (long long)__pfn_to_phys(md->pfn), addr); return; } -- GitLab From ad6b9c9d78b9beebef02ac7f566a08db7be3c320 Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Tue, 15 Feb 2011 12:41:49 +0100 Subject: [PATCH 0076/2822] ARM: 6671/1: LPAE: use phys_addr_t instead of unsigned long in outercache functions The unsigned long datatype is not sufficient for mapping physical addresses >= 4GB. This patch ensures that the phys_addr_t datatype is used to represent physical addresses when passed to the outer cache functions. Note that the definitions in struct outer_cache_fns remain as unsigned long because there are currently no outer cache implementations supporting physical addresses wider than 32-bits. Acked-by: Catalin Marinas Signed-off-by: Will Deacon Signed-off-by: Russell King --- arch/arm/include/asm/outercache.h | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/arch/arm/include/asm/outercache.h b/arch/arm/include/asm/outercache.h index fc19009252753..88ad892097644 100644 --- a/arch/arm/include/asm/outercache.h +++ b/arch/arm/include/asm/outercache.h @@ -21,6 +21,8 @@ #ifndef __ASM_OUTERCACHE_H #define __ASM_OUTERCACHE_H +#include + struct outer_cache_fns { void (*inv_range)(unsigned long, unsigned long); void (*clean_range)(unsigned long, unsigned long); @@ -37,17 +39,17 @@ struct outer_cache_fns { extern struct outer_cache_fns outer_cache; -static inline void outer_inv_range(unsigned long start, unsigned long end) +static inline void outer_inv_range(phys_addr_t start, phys_addr_t end) { if (outer_cache.inv_range) outer_cache.inv_range(start, end); } -static inline void outer_clean_range(unsigned long start, unsigned long end) +static inline void outer_clean_range(phys_addr_t start, phys_addr_t end) { if (outer_cache.clean_range) outer_cache.clean_range(start, end); } -static inline void outer_flush_range(unsigned long start, unsigned long end) +static inline void outer_flush_range(phys_addr_t start, phys_addr_t end) { if (outer_cache.flush_range) outer_cache.flush_range(start, end); @@ -73,11 +75,11 @@ static inline void outer_disable(void) #else -static inline void outer_inv_range(unsigned long start, unsigned long end) +static inline void outer_inv_range(phys_addr_t start, phys_addr_t end) { } -static inline void outer_clean_range(unsigned long start, unsigned long end) +static inline void outer_clean_range(phys_addr_t start, phys_addr_t end) { } -static inline void outer_flush_range(unsigned long start, unsigned long end) +static inline void outer_flush_range(phys_addr_t start, phys_addr_t end) { } static inline void outer_flush_all(void) { } static inline void outer_inv_all(void) { } -- GitLab From cae6292b653f5e3308bf2787a54b7dcd2cc7e2b3 Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Tue, 15 Feb 2011 12:42:57 +0100 Subject: [PATCH 0077/2822] ARM: 6672/1: LPAE: use phys_addr_t instead of unsigned long in mapping functions The unsigned long datatype is not sufficient for mapping physical addresses >= 4GB. This patch ensures that the phys_addr_t datatype is used to represent physical addresses when converting from a PFN. Acked-by: Catalin Marinas Signed-off-by: Will Deacon Signed-off-by: Russell King --- arch/arm/include/asm/pgtable.h | 2 +- arch/arm/mm/init.c | 6 +++--- arch/arm/mm/mmu.c | 7 ++++--- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/arch/arm/include/asm/pgtable.h b/arch/arm/include/asm/pgtable.h index ebcb6432f45f8..ca567914d303b 100644 --- a/arch/arm/include/asm/pgtable.h +++ b/arch/arm/include/asm/pgtable.h @@ -351,7 +351,7 @@ static inline pte_t *pmd_page_vaddr(pmd_t pmd) #define pte_unmap(pte) __pte_unmap(pte) #define pte_pfn(pte) (pte_val(pte) >> PAGE_SHIFT) -#define pfn_pte(pfn,prot) __pte(((pfn) << PAGE_SHIFT) | pgprot_val(prot)) +#define pfn_pte(pfn,prot) __pte(__pfn_to_phys(pfn) | pgprot_val(prot)) #define pte_page(pte) pfn_to_page(pte_pfn(pte)) #define mk_pte(page,prot) pfn_pte(page_to_pfn(page), prot) diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c index 5164069ced42f..14a00a1ef52f4 100644 --- a/arch/arm/mm/init.c +++ b/arch/arm/mm/init.c @@ -344,7 +344,7 @@ void __init bootmem_init(void) */ arm_bootmem_free(min, max_low, max_high); - high_memory = __va((max_low << PAGE_SHIFT) - 1) + 1; + high_memory = __va(((phys_addr_t)max_low << PAGE_SHIFT) - 1) + 1; /* * This doesn't seem to be used by the Linux memory manager any @@ -392,8 +392,8 @@ free_memmap(unsigned long start_pfn, unsigned long end_pfn) * Convert to physical addresses, and * round start upwards and end downwards. */ - pg = PAGE_ALIGN(__pa(start_pg)); - pgend = __pa(end_pg) & PAGE_MASK; + pg = (unsigned long)PAGE_ALIGN(__pa(start_pg)); + pgend = (unsigned long)__pa(end_pg) & PAGE_MASK; /* * If there are free pages between these, diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c index f512ad97dafe0..e09744e82d50f 100644 --- a/arch/arm/mm/mmu.c +++ b/arch/arm/mm/mmu.c @@ -591,7 +591,7 @@ static void __init create_36bit_mapping(struct map_desc *md, pgd_t *pgd; addr = md->virtual; - phys = (unsigned long)__pfn_to_phys(md->pfn); + phys = __pfn_to_phys(md->pfn); length = PAGE_ALIGN(md->length); if (!(cpu_architecture() >= CPU_ARCH_ARMv6 || cpu_is_xsc3())) { @@ -651,7 +651,8 @@ static void __init create_36bit_mapping(struct map_desc *md, */ static void __init create_mapping(struct map_desc *md) { - unsigned long phys, addr, length, end; + unsigned long addr, length, end; + phys_addr_t phys; const struct mem_type *type; pgd_t *pgd; @@ -680,7 +681,7 @@ static void __init create_mapping(struct map_desc *md) } addr = md->virtual & PAGE_MASK; - phys = (unsigned long)__pfn_to_phys(md->pfn); + phys = __pfn_to_phys(md->pfn); length = PAGE_ALIGN(md->length + (md->virtual & ~PAGE_MASK)); if (type->prot_l1 == 0 && ((addr | phys | length) & ~SECTION_MASK)) { -- GitLab From 9728c1b6a724daefc413b44e10253cdbb5e06d08 Mon Sep 17 00:00:00 2001 From: Russell King Date: Wed, 19 Jan 2011 23:29:12 +0000 Subject: [PATCH 0078/2822] ARM: versatile: support CLCD RGB565 layout with blue LSB RGB565 with blue in the LSB wasn't supported. Add support for this layout. Acked-by: Catalin Marinas Signed-off-by: Russell King --- arch/arm/mach-versatile/core.c | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/arch/arm/mach-versatile/core.c b/arch/arm/mach-versatile/core.c index 136c32e7ed8eb..2866c114e682d 100644 --- a/arch/arm/mach-versatile/core.c +++ b/arch/arm/mach-versatile/core.c @@ -630,18 +630,22 @@ static void versatile_clcd_disable(struct clcd_fb *fb) */ static void versatile_clcd_enable(struct clcd_fb *fb) { + struct fb_var_screeninfo *var = &fb->fb.var; void __iomem *sys_clcd = __io_address(VERSATILE_SYS_BASE) + VERSATILE_SYS_CLCD_OFFSET; u32 val; val = readl(sys_clcd); val &= ~SYS_CLCD_MODE_MASK; - switch (fb->fb.var.green.length) { + switch (var->green.length) { case 5: val |= SYS_CLCD_MODE_5551; break; case 6: - val |= SYS_CLCD_MODE_565_RLSB; + if (var->red.offset == 0) + val |= SYS_CLCD_MODE_565_RLSB; + else + val |= SYS_CLCD_MODE_565_BLSB; break; case 8: val |= SYS_CLCD_MODE_888; @@ -709,10 +713,19 @@ static void versatile_clcd_remove(struct clcd_fb *fb) fb->fb.screen_base, fb->fb.fix.smem_start); } +static void versatile_clcd_decode(struct clcd_fb *fb, struct clcd_regs *regs) +{ + clcdfb_decode(fb, regs); + + /* Always clear BGR for RGB565: we do the routing externally */ + if (fb->fb.var.green.length == 6) + regs->cntl &= ~CNTL_BGR; +} + static struct clcd_board clcd_plat_data = { .name = "Versatile", .check = clcdfb_check, - .decode = clcdfb_decode, + .decode = versatile_clcd_decode, .disable = versatile_clcd_disable, .enable = versatile_clcd_enable, .setup = versatile_clcd_setup, -- GitLab From e6b9c1f8a623bfaa545067df73213db1c9c8e7af Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 22 Jan 2011 11:02:10 +0000 Subject: [PATCH 0079/2822] ARM: integrator: support CLCD RGB5551 layout for 16bpp When the CLCD is in anything but RGB888 mode, its outputs are configured for RGB5551 output. Integrator/CP supports RGB565 via an external multiplexer, which we configure for RGB5551 or RGB565 based only on the bits per pixel. So when userspace asks for the RGB555 layout, the mux remains in RGB565 mode, and we produce incorrect colours. Fix this. Note that Integrator doesn't support BGR565 mode, but does support BGR5551. Acked-by: Catalin Marinas Signed-off-by: Russell King --- arch/arm/mach-integrator/include/mach/cm.h | 4 ++-- arch/arm/mach-integrator/integrator_cp.c | 14 ++++++++------ 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/arch/arm/mach-integrator/include/mach/cm.h b/arch/arm/mach-integrator/include/mach/cm.h index 1ab353e235955..445d57adb043a 100644 --- a/arch/arm/mach-integrator/include/mach/cm.h +++ b/arch/arm/mach-integrator/include/mach/cm.h @@ -24,9 +24,9 @@ void cm_control(u32, u32); #define CM_CTRL_LCDBIASDN (1 << 10) #define CM_CTRL_LCDMUXSEL_MASK (7 << 11) #define CM_CTRL_LCDMUXSEL_GENLCD (1 << 11) -#define CM_CTRL_LCDMUXSEL_VGA_16BPP (2 << 11) +#define CM_CTRL_LCDMUXSEL_VGA565_TFT555 (2 << 11) #define CM_CTRL_LCDMUXSEL_SHARPLCD (3 << 11) -#define CM_CTRL_LCDMUXSEL_VGA_8421BPP (4 << 11) +#define CM_CTRL_LCDMUXSEL_VGA555_TFT555 (4 << 11) #define CM_CTRL_LCDEN0 (1 << 14) #define CM_CTRL_LCDEN1 (1 << 15) #define CM_CTRL_STATIC1 (1 << 16) diff --git a/arch/arm/mach-integrator/integrator_cp.c b/arch/arm/mach-integrator/integrator_cp.c index e9327da1382e7..860090247b3bf 100644 --- a/arch/arm/mach-integrator/integrator_cp.c +++ b/arch/arm/mach-integrator/integrator_cp.c @@ -478,14 +478,16 @@ static struct clcd_panel vga = { */ static void cp_clcd_enable(struct clcd_fb *fb) { - u32 val; + struct fb_var_screeninfo *var = &fb->fb.var; + u32 val = CM_CTRL_STATIC1 | CM_CTRL_STATIC2; - if (fb->fb.var.bits_per_pixel <= 8) - val = CM_CTRL_LCDMUXSEL_VGA_8421BPP; + if (var->bits_per_pixel <= 8 || + (var->bits_per_pixel == 16 && var->green.length == 5)) + /* Pseudocolor, RGB555, BGR555 */ + val |= CM_CTRL_LCDMUXSEL_VGA555_TFT555; else if (fb->fb.var.bits_per_pixel <= 16) - val = CM_CTRL_LCDMUXSEL_VGA_16BPP - | CM_CTRL_LCDEN0 | CM_CTRL_LCDEN1 - | CM_CTRL_STATIC1 | CM_CTRL_STATIC2; + /* truecolor RGB565 */ + val |= CM_CTRL_LCDMUXSEL_VGA565_TFT555; else val = 0; /* no idea for this, don't trust the docs */ -- GitLab From ff6433225b08d74f77f6eb4c5bf5ca434a371492 Mon Sep 17 00:00:00 2001 From: Russell King Date: Wed, 19 Jan 2011 21:10:24 +0000 Subject: [PATCH 0080/2822] ARM: clcd: clean up CLCD announcement printks Make the CLCD announcement printk say which primecell part number has been found. Display the revision as an unsigned decimal, and display only the first 8 hex digits of the base address unless it's larger. Acked-by: Catalin Marinas Signed-off-by: Russell King --- drivers/video/amba-clcd.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/video/amba-clcd.c b/drivers/video/amba-clcd.c index 1c2c68356ea7e..aedbb345f8a90 100644 --- a/drivers/video/amba-clcd.c +++ b/drivers/video/amba-clcd.c @@ -443,8 +443,8 @@ static int clcdfb_register(struct clcd_fb *fb) fb_set_var(&fb->fb, &fb->fb.var); - printk(KERN_INFO "CLCD: %s hardware, %s display\n", - fb->board->name, fb->panel->mode.name); + dev_info(&fb->dev->dev, "%s hardware, %s display\n", + fb->board->name, fb->panel->mode.name); ret = register_framebuffer(&fb->fb); if (ret == 0) @@ -486,6 +486,10 @@ static int clcdfb_probe(struct amba_device *dev, struct amba_id *id) fb->dev = dev; fb->board = board; + dev_info(&fb->dev->dev, "PL%03x rev%u at 0x%08llx\n", + amba_part(dev), amba_rev(dev), + (unsigned long long)dev->res.start); + ret = fb->board->setup(fb); if (ret) goto free_fb; -- GitLab From 9c49e4ab84dd46769e7fd9773946e10c95bab680 Mon Sep 17 00:00:00 2001 From: Russell King Date: Wed, 19 Jan 2011 21:13:33 +0000 Subject: [PATCH 0081/2822] ARM: clcd: use amba_part() to determine if we have a PL110 primecell Instead of matching the entire peripheral ID, match against just the part number using the amba_xxx() macros. Acked-by: Catalin Marinas Signed-off-by: Russell King --- include/linux/amba/clcd.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/include/linux/amba/clcd.h b/include/linux/amba/clcd.h index be33b3affc8ad..2e511219a1610 100644 --- a/include/linux/amba/clcd.h +++ b/include/linux/amba/clcd.h @@ -212,12 +212,12 @@ static inline void clcdfb_decode(struct clcd_fb *fb, struct clcd_regs *regs) break; case 16: /* - * PL110 cannot choose between 5551 and 565 modes in - * its control register + * PL110 cannot choose between 5551 and 565 modes in its + * control register. It is possible to use 565 with + * custom external wiring. */ - if ((fb->dev->periphid & 0x000fffff) == 0x00041110) - val |= CNTL_LCDBPP16; - else if (fb->fb.var.green.length == 5) + if (amba_part(fb->dev) == 0x110 || + fb->fb.var.green.length == 5) val |= CNTL_LCDBPP16; else val |= CNTL_LCDBPP16_565; -- GitLab From 7b4e9ced69a120e7e7446e3303d2307aa29d891c Mon Sep 17 00:00:00 2001 From: Russell King Date: Fri, 21 Jan 2011 14:03:28 +0000 Subject: [PATCH 0082/2822] ARM: clcd: add method for describing display capabilities The ARM CLCD PL110 controller in TFT mode provides two output formats based on whether the controller is in 24bpp mode or not - either 5551 or 888. PL111 augments this with a 444 and 565 modes. Some implementations provide an external MUX on the PL110 output to reassign the bits to achieve 565 mode. Provide a system of capability flags to allow the CLCD driver to work out what is supported by each panel and board, and therefore which display formats are permitted. Acked-by: Catalin Marinas Signed-off-by: Russell King --- drivers/video/amba-clcd.c | 95 ++++++++++++++++++++++++++++++++++----- include/linux/amba/clcd.h | 82 ++++++++++++++++++++++++++------- 2 files changed, 149 insertions(+), 28 deletions(-) diff --git a/drivers/video/amba-clcd.c b/drivers/video/amba-clcd.c index aedbb345f8a90..8bd3706975332 100644 --- a/drivers/video/amba-clcd.c +++ b/drivers/video/amba-clcd.c @@ -120,8 +120,23 @@ static void clcdfb_enable(struct clcd_fb *fb, u32 cntl) static int clcdfb_set_bitfields(struct clcd_fb *fb, struct fb_var_screeninfo *var) { + u32 caps; int ret = 0; + if (fb->panel->caps && fb->board->caps) + caps = fb->panel->caps & fb->board->caps; + else { + /* Old way of specifying what can be used */ + caps = fb->panel->cntl & CNTL_BGR ? + CLCD_CAP_BGR : CLCD_CAP_RGB; + /* But mask out 444 modes as they weren't supported */ + caps &= ~CLCD_CAP_444; + } + + /* Only TFT panels can do RGB888/BGR888 */ + if (!(fb->panel->cntl & CNTL_LCDTFT)) + caps &= ~CLCD_CAP_888; + memset(&var->transp, 0, sizeof(var->transp)); var->red.msb_right = 0; @@ -133,6 +148,13 @@ clcdfb_set_bitfields(struct clcd_fb *fb, struct fb_var_screeninfo *var) case 2: case 4: case 8: + /* If we can't do 5551, reject */ + caps &= CLCD_CAP_5551; + if (!caps) { + ret = -EINVAL; + break; + } + var->red.length = var->bits_per_pixel; var->red.offset = 0; var->green.length = var->bits_per_pixel; @@ -140,23 +162,61 @@ clcdfb_set_bitfields(struct clcd_fb *fb, struct fb_var_screeninfo *var) var->blue.length = var->bits_per_pixel; var->blue.offset = 0; break; + case 16: - var->red.length = 5; - var->blue.length = 5; + /* If we can't do 444, 5551 or 565, reject */ + if (!(caps & (CLCD_CAP_444 | CLCD_CAP_5551 | CLCD_CAP_565))) { + ret = -EINVAL; + break; + } + /* - * Green length can be 5 or 6 depending whether - * we're operating in RGB555 or RGB565 mode. + * Green length can be 4, 5 or 6 depending whether + * we're operating in 444, 5551 or 565 mode. */ - if (var->green.length != 5 && var->green.length != 6) - var->green.length = 6; + if (var->green.length == 4 && caps & CLCD_CAP_444) + caps &= CLCD_CAP_444; + if (var->green.length == 5 && caps & CLCD_CAP_5551) + caps &= CLCD_CAP_5551; + else if (var->green.length == 6 && caps & CLCD_CAP_565) + caps &= CLCD_CAP_565; + else { + /* + * PL110 officially only supports RGB555, + * but may be wired up to allow RGB565. + */ + if (caps & CLCD_CAP_565) { + var->green.length = 6; + caps &= CLCD_CAP_565; + } else if (caps & CLCD_CAP_5551) { + var->green.length = 5; + caps &= CLCD_CAP_5551; + } else { + var->green.length = 4; + caps &= CLCD_CAP_444; + } + } + + if (var->green.length >= 5) { + var->red.length = 5; + var->blue.length = 5; + } else { + var->red.length = 4; + var->blue.length = 4; + } break; case 32: - if (fb->panel->cntl & CNTL_LCDTFT) { - var->red.length = 8; - var->green.length = 8; - var->blue.length = 8; + /* If we can't do 888, reject */ + caps &= CLCD_CAP_888; + if (!caps) { + ret = -EINVAL; break; } + + var->red.length = 8; + var->green.length = 8; + var->blue.length = 8; + break; default: ret = -EINVAL; break; @@ -168,7 +228,20 @@ clcdfb_set_bitfields(struct clcd_fb *fb, struct fb_var_screeninfo *var) * the bitfield length defined above. */ if (ret == 0 && var->bits_per_pixel >= 16) { - if (fb->panel->cntl & CNTL_BGR) { + bool bgr, rgb; + + bgr = caps & CLCD_CAP_BGR && var->blue.offset == 0; + rgb = caps & CLCD_CAP_RGB && var->red.offset == 0; + + if (!bgr && !rgb) + /* + * The requested format was not possible, try just + * our capabilities. One of BGR or RGB must be + * supported. + */ + bgr = caps & CLCD_CAP_BGR; + + if (bgr) { var->blue.offset = 0; var->green.offset = var->blue.offset + var->blue.length; var->red.offset = var->green.offset + var->green.length; diff --git a/include/linux/amba/clcd.h b/include/linux/amba/clcd.h index 2e511219a1610..24d26efd14326 100644 --- a/include/linux/amba/clcd.h +++ b/include/linux/amba/clcd.h @@ -53,6 +53,7 @@ #define CNTL_LCDBPP8 (3 << 1) #define CNTL_LCDBPP16 (4 << 1) #define CNTL_LCDBPP16_565 (6 << 1) +#define CNTL_LCDBPP16_444 (7 << 1) #define CNTL_LCDBPP24 (5 << 1) #define CNTL_LCDBW (1 << 4) #define CNTL_LCDTFT (1 << 5) @@ -66,6 +67,32 @@ #define CNTL_LDMAFIFOTIME (1 << 15) #define CNTL_WATERMARK (1 << 16) +enum { + /* individual formats */ + CLCD_CAP_RGB444 = (1 << 0), + CLCD_CAP_RGB5551 = (1 << 1), + CLCD_CAP_RGB565 = (1 << 2), + CLCD_CAP_RGB888 = (1 << 3), + CLCD_CAP_BGR444 = (1 << 4), + CLCD_CAP_BGR5551 = (1 << 5), + CLCD_CAP_BGR565 = (1 << 6), + CLCD_CAP_BGR888 = (1 << 7), + + /* connection layouts */ + CLCD_CAP_444 = CLCD_CAP_RGB444 | CLCD_CAP_BGR444, + CLCD_CAP_5551 = CLCD_CAP_RGB5551 | CLCD_CAP_BGR5551, + CLCD_CAP_565 = CLCD_CAP_RGB565 | CLCD_CAP_BGR565, + CLCD_CAP_888 = CLCD_CAP_RGB888 | CLCD_CAP_BGR888, + + /* red/blue ordering */ + CLCD_CAP_RGB = CLCD_CAP_RGB444 | CLCD_CAP_RGB5551 | + CLCD_CAP_RGB565 | CLCD_CAP_RGB888, + CLCD_CAP_BGR = CLCD_CAP_BGR444 | CLCD_CAP_BGR5551 | + CLCD_CAP_BGR565 | CLCD_CAP_BGR888, + + CLCD_CAP_ALL = CLCD_CAP_BGR | CLCD_CAP_RGB, +}; + struct clcd_panel { struct fb_videomode mode; signed short width; /* width in mm */ @@ -73,6 +100,7 @@ struct clcd_panel { u32 tim2; u32 tim3; u32 cntl; + u32 caps; unsigned int bpp:8, fixedtimings:1, grayscale:1; @@ -96,6 +124,11 @@ struct clcd_fb; struct clcd_board { const char *name; + /* + * Optional. Hardware capability flags. + */ + u32 caps; + /* * Optional. Check whether the var structure is acceptable * for this display. @@ -155,34 +188,35 @@ struct clcd_fb { static inline void clcdfb_decode(struct clcd_fb *fb, struct clcd_regs *regs) { + struct fb_var_screeninfo *var = &fb->fb.var; u32 val, cpl; /* * Program the CLCD controller registers and start the CLCD */ - val = ((fb->fb.var.xres / 16) - 1) << 2; - val |= (fb->fb.var.hsync_len - 1) << 8; - val |= (fb->fb.var.right_margin - 1) << 16; - val |= (fb->fb.var.left_margin - 1) << 24; + val = ((var->xres / 16) - 1) << 2; + val |= (var->hsync_len - 1) << 8; + val |= (var->right_margin - 1) << 16; + val |= (var->left_margin - 1) << 24; regs->tim0 = val; - val = fb->fb.var.yres; + val = var->yres; if (fb->panel->cntl & CNTL_LCDDUAL) val /= 2; val -= 1; - val |= (fb->fb.var.vsync_len - 1) << 10; - val |= fb->fb.var.lower_margin << 16; - val |= fb->fb.var.upper_margin << 24; + val |= (var->vsync_len - 1) << 10; + val |= var->lower_margin << 16; + val |= var->upper_margin << 24; regs->tim1 = val; val = fb->panel->tim2; - val |= fb->fb.var.sync & FB_SYNC_HOR_HIGH_ACT ? 0 : TIM2_IHS; - val |= fb->fb.var.sync & FB_SYNC_VERT_HIGH_ACT ? 0 : TIM2_IVS; + val |= var->sync & FB_SYNC_HOR_HIGH_ACT ? 0 : TIM2_IHS; + val |= var->sync & FB_SYNC_VERT_HIGH_ACT ? 0 : TIM2_IVS; - cpl = fb->fb.var.xres_virtual; + cpl = var->xres_virtual; if (fb->panel->cntl & CNTL_LCDTFT) /* TFT */ /* / 1 */; - else if (!fb->fb.var.grayscale) /* STN color */ + else if (!var->grayscale) /* STN color */ cpl = cpl * 8 / 3; else if (fb->panel->cntl & CNTL_LCDMONO8) /* STN monochrome, 8bit */ cpl /= 8; @@ -194,10 +228,22 @@ static inline void clcdfb_decode(struct clcd_fb *fb, struct clcd_regs *regs) regs->tim3 = fb->panel->tim3; val = fb->panel->cntl; - if (fb->fb.var.grayscale) + if (var->grayscale) val |= CNTL_LCDBW; - switch (fb->fb.var.bits_per_pixel) { + if (fb->panel->caps && fb->board->caps && + var->bits_per_pixel >= 16) { + /* + * if board and panel supply capabilities, we can support + * changing BGR/RGB depending on supplied parameters + */ + if (var->red.offset == 0) + val &= ~CNTL_BGR; + else + val |= CNTL_BGR; + } + + switch (var->bits_per_pixel) { case 1: val |= CNTL_LCDBPP1; break; @@ -217,10 +263,12 @@ static inline void clcdfb_decode(struct clcd_fb *fb, struct clcd_regs *regs) * custom external wiring. */ if (amba_part(fb->dev) == 0x110 || - fb->fb.var.green.length == 5) + var->green.length == 5) val |= CNTL_LCDBPP16; - else + else if (var->green.length == 6) val |= CNTL_LCDBPP16_565; + else + val |= CNTL_LCDBPP16_444; break; case 32: val |= CNTL_LCDBPP24; @@ -228,7 +276,7 @@ static inline void clcdfb_decode(struct clcd_fb *fb, struct clcd_regs *regs) } regs->cntl = val; - regs->pixclock = fb->fb.var.pixclock; + regs->pixclock = var->pixclock; } static inline int clcdfb_check(struct clcd_fb *fb, struct fb_var_screeninfo *var) -- GitLab From 420c34e4ccbbacab56d199e90a214e24380077dd Mon Sep 17 00:00:00 2001 From: Russell King Date: Tue, 18 Jan 2011 20:08:06 +0000 Subject: [PATCH 0083/2822] ARM: add versatile family consolidated CLCD support This consolidates the CLCD panel definitions and memory allocation into one location. Rename the Sanyo 2.5in and Epson 2.2in displays after their respective part numbers. Rather than using a general "Sanyo 2.5in" and "Epson 2.2in" description of the display panel, use the manufacturers part number to be more specific. This helps people identify what the timings actually refer to, which are panel specific. While here, add CLCD capability information to each panel definition, which has no effect until we add the board-level capabilities. Acked-by: Catalin Marinas Signed-off-by: Russell King --- arch/arm/Kconfig | 1 + arch/arm/plat-versatile/Kconfig | 6 + arch/arm/plat-versatile/Makefile | 1 + arch/arm/plat-versatile/clcd.c | 182 ++++++++++++++++++++ arch/arm/plat-versatile/include/plat/clcd.h | 9 + 5 files changed, 199 insertions(+) create mode 100644 arch/arm/plat-versatile/Kconfig create mode 100644 arch/arm/plat-versatile/clcd.c create mode 100644 arch/arm/plat-versatile/include/plat/clcd.h diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 70a017042ef0b..3087985010b96 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -1007,6 +1007,7 @@ source "arch/arm/mach-ux500/Kconfig" source "arch/arm/mach-versatile/Kconfig" source "arch/arm/mach-vexpress/Kconfig" +source "arch/arm/plat-versatile/Kconfig" source "arch/arm/mach-w90x900/Kconfig" diff --git a/arch/arm/plat-versatile/Kconfig b/arch/arm/plat-versatile/Kconfig new file mode 100644 index 0000000000000..22540f588fd38 --- /dev/null +++ b/arch/arm/plat-versatile/Kconfig @@ -0,0 +1,6 @@ +if PLAT_VERSATILE + +config PLAT_VERSATILE_CLCD + bool + +endif diff --git a/arch/arm/plat-versatile/Makefile b/arch/arm/plat-versatile/Makefile index 16dde08199349..8b3341c11ee51 100644 --- a/arch/arm/plat-versatile/Makefile +++ b/arch/arm/plat-versatile/Makefile @@ -6,3 +6,4 @@ ifeq ($(CONFIG_LEDS_CLASS),y) obj-$(CONFIG_ARCH_REALVIEW) += leds.o obj-$(CONFIG_ARCH_VERSATILE) += leds.o endif +obj-$(CONFIG_PLAT_VERSATILE_CLCD) += clcd.o diff --git a/arch/arm/plat-versatile/clcd.c b/arch/arm/plat-versatile/clcd.c new file mode 100644 index 0000000000000..6628cc27efc5f --- /dev/null +++ b/arch/arm/plat-versatile/clcd.c @@ -0,0 +1,182 @@ +#include +#include +#include +#include +#include + +static struct clcd_panel vga = { + .mode = { + .name = "VGA", + .refresh = 60, + .xres = 640, + .yres = 480, + .pixclock = 39721, + .left_margin = 40, + .right_margin = 24, + .upper_margin = 32, + .lower_margin = 11, + .hsync_len = 96, + .vsync_len = 2, + .sync = 0, + .vmode = FB_VMODE_NONINTERLACED, + }, + .width = -1, + .height = -1, + .tim2 = TIM2_BCD | TIM2_IPC, + .cntl = CNTL_LCDTFT | CNTL_BGR | CNTL_LCDVCOMP(1), + .caps = CLCD_CAP_5551 | CLCD_CAP_565 | CLCD_CAP_888, + .bpp = 16, +}; + +static struct clcd_panel xvga = { + .mode = { + .name = "XVGA", + .refresh = 60, + .xres = 1024, + .yres = 768, + .pixclock = 15748, + .left_margin = 152, + .right_margin = 48, + .upper_margin = 23, + .lower_margin = 3, + .hsync_len = 104, + .vsync_len = 4, + .sync = 0, + .vmode = FB_VMODE_NONINTERLACED, + }, + .width = -1, + .height = -1, + .tim2 = TIM2_BCD | TIM2_IPC, + .cntl = CNTL_LCDTFT | CNTL_BGR | CNTL_LCDVCOMP(1), + .caps = CLCD_CAP_5551 | CLCD_CAP_565 | CLCD_CAP_888, + .bpp = 16, +}; + +/* Sanyo TM38QV67A02A - 3.8 inch QVGA (320x240) Color TFT */ +static struct clcd_panel sanyo_tm38qv67a02a = { + .mode = { + .name = "Sanyo TM38QV67A02A", + .refresh = 116, + .xres = 320, + .yres = 240, + .pixclock = 100000, + .left_margin = 6, + .right_margin = 6, + .upper_margin = 5, + .lower_margin = 5, + .hsync_len = 6, + .vsync_len = 6, + .sync = 0, + .vmode = FB_VMODE_NONINTERLACED, + }, + .width = -1, + .height = -1, + .tim2 = TIM2_BCD, + .cntl = CNTL_LCDTFT | CNTL_BGR | CNTL_LCDVCOMP(1), + .caps = CLCD_CAP_5551, + .bpp = 16, +}; + +static struct clcd_panel sanyo_2_5_in = { + .mode = { + .name = "Sanyo QVGA Portrait", + .refresh = 116, + .xres = 240, + .yres = 320, + .pixclock = 100000, + .left_margin = 20, + .right_margin = 10, + .upper_margin = 2, + .lower_margin = 2, + .hsync_len = 10, + .vsync_len = 2, + .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, + .vmode = FB_VMODE_NONINTERLACED, + }, + .width = -1, + .height = -1, + .tim2 = TIM2_IVS | TIM2_IHS | TIM2_IPC, + .cntl = CNTL_LCDTFT | CNTL_BGR | CNTL_LCDVCOMP(1), + .caps = CLCD_CAP_5551, + .bpp = 16, +}; + +/* Epson L2F50113T00 - 2.2 inch 176x220 Color TFT */ +static struct clcd_panel epson_l2f50113t00 = { + .mode = { + .name = "Epson L2F50113T00", + .refresh = 390, + .xres = 176, + .yres = 220, + .pixclock = 62500, + .left_margin = 3, + .right_margin = 2, + .upper_margin = 1, + .lower_margin = 0, + .hsync_len = 3, + .vsync_len = 2, + .sync = 0, + .vmode = FB_VMODE_NONINTERLACED, + }, + .width = -1, + .height = -1, + .tim2 = TIM2_BCD | TIM2_IPC, + .cntl = CNTL_LCDTFT | CNTL_BGR | CNTL_LCDVCOMP(1), + .caps = CLCD_CAP_5551, + .bpp = 16, +}; + +static struct clcd_panel *panels[] = { + &vga, + &xvga, + &sanyo_tm38qv67a02a, + &sanyo_2_5_in, + &epson_l2f50113t00, +}; + +struct clcd_panel *versatile_clcd_get_panel(const char *name) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(panels); i++) + if (strcmp(panels[i]->mode.name, name) == 0) + break; + + if (i < ARRAY_SIZE(panels)) + return panels[i]; + + pr_err("CLCD: couldn't get parameters for panel %s\n", name); + + return NULL; +} + +int versatile_clcd_setup_dma(struct clcd_fb *fb, unsigned long framesize) +{ + dma_addr_t dma; + + fb->fb.screen_base = dma_alloc_writecombine(&fb->dev->dev, framesize, + &dma, GFP_KERNEL); + if (!fb->fb.screen_base) { + pr_err("CLCD: unable to map framebuffer\n"); + return -ENOMEM; + } + + fb->fb.fix.smem_start = dma; + fb->fb.fix.smem_len = framesize; + + return 0; +} + +int versatile_clcd_mmap_dma(struct clcd_fb *fb, struct vm_area_struct *vma) +{ + return dma_mmap_writecombine(&fb->dev->dev, vma, + fb->fb.screen_base, + fb->fb.fix.smem_start, + fb->fb.fix.smem_len); +} + +void versatile_clcd_remove_dma(struct clcd_fb *fb) +{ + dma_free_writecombine(&fb->dev->dev, fb->fb.fix.smem_len, + fb->fb.screen_base, fb->fb.fix.smem_start); +} diff --git a/arch/arm/plat-versatile/include/plat/clcd.h b/arch/arm/plat-versatile/include/plat/clcd.h new file mode 100644 index 0000000000000..6bb6a1d2019b4 --- /dev/null +++ b/arch/arm/plat-versatile/include/plat/clcd.h @@ -0,0 +1,9 @@ +#ifndef PLAT_CLCD_H +#define PLAT_CLCD_H + +struct clcd_panel *versatile_clcd_get_panel(const char *); +int versatile_clcd_setup_dma(struct clcd_fb *, unsigned long); +int versatile_clcd_mmap_dma(struct clcd_fb *, struct vm_area_struct *); +void versatile_clcd_remove_dma(struct clcd_fb *); + +#endif -- GitLab From 9dfec4fe6d2eb5580e5adcee8827dee3a16be49d Mon Sep 17 00:00:00 2001 From: Russell King Date: Tue, 18 Jan 2011 20:10:10 +0000 Subject: [PATCH 0084/2822] ARM: integrator: switch Integrator platforms to use consolidated CLCD This switches integrator platforms to use the consolidated CLCD panel support, including the display capabilities. These capabilities prevent the unsupported BGR565 mode being selected, while still allowing RGB5551, BGR5551 and RGB565 modes. Acked-by: Catalin Marinas Signed-off-by: Russell King --- arch/arm/mach-integrator/Kconfig | 1 + arch/arm/mach-integrator/impd1.c | 5 ++ arch/arm/mach-integrator/integrator_cp.c | 65 ++++-------------------- 3 files changed, 15 insertions(+), 56 deletions(-) diff --git a/arch/arm/mach-integrator/Kconfig b/arch/arm/mach-integrator/Kconfig index 769b0f10c8349..d701d32a07f1b 100644 --- a/arch/arm/mach-integrator/Kconfig +++ b/arch/arm/mach-integrator/Kconfig @@ -13,6 +13,7 @@ config ARCH_INTEGRATOR_CP bool "Support Integrator/CP platform" select ARCH_CINTEGRATOR select ARM_TIMER_SP804 + select PLAT_VERSATILE_CLCD help Include support for the ARM(R) Integrator CP platform. diff --git a/arch/arm/mach-integrator/impd1.c b/arch/arm/mach-integrator/impd1.c index 5db574f8ae3fd..8cbb75a96bd4b 100644 --- a/arch/arm/mach-integrator/impd1.c +++ b/arch/arm/mach-integrator/impd1.c @@ -121,6 +121,7 @@ static struct clcd_panel vga = { .height = -1, .tim2 = TIM2_BCD | TIM2_IPC, .cntl = CNTL_LCDTFT | CNTL_LCDVCOMP(1), + .caps = CLCD_CAP_5551, .connector = IMPD1_CTRL_DISP_VGA, .bpp = 16, .grayscale = 0, @@ -149,6 +150,7 @@ static struct clcd_panel svga = { .tim2 = TIM2_BCD, .cntl = CNTL_LCDTFT | CNTL_LCDVCOMP(1), .connector = IMPD1_CTRL_DISP_VGA, + .caps = CLCD_CAP_5551, .bpp = 16, .grayscale = 0, }; @@ -175,6 +177,7 @@ static struct clcd_panel prospector = { .height = -1, .tim2 = TIM2_BCD, .cntl = CNTL_LCDTFT | CNTL_LCDVCOMP(1), + .caps = CLCD_CAP_5551, .fixedtimings = 1, .connector = IMPD1_CTRL_DISP_LCD, .bpp = 16, @@ -206,6 +209,7 @@ static struct clcd_panel ltm10c209 = { .height = -1, .tim2 = TIM2_BCD, .cntl = CNTL_LCDTFT | CNTL_LCDVCOMP(1), + .caps = CLCD_CAP_5551, .fixedtimings = 1, .connector = IMPD1_CTRL_DISP_LCD, .bpp = 16, @@ -279,6 +283,7 @@ static void impd1fb_clcd_remove(struct clcd_fb *fb) static struct clcd_board impd1_clcd_data = { .name = "IM-PD/1", + .caps = CLCD_CAP_5551 | CLCD_CAP_888, .check = clcdfb_check, .decode = clcdfb_decode, .disable = impd1fb_clcd_disable, diff --git a/arch/arm/mach-integrator/integrator_cp.c b/arch/arm/mach-integrator/integrator_cp.c index 860090247b3bf..9c0203738aae0 100644 --- a/arch/arm/mach-integrator/integrator_cp.c +++ b/arch/arm/mach-integrator/integrator_cp.c @@ -42,6 +42,8 @@ #include +#include + #include "common.h" #define INTCP_PA_FLASH_BASE 0x24000000 @@ -449,30 +451,6 @@ static struct amba_device aaci_device = { /* * CLCD support */ -static struct clcd_panel vga = { - .mode = { - .name = "VGA", - .refresh = 60, - .xres = 640, - .yres = 480, - .pixclock = 39721, - .left_margin = 40, - .right_margin = 24, - .upper_margin = 32, - .lower_margin = 11, - .hsync_len = 96, - .vsync_len = 2, - .sync = 0, - .vmode = FB_VMODE_NONINTERLACED, - }, - .width = -1, - .height = -1, - .tim2 = TIM2_BCD | TIM2_IPC, - .cntl = CNTL_LCDTFT | CNTL_LCDVCOMP(1), - .bpp = 16, - .grayscale = 0, -}; - /* * Ensure VGA is selected. */ @@ -500,49 +478,24 @@ static void cp_clcd_enable(struct clcd_fb *fb) CM_CTRL_n24BITEN, val); } -static unsigned long framesize = SZ_1M; - static int cp_clcd_setup(struct clcd_fb *fb) { - dma_addr_t dma; - - fb->panel = &vga; - - fb->fb.screen_base = dma_alloc_writecombine(&fb->dev->dev, framesize, - &dma, GFP_KERNEL); - if (!fb->fb.screen_base) { - printk(KERN_ERR "CLCD: unable to map framebuffer\n"); - return -ENOMEM; - } - - fb->fb.fix.smem_start = dma; - fb->fb.fix.smem_len = framesize; - - return 0; -} - -static int cp_clcd_mmap(struct clcd_fb *fb, struct vm_area_struct *vma) -{ - return dma_mmap_writecombine(&fb->dev->dev, vma, - fb->fb.screen_base, - fb->fb.fix.smem_start, - fb->fb.fix.smem_len); -} + fb->panel = versatile_clcd_get_panel("VGA"); + if (!fb->panel) + return -EINVAL; -static void cp_clcd_remove(struct clcd_fb *fb) -{ - dma_free_writecombine(&fb->dev->dev, fb->fb.fix.smem_len, - fb->fb.screen_base, fb->fb.fix.smem_start); + return versatile_clcd_setup_dma(fb, SZ_1M); } static struct clcd_board clcd_data = { .name = "Integrator/CP", + .caps = CLCD_CAP_5551 | CLCD_CAP_RGB565 | CLCD_CAP_888, .check = clcdfb_check, .decode = clcdfb_decode, .enable = cp_clcd_enable, .setup = cp_clcd_setup, - .mmap = cp_clcd_mmap, - .remove = cp_clcd_remove, + .mmap = versatile_clcd_mmap_dma, + .remove = versatile_clcd_remove_dma, }; static struct amba_device clcd_device = { -- GitLab From 3414ba8c899023b604e6066d25bc9d516e059401 Mon Sep 17 00:00:00 2001 From: Russell King Date: Tue, 18 Jan 2011 20:12:10 +0000 Subject: [PATCH 0085/2822] ARM: versatile: switch Versatile to use consolidated CLCD This switches Versatile platforms to use the consolidated CLCD panel support, including the display capabilities. Versatile can support RGB5551, BGR5551, RGB565 and BGR565 modes. Acked-by: Catalin Marinas Signed-off-by: Russell King --- arch/arm/Kconfig | 1 + arch/arm/mach-versatile/core.c | 186 +++++++-------------------------- 2 files changed, 36 insertions(+), 151 deletions(-) diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 3087985010b96..b0d55b9f184e3 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -256,6 +256,7 @@ config ARCH_VERSATILE select GENERIC_CLOCKEVENTS select ARCH_WANT_OPTIONAL_GPIOLIB select PLAT_VERSATILE + select PLAT_VERSATILE_CLCD select ARM_TIMER_SP804 help This enables support for ARM Ltd Versatile board. diff --git a/arch/arm/mach-versatile/core.c b/arch/arm/mach-versatile/core.c index 2866c114e682d..b4f1f17eeb8df 100644 --- a/arch/arm/mach-versatile/core.c +++ b/arch/arm/mach-versatile/core.c @@ -50,6 +50,7 @@ #include #include +#include #include #include "core.h" @@ -476,127 +477,7 @@ static struct clk_lookup lookups[] = { #define SYS_CLCD_ID_SANYO_2_5 (0x07 << 8) #define SYS_CLCD_ID_VGA (0x1f << 8) -static struct clcd_panel vga = { - .mode = { - .name = "VGA", - .refresh = 60, - .xres = 640, - .yres = 480, - .pixclock = 39721, - .left_margin = 40, - .right_margin = 24, - .upper_margin = 32, - .lower_margin = 11, - .hsync_len = 96, - .vsync_len = 2, - .sync = 0, - .vmode = FB_VMODE_NONINTERLACED, - }, - .width = -1, - .height = -1, - .tim2 = TIM2_BCD | TIM2_IPC, - .cntl = CNTL_LCDTFT | CNTL_LCDVCOMP(1), - .bpp = 16, -}; - -static struct clcd_panel sanyo_3_8_in = { - .mode = { - .name = "Sanyo QVGA", - .refresh = 116, - .xres = 320, - .yres = 240, - .pixclock = 100000, - .left_margin = 6, - .right_margin = 6, - .upper_margin = 5, - .lower_margin = 5, - .hsync_len = 6, - .vsync_len = 6, - .sync = 0, - .vmode = FB_VMODE_NONINTERLACED, - }, - .width = -1, - .height = -1, - .tim2 = TIM2_BCD, - .cntl = CNTL_LCDTFT | CNTL_LCDVCOMP(1), - .bpp = 16, -}; - -static struct clcd_panel sanyo_2_5_in = { - .mode = { - .name = "Sanyo QVGA Portrait", - .refresh = 116, - .xres = 240, - .yres = 320, - .pixclock = 100000, - .left_margin = 20, - .right_margin = 10, - .upper_margin = 2, - .lower_margin = 2, - .hsync_len = 10, - .vsync_len = 2, - .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, - .vmode = FB_VMODE_NONINTERLACED, - }, - .width = -1, - .height = -1, - .tim2 = TIM2_IVS | TIM2_IHS | TIM2_IPC, - .cntl = CNTL_LCDTFT | CNTL_LCDVCOMP(1), - .bpp = 16, -}; - -static struct clcd_panel epson_2_2_in = { - .mode = { - .name = "Epson QCIF", - .refresh = 390, - .xres = 176, - .yres = 220, - .pixclock = 62500, - .left_margin = 3, - .right_margin = 2, - .upper_margin = 1, - .lower_margin = 0, - .hsync_len = 3, - .vsync_len = 2, - .sync = 0, - .vmode = FB_VMODE_NONINTERLACED, - }, - .width = -1, - .height = -1, - .tim2 = TIM2_BCD | TIM2_IPC, - .cntl = CNTL_LCDTFT | CNTL_LCDVCOMP(1), - .bpp = 16, -}; - -/* - * Detect which LCD panel is connected, and return the appropriate - * clcd_panel structure. Note: we do not have any information on - * the required timings for the 8.4in panel, so we presently assume - * VGA timings. - */ -static struct clcd_panel *versatile_clcd_panel(void) -{ - void __iomem *sys_clcd = __io_address(VERSATILE_SYS_BASE) + VERSATILE_SYS_CLCD_OFFSET; - struct clcd_panel *panel = &vga; - u32 val; - - val = readl(sys_clcd) & SYS_CLCD_ID_MASK; - if (val == SYS_CLCD_ID_SANYO_3_8) - panel = &sanyo_3_8_in; - else if (val == SYS_CLCD_ID_SANYO_2_5) - panel = &sanyo_2_5_in; - else if (val == SYS_CLCD_ID_EPSON_2_2) - panel = &epson_2_2_in; - else if (val == SYS_CLCD_ID_VGA) - panel = &vga; - else { - printk(KERN_ERR "CLCD: unknown LCD panel ID 0x%08x, using VGA\n", - val); - panel = &vga; - } - - return panel; -} +static bool is_sanyo_2_5_lcd; /* * Disable all display connectors on the interface module. @@ -614,7 +495,7 @@ static void versatile_clcd_disable(struct clcd_fb *fb) /* * If the LCD is Sanyo 2x5 in on the IB2 board, turn the back-light off */ - if (machine_is_versatile_ab() && fb->panel == &sanyo_2_5_in) { + if (machine_is_versatile_ab() && is_sanyo_2_5_lcd) { void __iomem *versatile_ib2_ctrl = __io_address(VERSATILE_IB2_CTRL); unsigned long ctrl; @@ -667,7 +548,7 @@ static void versatile_clcd_enable(struct clcd_fb *fb) /* * If the LCD is Sanyo 2x5 in on the IB2 board, turn the back-light on */ - if (machine_is_versatile_ab() && fb->panel == &sanyo_2_5_in) { + if (machine_is_versatile_ab() && is_sanyo_2_5_lcd) { void __iomem *versatile_ib2_ctrl = __io_address(VERSATILE_IB2_CTRL); unsigned long ctrl; @@ -678,39 +559,41 @@ static void versatile_clcd_enable(struct clcd_fb *fb) #endif } -static unsigned long framesize = SZ_1M; - +/* + * Detect which LCD panel is connected, and return the appropriate + * clcd_panel structure. Note: we do not have any information on + * the required timings for the 8.4in panel, so we presently assume + * VGA timings. + */ static int versatile_clcd_setup(struct clcd_fb *fb) { - dma_addr_t dma; + void __iomem *sys_clcd = __io_address(VERSATILE_SYS_BASE) + VERSATILE_SYS_CLCD_OFFSET; + const char *panel_name; + u32 val; - fb->panel = versatile_clcd_panel(); + is_sanyo_2_5_lcd = false; - fb->fb.screen_base = dma_alloc_writecombine(&fb->dev->dev, framesize, - &dma, GFP_KERNEL); - if (!fb->fb.screen_base) { - printk(KERN_ERR "CLCD: unable to map framebuffer\n"); - return -ENOMEM; + val = readl(sys_clcd) & SYS_CLCD_ID_MASK; + if (val == SYS_CLCD_ID_SANYO_3_8) + panel_name = "Sanyo TM38QV67A02A"; + else if (val == SYS_CLCD_ID_SANYO_2_5) { + panel_name = "Sanyo QVGA Portrait"; + is_sanyo_2_5_lcd = true; + } else if (val == SYS_CLCD_ID_EPSON_2_2) + panel_name = "Epson L2F50113T00"; + else if (val == SYS_CLCD_ID_VGA) + panel_name = "VGA"; + else { + printk(KERN_ERR "CLCD: unknown LCD panel ID 0x%08x, using VGA\n", + val); + panel_name = "VGA"; } - fb->fb.fix.smem_start = dma; - fb->fb.fix.smem_len = framesize; + fb->panel = versatile_clcd_get_panel(panel_name); + if (!fb->panel) + return -EINVAL; - return 0; -} - -static int versatile_clcd_mmap(struct clcd_fb *fb, struct vm_area_struct *vma) -{ - return dma_mmap_writecombine(&fb->dev->dev, vma, - fb->fb.screen_base, - fb->fb.fix.smem_start, - fb->fb.fix.smem_len); -} - -static void versatile_clcd_remove(struct clcd_fb *fb) -{ - dma_free_writecombine(&fb->dev->dev, fb->fb.fix.smem_len, - fb->fb.screen_base, fb->fb.fix.smem_start); + return versatile_clcd_setup_dma(fb, SZ_1M); } static void versatile_clcd_decode(struct clcd_fb *fb, struct clcd_regs *regs) @@ -724,13 +607,14 @@ static void versatile_clcd_decode(struct clcd_fb *fb, struct clcd_regs *regs) static struct clcd_board clcd_plat_data = { .name = "Versatile", + .caps = CLCD_CAP_5551 | CLCD_CAP_565 | CLCD_CAP_888, .check = clcdfb_check, .decode = versatile_clcd_decode, .disable = versatile_clcd_disable, .enable = versatile_clcd_enable, .setup = versatile_clcd_setup, - .mmap = versatile_clcd_mmap, - .remove = versatile_clcd_remove, + .mmap = versatile_clcd_mmap_dma, + .remove = versatile_clcd_remove_dma, }; static struct pl061_platform_data gpio0_plat_data = { -- GitLab From 3cb5ee496ae99ee89e378d628b19cb5a904b1397 Mon Sep 17 00:00:00 2001 From: Russell King Date: Tue, 18 Jan 2011 20:13:20 +0000 Subject: [PATCH 0086/2822] ARM: realview: switch Realview to use consolidated CLCD This switches Realview platforms to use the consolidated CLCD panel support, including the display capabilities. As Realview uses a PL111, it can support the full range of pixel formats - 444, 5551, 565 in both RGB and BGR mode. Acked-by: Catalin Marinas Signed-off-by: Russell King --- arch/arm/Kconfig | 1 + arch/arm/mach-realview/core.c | 214 ++++++---------------------------- 2 files changed, 35 insertions(+), 180 deletions(-) diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index b0d55b9f184e3..7ee15c2933f89 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -241,6 +241,7 @@ config ARCH_REALVIEW select GENERIC_CLOCKEVENTS select ARCH_WANT_OPTIONAL_GPIOLIB select PLAT_VERSATILE + select PLAT_VERSATILE_CLCD select ARM_TIMER_SP804 select GPIO_PL061 if GPIOLIB help diff --git a/arch/arm/mach-realview/core.c b/arch/arm/mach-realview/core.c index 1c6602cf50e4d..a18a5a66c4c39 100644 --- a/arch/arm/mach-realview/core.c +++ b/arch/arm/mach-realview/core.c @@ -51,6 +51,7 @@ #include #include +#include #include #include "core.h" @@ -385,157 +386,6 @@ core_initcall(clk_init); #define SYS_CLCD_ID_SANYO_2_5 (0x07 << 8) #define SYS_CLCD_ID_VGA (0x1f << 8) -static struct clcd_panel vga = { - .mode = { - .name = "VGA", - .refresh = 60, - .xres = 640, - .yres = 480, - .pixclock = 39721, - .left_margin = 40, - .right_margin = 24, - .upper_margin = 32, - .lower_margin = 11, - .hsync_len = 96, - .vsync_len = 2, - .sync = 0, - .vmode = FB_VMODE_NONINTERLACED, - }, - .width = -1, - .height = -1, - .tim2 = TIM2_BCD | TIM2_IPC, - .cntl = CNTL_LCDTFT | CNTL_BGR | CNTL_LCDVCOMP(1), - .bpp = 16, -}; - -static struct clcd_panel xvga = { - .mode = { - .name = "XVGA", - .refresh = 60, - .xres = 1024, - .yres = 768, - .pixclock = 15748, - .left_margin = 152, - .right_margin = 48, - .upper_margin = 23, - .lower_margin = 3, - .hsync_len = 104, - .vsync_len = 4, - .sync = 0, - .vmode = FB_VMODE_NONINTERLACED, - }, - .width = -1, - .height = -1, - .tim2 = TIM2_BCD | TIM2_IPC, - .cntl = CNTL_LCDTFT | CNTL_BGR | CNTL_LCDVCOMP(1), - .bpp = 16, -}; - -static struct clcd_panel sanyo_3_8_in = { - .mode = { - .name = "Sanyo QVGA", - .refresh = 116, - .xres = 320, - .yres = 240, - .pixclock = 100000, - .left_margin = 6, - .right_margin = 6, - .upper_margin = 5, - .lower_margin = 5, - .hsync_len = 6, - .vsync_len = 6, - .sync = 0, - .vmode = FB_VMODE_NONINTERLACED, - }, - .width = -1, - .height = -1, - .tim2 = TIM2_BCD, - .cntl = CNTL_LCDTFT | CNTL_BGR | CNTL_LCDVCOMP(1), - .bpp = 16, -}; - -static struct clcd_panel sanyo_2_5_in = { - .mode = { - .name = "Sanyo QVGA Portrait", - .refresh = 116, - .xres = 240, - .yres = 320, - .pixclock = 100000, - .left_margin = 20, - .right_margin = 10, - .upper_margin = 2, - .lower_margin = 2, - .hsync_len = 10, - .vsync_len = 2, - .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, - .vmode = FB_VMODE_NONINTERLACED, - }, - .width = -1, - .height = -1, - .tim2 = TIM2_IVS | TIM2_IHS | TIM2_IPC, - .cntl = CNTL_LCDTFT | CNTL_BGR | CNTL_LCDVCOMP(1), - .bpp = 16, -}; - -static struct clcd_panel epson_2_2_in = { - .mode = { - .name = "Epson QCIF", - .refresh = 390, - .xres = 176, - .yres = 220, - .pixclock = 62500, - .left_margin = 3, - .right_margin = 2, - .upper_margin = 1, - .lower_margin = 0, - .hsync_len = 3, - .vsync_len = 2, - .sync = 0, - .vmode = FB_VMODE_NONINTERLACED, - }, - .width = -1, - .height = -1, - .tim2 = TIM2_BCD | TIM2_IPC, - .cntl = CNTL_LCDTFT | CNTL_BGR | CNTL_LCDVCOMP(1), - .bpp = 16, -}; - -/* - * Detect which LCD panel is connected, and return the appropriate - * clcd_panel structure. Note: we do not have any information on - * the required timings for the 8.4in panel, so we presently assume - * VGA timings. - */ -static struct clcd_panel *realview_clcd_panel(void) -{ - void __iomem *sys_clcd = __io_address(REALVIEW_SYS_BASE) + REALVIEW_SYS_CLCD_OFFSET; - struct clcd_panel *vga_panel; - struct clcd_panel *panel; - u32 val; - - if (machine_is_realview_eb()) - vga_panel = &vga; - else - vga_panel = &xvga; - - val = readl(sys_clcd) & SYS_CLCD_ID_MASK; - if (val == SYS_CLCD_ID_SANYO_3_8) - panel = &sanyo_3_8_in; - else if (val == SYS_CLCD_ID_SANYO_2_5) - panel = &sanyo_2_5_in; - else if (val == SYS_CLCD_ID_EPSON_2_2) - panel = &epson_2_2_in; - else if (val == SYS_CLCD_ID_VGA) - panel = vga_panel; - else { - printk(KERN_ERR "CLCD: unknown LCD panel ID 0x%08x, using VGA\n", - val); - panel = vga_panel; - } - - return panel; -} - /* * Disable all display connectors on the interface module. */ @@ -565,56 +415,60 @@ static void realview_clcd_enable(struct clcd_fb *fb) writel(val, sys_clcd); } +/* + * Detect which LCD panel is connected, and return the appropriate + * clcd_panel structure. Note: we do not have any information on + * the required timings for the 8.4in panel, so we presently assume + * VGA timings. + */ static int realview_clcd_setup(struct clcd_fb *fb) { + void __iomem *sys_clcd = __io_address(REALVIEW_SYS_BASE) + REALVIEW_SYS_CLCD_OFFSET; + const char *panel_name, *vga_panel_name; unsigned long framesize; - dma_addr_t dma; + u32 val; - if (machine_is_realview_eb()) + if (machine_is_realview_eb()) { /* VGA, 16bpp */ framesize = 640 * 480 * 2; - else + vga_panel_name = "VGA"; + } else { /* XVGA, 16bpp */ framesize = 1024 * 768 * 2; - - fb->panel = realview_clcd_panel(); - - fb->fb.screen_base = dma_alloc_writecombine(&fb->dev->dev, framesize, - &dma, GFP_KERNEL | GFP_DMA); - if (!fb->fb.screen_base) { - printk(KERN_ERR "CLCD: unable to map framebuffer\n"); - return -ENOMEM; + vga_panel_name = "XVGA"; } - fb->fb.fix.smem_start = dma; - fb->fb.fix.smem_len = framesize; - - return 0; -} + val = readl(sys_clcd) & SYS_CLCD_ID_MASK; + if (val == SYS_CLCD_ID_SANYO_3_8) + panel_name = "Sanyo TM38QV67A02A"; + else if (val == SYS_CLCD_ID_SANYO_2_5) + panel_name = "Sanyo QVGA Portrait"; + else if (val == SYS_CLCD_ID_EPSON_2_2) + panel_name = "Epson L2F50113T00"; + else if (val == SYS_CLCD_ID_VGA) + panel_name = vga_panel_name; + else { + pr_err("CLCD: unknown LCD panel ID 0x%08x, using VGA\n", val); + panel_name = vga_panel_name; + } -static int realview_clcd_mmap(struct clcd_fb *fb, struct vm_area_struct *vma) -{ - return dma_mmap_writecombine(&fb->dev->dev, vma, - fb->fb.screen_base, - fb->fb.fix.smem_start, - fb->fb.fix.smem_len); -} + fb->panel = versatile_clcd_get_panel(panel_name); + if (!fb->panel) + return -EINVAL; -static void realview_clcd_remove(struct clcd_fb *fb) -{ - dma_free_writecombine(&fb->dev->dev, fb->fb.fix.smem_len, - fb->fb.screen_base, fb->fb.fix.smem_start); + return versatile_clcd_setup_dma(fb, framesize); } struct clcd_board clcd_plat_data = { .name = "RealView", + .caps = CLCD_CAP_ALL, .check = clcdfb_check, .decode = clcdfb_decode, .disable = realview_clcd_disable, .enable = realview_clcd_enable, .setup = realview_clcd_setup, - .mmap = realview_clcd_mmap, - .remove = realview_clcd_remove, + .mmap = versatile_clcd_mmap_dma, + .remove = versatile_clcd_remove_dma, }; #ifdef CONFIG_LEDS -- GitLab From 0fb44b910f6873c49066e8d0bf681a058fc01b67 Mon Sep 17 00:00:00 2001 From: Russell King Date: Tue, 18 Jan 2011 20:13:51 +0000 Subject: [PATCH 0087/2822] ARM: vexpress: switch Versatile Express to use consolidated CLCD This switches Versatile Express to use the conslidated CLCD panel support, including the display capabilities. As Versatile Express uses a PL111, it can support the full range of pixel formats - 444, 5551, 565 in both RGB and BGR mode. Acked-by: Catalin Marinas Signed-off-by: Russell King --- arch/arm/Kconfig | 1 + arch/arm/mach-vexpress/ct-ca9x4.c | 58 +++++-------------------------- 2 files changed, 10 insertions(+), 49 deletions(-) diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 7ee15c2933f89..4f0e83e079891 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -274,6 +274,7 @@ config ARCH_VEXPRESS select HAVE_PATA_PLATFORM select ICST select PLAT_VERSATILE + select PLAT_VERSATILE_CLCD help This enables support for the ARM Ltd Versatile Express boards. diff --git a/arch/arm/mach-vexpress/ct-ca9x4.c b/arch/arm/mach-vexpress/ct-ca9x4.c index e628402b754cd..27baed18a256e 100644 --- a/arch/arm/mach-vexpress/ct-ca9x4.c +++ b/arch/arm/mach-vexpress/ct-ca9x4.c @@ -30,6 +30,8 @@ #include +#include + #define V2M_PA_CS7 0x10000000 static struct map_desc ct_ca9x4_io_desc[] __initdata = { @@ -80,29 +82,6 @@ static struct sys_timer ct_ca9x4_timer = { }; #endif -static struct clcd_panel xvga_panel = { - .mode = { - .name = "XVGA", - .refresh = 60, - .xres = 1024, - .yres = 768, - .pixclock = 15384, - .left_margin = 168, - .right_margin = 8, - .upper_margin = 29, - .lower_margin = 3, - .hsync_len = 144, - .vsync_len = 6, - .sync = 0, - .vmode = FB_VMODE_NONINTERLACED, - }, - .width = -1, - .height = -1, - .tim2 = TIM2_BCD | TIM2_IPC, - .cntl = CNTL_LCDTFT | CNTL_BGR | CNTL_LCDVCOMP(1), - .bpp = 16, -}; - static void ct_ca9x4_clcd_enable(struct clcd_fb *fb) { v2m_cfg_write(SYS_CFG_MUXFPGA | SYS_CFG_SITE_DB1, 0); @@ -112,42 +91,23 @@ static void ct_ca9x4_clcd_enable(struct clcd_fb *fb) static int ct_ca9x4_clcd_setup(struct clcd_fb *fb) { unsigned long framesize = 1024 * 768 * 2; - dma_addr_t dma; - - fb->panel = &xvga_panel; - fb->fb.screen_base = dma_alloc_writecombine(&fb->dev->dev, framesize, - &dma, GFP_KERNEL); - if (!fb->fb.screen_base) { - printk(KERN_ERR "CLCD: unable to map frame buffer\n"); - return -ENOMEM; - } - fb->fb.fix.smem_start = dma; - fb->fb.fix.smem_len = framesize; + fb->panel = versatile_clcd_get_panel("XVGA"); + if (!fb->panel) + return -EINVAL; - return 0; -} - -static int ct_ca9x4_clcd_mmap(struct clcd_fb *fb, struct vm_area_struct *vma) -{ - return dma_mmap_writecombine(&fb->dev->dev, vma, fb->fb.screen_base, - fb->fb.fix.smem_start, fb->fb.fix.smem_len); -} - -static void ct_ca9x4_clcd_remove(struct clcd_fb *fb) -{ - dma_free_writecombine(&fb->dev->dev, fb->fb.fix.smem_len, - fb->fb.screen_base, fb->fb.fix.smem_start); + return versatile_clcd_setup_dma(fb, framesize); } static struct clcd_board ct_ca9x4_clcd_data = { .name = "CT-CA9X4", + .caps = CLCD_CAP_5551 | CLCD_CAP_565, .check = clcdfb_check, .decode = clcdfb_decode, .enable = ct_ca9x4_clcd_enable, .setup = ct_ca9x4_clcd_setup, - .mmap = ct_ca9x4_clcd_mmap, - .remove = ct_ca9x4_clcd_remove, + .mmap = versatile_clcd_mmap_dma, + .remove = versatile_clcd_remove_dma, }; static AMBA_DEVICE(clcd, "ct:clcd", CT_CA9X4_CLCDC, &ct_ca9x4_clcd_data); -- GitLab From c735c9873d0c2f269fd16f4b04903da41a44cbcf Mon Sep 17 00:00:00 2001 From: Russell King Date: Tue, 11 Jan 2011 13:00:04 +0000 Subject: [PATCH 0088/2822] ARM: integrator: use new init_early for clock tree init Initialize the clock tree early. Acked-by: Catalin Marinas Signed-off-by: Russell King --- arch/arm/mach-integrator/common.h | 1 + arch/arm/mach-integrator/core.c | 7 +++++-- arch/arm/mach-integrator/integrator_ap.c | 3 ++- arch/arm/mach-integrator/integrator_cp.c | 11 +++++++++-- 4 files changed, 17 insertions(+), 5 deletions(-) diff --git a/arch/arm/mach-integrator/common.h b/arch/arm/mach-integrator/common.h index 5f96e1518aa94..a08f9b0299dfa 100644 --- a/arch/arm/mach-integrator/common.h +++ b/arch/arm/mach-integrator/common.h @@ -1 +1,2 @@ +void integrator_init_early(void); void integrator_reserve(void); diff --git a/arch/arm/mach-integrator/core.c b/arch/arm/mach-integrator/core.c index b8e884b450da7..77315b995681c 100644 --- a/arch/arm/mach-integrator/core.c +++ b/arch/arm/mach-integrator/core.c @@ -144,12 +144,15 @@ static struct clk_lookup lookups[] = { } }; +void __init integrator_init_early(void) +{ + clkdev_add_table(lookups, ARRAY_SIZE(lookups)); +} + static int __init integrator_init(void) { int i; - clkdev_add_table(lookups, ARRAY_SIZE(lookups)); - for (i = 0; i < ARRAY_SIZE(amba_devs); i++) { struct amba_device *d = amba_devs[i]; amba_device_register(d, &iomem_resource); diff --git a/arch/arm/mach-integrator/integrator_ap.c b/arch/arm/mach-integrator/integrator_ap.c index b666443b5cbba..4f06b5d724890 100644 --- a/arch/arm/mach-integrator/integrator_ap.c +++ b/arch/arm/mach-integrator/integrator_ap.c @@ -499,8 +499,9 @@ static struct sys_timer ap_timer = { MACHINE_START(INTEGRATOR, "ARM-Integrator") /* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */ .boot_params = 0x00000100, - .map_io = ap_map_io, .reserve = integrator_reserve, + .map_io = ap_map_io, + .init_early = integrator_init_early, .init_irq = ap_init_irq, .timer = &ap_timer, .init_machine = ap_init, diff --git a/arch/arm/mach-integrator/integrator_cp.c b/arch/arm/mach-integrator/integrator_cp.c index 9c0203738aae0..e6700aab849a0 100644 --- a/arch/arm/mach-integrator/integrator_cp.c +++ b/arch/arm/mach-integrator/integrator_cp.c @@ -520,11 +520,17 @@ static struct amba_device *amba_devs[] __initdata = { &clcd_device, }; +static void __init intcp_init_early(void) +{ + clkdev_add_table(cp_lookups, ARRAY_SIZE(cp_lookups)); + + integrator_init_early(); +} + static void __init intcp_init(void) { int i; - clkdev_add_table(cp_lookups, ARRAY_SIZE(cp_lookups)); platform_add_devices(intcp_devs, ARRAY_SIZE(intcp_devs)); for (i = 0; i < ARRAY_SIZE(amba_devs); i++) { @@ -554,8 +560,9 @@ static struct sys_timer cp_timer = { MACHINE_START(CINTEGRATOR, "ARM-IntegratorCP") /* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */ .boot_params = 0x00000100, - .map_io = intcp_map_io, .reserve = integrator_reserve, + .map_io = intcp_map_io, + .init_early = intcp_init_early, .init_irq = intcp_init_irq, .timer = &cp_timer, .init_machine = intcp_init, -- GitLab From ad3bb19c5bd17cebe8e9a97dc0b53e274a05f23b Mon Sep 17 00:00:00 2001 From: Russell King Date: Tue, 11 Jan 2011 12:55:38 +0000 Subject: [PATCH 0089/2822] ARM: versatile: use new init_early for clock tree and sched_clock init Initialize the clock tree and our sched_clock() early. Acked-by: Catalin Marinas Signed-off-by: Russell King --- arch/arm/mach-versatile/core.c | 23 +++++++++++------------ arch/arm/mach-versatile/core.h | 1 + arch/arm/mach-versatile/versatile_ab.c | 1 + arch/arm/mach-versatile/versatile_pb.c | 1 + 4 files changed, 14 insertions(+), 12 deletions(-) diff --git a/arch/arm/mach-versatile/core.c b/arch/arm/mach-versatile/core.c index b4f1f17eeb8df..606e046905e30 100644 --- a/arch/arm/mach-versatile/core.c +++ b/arch/arm/mach-versatile/core.c @@ -762,14 +762,21 @@ static void versatile_leds_event(led_event_t ledevt) } #endif /* CONFIG_LEDS */ -void __init versatile_init(void) +/* Early initializations */ +void __init versatile_init_early(void) { - int i; - - osc4_clk.vcoreg = __io_address(VERSATILE_SYS_BASE) + VERSATILE_SYS_OSCCLCD_OFFSET; + void __iomem *sys = __io_address(VERSATILE_SYS_BASE); + osc4_clk.vcoreg = sys + VERSATILE_SYS_OSCCLCD_OFFSET; clkdev_add_table(lookups, ARRAY_SIZE(lookups)); + versatile_sched_clock_init(sys + VERSATILE_SYS_24MHz_OFFSET, 24000000); +} + +void __init versatile_init(void) +{ + int i; + platform_device_register(&versatile_flash_device); platform_device_register(&versatile_i2c_device); platform_device_register(&smc91x_device); @@ -785,12 +792,6 @@ void __init versatile_init(void) #endif } -/* - * The sched_clock counter - */ -#define REFCOUNTER (__io_address(VERSATILE_SYS_BASE) + \ - VERSATILE_SYS_24MHz_OFFSET) - /* * Where is the timer (VA)? */ @@ -806,8 +807,6 @@ static void __init versatile_timer_init(void) { u32 val; - versatile_sched_clock_init(REFCOUNTER, 24000000); - /* * set clock frequency: * VERSATILE_REFCLK is 32KHz diff --git a/arch/arm/mach-versatile/core.h b/arch/arm/mach-versatile/core.h index 9d39886a8351d..e04768a6c5dcf 100644 --- a/arch/arm/mach-versatile/core.h +++ b/arch/arm/mach-versatile/core.h @@ -25,6 +25,7 @@ #include extern void __init versatile_init(void); +extern void __init versatile_init_early(void); extern void __init versatile_init_irq(void); extern void __init versatile_map_io(void); extern struct sys_timer versatile_timer; diff --git a/arch/arm/mach-versatile/versatile_ab.c b/arch/arm/mach-versatile/versatile_ab.c index aa9730fb13bfa..f8ae64b3eed09 100644 --- a/arch/arm/mach-versatile/versatile_ab.c +++ b/arch/arm/mach-versatile/versatile_ab.c @@ -37,6 +37,7 @@ MACHINE_START(VERSATILE_AB, "ARM-Versatile AB") /* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */ .boot_params = 0x00000100, .map_io = versatile_map_io, + .init_early = versatile_init_early, .init_irq = versatile_init_irq, .timer = &versatile_timer, .init_machine = versatile_init, diff --git a/arch/arm/mach-versatile/versatile_pb.c b/arch/arm/mach-versatile/versatile_pb.c index bf469642a3f81..97fb30691c47b 100644 --- a/arch/arm/mach-versatile/versatile_pb.c +++ b/arch/arm/mach-versatile/versatile_pb.c @@ -110,6 +110,7 @@ MACHINE_START(VERSATILE_PB, "ARM-Versatile PB") /* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */ .boot_params = 0x00000100, .map_io = versatile_map_io, + .init_early = versatile_init_early, .init_irq = versatile_init_irq, .timer = &versatile_timer, .init_machine = versatile_pb_init, -- GitLab From 631e55f966668d7a957342b38d7148643d919d73 Mon Sep 17 00:00:00 2001 From: Russell King Date: Tue, 11 Jan 2011 13:05:01 +0000 Subject: [PATCH 0090/2822] ARM: realview: use new init_early for clock tree and sched_clock init Initialize the clock tree and our sched_clock() early. Acked-by: Catalin Marinas Signed-off-by: Russell King --- arch/arm/mach-realview/core.c | 19 ++++++------------- arch/arm/mach-realview/core.h | 1 + arch/arm/mach-realview/realview_eb.c | 1 + arch/arm/mach-realview/realview_pb1176.c | 1 + arch/arm/mach-realview/realview_pb11mp.c | 1 + arch/arm/mach-realview/realview_pba8.c | 1 + arch/arm/mach-realview/realview_pbx.c | 1 + 7 files changed, 12 insertions(+), 13 deletions(-) diff --git a/arch/arm/mach-realview/core.c b/arch/arm/mach-realview/core.c index a18a5a66c4c39..75dbc8791d05e 100644 --- a/arch/arm/mach-realview/core.c +++ b/arch/arm/mach-realview/core.c @@ -360,18 +360,19 @@ static struct clk_lookup lookups[] = { } }; -static int __init clk_init(void) +void __init realview_init_early(void) { + void __iomem *sys = __io_address(REALVIEW_SYS_BASE); + if (machine_is_realview_pb1176()) - oscvco_clk.vcoreg = __io_address(REALVIEW_SYS_BASE) + REALVIEW_SYS_OSC0_OFFSET; + oscvco_clk.vcoreg = sys + REALVIEW_SYS_OSC0_OFFSET; else - oscvco_clk.vcoreg = __io_address(REALVIEW_SYS_BASE) + REALVIEW_SYS_OSC4_OFFSET; + oscvco_clk.vcoreg = sys + REALVIEW_SYS_OSC4_OFFSET; clkdev_add_table(lookups, ARRAY_SIZE(lookups)); - return 0; + versatile_sched_clock_init(sys + REALVIEW_SYS_24MHz_OFFSET, 24000000); } -core_initcall(clk_init); /* * CLCD support. @@ -509,12 +510,6 @@ void realview_leds_event(led_event_t ledevt) } #endif /* CONFIG_LEDS */ -/* - * The sched_clock counter - */ -#define REFCOUNTER (__io_address(REALVIEW_SYS_BASE) + \ - REALVIEW_SYS_24MHz_OFFSET) - /* * Where is the timer (VA)? */ @@ -530,8 +525,6 @@ void __init realview_timer_init(unsigned int timer_irq) { u32 val; - versatile_sched_clock_init(REFCOUNTER, 24000000); - /* * set clock frequency: * REALVIEW_REFCLK is 32KHz diff --git a/arch/arm/mach-realview/core.h b/arch/arm/mach-realview/core.h index 693239ddc39e4..27c9273870835 100644 --- a/arch/arm/mach-realview/core.h +++ b/arch/arm/mach-realview/core.h @@ -63,6 +63,7 @@ extern void realview_timer_init(unsigned int timer_irq); extern int realview_flash_register(struct resource *res, u32 num); extern int realview_eth_register(const char *name, struct resource *res); extern int realview_usb_register(struct resource *res); +extern void realview_init_early(void); extern void realview_fixup(struct machine_desc *mdesc, struct tag *tags, char **from, struct meminfo *meminfo); extern void (*realview_reset)(char); diff --git a/arch/arm/mach-realview/realview_eb.c b/arch/arm/mach-realview/realview_eb.c index 6ef5c5e528b25..c00e52754efef 100644 --- a/arch/arm/mach-realview/realview_eb.c +++ b/arch/arm/mach-realview/realview_eb.c @@ -487,6 +487,7 @@ MACHINE_START(REALVIEW_EB, "ARM-RealView EB") .boot_params = PHYS_OFFSET + 0x00000100, .fixup = realview_fixup, .map_io = realview_eb_map_io, + .init_early = realview_init_early, .init_irq = gic_init_irq, .timer = &realview_eb_timer, .init_machine = realview_eb_init, diff --git a/arch/arm/mach-realview/realview_pb1176.c b/arch/arm/mach-realview/realview_pb1176.c index cbdc97a5685fc..f0447bbf809ba 100644 --- a/arch/arm/mach-realview/realview_pb1176.c +++ b/arch/arm/mach-realview/realview_pb1176.c @@ -382,6 +382,7 @@ MACHINE_START(REALVIEW_PB1176, "ARM-RealView PB1176") .boot_params = PHYS_OFFSET + 0x00000100, .fixup = realview_pb1176_fixup, .map_io = realview_pb1176_map_io, + .init_early = realview_init_early, .init_irq = gic_init_irq, .timer = &realview_pb1176_timer, .init_machine = realview_pb1176_init, diff --git a/arch/arm/mach-realview/realview_pb11mp.c b/arch/arm/mach-realview/realview_pb11mp.c index 8e8ab7d29a6a0..3b4f78870ac19 100644 --- a/arch/arm/mach-realview/realview_pb11mp.c +++ b/arch/arm/mach-realview/realview_pb11mp.c @@ -384,6 +384,7 @@ MACHINE_START(REALVIEW_PB11MP, "ARM-RealView PB11MPCore") .boot_params = PHYS_OFFSET + 0x00000100, .fixup = realview_fixup, .map_io = realview_pb11mp_map_io, + .init_early = realview_init_early, .init_irq = gic_init_irq, .timer = &realview_pb11mp_timer, .init_machine = realview_pb11mp_init, diff --git a/arch/arm/mach-realview/realview_pba8.c b/arch/arm/mach-realview/realview_pba8.c index 841118e3e118c..f98d4fa74e309 100644 --- a/arch/arm/mach-realview/realview_pba8.c +++ b/arch/arm/mach-realview/realview_pba8.c @@ -334,6 +334,7 @@ MACHINE_START(REALVIEW_PBA8, "ARM-RealView PB-A8") .boot_params = PHYS_OFFSET + 0x00000100, .fixup = realview_fixup, .map_io = realview_pba8_map_io, + .init_early = realview_init_early, .init_irq = gic_init_irq, .timer = &realview_pba8_timer, .init_machine = realview_pba8_init, diff --git a/arch/arm/mach-realview/realview_pbx.c b/arch/arm/mach-realview/realview_pbx.c index 02b755b009dbc..b0521e1bb1ae8 100644 --- a/arch/arm/mach-realview/realview_pbx.c +++ b/arch/arm/mach-realview/realview_pbx.c @@ -417,6 +417,7 @@ MACHINE_START(REALVIEW_PBX, "ARM-RealView PBX") .boot_params = PHYS_OFFSET + 0x00000100, .fixup = realview_pbx_fixup, .map_io = realview_pbx_map_io, + .init_early = realview_init_early, .init_irq = gic_init_irq, .timer = &realview_pbx_timer, .init_machine = realview_pbx_init, -- GitLab From 493a451bb559476d2f7f189670be2172ca3010b4 Mon Sep 17 00:00:00 2001 From: Russell King Date: Tue, 11 Jan 2011 13:07:52 +0000 Subject: [PATCH 0091/2822] ARM: vexpress: use new init_early for clock tree and sched_clock init Initialize the clock tree and our sched_clock() early. Acked-by: Catalin Marinas Signed-off-by: Russell King --- arch/arm/mach-vexpress/core.h | 1 + arch/arm/mach-vexpress/ct-ca9x4.c | 10 ++++++++-- arch/arm/mach-vexpress/v2m.c | 6 ++++-- 3 files changed, 13 insertions(+), 4 deletions(-) diff --git a/arch/arm/mach-vexpress/core.h b/arch/arm/mach-vexpress/core.h index 362780d868de0..e0312a1dce3a8 100644 --- a/arch/arm/mach-vexpress/core.h +++ b/arch/arm/mach-vexpress/core.h @@ -21,4 +21,5 @@ struct amba_device name##_device = { \ struct map_desc; void v2m_map_io(struct map_desc *tile, size_t num); +void v2m_init_early(void); extern struct sys_timer v2m_timer; diff --git a/arch/arm/mach-vexpress/ct-ca9x4.c b/arch/arm/mach-vexpress/ct-ca9x4.c index 27baed18a256e..ff48ebc1a40be 100644 --- a/arch/arm/mach-vexpress/ct-ca9x4.c +++ b/arch/arm/mach-vexpress/ct-ca9x4.c @@ -180,6 +180,13 @@ static struct platform_device pmu_device = { .resource = pmu_resources, }; +static void __init ct_ca9x4_init_early(void) +{ + clkdev_add_table(lookups, ARRAY_SIZE(lookups)); + + v2m_init_early(); +} + static void __init ct_ca9x4_init(void) { int i; @@ -194,8 +201,6 @@ static void __init ct_ca9x4_init(void) l2x0_init(l2x0_base, 0x00400000, 0xfe0fffff); #endif - clkdev_add_table(lookups, ARRAY_SIZE(lookups)); - for (i = 0; i < ARRAY_SIZE(ct_ca9x4_amba_devs); i++) amba_device_register(ct_ca9x4_amba_devs[i], &iomem_resource); @@ -206,6 +211,7 @@ MACHINE_START(VEXPRESS, "ARM-Versatile Express CA9x4") .boot_params = PHYS_OFFSET + 0x00000100, .map_io = ct_ca9x4_map_io, .init_irq = ct_ca9x4_init_irq, + .init_early = ct_ca9x4_init_early, #if 0 .timer = &ct_ca9x4_timer, #else diff --git a/arch/arm/mach-vexpress/v2m.c b/arch/arm/mach-vexpress/v2m.c index f35d646a1bf16..63ef663fb0be7 100644 --- a/arch/arm/mach-vexpress/v2m.c +++ b/arch/arm/mach-vexpress/v2m.c @@ -49,13 +49,15 @@ void __init v2m_map_io(struct map_desc *tile, size_t num) iotable_init(tile, num); } +void __init v2m_init_early(void) +{ + versatile_sched_clock_init(MMIO_P2V(V2M_SYS_24MHZ), 24000000); +} static void __init v2m_timer_init(void) { u32 scctrl; - versatile_sched_clock_init(MMIO_P2V(V2M_SYS_24MHZ), 24000000); - /* Select 1MHz TIMCLK as the reference clock for SP804 timers */ scctrl = readl(MMIO_P2V(V2M_SYSCTL + SCCTRL)); scctrl |= SCCTRL_TIMEREN0SEL_TIMCLK; -- GitLab From 5e4b822f298b49d2940e09c31695a64417a836b9 Mon Sep 17 00:00:00 2001 From: Russell King Date: Tue, 18 Jan 2011 19:47:40 +0000 Subject: [PATCH 0092/2822] ARM: versatile: remove old AMBA device DMA definitions The AMBA DMA macro definitions are not used, and the AMBA Primecell DMA support makes no use of them either, so they can be removed. Acked-by: Catalin Marinas Signed-off-by: Russell King --- arch/arm/mach-versatile/core.c | 18 ------------------ arch/arm/mach-versatile/core.h | 1 - arch/arm/mach-versatile/versatile_pb.c | 5 ----- 3 files changed, 24 deletions(-) diff --git a/arch/arm/mach-versatile/core.c b/arch/arm/mach-versatile/core.c index 606e046905e30..630a1c96f90bb 100644 --- a/arch/arm/mach-versatile/core.c +++ b/arch/arm/mach-versatile/core.c @@ -634,53 +634,35 @@ static struct pl022_ssp_controller ssp0_plat_data = { }; #define AACI_IRQ { IRQ_AACI, NO_IRQ } -#define AACI_DMA { 0x80, 0x81 } #define MMCI0_IRQ { IRQ_MMCI0A,IRQ_SIC_MMCI0B } -#define MMCI0_DMA { 0x84, 0 } #define KMI0_IRQ { IRQ_SIC_KMI0, NO_IRQ } -#define KMI0_DMA { 0, 0 } #define KMI1_IRQ { IRQ_SIC_KMI1, NO_IRQ } -#define KMI1_DMA { 0, 0 } /* * These devices are connected directly to the multi-layer AHB switch */ #define SMC_IRQ { NO_IRQ, NO_IRQ } -#define SMC_DMA { 0, 0 } #define MPMC_IRQ { NO_IRQ, NO_IRQ } -#define MPMC_DMA { 0, 0 } #define CLCD_IRQ { IRQ_CLCDINT, NO_IRQ } -#define CLCD_DMA { 0, 0 } #define DMAC_IRQ { IRQ_DMAINT, NO_IRQ } -#define DMAC_DMA { 0, 0 } /* * These devices are connected via the core APB bridge */ #define SCTL_IRQ { NO_IRQ, NO_IRQ } -#define SCTL_DMA { 0, 0 } #define WATCHDOG_IRQ { IRQ_WDOGINT, NO_IRQ } -#define WATCHDOG_DMA { 0, 0 } #define GPIO0_IRQ { IRQ_GPIOINT0, NO_IRQ } -#define GPIO0_DMA { 0, 0 } #define GPIO1_IRQ { IRQ_GPIOINT1, NO_IRQ } -#define GPIO1_DMA { 0, 0 } #define RTC_IRQ { IRQ_RTCINT, NO_IRQ } -#define RTC_DMA { 0, 0 } /* * These devices are connected via the DMA APB bridge */ #define SCI_IRQ { IRQ_SCIINT, NO_IRQ } -#define SCI_DMA { 7, 6 } #define UART0_IRQ { IRQ_UARTINT0, NO_IRQ } -#define UART0_DMA { 15, 14 } #define UART1_IRQ { IRQ_UARTINT1, NO_IRQ } -#define UART1_DMA { 13, 12 } #define UART2_IRQ { IRQ_UARTINT2, NO_IRQ } -#define UART2_DMA { 11, 10 } #define SSP_IRQ { IRQ_SSPINT, NO_IRQ } -#define SSP_DMA { 9, 8 } /* FPGA Primecells */ AMBA_DEVICE(aaci, "fpga:04", AACI, NULL); diff --git a/arch/arm/mach-versatile/core.h b/arch/arm/mach-versatile/core.h index e04768a6c5dcf..fd6404e5d7882 100644 --- a/arch/arm/mach-versatile/core.h +++ b/arch/arm/mach-versatile/core.h @@ -45,7 +45,6 @@ static struct amba_device name##_device = { \ }, \ .dma_mask = ~0, \ .irq = base##_IRQ, \ - /* .dma = base##_DMA,*/ \ } #endif diff --git a/arch/arm/mach-versatile/versatile_pb.c b/arch/arm/mach-versatile/versatile_pb.c index 97fb30691c47b..37c23dfeefb7d 100644 --- a/arch/arm/mach-versatile/versatile_pb.c +++ b/arch/arm/mach-versatile/versatile_pb.c @@ -59,19 +59,14 @@ static struct pl061_platform_data gpio3_plat_data = { }; #define UART3_IRQ { IRQ_SIC_UART3, NO_IRQ } -#define UART3_DMA { 0x86, 0x87 } #define SCI1_IRQ { IRQ_SIC_SCI3, NO_IRQ } -#define SCI1_DMA { 0x88, 0x89 } #define MMCI1_IRQ { IRQ_MMCI1A, IRQ_SIC_MMCI1B } -#define MMCI1_DMA { 0x85, 0 } /* * These devices are connected via the core APB bridge */ #define GPIO2_IRQ { IRQ_GPIOINT2, NO_IRQ } -#define GPIO2_DMA { 0, 0 } #define GPIO3_IRQ { IRQ_GPIOINT3, NO_IRQ } -#define GPIO3_DMA { 0, 0 } /* * These devices are connected via the DMA APB bridge -- GitLab From f093728c0ddc30bef5792b7faf2743024b166350 Mon Sep 17 00:00:00 2001 From: Russell King Date: Tue, 18 Jan 2011 19:48:57 +0000 Subject: [PATCH 0093/2822] ARM: realview: remove old AMBA device DMA definitions The AMBA DMA macro definitions are not used, and the AMBA Primecell DMA support makes no use of them either, so they can be removed. Acked-by: Catalin Marinas Signed-off-by: Russell King --- arch/arm/mach-realview/core.h | 1 - arch/arm/mach-realview/realview_eb.c | 21 --------------------- arch/arm/mach-realview/realview_pb1176.c | 21 --------------------- arch/arm/mach-realview/realview_pb11mp.c | 21 --------------------- arch/arm/mach-realview/realview_pba8.c | 21 --------------------- arch/arm/mach-realview/realview_pbx.c | 21 --------------------- 6 files changed, 106 deletions(-) diff --git a/arch/arm/mach-realview/core.h b/arch/arm/mach-realview/core.h index 27c9273870835..5c83d1e87a03b 100644 --- a/arch/arm/mach-realview/core.h +++ b/arch/arm/mach-realview/core.h @@ -42,7 +42,6 @@ static struct amba_device name##_device = { \ }, \ .dma_mask = ~0, \ .irq = base##_IRQ, \ - /* .dma = base##_DMA,*/ \ } struct machine_desc; diff --git a/arch/arm/mach-realview/realview_eb.c b/arch/arm/mach-realview/realview_eb.c index c00e52754efef..d0f851b886db0 100644 --- a/arch/arm/mach-realview/realview_eb.c +++ b/arch/arm/mach-realview/realview_eb.c @@ -144,60 +144,39 @@ static struct pl022_ssp_controller ssp0_plat_data = { * These devices are connected via the core APB bridge */ #define GPIO2_IRQ { IRQ_EB_GPIO2, NO_IRQ } -#define GPIO2_DMA { 0, 0 } #define GPIO3_IRQ { IRQ_EB_GPIO3, NO_IRQ } -#define GPIO3_DMA { 0, 0 } #define AACI_IRQ { IRQ_EB_AACI, NO_IRQ } -#define AACI_DMA { 0x80, 0x81 } #define MMCI0_IRQ { IRQ_EB_MMCI0A, IRQ_EB_MMCI0B } -#define MMCI0_DMA { 0x84, 0 } #define KMI0_IRQ { IRQ_EB_KMI0, NO_IRQ } -#define KMI0_DMA { 0, 0 } #define KMI1_IRQ { IRQ_EB_KMI1, NO_IRQ } -#define KMI1_DMA { 0, 0 } /* * These devices are connected directly to the multi-layer AHB switch */ #define EB_SMC_IRQ { NO_IRQ, NO_IRQ } -#define EB_SMC_DMA { 0, 0 } #define MPMC_IRQ { NO_IRQ, NO_IRQ } -#define MPMC_DMA { 0, 0 } #define EB_CLCD_IRQ { IRQ_EB_CLCD, NO_IRQ } -#define EB_CLCD_DMA { 0, 0 } #define DMAC_IRQ { IRQ_EB_DMA, NO_IRQ } -#define DMAC_DMA { 0, 0 } /* * These devices are connected via the core APB bridge */ #define SCTL_IRQ { NO_IRQ, NO_IRQ } -#define SCTL_DMA { 0, 0 } #define EB_WATCHDOG_IRQ { IRQ_EB_WDOG, NO_IRQ } -#define EB_WATCHDOG_DMA { 0, 0 } #define EB_GPIO0_IRQ { IRQ_EB_GPIO0, NO_IRQ } -#define EB_GPIO0_DMA { 0, 0 } #define GPIO1_IRQ { IRQ_EB_GPIO1, NO_IRQ } -#define GPIO1_DMA { 0, 0 } #define EB_RTC_IRQ { IRQ_EB_RTC, NO_IRQ } -#define EB_RTC_DMA { 0, 0 } /* * These devices are connected via the DMA APB bridge */ #define SCI_IRQ { IRQ_EB_SCI, NO_IRQ } -#define SCI_DMA { 7, 6 } #define EB_UART0_IRQ { IRQ_EB_UART0, NO_IRQ } -#define EB_UART0_DMA { 15, 14 } #define EB_UART1_IRQ { IRQ_EB_UART1, NO_IRQ } -#define EB_UART1_DMA { 13, 12 } #define EB_UART2_IRQ { IRQ_EB_UART2, NO_IRQ } -#define EB_UART2_DMA { 11, 10 } #define EB_UART3_IRQ { IRQ_EB_UART3, NO_IRQ } -#define EB_UART3_DMA { 0x86, 0x87 } #define EB_SSP_IRQ { IRQ_EB_SSP, NO_IRQ } -#define EB_SSP_DMA { 9, 8 } /* FPGA Primecells */ AMBA_DEVICE(aaci, "fpga:aaci", AACI, NULL); diff --git a/arch/arm/mach-realview/realview_pb1176.c b/arch/arm/mach-realview/realview_pb1176.c index f0447bbf809ba..61f6a9d853fc9 100644 --- a/arch/arm/mach-realview/realview_pb1176.c +++ b/arch/arm/mach-realview/realview_pb1176.c @@ -134,47 +134,26 @@ static struct pl022_ssp_controller ssp0_plat_data = { * RealView PB1176 AMBA devices */ #define GPIO2_IRQ { IRQ_PB1176_GPIO2, NO_IRQ } -#define GPIO2_DMA { 0, 0 } #define GPIO3_IRQ { IRQ_PB1176_GPIO3, NO_IRQ } -#define GPIO3_DMA { 0, 0 } #define AACI_IRQ { IRQ_PB1176_AACI, NO_IRQ } -#define AACI_DMA { 0x80, 0x81 } #define MMCI0_IRQ { IRQ_PB1176_MMCI0A, IRQ_PB1176_MMCI0B } -#define MMCI0_DMA { 0x84, 0 } #define KMI0_IRQ { IRQ_PB1176_KMI0, NO_IRQ } -#define KMI0_DMA { 0, 0 } #define KMI1_IRQ { IRQ_PB1176_KMI1, NO_IRQ } -#define KMI1_DMA { 0, 0 } #define PB1176_SMC_IRQ { NO_IRQ, NO_IRQ } -#define PB1176_SMC_DMA { 0, 0 } #define MPMC_IRQ { NO_IRQ, NO_IRQ } -#define MPMC_DMA { 0, 0 } #define PB1176_CLCD_IRQ { IRQ_DC1176_CLCD, NO_IRQ } -#define PB1176_CLCD_DMA { 0, 0 } #define SCTL_IRQ { NO_IRQ, NO_IRQ } -#define SCTL_DMA { 0, 0 } #define PB1176_WATCHDOG_IRQ { IRQ_DC1176_WATCHDOG, NO_IRQ } -#define PB1176_WATCHDOG_DMA { 0, 0 } #define PB1176_GPIO0_IRQ { IRQ_PB1176_GPIO0, NO_IRQ } -#define PB1176_GPIO0_DMA { 0, 0 } #define GPIO1_IRQ { IRQ_PB1176_GPIO1, NO_IRQ } -#define GPIO1_DMA { 0, 0 } #define PB1176_RTC_IRQ { IRQ_DC1176_RTC, NO_IRQ } -#define PB1176_RTC_DMA { 0, 0 } #define SCI_IRQ { IRQ_PB1176_SCI, NO_IRQ } -#define SCI_DMA { 7, 6 } #define PB1176_UART0_IRQ { IRQ_DC1176_UART0, NO_IRQ } -#define PB1176_UART0_DMA { 15, 14 } #define PB1176_UART1_IRQ { IRQ_DC1176_UART1, NO_IRQ } -#define PB1176_UART1_DMA { 13, 12 } #define PB1176_UART2_IRQ { IRQ_DC1176_UART2, NO_IRQ } -#define PB1176_UART2_DMA { 11, 10 } #define PB1176_UART3_IRQ { IRQ_DC1176_UART3, NO_IRQ } -#define PB1176_UART3_DMA { 0x86, 0x87 } #define PB1176_UART4_IRQ { IRQ_PB1176_UART4, NO_IRQ } -#define PB1176_UART4_DMA { 0, 0 } #define PB1176_SSP_IRQ { IRQ_DC1176_SSP, NO_IRQ } -#define PB1176_SSP_DMA { 9, 8 } /* FPGA Primecells */ AMBA_DEVICE(aaci, "fpga:aaci", AACI, NULL); diff --git a/arch/arm/mach-realview/realview_pb11mp.c b/arch/arm/mach-realview/realview_pb11mp.c index 3b4f78870ac19..27bfeca891294 100644 --- a/arch/arm/mach-realview/realview_pb11mp.c +++ b/arch/arm/mach-realview/realview_pb11mp.c @@ -136,47 +136,26 @@ static struct pl022_ssp_controller ssp0_plat_data = { */ #define GPIO2_IRQ { IRQ_PB11MP_GPIO2, NO_IRQ } -#define GPIO2_DMA { 0, 0 } #define GPIO3_IRQ { IRQ_PB11MP_GPIO3, NO_IRQ } -#define GPIO3_DMA { 0, 0 } #define AACI_IRQ { IRQ_TC11MP_AACI, NO_IRQ } -#define AACI_DMA { 0x80, 0x81 } #define MMCI0_IRQ { IRQ_TC11MP_MMCI0A, IRQ_TC11MP_MMCI0B } -#define MMCI0_DMA { 0x84, 0 } #define KMI0_IRQ { IRQ_TC11MP_KMI0, NO_IRQ } -#define KMI0_DMA { 0, 0 } #define KMI1_IRQ { IRQ_TC11MP_KMI1, NO_IRQ } -#define KMI1_DMA { 0, 0 } #define PB11MP_SMC_IRQ { NO_IRQ, NO_IRQ } -#define PB11MP_SMC_DMA { 0, 0 } #define MPMC_IRQ { NO_IRQ, NO_IRQ } -#define MPMC_DMA { 0, 0 } #define PB11MP_CLCD_IRQ { IRQ_PB11MP_CLCD, NO_IRQ } -#define PB11MP_CLCD_DMA { 0, 0 } #define DMAC_IRQ { IRQ_PB11MP_DMAC, NO_IRQ } -#define DMAC_DMA { 0, 0 } #define SCTL_IRQ { NO_IRQ, NO_IRQ } -#define SCTL_DMA { 0, 0 } #define PB11MP_WATCHDOG_IRQ { IRQ_PB11MP_WATCHDOG, NO_IRQ } -#define PB11MP_WATCHDOG_DMA { 0, 0 } #define PB11MP_GPIO0_IRQ { IRQ_PB11MP_GPIO0, NO_IRQ } -#define PB11MP_GPIO0_DMA { 0, 0 } #define GPIO1_IRQ { IRQ_PB11MP_GPIO1, NO_IRQ } -#define GPIO1_DMA { 0, 0 } #define PB11MP_RTC_IRQ { IRQ_TC11MP_RTC, NO_IRQ } -#define PB11MP_RTC_DMA { 0, 0 } #define SCI_IRQ { IRQ_PB11MP_SCI, NO_IRQ } -#define SCI_DMA { 7, 6 } #define PB11MP_UART0_IRQ { IRQ_TC11MP_UART0, NO_IRQ } -#define PB11MP_UART0_DMA { 15, 14 } #define PB11MP_UART1_IRQ { IRQ_TC11MP_UART1, NO_IRQ } -#define PB11MP_UART1_DMA { 13, 12 } #define PB11MP_UART2_IRQ { IRQ_PB11MP_UART2, NO_IRQ } -#define PB11MP_UART2_DMA { 11, 10 } #define PB11MP_UART3_IRQ { IRQ_PB11MP_UART3, NO_IRQ } -#define PB11MP_UART3_DMA { 0x86, 0x87 } #define PB11MP_SSP_IRQ { IRQ_PB11MP_SSP, NO_IRQ } -#define PB11MP_SSP_DMA { 9, 8 } /* FPGA Primecells */ AMBA_DEVICE(aaci, "fpga:aaci", AACI, NULL); diff --git a/arch/arm/mach-realview/realview_pba8.c b/arch/arm/mach-realview/realview_pba8.c index f98d4fa74e309..11972df94313d 100644 --- a/arch/arm/mach-realview/realview_pba8.c +++ b/arch/arm/mach-realview/realview_pba8.c @@ -126,47 +126,26 @@ static struct pl022_ssp_controller ssp0_plat_data = { */ #define GPIO2_IRQ { IRQ_PBA8_GPIO2, NO_IRQ } -#define GPIO2_DMA { 0, 0 } #define GPIO3_IRQ { IRQ_PBA8_GPIO3, NO_IRQ } -#define GPIO3_DMA { 0, 0 } #define AACI_IRQ { IRQ_PBA8_AACI, NO_IRQ } -#define AACI_DMA { 0x80, 0x81 } #define MMCI0_IRQ { IRQ_PBA8_MMCI0A, IRQ_PBA8_MMCI0B } -#define MMCI0_DMA { 0x84, 0 } #define KMI0_IRQ { IRQ_PBA8_KMI0, NO_IRQ } -#define KMI0_DMA { 0, 0 } #define KMI1_IRQ { IRQ_PBA8_KMI1, NO_IRQ } -#define KMI1_DMA { 0, 0 } #define PBA8_SMC_IRQ { NO_IRQ, NO_IRQ } -#define PBA8_SMC_DMA { 0, 0 } #define MPMC_IRQ { NO_IRQ, NO_IRQ } -#define MPMC_DMA { 0, 0 } #define PBA8_CLCD_IRQ { IRQ_PBA8_CLCD, NO_IRQ } -#define PBA8_CLCD_DMA { 0, 0 } #define DMAC_IRQ { IRQ_PBA8_DMAC, NO_IRQ } -#define DMAC_DMA { 0, 0 } #define SCTL_IRQ { NO_IRQ, NO_IRQ } -#define SCTL_DMA { 0, 0 } #define PBA8_WATCHDOG_IRQ { IRQ_PBA8_WATCHDOG, NO_IRQ } -#define PBA8_WATCHDOG_DMA { 0, 0 } #define PBA8_GPIO0_IRQ { IRQ_PBA8_GPIO0, NO_IRQ } -#define PBA8_GPIO0_DMA { 0, 0 } #define GPIO1_IRQ { IRQ_PBA8_GPIO1, NO_IRQ } -#define GPIO1_DMA { 0, 0 } #define PBA8_RTC_IRQ { IRQ_PBA8_RTC, NO_IRQ } -#define PBA8_RTC_DMA { 0, 0 } #define SCI_IRQ { IRQ_PBA8_SCI, NO_IRQ } -#define SCI_DMA { 7, 6 } #define PBA8_UART0_IRQ { IRQ_PBA8_UART0, NO_IRQ } -#define PBA8_UART0_DMA { 15, 14 } #define PBA8_UART1_IRQ { IRQ_PBA8_UART1, NO_IRQ } -#define PBA8_UART1_DMA { 13, 12 } #define PBA8_UART2_IRQ { IRQ_PBA8_UART2, NO_IRQ } -#define PBA8_UART2_DMA { 11, 10 } #define PBA8_UART3_IRQ { IRQ_PBA8_UART3, NO_IRQ } -#define PBA8_UART3_DMA { 0x86, 0x87 } #define PBA8_SSP_IRQ { IRQ_PBA8_SSP, NO_IRQ } -#define PBA8_SSP_DMA { 9, 8 } /* FPGA Primecells */ AMBA_DEVICE(aaci, "fpga:aaci", AACI, NULL); diff --git a/arch/arm/mach-realview/realview_pbx.c b/arch/arm/mach-realview/realview_pbx.c index b0521e1bb1ae8..73ab3ca9355ef 100644 --- a/arch/arm/mach-realview/realview_pbx.c +++ b/arch/arm/mach-realview/realview_pbx.c @@ -148,47 +148,26 @@ static struct pl022_ssp_controller ssp0_plat_data = { */ #define GPIO2_IRQ { IRQ_PBX_GPIO2, NO_IRQ } -#define GPIO2_DMA { 0, 0 } #define GPIO3_IRQ { IRQ_PBX_GPIO3, NO_IRQ } -#define GPIO3_DMA { 0, 0 } #define AACI_IRQ { IRQ_PBX_AACI, NO_IRQ } -#define AACI_DMA { 0x80, 0x81 } #define MMCI0_IRQ { IRQ_PBX_MMCI0A, IRQ_PBX_MMCI0B } -#define MMCI0_DMA { 0x84, 0 } #define KMI0_IRQ { IRQ_PBX_KMI0, NO_IRQ } -#define KMI0_DMA { 0, 0 } #define KMI1_IRQ { IRQ_PBX_KMI1, NO_IRQ } -#define KMI1_DMA { 0, 0 } #define PBX_SMC_IRQ { NO_IRQ, NO_IRQ } -#define PBX_SMC_DMA { 0, 0 } #define MPMC_IRQ { NO_IRQ, NO_IRQ } -#define MPMC_DMA { 0, 0 } #define PBX_CLCD_IRQ { IRQ_PBX_CLCD, NO_IRQ } -#define PBX_CLCD_DMA { 0, 0 } #define DMAC_IRQ { IRQ_PBX_DMAC, NO_IRQ } -#define DMAC_DMA { 0, 0 } #define SCTL_IRQ { NO_IRQ, NO_IRQ } -#define SCTL_DMA { 0, 0 } #define PBX_WATCHDOG_IRQ { IRQ_PBX_WATCHDOG, NO_IRQ } -#define PBX_WATCHDOG_DMA { 0, 0 } #define PBX_GPIO0_IRQ { IRQ_PBX_GPIO0, NO_IRQ } -#define PBX_GPIO0_DMA { 0, 0 } #define GPIO1_IRQ { IRQ_PBX_GPIO1, NO_IRQ } -#define GPIO1_DMA { 0, 0 } #define PBX_RTC_IRQ { IRQ_PBX_RTC, NO_IRQ } -#define PBX_RTC_DMA { 0, 0 } #define SCI_IRQ { IRQ_PBX_SCI, NO_IRQ } -#define SCI_DMA { 7, 6 } #define PBX_UART0_IRQ { IRQ_PBX_UART0, NO_IRQ } -#define PBX_UART0_DMA { 15, 14 } #define PBX_UART1_IRQ { IRQ_PBX_UART1, NO_IRQ } -#define PBX_UART1_DMA { 13, 12 } #define PBX_UART2_IRQ { IRQ_PBX_UART2, NO_IRQ } -#define PBX_UART2_DMA { 11, 10 } #define PBX_UART3_IRQ { IRQ_PBX_UART3, NO_IRQ } -#define PBX_UART3_DMA { 0x86, 0x87 } #define PBX_SSP_IRQ { IRQ_PBX_SSP, NO_IRQ } -#define PBX_SSP_DMA { 9, 8 } /* FPGA Primecells */ AMBA_DEVICE(aaci, "fpga:aaci", AACI, NULL); -- GitLab From dc37c31bbfaf87118d6c827be0a38a512a40b741 Mon Sep 17 00:00:00 2001 From: Russell King Date: Tue, 18 Jan 2011 20:26:08 +0000 Subject: [PATCH 0094/2822] ARM: rationalize versatile family Kconfig/Makefile Move leds and sched_clock build conditionals out of the Makefile into the Kconfig file. Move selection of HAVE_SCHED_CLOCK into the platform Kconfig rather than duplicating it three times in the main architecture Kconfig. Acked-by: Catalin Marinas Signed-off-by: Russell King --- arch/arm/Kconfig | 3 --- arch/arm/plat-versatile/Kconfig | 8 ++++++++ arch/arm/plat-versatile/Makefile | 10 +++------- 3 files changed, 11 insertions(+), 10 deletions(-) diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 4f0e83e079891..fe8d6fa12fe77 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -236,7 +236,6 @@ config ARCH_REALVIEW bool "ARM Ltd. RealView family" select ARM_AMBA select CLKDEV_LOOKUP - select HAVE_SCHED_CLOCK select ICST select GENERIC_CLOCKEVENTS select ARCH_WANT_OPTIONAL_GPIOLIB @@ -252,7 +251,6 @@ config ARCH_VERSATILE select ARM_AMBA select ARM_VIC select CLKDEV_LOOKUP - select HAVE_SCHED_CLOCK select ICST select GENERIC_CLOCKEVENTS select ARCH_WANT_OPTIONAL_GPIOLIB @@ -270,7 +268,6 @@ config ARCH_VEXPRESS select CLKDEV_LOOKUP select GENERIC_CLOCKEVENTS select HAVE_CLK - select HAVE_SCHED_CLOCK select HAVE_PATA_PLATFORM select ICST select PLAT_VERSATILE diff --git a/arch/arm/plat-versatile/Kconfig b/arch/arm/plat-versatile/Kconfig index 22540f588fd38..c5e2cd014c61d 100644 --- a/arch/arm/plat-versatile/Kconfig +++ b/arch/arm/plat-versatile/Kconfig @@ -3,4 +3,12 @@ if PLAT_VERSATILE config PLAT_VERSATILE_CLCD bool +config PLAT_VERSATILE_LEDS + def_bool y if LEDS_CLASS + depends on ARCH_REALVIEW || ARCH_VERSATILE + +config PLAT_VERSATILE_SCHED_CLOCK + def_bool y if !ARCH_INTEGRATOR + select HAVE_SCHED_CLOCK + endif diff --git a/arch/arm/plat-versatile/Makefile b/arch/arm/plat-versatile/Makefile index 8b3341c11ee51..de6f42f003b37 100644 --- a/arch/arm/plat-versatile/Makefile +++ b/arch/arm/plat-versatile/Makefile @@ -1,9 +1,5 @@ obj-y := clock.o -ifneq ($(CONFIG_ARCH_INTEGRATOR),y) -obj-y += sched-clock.o -endif -ifeq ($(CONFIG_LEDS_CLASS),y) -obj-$(CONFIG_ARCH_REALVIEW) += leds.o -obj-$(CONFIG_ARCH_VERSATILE) += leds.o -endif obj-$(CONFIG_PLAT_VERSATILE_CLCD) += clcd.o +obj-$(CONFIG_PLAT_VERSATILE_LEDS) += leds.o +obj-$(CONFIG_PLAT_VERSATILE_SCHED_CLOCK) += sched-clock.o + -- GitLab From c41b16f8c9d9dc74ed5669d4a3e3d42374c9e609 Mon Sep 17 00:00:00 2001 From: Russell King Date: Wed, 19 Jan 2011 15:32:15 +0000 Subject: [PATCH 0095/2822] ARM: integrator/versatile: consolidate FPGA IRQ handling code Consolidate the FPGA IRQ handling code. Integrator/AP and Versatile have one FPGA-based IRQ handler each. Integrator/CP has three. Acked-by: Catalin Marinas Signed-off-by: Russell King --- arch/arm/Kconfig | 2 + arch/arm/mach-integrator/integrator_ap.c | 41 ++--- arch/arm/mach-integrator/integrator_cp.c | 142 ++++-------------- arch/arm/mach-versatile/core.c | 57 +------ .../mach-versatile/include/mach/hardware.h | 2 +- arch/arm/plat-versatile/Kconfig | 3 + arch/arm/plat-versatile/Makefile | 1 + arch/arm/plat-versatile/fpga-irq.c | 72 +++++++++ .../plat-versatile/include/plat/fpga-irq.h | 12 ++ 9 files changed, 140 insertions(+), 192 deletions(-) create mode 100644 arch/arm/plat-versatile/fpga-irq.c create mode 100644 arch/arm/plat-versatile/include/plat/fpga-irq.h diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index fe8d6fa12fe77..a6ccef6d9d72b 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -229,6 +229,7 @@ config ARCH_INTEGRATOR select ICST select GENERIC_CLOCKEVENTS select PLAT_VERSATILE + select PLAT_VERSATILE_FPGA_IRQ help Support for ARM's Integrator platform. @@ -256,6 +257,7 @@ config ARCH_VERSATILE select ARCH_WANT_OPTIONAL_GPIOLIB select PLAT_VERSATILE select PLAT_VERSATILE_CLCD + select PLAT_VERSATILE_FPGA_IRQ select ARM_TIMER_SP804 help This enables support for ARM Ltd Versatile board. diff --git a/arch/arm/mach-integrator/integrator_ap.c b/arch/arm/mach-integrator/integrator_ap.c index 4f06b5d724890..980803ff348ce 100644 --- a/arch/arm/mach-integrator/integrator_ap.c +++ b/arch/arm/mach-integrator/integrator_ap.c @@ -48,6 +48,8 @@ #include #include +#include + #include "common.h" /* @@ -57,10 +59,10 @@ * Setup a VA for the Integrator interrupt controller (for header #0, * just for now). */ -#define VA_IC_BASE IO_ADDRESS(INTEGRATOR_IC_BASE) -#define VA_SC_BASE IO_ADDRESS(INTEGRATOR_SC_BASE) -#define VA_EBI_BASE IO_ADDRESS(INTEGRATOR_EBI_BASE) -#define VA_CMIC_BASE IO_ADDRESS(INTEGRATOR_HDR_IC) +#define VA_IC_BASE __io_address(INTEGRATOR_IC_BASE) +#define VA_SC_BASE __io_address(INTEGRATOR_SC_BASE) +#define VA_EBI_BASE __io_address(INTEGRATOR_EBI_BASE) +#define VA_CMIC_BASE __io_address(INTEGRATOR_HDR_IC) /* * Logical Physical @@ -156,27 +158,14 @@ static void __init ap_map_io(void) #define INTEGRATOR_SC_VALID_INT 0x003fffff -static void sc_mask_irq(struct irq_data *d) -{ - writel(1 << d->irq, VA_IC_BASE + IRQ_ENABLE_CLEAR); -} - -static void sc_unmask_irq(struct irq_data *d) -{ - writel(1 << d->irq, VA_IC_BASE + IRQ_ENABLE_SET); -} - -static struct irq_chip sc_chip = { - .name = "SC", - .irq_ack = sc_mask_irq, - .irq_mask = sc_mask_irq, - .irq_unmask = sc_unmask_irq, +static struct fpga_irq_data sc_irq_data = { + .base = VA_IC_BASE, + .irq_start = 0, + .chip.name = "SC", }; static void __init ap_init_irq(void) { - unsigned int i; - /* Disable all interrupts initially. */ /* Do the core module ones */ writel(-1, VA_CMIC_BASE + IRQ_ENABLE_CLEAR); @@ -185,13 +174,7 @@ static void __init ap_init_irq(void) writel(-1, VA_IC_BASE + IRQ_ENABLE_CLEAR); writel(-1, VA_IC_BASE + FIQ_ENABLE_CLEAR); - for (i = 0; i < NR_IRQS; i++) { - if (((1 << i) & INTEGRATOR_SC_VALID_INT) != 0) { - set_irq_chip(i, &sc_chip); - set_irq_handler(i, handle_level_irq); - set_irq_flags(i, IRQF_VALID | IRQF_PROBE); - } - } + fpga_irq_init(-1, INTEGRATOR_SC_VALID_INT, &sc_irq_data); } #ifdef CONFIG_PM @@ -282,7 +265,7 @@ static void ap_flash_exit(void) static void ap_flash_set_vpp(int on) { - unsigned long reg = on ? SC_CTRLS : SC_CTRLC; + void __iomem *reg = on ? SC_CTRLS : SC_CTRLC; writel(INTEGRATOR_SC_CTRL_nFLVPPEN, reg); } diff --git a/arch/arm/mach-integrator/integrator_cp.c b/arch/arm/mach-integrator/integrator_cp.c index e6700aab849a0..05da36f754dd9 100644 --- a/arch/arm/mach-integrator/integrator_cp.c +++ b/arch/arm/mach-integrator/integrator_cp.c @@ -43,6 +43,7 @@ #include #include +#include #include "common.h" @@ -51,9 +52,9 @@ #define INTCP_PA_CLCD_BASE 0xc0000000 -#define INTCP_VA_CIC_BASE IO_ADDRESS(INTEGRATOR_HDR_BASE + 0x40) -#define INTCP_VA_PIC_BASE IO_ADDRESS(INTEGRATOR_IC_BASE) -#define INTCP_VA_SIC_BASE IO_ADDRESS(INTEGRATOR_CP_SIC_BASE) +#define INTCP_VA_CIC_BASE __io_address(INTEGRATOR_HDR_BASE + 0x40) +#define INTCP_VA_PIC_BASE __io_address(INTEGRATOR_IC_BASE) +#define INTCP_VA_SIC_BASE __io_address(INTEGRATOR_CP_SIC_BASE) #define INTCP_ETH_SIZE 0x10 @@ -141,129 +142,48 @@ static void __init intcp_map_io(void) iotable_init(intcp_io_desc, ARRAY_SIZE(intcp_io_desc)); } -#define cic_writel __raw_writel -#define cic_readl __raw_readl -#define pic_writel __raw_writel -#define pic_readl __raw_readl -#define sic_writel __raw_writel -#define sic_readl __raw_readl - -static void cic_mask_irq(struct irq_data *d) -{ - unsigned int irq = d->irq - IRQ_CIC_START; - cic_writel(1 << irq, INTCP_VA_CIC_BASE + IRQ_ENABLE_CLEAR); -} - -static void cic_unmask_irq(struct irq_data *d) -{ - unsigned int irq = d->irq - IRQ_CIC_START; - cic_writel(1 << irq, INTCP_VA_CIC_BASE + IRQ_ENABLE_SET); -} - -static struct irq_chip cic_chip = { - .name = "CIC", - .irq_ack = cic_mask_irq, - .irq_mask = cic_mask_irq, - .irq_unmask = cic_unmask_irq, +static struct fpga_irq_data cic_irq_data = { + .base = INTCP_VA_CIC_BASE, + .irq_start = IRQ_CIC_START, + .chip.name = "CIC", }; -static void pic_mask_irq(struct irq_data *d) -{ - unsigned int irq = d->irq - IRQ_PIC_START; - pic_writel(1 << irq, INTCP_VA_PIC_BASE + IRQ_ENABLE_CLEAR); -} - -static void pic_unmask_irq(struct irq_data *d) -{ - unsigned int irq = d->irq - IRQ_PIC_START; - pic_writel(1 << irq, INTCP_VA_PIC_BASE + IRQ_ENABLE_SET); -} - -static struct irq_chip pic_chip = { - .name = "PIC", - .irq_ack = pic_mask_irq, - .irq_mask = pic_mask_irq, - .irq_unmask = pic_unmask_irq, +static struct fpga_irq_data pic_irq_data = { + .base = INTCP_VA_PIC_BASE, + .irq_start = IRQ_PIC_START, + .chip.name = "PIC", }; -static void sic_mask_irq(struct irq_data *d) -{ - unsigned int irq = d->irq - IRQ_SIC_START; - sic_writel(1 << irq, INTCP_VA_SIC_BASE + IRQ_ENABLE_CLEAR); -} - -static void sic_unmask_irq(struct irq_data *d) -{ - unsigned int irq = d->irq - IRQ_SIC_START; - sic_writel(1 << irq, INTCP_VA_SIC_BASE + IRQ_ENABLE_SET); -} - -static struct irq_chip sic_chip = { - .name = "SIC", - .irq_ack = sic_mask_irq, - .irq_mask = sic_mask_irq, - .irq_unmask = sic_unmask_irq, +static struct fpga_irq_data sic_irq_data = { + .base = INTCP_VA_SIC_BASE, + .irq_start = IRQ_SIC_START, + .chip.name = "SIC", }; -static void -sic_handle_irq(unsigned int irq, struct irq_desc *desc) -{ - unsigned long status = sic_readl(INTCP_VA_SIC_BASE + IRQ_STATUS); - - if (status == 0) { - do_bad_IRQ(irq, desc); - return; - } - - do { - irq = ffs(status) - 1; - status &= ~(1 << irq); - - irq += IRQ_SIC_START; - - generic_handle_irq(irq); - } while (status); -} - static void __init intcp_init_irq(void) { - unsigned int i; + u32 pic_mask, sic_mask; + + pic_mask = ~((~0u) << (11 - IRQ_PIC_START)); + pic_mask |= (~((~0u) << (29 - 22))) << 22; + sic_mask = ~((~0u) << (1 + IRQ_SIC_END - IRQ_SIC_START)); /* * Disable all interrupt sources */ - pic_writel(0xffffffff, INTCP_VA_PIC_BASE + IRQ_ENABLE_CLEAR); - pic_writel(0xffffffff, INTCP_VA_PIC_BASE + FIQ_ENABLE_CLEAR); - - for (i = IRQ_PIC_START; i <= IRQ_PIC_END; i++) { - if (i == 11) - i = 22; - if (i == 29) - break; - set_irq_chip(i, &pic_chip); - set_irq_handler(i, handle_level_irq); - set_irq_flags(i, IRQF_VALID | IRQF_PROBE); - } + writel(0xffffffff, INTCP_VA_PIC_BASE + IRQ_ENABLE_CLEAR); + writel(0xffffffff, INTCP_VA_PIC_BASE + FIQ_ENABLE_CLEAR); + writel(0xffffffff, INTCP_VA_CIC_BASE + IRQ_ENABLE_CLEAR); + writel(0xffffffff, INTCP_VA_CIC_BASE + FIQ_ENABLE_CLEAR); + writel(sic_mask, INTCP_VA_SIC_BASE + IRQ_ENABLE_CLEAR); + writel(sic_mask, INTCP_VA_SIC_BASE + FIQ_ENABLE_CLEAR); - cic_writel(0xffffffff, INTCP_VA_CIC_BASE + IRQ_ENABLE_CLEAR); - cic_writel(0xffffffff, INTCP_VA_CIC_BASE + FIQ_ENABLE_CLEAR); + fpga_irq_init(-1, pic_mask, &pic_irq_data); - for (i = IRQ_CIC_START; i <= IRQ_CIC_END; i++) { - set_irq_chip(i, &cic_chip); - set_irq_handler(i, handle_level_irq); - set_irq_flags(i, IRQF_VALID); - } - - sic_writel(0x00000fff, INTCP_VA_SIC_BASE + IRQ_ENABLE_CLEAR); - sic_writel(0x00000fff, INTCP_VA_SIC_BASE + FIQ_ENABLE_CLEAR); - - for (i = IRQ_SIC_START; i <= IRQ_SIC_END; i++) { - set_irq_chip(i, &sic_chip); - set_irq_handler(i, handle_level_irq); - set_irq_flags(i, IRQF_VALID | IRQF_PROBE); - } + fpga_irq_init(-1, ~((~0u) << (1 + IRQ_CIC_END - IRQ_CIC_START)), + &cic_irq_data); - set_irq_chained_handler(IRQ_CP_CPPLDINT, sic_handle_irq); + fpga_irq_init(IRQ_CP_CPPLDINT, sic_mask, &sic_irq_data); } /* diff --git a/arch/arm/mach-versatile/core.c b/arch/arm/mach-versatile/core.c index 630a1c96f90bb..eb7ffa0ee8b54 100644 --- a/arch/arm/mach-versatile/core.c +++ b/arch/arm/mach-versatile/core.c @@ -51,6 +51,7 @@ #include #include +#include #include #include "core.h" @@ -64,47 +65,12 @@ #define VA_VIC_BASE __io_address(VERSATILE_VIC_BASE) #define VA_SIC_BASE __io_address(VERSATILE_SIC_BASE) -static void sic_mask_irq(struct irq_data *d) -{ - unsigned int irq = d->irq - IRQ_SIC_START; - - writel(1 << irq, VA_SIC_BASE + SIC_IRQ_ENABLE_CLEAR); -} - -static void sic_unmask_irq(struct irq_data *d) -{ - unsigned int irq = d->irq - IRQ_SIC_START; - - writel(1 << irq, VA_SIC_BASE + SIC_IRQ_ENABLE_SET); -} - -static struct irq_chip sic_chip = { - .name = "SIC", - .irq_ack = sic_mask_irq, - .irq_mask = sic_mask_irq, - .irq_unmask = sic_unmask_irq, +static struct fpga_irq_data sic_irq = { + .base = VA_SIC_BASE, + .irq_start = IRQ_SIC_START, + .chip.name = "SIC", }; -static void -sic_handle_irq(unsigned int irq, struct irq_desc *desc) -{ - unsigned long status = readl(VA_SIC_BASE + SIC_IRQ_STATUS); - - if (status == 0) { - do_bad_IRQ(irq, desc); - return; - } - - do { - irq = ffs(status) - 1; - status &= ~(1 << irq); - - irq += IRQ_SIC_START; - - generic_handle_irq(irq); - } while (status); -} - #if 1 #define IRQ_MMCI0A IRQ_VICSOURCE22 #define IRQ_AACI IRQ_VICSOURCE24 @@ -119,22 +85,11 @@ sic_handle_irq(unsigned int irq, struct irq_desc *desc) void __init versatile_init_irq(void) { - unsigned int i; - vic_init(VA_VIC_BASE, IRQ_VIC_START, ~0, 0); - set_irq_chained_handler(IRQ_VICSOURCE31, sic_handle_irq); - - /* Do second interrupt controller */ writel(~0, VA_SIC_BASE + SIC_IRQ_ENABLE_CLEAR); - for (i = IRQ_SIC_START; i <= IRQ_SIC_END; i++) { - if ((PIC_MASK & (1 << (i - IRQ_SIC_START))) == 0) { - set_irq_chip(i, &sic_chip); - set_irq_handler(i, handle_level_irq); - set_irq_flags(i, IRQF_VALID | IRQF_PROBE); - } - } + fpga_irq_init(IRQ_VICSOURCE31, ~PIC_MASK, &sic_irq); /* * Interrupts on secondary controller from 0 to 8 are routed to diff --git a/arch/arm/mach-versatile/include/mach/hardware.h b/arch/arm/mach-versatile/include/mach/hardware.h index b5e75bb449651..6911e1f5f1560 100644 --- a/arch/arm/mach-versatile/include/mach/hardware.h +++ b/arch/arm/mach-versatile/include/mach/hardware.h @@ -39,6 +39,6 @@ /* macro to get at IO space when running virtually */ #define IO_ADDRESS(x) (((x) & 0x0fffffff) + (((x) >> 4) & 0x0f000000) + 0xf0000000) -#define __io_address(n) __io(IO_ADDRESS(n)) +#define __io_address(n) ((void __iomem __force *)IO_ADDRESS(n)) #endif diff --git a/arch/arm/plat-versatile/Kconfig b/arch/arm/plat-versatile/Kconfig index c5e2cd014c61d..0b275008d3e0b 100644 --- a/arch/arm/plat-versatile/Kconfig +++ b/arch/arm/plat-versatile/Kconfig @@ -3,6 +3,9 @@ if PLAT_VERSATILE config PLAT_VERSATILE_CLCD bool +config PLAT_VERSATILE_FPGA_IRQ + bool + config PLAT_VERSATILE_LEDS def_bool y if LEDS_CLASS depends on ARCH_REALVIEW || ARCH_VERSATILE diff --git a/arch/arm/plat-versatile/Makefile b/arch/arm/plat-versatile/Makefile index de6f42f003b37..41f57f4b90382 100644 --- a/arch/arm/plat-versatile/Makefile +++ b/arch/arm/plat-versatile/Makefile @@ -1,5 +1,6 @@ obj-y := clock.o obj-$(CONFIG_PLAT_VERSATILE_CLCD) += clcd.o +obj-$(CONFIG_PLAT_VERSATILE_FPGA_IRQ) += fpga-irq.o obj-$(CONFIG_PLAT_VERSATILE_LEDS) += leds.o obj-$(CONFIG_PLAT_VERSATILE_SCHED_CLOCK) += sched-clock.o diff --git a/arch/arm/plat-versatile/fpga-irq.c b/arch/arm/plat-versatile/fpga-irq.c new file mode 100644 index 0000000000000..31d945d37e4f1 --- /dev/null +++ b/arch/arm/plat-versatile/fpga-irq.c @@ -0,0 +1,72 @@ +/* + * Support for Versatile FPGA-based IRQ controllers + */ +#include +#include + +#include +#include + +#define IRQ_STATUS 0x00 +#define IRQ_RAW_STATUS 0x04 +#define IRQ_ENABLE_SET 0x08 +#define IRQ_ENABLE_CLEAR 0x0c + +static void fpga_irq_mask(struct irq_data *d) +{ + struct fpga_irq_data *f = irq_data_get_irq_chip_data(d); + u32 mask = 1 << (d->irq - f->irq_start); + + writel(mask, f->base + IRQ_ENABLE_CLEAR); +} + +static void fpga_irq_unmask(struct irq_data *d) +{ + struct fpga_irq_data *f = irq_data_get_irq_chip_data(d); + u32 mask = 1 << (d->irq - f->irq_start); + + writel(mask, f->base + IRQ_ENABLE_SET); +} + +static void fpga_irq_handle(unsigned int irq, struct irq_desc *desc) +{ + struct fpga_irq_data *f = get_irq_desc_data(desc); + u32 status = readl(f->base + IRQ_STATUS); + + if (status == 0) { + do_bad_IRQ(irq, desc); + return; + } + + do { + irq = ffs(status) - 1; + status &= ~(1 << irq); + + generic_handle_irq(irq + f->irq_start); + } while (status); +} + +void __init fpga_irq_init(int parent_irq, u32 valid, struct fpga_irq_data *f) +{ + unsigned int i; + + f->chip.irq_ack = fpga_irq_mask; + f->chip.irq_mask = fpga_irq_mask; + f->chip.irq_unmask = fpga_irq_unmask; + + if (parent_irq != -1) { + set_irq_data(parent_irq, f); + set_irq_chained_handler(parent_irq, fpga_irq_handle); + } + + for (i = 0; i < 32; i++) { + if (valid & (1 << i)) { + unsigned int irq = f->irq_start + i; + + set_irq_chip_data(irq, f); + set_irq_chip(irq, &f->chip); + set_irq_handler(irq, handle_level_irq); + set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); + } + } +} diff --git a/arch/arm/plat-versatile/include/plat/fpga-irq.h b/arch/arm/plat-versatile/include/plat/fpga-irq.h new file mode 100644 index 0000000000000..627fafd1e5951 --- /dev/null +++ b/arch/arm/plat-versatile/include/plat/fpga-irq.h @@ -0,0 +1,12 @@ +#ifndef PLAT_FPGA_IRQ_H +#define PLAT_FPGA_IRQ_H + +struct fpga_irq_data { + void __iomem *base; + unsigned int irq_start; + struct irq_chip chip; +}; + +void fpga_irq_init(int, u32, struct fpga_irq_data *); + +#endif -- GitLab From cdab142a80d859984eb5e3876e0e762b1f0bded9 Mon Sep 17 00:00:00 2001 From: Russell King Date: Wed, 19 Jan 2011 10:07:38 +0000 Subject: [PATCH 0096/2822] ARM: realview/vexpress: consolidate localtimer support Realview and Versatile Express local timer support is identical, so consolidate the implementations. Acked-by: Catalin Marinas Signed-off-by: Russell King --- arch/arm/mach-realview/Makefile | 1 - arch/arm/mach-realview/localtimer.c | 26 ------------------- arch/arm/mach-vexpress/Makefile | 1 - arch/arm/plat-versatile/Makefile | 1 + .../localtimer.c | 2 +- 5 files changed, 2 insertions(+), 29 deletions(-) delete mode 100644 arch/arm/mach-realview/localtimer.c rename arch/arm/{mach-vexpress => plat-versatile}/localtimer.c (92%) diff --git a/arch/arm/mach-realview/Makefile b/arch/arm/mach-realview/Makefile index a01b76b7c9567..ba85e5290b71c 100644 --- a/arch/arm/mach-realview/Makefile +++ b/arch/arm/mach-realview/Makefile @@ -10,4 +10,3 @@ obj-$(CONFIG_MACH_REALVIEW_PBA8) += realview_pba8.o obj-$(CONFIG_MACH_REALVIEW_PBX) += realview_pbx.o obj-$(CONFIG_SMP) += platsmp.o headsmp.o obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o -obj-$(CONFIG_LOCAL_TIMERS) += localtimer.o diff --git a/arch/arm/mach-realview/localtimer.c b/arch/arm/mach-realview/localtimer.c deleted file mode 100644 index 60b4e111f4596..0000000000000 --- a/arch/arm/mach-realview/localtimer.c +++ /dev/null @@ -1,26 +0,0 @@ -/* - * linux/arch/arm/mach-realview/localtimer.c - * - * Copyright (C) 2002 ARM Ltd. - * All Rights Reserved - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ -#include -#include -#include - -#include -#include -#include - -/* - * Setup the local clock events for a CPU. - */ -void __cpuinit local_timer_setup(struct clock_event_device *evt) -{ - evt->irq = IRQ_LOCALTIMER; - twd_timer_setup(evt); -} diff --git a/arch/arm/mach-vexpress/Makefile b/arch/arm/mach-vexpress/Makefile index 2c0ac7de28142..cfe344ec1d6da 100644 --- a/arch/arm/mach-vexpress/Makefile +++ b/arch/arm/mach-vexpress/Makefile @@ -6,4 +6,3 @@ obj-y := v2m.o obj-$(CONFIG_ARCH_VEXPRESS_CA9X4) += ct-ca9x4.o obj-$(CONFIG_SMP) += platsmp.o headsmp.o obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o -obj-$(CONFIG_LOCAL_TIMERS) += localtimer.o diff --git a/arch/arm/plat-versatile/Makefile b/arch/arm/plat-versatile/Makefile index 41f57f4b90382..b511abb101980 100644 --- a/arch/arm/plat-versatile/Makefile +++ b/arch/arm/plat-versatile/Makefile @@ -1,4 +1,5 @@ obj-y := clock.o +obj-$(CONFIG_LOCAL_TIMERS) += localtimer.o obj-$(CONFIG_PLAT_VERSATILE_CLCD) += clcd.o obj-$(CONFIG_PLAT_VERSATILE_FPGA_IRQ) += fpga-irq.o obj-$(CONFIG_PLAT_VERSATILE_LEDS) += leds.o diff --git a/arch/arm/mach-vexpress/localtimer.c b/arch/arm/plat-versatile/localtimer.c similarity index 92% rename from arch/arm/mach-vexpress/localtimer.c rename to arch/arm/plat-versatile/localtimer.c index c0e3a59a0bfca..83ebee569333c 100644 --- a/arch/arm/mach-vexpress/localtimer.c +++ b/arch/arm/plat-versatile/localtimer.c @@ -1,5 +1,5 @@ /* - * linux/arch/arm/mach-vexpress/localtimer.c + * linux/arch/arm/plat-versatile/localtimer.c * * Copyright (C) 2002 ARM Ltd. * All Rights Reserved -- GitLab From 0462b4477ea3260304bbcd97c64c0b704b4f0f85 Mon Sep 17 00:00:00 2001 From: Russell King Date: Wed, 19 Jan 2011 10:24:56 +0000 Subject: [PATCH 0097/2822] ARM: realview/vexpress: consolidate SMP bringup code Realview and Versatile Express share the same SMP bringup code, so consolidate the two implementations. Acked-by: Catalin Marinas Signed-off-by: Russell King --- arch/arm/mach-realview/Makefile | 2 +- arch/arm/mach-realview/headsmp.S | 40 ------- arch/arm/mach-realview/platsmp.c | 98 +---------------- arch/arm/mach-vexpress/Makefile | 2 +- arch/arm/mach-vexpress/platsmp.c | 94 +--------------- arch/arm/plat-versatile/Makefile | 2 +- .../headsmp.S | 8 +- arch/arm/plat-versatile/platsmp.c | 104 ++++++++++++++++++ 8 files changed, 116 insertions(+), 234 deletions(-) delete mode 100644 arch/arm/mach-realview/headsmp.S rename arch/arm/{mach-vexpress => plat-versatile}/headsmp.S (75%) create mode 100644 arch/arm/plat-versatile/platsmp.c diff --git a/arch/arm/mach-realview/Makefile b/arch/arm/mach-realview/Makefile index ba85e5290b71c..541fa4c109ef0 100644 --- a/arch/arm/mach-realview/Makefile +++ b/arch/arm/mach-realview/Makefile @@ -8,5 +8,5 @@ obj-$(CONFIG_MACH_REALVIEW_PB11MP) += realview_pb11mp.o obj-$(CONFIG_MACH_REALVIEW_PB1176) += realview_pb1176.o obj-$(CONFIG_MACH_REALVIEW_PBA8) += realview_pba8.o obj-$(CONFIG_MACH_REALVIEW_PBX) += realview_pbx.o -obj-$(CONFIG_SMP) += platsmp.o headsmp.o +obj-$(CONFIG_SMP) += platsmp.o obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o diff --git a/arch/arm/mach-realview/headsmp.S b/arch/arm/mach-realview/headsmp.S deleted file mode 100644 index b34be4554d40d..0000000000000 --- a/arch/arm/mach-realview/headsmp.S +++ /dev/null @@ -1,40 +0,0 @@ -/* - * linux/arch/arm/mach-realview/headsmp.S - * - * Copyright (c) 2003 ARM Limited - * All Rights Reserved - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ -#include -#include - - __INIT - -/* - * Realview specific entry point for secondary CPUs. This provides - * a "holding pen" into which all secondary cores are held until we're - * ready for them to initialise. - */ -ENTRY(realview_secondary_startup) - mrc p15, 0, r0, c0, c0, 5 - and r0, r0, #15 - adr r4, 1f - ldmia r4, {r5, r6} - sub r4, r4, r5 - add r6, r6, r4 -pen: ldr r7, [r6] - cmp r7, r0 - bne pen - - /* - * we've been released from the holding pen: secondary_stack - * should now contain the SVC stack for this core - */ - b secondary_startup - - .align -1: .long . - .long pen_release diff --git a/arch/arm/mach-realview/platsmp.c b/arch/arm/mach-realview/platsmp.c index 6959d13d908a1..23919229e12de 100644 --- a/arch/arm/mach-realview/platsmp.c +++ b/arch/arm/mach-realview/platsmp.c @@ -10,44 +10,21 @@ */ #include #include -#include -#include -#include #include #include -#include #include #include +#include #include #include #include #include -#include #include "core.h" -extern void realview_secondary_startup(void); - -/* - * control for which core is the next to come out of the secondary - * boot "holding pen" - */ -volatile int __cpuinitdata pen_release = -1; - -/* - * Write pen_release in a way that is guaranteed to be visible to all - * observers, irrespective of whether they're taking part in coherency - * or not. This is necessary for the hotplug code to work reliably. - */ -static void __cpuinit write_pen_release(int val) -{ - pen_release = val; - smp_wmb(); - __cpuc_flush_dcache_area((void *)&pen_release, sizeof(pen_release)); - outer_clean_range(__pa(&pen_release), __pa(&pen_release + 1)); -} +extern void versatile_secondary_startup(void); static void __iomem *scu_base_addr(void) { @@ -62,75 +39,6 @@ static void __iomem *scu_base_addr(void) return (void __iomem *)0; } -static DEFINE_SPINLOCK(boot_lock); - -void __cpuinit platform_secondary_init(unsigned int cpu) -{ - /* - * if any interrupts are already enabled for the primary - * core (e.g. timer irq), then they will not have been enabled - * for us: do so - */ - gic_secondary_init(0); - - /* - * let the primary processor know we're out of the - * pen, then head off into the C entry point - */ - write_pen_release(-1); - - /* - * Synchronise with the boot thread. - */ - spin_lock(&boot_lock); - spin_unlock(&boot_lock); -} - -int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle) -{ - unsigned long timeout; - - /* - * set synchronisation state between this boot processor - * and the secondary one - */ - spin_lock(&boot_lock); - - /* - * The secondary processor is waiting to be released from - * the holding pen - release it, then wait for it to flag - * that it has been released by resetting pen_release. - * - * Note that "pen_release" is the hardware CPU ID, whereas - * "cpu" is Linux's internal ID. - */ - write_pen_release(cpu); - - /* - * Send the secondary CPU a soft interrupt, thereby causing - * the boot monitor to read the system wide flags register, - * and branch to the address found there. - */ - smp_cross_call(cpumask_of(cpu), 1); - - timeout = jiffies + (1 * HZ); - while (time_before(jiffies, timeout)) { - smp_rmb(); - if (pen_release == -1) - break; - - udelay(10); - } - - /* - * now the secondary core is starting up let it run its - * calibrations, then wait for it to finish - */ - spin_unlock(&boot_lock); - - return pen_release != -1 ? -ENOSYS : 0; -} - /* * Initialise the CPU possible map early - this describes the CPUs * which may be present or become present in the system. @@ -174,6 +82,6 @@ void __init platform_smp_prepare_cpus(unsigned int max_cpus) * until it receives a soft interrupt, and then the * secondary CPU branches to this address. */ - __raw_writel(BSYM(virt_to_phys(realview_secondary_startup)), + __raw_writel(BSYM(virt_to_phys(versatile_secondary_startup)), __io_address(REALVIEW_SYS_FLAGSSET)); } diff --git a/arch/arm/mach-vexpress/Makefile b/arch/arm/mach-vexpress/Makefile index cfe344ec1d6da..90551b9780ab1 100644 --- a/arch/arm/mach-vexpress/Makefile +++ b/arch/arm/mach-vexpress/Makefile @@ -4,5 +4,5 @@ obj-y := v2m.o obj-$(CONFIG_ARCH_VEXPRESS_CA9X4) += ct-ca9x4.o -obj-$(CONFIG_SMP) += platsmp.o headsmp.o +obj-$(CONFIG_SMP) += platsmp.o obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o diff --git a/arch/arm/mach-vexpress/platsmp.c b/arch/arm/mach-vexpress/platsmp.c index 634bf1d3a311d..18927023c2cc4 100644 --- a/arch/arm/mach-vexpress/platsmp.c +++ b/arch/arm/mach-vexpress/platsmp.c @@ -10,13 +10,9 @@ */ #include #include -#include -#include -#include #include #include -#include #include #include @@ -26,99 +22,13 @@ #include "core.h" -extern void vexpress_secondary_startup(void); - -/* - * control for which core is the next to come out of the secondary - * boot "holding pen" - */ -volatile int __cpuinitdata pen_release = -1; - -/* - * Write pen_release in a way that is guaranteed to be visible to all - * observers, irrespective of whether they're taking part in coherency - * or not. This is necessary for the hotplug code to work reliably. - */ -static void __cpuinit write_pen_release(int val) -{ - pen_release = val; - smp_wmb(); - __cpuc_flush_dcache_area((void *)&pen_release, sizeof(pen_release)); - outer_clean_range(__pa(&pen_release), __pa(&pen_release + 1)); -} +extern void versatile_secondary_startup(void); static void __iomem *scu_base_addr(void) { return MMIO_P2V(A9_MPCORE_SCU); } -static DEFINE_SPINLOCK(boot_lock); - -void __cpuinit platform_secondary_init(unsigned int cpu) -{ - /* - * if any interrupts are already enabled for the primary - * core (e.g. timer irq), then they will not have been enabled - * for us: do so - */ - gic_secondary_init(0); - - /* - * let the primary processor know we're out of the - * pen, then head off into the C entry point - */ - write_pen_release(-1); - - /* - * Synchronise with the boot thread. - */ - spin_lock(&boot_lock); - spin_unlock(&boot_lock); -} - -int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle) -{ - unsigned long timeout; - - /* - * Set synchronisation state between this boot processor - * and the secondary one - */ - spin_lock(&boot_lock); - - /* - * This is really belt and braces; we hold unintended secondary - * CPUs in the holding pen until we're ready for them. However, - * since we haven't sent them a soft interrupt, they shouldn't - * be there. - */ - write_pen_release(cpu); - - /* - * Send the secondary CPU a soft interrupt, thereby causing - * the boot monitor to read the system wide flags register, - * and branch to the address found there. - */ - smp_cross_call(cpumask_of(cpu), 1); - - timeout = jiffies + (1 * HZ); - while (time_before(jiffies, timeout)) { - smp_rmb(); - if (pen_release == -1) - break; - - udelay(10); - } - - /* - * now the secondary core is starting up let it run its - * calibrations, then wait for it to finish - */ - spin_unlock(&boot_lock); - - return pen_release != -1 ? -ENOSYS : 0; -} - /* * Initialise the CPU possible map early - this describes the CPUs * which may be present or become present in the system. @@ -163,6 +73,6 @@ void __init platform_smp_prepare_cpus(unsigned int max_cpus) * secondary CPU branches to this address. */ writel(~0, MMIO_P2V(V2M_SYS_FLAGSCLR)); - writel(BSYM(virt_to_phys(vexpress_secondary_startup)), + writel(BSYM(virt_to_phys(versatile_secondary_startup)), MMIO_P2V(V2M_SYS_FLAGSSET)); } diff --git a/arch/arm/plat-versatile/Makefile b/arch/arm/plat-versatile/Makefile index b511abb101980..69714db47c333 100644 --- a/arch/arm/plat-versatile/Makefile +++ b/arch/arm/plat-versatile/Makefile @@ -4,4 +4,4 @@ obj-$(CONFIG_PLAT_VERSATILE_CLCD) += clcd.o obj-$(CONFIG_PLAT_VERSATILE_FPGA_IRQ) += fpga-irq.o obj-$(CONFIG_PLAT_VERSATILE_LEDS) += leds.o obj-$(CONFIG_PLAT_VERSATILE_SCHED_CLOCK) += sched-clock.o - +obj-$(CONFIG_SMP) += headsmp.o platsmp.o diff --git a/arch/arm/mach-vexpress/headsmp.S b/arch/arm/plat-versatile/headsmp.S similarity index 75% rename from arch/arm/mach-vexpress/headsmp.S rename to arch/arm/plat-versatile/headsmp.S index 7a3f0632947c7..d397a1fb2f541 100644 --- a/arch/arm/mach-vexpress/headsmp.S +++ b/arch/arm/plat-versatile/headsmp.S @@ -1,5 +1,5 @@ /* - * linux/arch/arm/mach-vexpress/headsmp.S + * linux/arch/arm/plat-versatile/headsmp.S * * Copyright (c) 2003 ARM Limited * All Rights Reserved @@ -14,11 +14,11 @@ __INIT /* - * Versatile Express specific entry point for secondary CPUs. This - * provides a "holding pen" into which all secondary cores are held + * Realview/Versatile Express specific entry point for secondary CPUs. + * This provides a "holding pen" into which all secondary cores are held * until we're ready for them to initialise. */ -ENTRY(vexpress_secondary_startup) +ENTRY(versatile_secondary_startup) mrc p15, 0, r0, c0, c0, 5 and r0, r0, #15 adr r4, 1f diff --git a/arch/arm/plat-versatile/platsmp.c b/arch/arm/plat-versatile/platsmp.c new file mode 100644 index 0000000000000..ba3d471d4bcfa --- /dev/null +++ b/arch/arm/plat-versatile/platsmp.c @@ -0,0 +1,104 @@ +/* + * linux/arch/arm/plat-versatile/platsmp.c + * + * Copyright (C) 2002 ARM Ltd. + * All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#include +#include +#include +#include +#include +#include + +#include + +/* + * control for which core is the next to come out of the secondary + * boot "holding pen" + */ +volatile int __cpuinitdata pen_release = -1; + +/* + * Write pen_release in a way that is guaranteed to be visible to all + * observers, irrespective of whether they're taking part in coherency + * or not. This is necessary for the hotplug code to work reliably. + */ +static void __cpuinit write_pen_release(int val) +{ + pen_release = val; + smp_wmb(); + __cpuc_flush_dcache_area((void *)&pen_release, sizeof(pen_release)); + outer_clean_range(__pa(&pen_release), __pa(&pen_release + 1)); +} + +static DEFINE_SPINLOCK(boot_lock); + +void __cpuinit platform_secondary_init(unsigned int cpu) +{ + /* + * if any interrupts are already enabled for the primary + * core (e.g. timer irq), then they will not have been enabled + * for us: do so + */ + gic_secondary_init(0); + + /* + * let the primary processor know we're out of the + * pen, then head off into the C entry point + */ + write_pen_release(-1); + + /* + * Synchronise with the boot thread. + */ + spin_lock(&boot_lock); + spin_unlock(&boot_lock); +} + +int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle) +{ + unsigned long timeout; + + /* + * Set synchronisation state between this boot processor + * and the secondary one + */ + spin_lock(&boot_lock); + + /* + * This is really belt and braces; we hold unintended secondary + * CPUs in the holding pen until we're ready for them. However, + * since we haven't sent them a soft interrupt, they shouldn't + * be there. + */ + write_pen_release(cpu); + + /* + * Send the secondary CPU a soft interrupt, thereby causing + * the boot monitor to read the system wide flags register, + * and branch to the address found there. + */ + smp_cross_call(cpumask_of(cpu), 1); + + timeout = jiffies + (1 * HZ); + while (time_before(jiffies, timeout)) { + smp_rmb(); + if (pen_release == -1) + break; + + udelay(10); + } + + /* + * now the secondary core is starting up let it run its + * calibrations, then wait for it to finish + */ + spin_unlock(&boot_lock); + + return pen_release != -1 ? -ENOSYS : 0; +} -- GitLab From d77e270c53a4911d23ded9f4ab8b175a3fe3bb34 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 22 Jan 2011 11:37:54 +0000 Subject: [PATCH 0098/2822] ARM: integrator: add Integrator/CP sched_clock support Integrator/CP has the 24MHz counter which Versatile and later platforms also have, which we use for sched_clock support. Allow this counter to be used when building a kernel targetting Integrator/CP alone. Integrator/AP does not have this counter, so we must exclude support for the Integrator family when this is enabled. Acked-by: Catalin Marinas Signed-off-by: Russell King --- arch/arm/mach-integrator/integrator_cp.c | 7 +++++++ arch/arm/plat-versatile/Kconfig | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/arch/arm/mach-integrator/integrator_cp.c b/arch/arm/mach-integrator/integrator_cp.c index 05da36f754dd9..9e3ce26023e87 100644 --- a/arch/arm/mach-integrator/integrator_cp.c +++ b/arch/arm/mach-integrator/integrator_cp.c @@ -44,6 +44,7 @@ #include #include +#include #include "common.h" @@ -440,11 +441,17 @@ static struct amba_device *amba_devs[] __initdata = { &clcd_device, }; +#define REFCOUNTER (__io_address(INTEGRATOR_HDR_BASE) + 0x28) + static void __init intcp_init_early(void) { clkdev_add_table(cp_lookups, ARRAY_SIZE(cp_lookups)); integrator_init_early(); + +#ifdef CONFIG_PLAT_VERSATILE_SCHED_CLOCK + versatile_sched_clock_init(REFCOUNTER, 24000000); +#endif } static void __init intcp_init(void) diff --git a/arch/arm/plat-versatile/Kconfig b/arch/arm/plat-versatile/Kconfig index 0b275008d3e0b..52353beb369d6 100644 --- a/arch/arm/plat-versatile/Kconfig +++ b/arch/arm/plat-versatile/Kconfig @@ -11,7 +11,7 @@ config PLAT_VERSATILE_LEDS depends on ARCH_REALVIEW || ARCH_VERSATILE config PLAT_VERSATILE_SCHED_CLOCK - def_bool y if !ARCH_INTEGRATOR + def_bool y if !ARCH_INTEGRATOR_AP select HAVE_SCHED_CLOCK endif -- GitLab From 5bc970e803ad2b1f26771f39376a79dbf0f5bf64 Mon Sep 17 00:00:00 2001 From: Sunil Mushran Date: Tue, 28 Dec 2010 23:26:03 -0800 Subject: [PATCH 0099/2822] ocfs2: Use hrtimer to track ocfs2 fs lock stats Patch makes use of the hrtimer to track times in ocfs2 lock stats. The patch is a bit involved to ensure no additional impact on the memory footprint. The size of ocfs2_inode_cache remains 1280 bytes on 32-bit systems. A related change was to modify the unit of the max wait time from nanosec to microsec allowing us to track max time larger than 4 secs. This change necessitated the bumping of the output version in the debugfs file, locking_state, from 2 to 3. Signed-off-by: Sunil Mushran Signed-off-by: Joel Becker --- fs/ocfs2/dlmglue.c | 97 ++++++++++++++++++++++++---------------------- fs/ocfs2/ocfs2.h | 23 ++++++----- 2 files changed, 64 insertions(+), 56 deletions(-) diff --git a/fs/ocfs2/dlmglue.c b/fs/ocfs2/dlmglue.c index e8d94d722ecb8..7484bb9a34388 100644 --- a/fs/ocfs2/dlmglue.c +++ b/fs/ocfs2/dlmglue.c @@ -64,7 +64,7 @@ struct ocfs2_mask_waiter { unsigned long mw_mask; unsigned long mw_goal; #ifdef CONFIG_OCFS2_FS_STATS - unsigned long long mw_lock_start; + ktime_t mw_lock_start; #endif }; @@ -435,44 +435,41 @@ static void ocfs2_remove_lockres_tracking(struct ocfs2_lock_res *res) #ifdef CONFIG_OCFS2_FS_STATS static void ocfs2_init_lock_stats(struct ocfs2_lock_res *res) { - res->l_lock_num_prmode = 0; - res->l_lock_num_prmode_failed = 0; - res->l_lock_total_prmode = 0; - res->l_lock_max_prmode = 0; - res->l_lock_num_exmode = 0; - res->l_lock_num_exmode_failed = 0; - res->l_lock_total_exmode = 0; - res->l_lock_max_exmode = 0; res->l_lock_refresh = 0; + memset(&res->l_lock_prmode, 0, sizeof(struct ocfs2_lock_stats)); + memset(&res->l_lock_exmode, 0, sizeof(struct ocfs2_lock_stats)); } static void ocfs2_update_lock_stats(struct ocfs2_lock_res *res, int level, struct ocfs2_mask_waiter *mw, int ret) { - unsigned long long *num, *sum; - unsigned int *max, *failed; - struct timespec ts = current_kernel_time(); - unsigned long long time = timespec_to_ns(&ts) - mw->mw_lock_start; - - if (level == LKM_PRMODE) { - num = &res->l_lock_num_prmode; - sum = &res->l_lock_total_prmode; - max = &res->l_lock_max_prmode; - failed = &res->l_lock_num_prmode_failed; - } else if (level == LKM_EXMODE) { - num = &res->l_lock_num_exmode; - sum = &res->l_lock_total_exmode; - max = &res->l_lock_max_exmode; - failed = &res->l_lock_num_exmode_failed; - } else + u32 usec; + ktime_t kt; + struct ocfs2_lock_stats *stats; + + if (level == LKM_PRMODE) + stats = &res->l_lock_prmode; + else if (level == LKM_EXMODE) + stats = &res->l_lock_exmode; + else return; - (*num)++; - (*sum) += time; - if (time > *max) - *max = time; + kt = ktime_sub(ktime_get(), mw->mw_lock_start); + usec = ktime_to_us(kt); + + stats->ls_gets++; + stats->ls_total += ktime_to_ns(kt); + /* overflow */ + if (unlikely(stats->ls_gets) == 0) { + stats->ls_gets++; + stats->ls_total = ktime_to_ns(kt); + } + + if (stats->ls_max < usec) + stats->ls_max = usec; + if (ret) - (*failed)++; + stats->ls_fail++; } static inline void ocfs2_track_lock_refresh(struct ocfs2_lock_res *lockres) @@ -482,8 +479,7 @@ static inline void ocfs2_track_lock_refresh(struct ocfs2_lock_res *lockres) static inline void ocfs2_init_start_time(struct ocfs2_mask_waiter *mw) { - struct timespec ts = current_kernel_time(); - mw->mw_lock_start = timespec_to_ns(&ts); + mw->mw_lock_start = ktime_get(); } #else static inline void ocfs2_init_lock_stats(struct ocfs2_lock_res *res) @@ -2869,8 +2865,15 @@ static void *ocfs2_dlm_seq_next(struct seq_file *m, void *v, loff_t *pos) return iter; } -/* So that debugfs.ocfs2 can determine which format is being used */ -#define OCFS2_DLM_DEBUG_STR_VERSION 2 +/* + * Version is used by debugfs.ocfs2 to determine the format being used + * + * New in version 2 + * - Lock stats printed + * New in version 3 + * - Max time in lock stats is in usecs (instead of nsecs) + */ +#define OCFS2_DLM_DEBUG_STR_VERSION 3 static int ocfs2_dlm_seq_show(struct seq_file *m, void *v) { int i; @@ -2912,18 +2915,18 @@ static int ocfs2_dlm_seq_show(struct seq_file *m, void *v) seq_printf(m, "0x%x\t", lvb[i]); #ifdef CONFIG_OCFS2_FS_STATS -# define lock_num_prmode(_l) (_l)->l_lock_num_prmode -# define lock_num_exmode(_l) (_l)->l_lock_num_exmode -# define lock_num_prmode_failed(_l) (_l)->l_lock_num_prmode_failed -# define lock_num_exmode_failed(_l) (_l)->l_lock_num_exmode_failed -# define lock_total_prmode(_l) (_l)->l_lock_total_prmode -# define lock_total_exmode(_l) (_l)->l_lock_total_exmode -# define lock_max_prmode(_l) (_l)->l_lock_max_prmode -# define lock_max_exmode(_l) (_l)->l_lock_max_exmode -# define lock_refresh(_l) (_l)->l_lock_refresh +# define lock_num_prmode(_l) ((_l)->l_lock_prmode.ls_gets) +# define lock_num_exmode(_l) ((_l)->l_lock_exmode.ls_gets) +# define lock_num_prmode_failed(_l) ((_l)->l_lock_prmode.ls_fail) +# define lock_num_exmode_failed(_l) ((_l)->l_lock_exmode.ls_fail) +# define lock_total_prmode(_l) ((_l)->l_lock_prmode.ls_total) +# define lock_total_exmode(_l) ((_l)->l_lock_exmode.ls_total) +# define lock_max_prmode(_l) ((_l)->l_lock_prmode.ls_max) +# define lock_max_exmode(_l) ((_l)->l_lock_exmode.ls_max) +# define lock_refresh(_l) ((_l)->l_lock_refresh) #else -# define lock_num_prmode(_l) (0ULL) -# define lock_num_exmode(_l) (0ULL) +# define lock_num_prmode(_l) (0) +# define lock_num_exmode(_l) (0) # define lock_num_prmode_failed(_l) (0) # define lock_num_exmode_failed(_l) (0) # define lock_total_prmode(_l) (0ULL) @@ -2933,8 +2936,8 @@ static int ocfs2_dlm_seq_show(struct seq_file *m, void *v) # define lock_refresh(_l) (0) #endif /* The following seq_print was added in version 2 of this output */ - seq_printf(m, "%llu\t" - "%llu\t" + seq_printf(m, "%u\t" + "%u\t" "%u\t" "%u\t" "%llu\t" diff --git a/fs/ocfs2/ocfs2.h b/fs/ocfs2/ocfs2.h index 51cd6898e7f1c..4e3d3c1363f3f 100644 --- a/fs/ocfs2/ocfs2.h +++ b/fs/ocfs2/ocfs2.h @@ -147,6 +147,17 @@ struct ocfs2_lock_res_ops; typedef void (*ocfs2_lock_callback)(int status, unsigned long data); +#ifdef CONFIG_OCFS2_FS_STATS +struct ocfs2_lock_stats { + u64 ls_total; /* Total wait in NSEC */ + u32 ls_gets; /* Num acquires */ + u32 ls_fail; /* Num failed acquires */ + + /* Storing max wait in usecs saves 24 bytes per inode */ + u32 ls_max; /* Max wait in USEC */ +}; +#endif + struct ocfs2_lock_res { void *l_priv; struct ocfs2_lock_res_ops *l_ops; @@ -182,15 +193,9 @@ struct ocfs2_lock_res { struct list_head l_debug_list; #ifdef CONFIG_OCFS2_FS_STATS - unsigned long long l_lock_num_prmode; /* PR acquires */ - unsigned long long l_lock_num_exmode; /* EX acquires */ - unsigned int l_lock_num_prmode_failed; /* Failed PR gets */ - unsigned int l_lock_num_exmode_failed; /* Failed EX gets */ - unsigned long long l_lock_total_prmode; /* Tot wait for PR */ - unsigned long long l_lock_total_exmode; /* Tot wait for EX */ - unsigned int l_lock_max_prmode; /* Max wait for PR */ - unsigned int l_lock_max_exmode; /* Max wait for EX */ - unsigned int l_lock_refresh; /* Disk refreshes */ + struct ocfs2_lock_stats l_lock_prmode; /* PR mode stats */ + u32 l_lock_refresh; /* Disk refreshes */ + struct ocfs2_lock_stats l_lock_exmode; /* EX mode stats */ #endif #ifdef CONFIG_DEBUG_LOCK_ALLOC struct lockdep_map l_lockdep_map; -- GitLab From 1dd9ffc827b8591aabcf5fea6ea83b69e846deb9 Mon Sep 17 00:00:00 2001 From: Tao Ma Date: Mon, 24 Jan 2011 23:23:30 +0800 Subject: [PATCH 0100/2822] ocfs2: optimize ocfs2_check_dir_entry() with unlikely() annotations In cad3f00, ext4_check_dir_entry was modified by adding some unlikely. Ted described it as "This function gets called a lot for large directories, and the answer is almost always 'no, no, there's no problem'. This means using unlikely() is a good thing." ext3 added the similar change in commit a4ae309. So change it accordingly in ocfs2. Cc: Joel Becker Signed-off-by: Tao Ma Signed-off-by: Joel Becker --- fs/ocfs2/dir.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/fs/ocfs2/dir.c b/fs/ocfs2/dir.c index d417b3f9b0c73..41b356fefaa55 100644 --- a/fs/ocfs2/dir.c +++ b/fs/ocfs2/dir.c @@ -322,21 +322,23 @@ static int ocfs2_check_dir_entry(struct inode * dir, const char *error_msg = NULL; const int rlen = le16_to_cpu(de->rec_len); - if (rlen < OCFS2_DIR_REC_LEN(1)) + if (unlikely(rlen < OCFS2_DIR_REC_LEN(1))) error_msg = "rec_len is smaller than minimal"; - else if (rlen % 4 != 0) + else if (unlikely(rlen % 4 != 0)) error_msg = "rec_len % 4 != 0"; - else if (rlen < OCFS2_DIR_REC_LEN(de->name_len)) + else if (unlikely(rlen < OCFS2_DIR_REC_LEN(de->name_len))) error_msg = "rec_len is too small for name_len"; - else if (((char *) de - bh->b_data) + rlen > dir->i_sb->s_blocksize) + else if (unlikely( + ((char *) de - bh->b_data) + rlen > dir->i_sb->s_blocksize)) error_msg = "directory entry across blocks"; - if (error_msg != NULL) + if (unlikely(error_msg != NULL)) mlog(ML_ERROR, "bad entry in directory #%llu: %s - " "offset=%lu, inode=%llu, rec_len=%d, name_len=%d\n", (unsigned long long)OCFS2_I(dir)->ip_blkno, error_msg, offset, (unsigned long long)le64_to_cpu(de->inode), rlen, de->name_len); + return error_msg == NULL ? 1 : 0; } -- GitLab From 1936a267f1b5a32d4a846608fdcce82ca0f6ac8e Mon Sep 17 00:00:00 2001 From: Tristan Ye Date: Sun, 30 Jan 2011 14:25:59 +0800 Subject: [PATCH 0101/2822] Ocfs2: Using macro to set/clear *FILLED* flags in info handler. It's a best-effort attempt to simplize duplicated codes here. Signed-off-by: Tristan Ye Signed-off-by: Joel Becker --- fs/ocfs2/ioctl.c | 38 ++++++++++++++++++++++++++++++-------- 1 file changed, 30 insertions(+), 8 deletions(-) diff --git a/fs/ocfs2/ioctl.c b/fs/ocfs2/ioctl.c index 7a48681961521..731cf4670b97f 100644 --- a/fs/ocfs2/ioctl.c +++ b/fs/ocfs2/ioctl.c @@ -46,6 +46,22 @@ static inline void __o2info_set_request_error(struct ocfs2_info_request *kreq, #define o2info_set_request_error(a, b) \ __o2info_set_request_error((struct ocfs2_info_request *)&(a), b) +static inline void __o2info_set_request_filled(struct ocfs2_info_request *req) +{ + req->ir_flags |= OCFS2_INFO_FL_FILLED; +} + +#define o2info_set_request_filled(a) \ + __o2info_set_request_filled((struct ocfs2_info_request *)&(a)) + +static inline void __o2info_clear_request_filled(struct ocfs2_info_request *req) +{ + req->ir_flags &= ~OCFS2_INFO_FL_FILLED; +} + +#define o2info_clear_request_filled(a) \ + __o2info_clear_request_filled((struct ocfs2_info_request *)&(a)) + static int ocfs2_get_inode_attr(struct inode *inode, unsigned *flags) { int status; @@ -139,7 +155,8 @@ int ocfs2_info_handle_blocksize(struct inode *inode, goto bail; oib.ib_blocksize = inode->i_sb->s_blocksize; - oib.ib_req.ir_flags |= OCFS2_INFO_FL_FILLED; + + o2info_set_request_filled(oib); if (o2info_to_user(oib, req)) goto bail; @@ -163,7 +180,8 @@ int ocfs2_info_handle_clustersize(struct inode *inode, goto bail; oic.ic_clustersize = osb->s_clustersize; - oic.ic_req.ir_flags |= OCFS2_INFO_FL_FILLED; + + o2info_set_request_filled(oic); if (o2info_to_user(oic, req)) goto bail; @@ -187,7 +205,8 @@ int ocfs2_info_handle_maxslots(struct inode *inode, goto bail; oim.im_max_slots = osb->max_slots; - oim.im_req.ir_flags |= OCFS2_INFO_FL_FILLED; + + o2info_set_request_filled(oim); if (o2info_to_user(oim, req)) goto bail; @@ -211,7 +230,8 @@ int ocfs2_info_handle_label(struct inode *inode, goto bail; memcpy(oil.il_label, osb->vol_label, OCFS2_MAX_VOL_LABEL_LEN); - oil.il_req.ir_flags |= OCFS2_INFO_FL_FILLED; + + o2info_set_request_filled(oil); if (o2info_to_user(oil, req)) goto bail; @@ -235,7 +255,8 @@ int ocfs2_info_handle_uuid(struct inode *inode, goto bail; memcpy(oiu.iu_uuid_str, osb->uuid_str, OCFS2_TEXT_UUID_LEN + 1); - oiu.iu_req.ir_flags |= OCFS2_INFO_FL_FILLED; + + o2info_set_request_filled(oiu); if (o2info_to_user(oiu, req)) goto bail; @@ -261,7 +282,8 @@ int ocfs2_info_handle_fs_features(struct inode *inode, oif.if_compat_features = osb->s_feature_compat; oif.if_incompat_features = osb->s_feature_incompat; oif.if_ro_compat_features = osb->s_feature_ro_compat; - oif.if_req.ir_flags |= OCFS2_INFO_FL_FILLED; + + o2info_set_request_filled(oif); if (o2info_to_user(oif, req)) goto bail; @@ -286,7 +308,7 @@ int ocfs2_info_handle_journal_size(struct inode *inode, oij.ij_journal_size = osb->journal->j_inode->i_size; - oij.ij_req.ir_flags |= OCFS2_INFO_FL_FILLED; + o2info_set_request_filled(oij); if (o2info_to_user(oij, req)) goto bail; @@ -308,7 +330,7 @@ int ocfs2_info_handle_unknown(struct inode *inode, if (o2info_from_user(oir, req)) goto bail; - oir.ir_flags &= ~OCFS2_INFO_FL_FILLED; + o2info_clear_request_filled(oir); if (o2info_to_user(oir, req)) goto bail; -- GitLab From ef6b689b63b9f5227ccee6f16dd9ee3faf58a464 Mon Sep 17 00:00:00 2001 From: Tao Ma Date: Mon, 21 Feb 2011 11:10:44 +0800 Subject: [PATCH 0102/2822] ocfs2: Remove ENTRY from masklog. ENTRY is used to record the entry of a function. But because it is added in so many functions, if we enable it, the system logs get filled up quickly and cause too much I/O. So actually no one can open it for a production system or even for a test. So for mlog_entry_void, we just remove it. for mlog_entry(...), we replace it with mlog(0,...), and they will be replace by trace event later. Signed-off-by: Tao Ma --- fs/ocfs2/alloc.c | 28 +------------ fs/ocfs2/aops.c | 16 ++++---- fs/ocfs2/buffer_head_io.c | 10 ++--- fs/ocfs2/cluster/heartbeat.c | 2 - fs/ocfs2/cluster/masklog.c | 1 - fs/ocfs2/cluster/masklog.h | 13 +----- fs/ocfs2/dcache.c | 4 +- fs/ocfs2/dir.c | 20 +++------ fs/ocfs2/dlm/dlmconvert.c | 6 +-- fs/ocfs2/dlm/dlmdomain.c | 8 ++-- fs/ocfs2/dlm/dlmlock.c | 10 ++--- fs/ocfs2/dlm/dlmmaster.c | 6 +-- fs/ocfs2/dlm/dlmrecovery.c | 4 -- fs/ocfs2/dlm/dlmunlock.c | 4 +- fs/ocfs2/dlmglue.c | 78 ------------------------------------ fs/ocfs2/export.c | 12 +++--- fs/ocfs2/extent_map.c | 8 ++-- fs/ocfs2/file.c | 73 +++++++++++++++------------------ fs/ocfs2/inode.c | 28 +++++-------- fs/ocfs2/journal.c | 43 ++++++-------------- fs/ocfs2/localalloc.c | 26 +++--------- fs/ocfs2/mmap.c | 2 +- fs/ocfs2/namei.c | 74 ++++++++++++++++------------------ fs/ocfs2/quota_global.c | 14 +++---- fs/ocfs2/quota_local.c | 2 +- fs/ocfs2/resize.c | 8 +--- fs/ocfs2/slot_map.c | 2 - fs/ocfs2/suballoc.c | 35 +++------------- fs/ocfs2/super.c | 32 +++------------ fs/ocfs2/symlink.c | 6 --- fs/ocfs2/xattr.c | 4 +- 31 files changed, 161 insertions(+), 418 deletions(-) diff --git a/fs/ocfs2/alloc.c b/fs/ocfs2/alloc.c index e4984e259cb6b..47a6ce84e67f3 100644 --- a/fs/ocfs2/alloc.c +++ b/fs/ocfs2/alloc.c @@ -965,8 +965,6 @@ int ocfs2_num_free_extents(struct ocfs2_super *osb, struct buffer_head *eb_bh = NULL; u64 last_eb_blk = 0; - mlog_entry_void(); - el = et->et_root_el; last_eb_blk = ocfs2_et_get_last_eb_blk(et); @@ -1010,8 +1008,6 @@ static int ocfs2_create_new_meta_bhs(handle_t *handle, OCFS2_SB(ocfs2_metadata_cache_get_super(et->et_ci)); struct ocfs2_extent_block *eb; - mlog_entry_void(); - count = 0; while (count < wanted) { status = ocfs2_claim_metadata(handle, @@ -1173,8 +1169,6 @@ static int ocfs2_add_branch(handle_t *handle, struct ocfs2_extent_list *el; u32 new_cpos, root_end; - mlog_entry_void(); - BUG_ON(!last_eb_bh || !*last_eb_bh); if (eb_bh) { @@ -1353,8 +1347,6 @@ static int ocfs2_shift_tree_depth(handle_t *handle, struct ocfs2_extent_list *root_el; struct ocfs2_extent_list *eb_el; - mlog_entry_void(); - status = ocfs2_create_new_meta_bhs(handle, et, 1, meta_ac, &new_eb_bh); if (status < 0) { @@ -1446,8 +1438,6 @@ static int ocfs2_find_branch_target(struct ocfs2_extent_tree *et, struct buffer_head *bh = NULL; struct buffer_head *lowest_bh = NULL; - mlog_entry_void(); - *target_bh = NULL; el = et->et_root_el; @@ -5795,8 +5785,8 @@ int ocfs2_truncate_log_append(struct ocfs2_super *osb, struct ocfs2_dinode *di; struct ocfs2_truncate_log *tl; - mlog_entry("start_blk = %llu, num_clusters = %u\n", - (unsigned long long)start_blk, num_clusters); + mlog(0, "start_blk = %llu, num_clusters = %u\n", + (unsigned long long)start_blk, num_clusters); BUG_ON(mutex_trylock(&tl_inode->i_mutex)); @@ -5878,8 +5868,6 @@ static int ocfs2_replay_truncate_records(struct ocfs2_super *osb, struct inode *tl_inode = osb->osb_tl_inode; struct buffer_head *tl_bh = osb->osb_tl_bh; - mlog_entry_void(); - di = (struct ocfs2_dinode *) tl_bh->b_data; tl = &di->id2.i_dealloc; i = le16_to_cpu(tl->tl_used) - 1; @@ -5949,8 +5937,6 @@ int __ocfs2_flush_truncate_log(struct ocfs2_super *osb) struct ocfs2_dinode *di; struct ocfs2_truncate_log *tl; - mlog_entry_void(); - BUG_ON(mutex_trylock(&tl_inode->i_mutex)); di = (struct ocfs2_dinode *) tl_bh->b_data; @@ -6032,8 +6018,6 @@ static void ocfs2_truncate_log_worker(struct work_struct *work) container_of(work, struct ocfs2_super, osb_truncate_log_wq.work); - mlog_entry_void(); - status = ocfs2_flush_truncate_log(osb); if (status < 0) mlog_errno(status); @@ -6174,8 +6158,6 @@ int ocfs2_complete_truncate_log_recovery(struct ocfs2_super *osb, struct inode *tl_inode = osb->osb_tl_inode; struct ocfs2_truncate_log *tl; - mlog_entry_void(); - if (OCFS2_I(tl_inode)->ip_blkno == le64_to_cpu(tl_copy->i_blkno)) { mlog(ML_ERROR, "Asked to recover my own truncate log!\n"); return -EINVAL; @@ -6228,8 +6210,6 @@ void ocfs2_truncate_log_shutdown(struct ocfs2_super *osb) int status; struct inode *tl_inode = osb->osb_tl_inode; - mlog_entry_void(); - if (tl_inode) { cancel_delayed_work(&osb->osb_truncate_log_wq); flush_workqueue(ocfs2_wq); @@ -6251,8 +6231,6 @@ int ocfs2_truncate_log_init(struct ocfs2_super *osb) struct inode *tl_inode = NULL; struct buffer_head *tl_bh = NULL; - mlog_entry_void(); - status = ocfs2_get_truncate_log_info(osb, osb->slot_num, &tl_inode, @@ -7005,8 +6983,6 @@ int ocfs2_commit_truncate(struct ocfs2_super *osb, struct ocfs2_extent_tree et; struct ocfs2_cached_dealloc_ctxt dealloc; - mlog_entry_void(); - ocfs2_init_dinode_extent_tree(&et, INODE_CACHE(inode), di_bh); ocfs2_init_dealloc_ctxt(&dealloc); diff --git a/fs/ocfs2/aops.c b/fs/ocfs2/aops.c index 1fbb0e20131bf..5dbfc9e45195c 100644 --- a/fs/ocfs2/aops.c +++ b/fs/ocfs2/aops.c @@ -59,8 +59,8 @@ static int ocfs2_symlink_get_block(struct inode *inode, sector_t iblock, struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); void *kaddr; - mlog_entry("(0x%p, %llu, 0x%p, %d)\n", inode, - (unsigned long long)iblock, bh_result, create); + mlog(0, "(0x%p, %llu, 0x%p, %d)\n", inode, + (unsigned long long)iblock, bh_result, create); BUG_ON(ocfs2_inode_is_fast_symlink(inode)); @@ -136,8 +136,8 @@ int ocfs2_get_block(struct inode *inode, sector_t iblock, u64 p_blkno, count, past_eof; struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); - mlog_entry("(0x%p, %llu, 0x%p, %d)\n", inode, - (unsigned long long)iblock, bh_result, create); + mlog(0, "(0x%p, %llu, 0x%p, %d)\n", inode, + (unsigned long long)iblock, bh_result, create); if (OCFS2_I(inode)->ip_flags & OCFS2_INODE_SYSTEM_FILE) mlog(ML_NOTICE, "get_block on system inode 0x%p (%lu)\n", @@ -278,7 +278,7 @@ static int ocfs2_readpage(struct file *file, struct page *page) loff_t start = (loff_t)page->index << PAGE_CACHE_SHIFT; int ret, unlock = 1; - mlog_entry("(0x%p, %lu)\n", file, (page ? page->index : 0)); + mlog(0, "(0x%p, %lu)\n", file, (page ? page->index : 0)); ret = ocfs2_inode_lock_with_page(inode, NULL, 0, page); if (ret != 0) { @@ -398,7 +398,7 @@ static int ocfs2_writepage(struct page *page, struct writeback_control *wbc) { int ret; - mlog_entry("(0x%p)\n", page); + mlog(0, "(0x%p)\n", page); ret = block_write_full_page(page, ocfs2_get_block, wbc); @@ -450,7 +450,7 @@ static sector_t ocfs2_bmap(struct address_space *mapping, sector_t block) int err = 0; struct inode *inode = mapping->host; - mlog_entry("(block = %llu)\n", (unsigned long long)block); + mlog(0, "(block = %llu)\n", (unsigned long long)block); /* We don't need to lock journal system files, since they aren't * accessed concurrently from multiple nodes. @@ -618,8 +618,6 @@ static ssize_t ocfs2_direct_IO(int rw, struct inode *inode = file->f_path.dentry->d_inode->i_mapping->host; int ret; - mlog_entry_void(); - /* * Fallback to buffered I/O if we see an inode without * extents. diff --git a/fs/ocfs2/buffer_head_io.c b/fs/ocfs2/buffer_head_io.c index f9d5d3ffc75a9..024bd45b7a48d 100644 --- a/fs/ocfs2/buffer_head_io.c +++ b/fs/ocfs2/buffer_head_io.c @@ -55,8 +55,8 @@ int ocfs2_write_block(struct ocfs2_super *osb, struct buffer_head *bh, { int ret = 0; - mlog_entry("(bh->b_blocknr = %llu, ci=%p)\n", - (unsigned long long)bh->b_blocknr, ci); + mlog(0, "(bh->b_blocknr = %llu, ci=%p)\n", + (unsigned long long)bh->b_blocknr, ci); BUG_ON(bh->b_blocknr < OCFS2_SUPER_BLOCK_BLKNO); BUG_ON(buffer_jbd(bh)); @@ -186,8 +186,8 @@ int ocfs2_read_blocks(struct ocfs2_caching_info *ci, u64 block, int nr, struct buffer_head *bh; struct super_block *sb = ocfs2_metadata_cache_get_super(ci); - mlog_entry("(ci=%p, block=(%llu), nr=(%d), flags=%d)\n", - ci, (unsigned long long)block, nr, flags); + mlog(0, "(ci=%p, block=(%llu), nr=(%d), flags=%d)\n", + ci, (unsigned long long)block, nr, flags); BUG_ON(!ci); BUG_ON((flags & OCFS2_BH_READAHEAD) && @@ -408,8 +408,6 @@ int ocfs2_write_super_or_backup(struct ocfs2_super *osb, int ret = 0; struct ocfs2_dinode *di = (struct ocfs2_dinode *)bh->b_data; - mlog_entry_void(); - BUG_ON(buffer_jbd(bh)); ocfs2_check_super_or_backup(osb->sb, bh->b_blocknr); diff --git a/fs/ocfs2/cluster/heartbeat.c b/fs/ocfs2/cluster/heartbeat.c index b108e863d8f65..929178ce17a23 100644 --- a/fs/ocfs2/cluster/heartbeat.c +++ b/fs/ocfs2/cluster/heartbeat.c @@ -1658,8 +1658,6 @@ static int o2hb_populate_slot_data(struct o2hb_region *reg) struct o2hb_disk_slot *slot; struct o2hb_disk_heartbeat_block *hb_block; - mlog_entry_void(); - ret = o2hb_read_slots(reg, reg->hr_blocks); if (ret) { mlog_errno(ret); diff --git a/fs/ocfs2/cluster/masklog.c b/fs/ocfs2/cluster/masklog.c index 6c61771469af2..bac64570c5259 100644 --- a/fs/ocfs2/cluster/masklog.c +++ b/fs/ocfs2/cluster/masklog.c @@ -80,7 +80,6 @@ struct mlog_attribute { } static struct mlog_attribute mlog_attrs[MLOG_MAX_BITS] = { - define_mask(ENTRY), define_mask(EXIT), define_mask(TCP), define_mask(MSG), diff --git a/fs/ocfs2/cluster/masklog.h b/fs/ocfs2/cluster/masklog.h index 34d6544357d97..6e20877436b94 100644 --- a/fs/ocfs2/cluster/masklog.h +++ b/fs/ocfs2/cluster/masklog.h @@ -82,7 +82,6 @@ /* bits that are frequently given and infrequently matched in the low word */ /* NOTE: If you add a flag, you need to also update masklog.c! */ -#define ML_ENTRY 0x0000000000000001ULL /* func call entry */ #define ML_EXIT 0x0000000000000002ULL /* func call exit */ #define ML_TCP 0x0000000000000004ULL /* net cluster/tcp.c */ #define ML_MSG 0x0000000000000008ULL /* net network messages */ @@ -124,7 +123,7 @@ #define ML_KTHREAD 0x4000000000000000ULL /* kernel thread activity */ #define MLOG_INITIAL_AND_MASK (ML_ERROR|ML_NOTICE) -#define MLOG_INITIAL_NOT_MASK (ML_ENTRY|ML_EXIT) +#define MLOG_INITIAL_NOT_MASK (ML_EXIT) #ifndef MLOG_MASK_PREFIX #define MLOG_MASK_PREFIX 0 #endif @@ -223,14 +222,6 @@ extern struct mlog_bits mlog_and_bits, mlog_not_bits; } while (0) #if defined(CONFIG_OCFS2_DEBUG_MASKLOG) -#define mlog_entry(fmt, args...) do { \ - mlog(ML_ENTRY, "ENTRY:" fmt , ##args); \ -} while (0) - -#define mlog_entry_void() do { \ - mlog(ML_ENTRY, "ENTRY:\n"); \ -} while (0) - /* * We disable this for sparse. */ @@ -267,8 +258,6 @@ extern struct mlog_bits mlog_and_bits, mlog_not_bits; mlog(ML_EXIT, "EXIT\n"); \ } while (0) #else -#define mlog_entry(...) do { } while (0) -#define mlog_entry_void(...) do { } while (0) #define mlog_exit(...) do { } while (0) #define mlog_exit_ptr(...) do { } while (0) #define mlog_exit_void(...) do { } while (0) diff --git a/fs/ocfs2/dcache.c b/fs/ocfs2/dcache.c index 7eb90403fc8af..67d17a45773b0 100644 --- a/fs/ocfs2/dcache.c +++ b/fs/ocfs2/dcache.c @@ -62,8 +62,8 @@ static int ocfs2_dentry_revalidate(struct dentry *dentry, inode = dentry->d_inode; osb = OCFS2_SB(dentry->d_sb); - mlog_entry("(0x%p, '%.*s')\n", dentry, - dentry->d_name.len, dentry->d_name.name); + mlog(0, "(0x%p, '%.*s')\n", dentry, + dentry->d_name.len, dentry->d_name.name); /* For a negative dentry - * check the generation number of the parent and compare with the diff --git a/fs/ocfs2/dir.c b/fs/ocfs2/dir.c index d417b3f9b0c73..2c983f083f8ac 100644 --- a/fs/ocfs2/dir.c +++ b/fs/ocfs2/dir.c @@ -367,8 +367,6 @@ static int inline ocfs2_search_dirblock(struct buffer_head *bh, int de_len; int ret = 0; - mlog_entry_void(); - de_buf = first_de; dlimit = de_buf + bytes; @@ -706,8 +704,6 @@ static struct buffer_head *ocfs2_find_entry_el(const char *name, int namelen, int num = 0; int nblocks, i, err; - mlog_entry_void(); - sb = dir->i_sb; nblocks = i_size_read(dir) >> sb->s_blocksize_bits; @@ -1166,7 +1162,7 @@ static int __ocfs2_delete_entry(handle_t *handle, struct inode *dir, int i, status = -ENOENT; ocfs2_journal_access_func access = ocfs2_journal_access_db; - mlog_entry("(0x%p, 0x%p, 0x%p, 0x%p)\n", handle, dir, de_del, bh); + mlog(0, "(0x%p, 0x%p, 0x%p, 0x%p)\n", handle, dir, de_del, bh); if (OCFS2_I(dir)->ip_dyn_features & OCFS2_INLINE_DATA_FL) access = ocfs2_journal_access_di; @@ -1632,8 +1628,6 @@ int __ocfs2_add_entry(handle_t *handle, struct buffer_head *insert_bh = lookup->dl_leaf_bh; char *data_start = insert_bh->b_data; - mlog_entry_void(); - if (!namelen) return -EINVAL; @@ -2028,8 +2022,8 @@ int ocfs2_readdir(struct file * filp, void * dirent, filldir_t filldir) struct inode *inode = filp->f_path.dentry->d_inode; int lock_level = 0; - mlog_entry("dirino=%llu\n", - (unsigned long long)OCFS2_I(inode)->ip_blkno); + mlog(0, "dirino=%llu\n", + (unsigned long long)OCFS2_I(inode)->ip_blkno); error = ocfs2_inode_lock_atime(inode, filp->f_vfsmnt, &lock_level); if (lock_level && error >= 0) { @@ -2114,8 +2108,8 @@ int ocfs2_check_dir_for_entry(struct inode *dir, int ret; struct ocfs2_dir_lookup_result lookup = { NULL, }; - mlog_entry("dir %llu, name '%.*s'\n", - (unsigned long long)OCFS2_I(dir)->ip_blkno, namelen, name); + mlog(0, "dir %llu, name '%.*s'\n", + (unsigned long long)OCFS2_I(dir)->ip_blkno, namelen, name); ret = -EEXIST; if (ocfs2_find_entry(name, namelen, dir, &lookup) == 0) @@ -2324,8 +2318,6 @@ static int ocfs2_fill_new_dir_el(struct ocfs2_super *osb, struct buffer_head *new_bh = NULL; struct ocfs2_dir_entry *de; - mlog_entry_void(); - if (ocfs2_new_dir_wants_trailer(inode)) size = ocfs2_dir_trailer_blk_off(parent->i_sb); @@ -3270,8 +3262,6 @@ static int ocfs2_extend_dir(struct ocfs2_super *osb, struct ocfs2_extent_tree et; struct buffer_head *dx_root_bh = lookup->dl_dx_root_bh; - mlog_entry_void(); - if (OCFS2_I(dir)->ip_dyn_features & OCFS2_INLINE_DATA_FL) { /* * This would be a code error as an inline directory should diff --git a/fs/ocfs2/dlm/dlmconvert.c b/fs/ocfs2/dlm/dlmconvert.c index 9f30491e5e88a..29a886d1e82c8 100644 --- a/fs/ocfs2/dlm/dlmconvert.c +++ b/fs/ocfs2/dlm/dlmconvert.c @@ -128,8 +128,8 @@ static enum dlm_status __dlmconvert_master(struct dlm_ctxt *dlm, assert_spin_locked(&res->spinlock); - mlog_entry("type=%d, convert_type=%d, new convert_type=%d\n", - lock->ml.type, lock->ml.convert_type, type); + mlog(0, "type=%d, convert_type=%d, new convert_type=%d\n", + lock->ml.type, lock->ml.convert_type, type); spin_lock(&lock->spinlock); @@ -353,7 +353,7 @@ static enum dlm_status dlm_send_remote_convert_request(struct dlm_ctxt *dlm, struct kvec vec[2]; size_t veclen = 1; - mlog_entry("%.*s\n", res->lockname.len, res->lockname.name); + mlog(0, "%.*s\n", res->lockname.len, res->lockname.name); memset(&convert, 0, sizeof(struct dlm_convert_lock)); convert.node_idx = dlm->node_num; diff --git a/fs/ocfs2/dlm/dlmdomain.c b/fs/ocfs2/dlm/dlmdomain.c index 7e38a072d7202..5391f28d940b3 100644 --- a/fs/ocfs2/dlm/dlmdomain.c +++ b/fs/ocfs2/dlm/dlmdomain.c @@ -188,7 +188,7 @@ struct dlm_lock_resource * __dlm_lookup_lockres_full(struct dlm_ctxt *dlm, struct hlist_head *bucket; struct hlist_node *list; - mlog_entry("%.*s\n", len, name); + mlog(0, "%.*s\n", len, name); assert_spin_locked(&dlm->spinlock); @@ -222,7 +222,7 @@ struct dlm_lock_resource * __dlm_lookup_lockres(struct dlm_ctxt *dlm, { struct dlm_lock_resource *res = NULL; - mlog_entry("%.*s\n", len, name); + mlog(0, "%.*s\n", len, name); assert_spin_locked(&dlm->spinlock); @@ -531,7 +531,7 @@ static int dlm_exit_domain_handler(struct o2net_msg *msg, u32 len, void *data, unsigned int node; struct dlm_exit_domain *exit_msg = (struct dlm_exit_domain *) msg->buf; - mlog_entry("%p %u %p", msg, len, data); + mlog(0, "%p %u %p", msg, len, data); if (!dlm_grab(dlm)) return 0; @@ -1553,7 +1553,7 @@ static int dlm_try_to_join_domain(struct dlm_ctxt *dlm) struct domain_join_ctxt *ctxt; enum dlm_query_join_response_code response = JOIN_DISALLOW; - mlog_entry("%p", dlm); + mlog(0, "%p", dlm); ctxt = kzalloc(sizeof(*ctxt), GFP_KERNEL); if (!ctxt) { diff --git a/fs/ocfs2/dlm/dlmlock.c b/fs/ocfs2/dlm/dlmlock.c index 7009292aac5ad..8d39e0fd66f73 100644 --- a/fs/ocfs2/dlm/dlmlock.c +++ b/fs/ocfs2/dlm/dlmlock.c @@ -128,7 +128,7 @@ static enum dlm_status dlmlock_master(struct dlm_ctxt *dlm, int call_ast = 0, kick_thread = 0; enum dlm_status status = DLM_NORMAL; - mlog_entry("type=%d\n", lock->ml.type); + mlog(0, "type=%d\n", lock->ml.type); spin_lock(&res->spinlock); /* if called from dlm_create_lock_handler, need to @@ -227,8 +227,8 @@ static enum dlm_status dlmlock_remote(struct dlm_ctxt *dlm, enum dlm_status status = DLM_DENIED; int lockres_changed = 1; - mlog_entry("type=%d\n", lock->ml.type); - mlog(0, "lockres %.*s, flags = 0x%x\n", res->lockname.len, + mlog(0, "type=%d, lockres %.*s, flags = 0x%x\n", + lock->ml.type, res->lockname.len, res->lockname.name, flags); spin_lock(&res->spinlock); @@ -308,8 +308,6 @@ static enum dlm_status dlm_send_remote_lock_request(struct dlm_ctxt *dlm, int tmpret, status = 0; enum dlm_status ret; - mlog_entry_void(); - memset(&create, 0, sizeof(create)); create.node_idx = dlm->node_num; create.requested_type = lock->ml.type; @@ -477,8 +475,6 @@ int dlm_create_lock_handler(struct o2net_msg *msg, u32 len, void *data, BUG_ON(!dlm); - mlog_entry_void(); - if (!dlm_grab(dlm)) return DLM_REJECTED; diff --git a/fs/ocfs2/dlm/dlmmaster.c b/fs/ocfs2/dlm/dlmmaster.c index 59f0f6bdfc621..9d67610dfc74f 100644 --- a/fs/ocfs2/dlm/dlmmaster.c +++ b/fs/ocfs2/dlm/dlmmaster.c @@ -426,8 +426,6 @@ static void dlm_mle_release(struct kref *kref) struct dlm_master_list_entry *mle; struct dlm_ctxt *dlm; - mlog_entry_void(); - mle = container_of(kref, struct dlm_master_list_entry, mle_refs); dlm = mle->dlm; @@ -3120,8 +3118,6 @@ static int dlm_add_migration_mle(struct dlm_ctxt *dlm, *oldmle = NULL; - mlog_entry_void(); - assert_spin_locked(&dlm->spinlock); assert_spin_locked(&dlm->master_lock); @@ -3261,7 +3257,7 @@ void dlm_clean_master_list(struct dlm_ctxt *dlm, u8 dead_node) struct hlist_node *list; unsigned int i; - mlog_entry("dlm=%s, dead node=%u\n", dlm->name, dead_node); + mlog(0, "dlm=%s, dead node=%u\n", dlm->name, dead_node); top: assert_spin_locked(&dlm->spinlock); diff --git a/fs/ocfs2/dlm/dlmrecovery.c b/fs/ocfs2/dlm/dlmrecovery.c index aaaffbcbe9163..6602b23c2ab3f 100644 --- a/fs/ocfs2/dlm/dlmrecovery.c +++ b/fs/ocfs2/dlm/dlmrecovery.c @@ -2083,8 +2083,6 @@ static void dlm_finish_local_lockres_recovery(struct dlm_ctxt *dlm, struct hlist_head *bucket; struct dlm_lock_resource *res, *next; - mlog_entry_void(); - assert_spin_locked(&dlm->spinlock); list_for_each_entry_safe(res, next, &dlm->reco.resources, recovering) { @@ -2607,8 +2605,6 @@ static int dlm_send_begin_reco_message(struct dlm_ctxt *dlm, u8 dead_node) int nodenum; int status; - mlog_entry("%u\n", dead_node); - mlog(0, "%s: dead node is %u\n", dlm->name, dead_node); spin_lock(&dlm->spinlock); diff --git a/fs/ocfs2/dlm/dlmunlock.c b/fs/ocfs2/dlm/dlmunlock.c index 817287c6a6db6..850aa7e875377 100644 --- a/fs/ocfs2/dlm/dlmunlock.c +++ b/fs/ocfs2/dlm/dlmunlock.c @@ -317,7 +317,7 @@ static enum dlm_status dlm_send_remote_unlock_request(struct dlm_ctxt *dlm, struct kvec vec[2]; size_t veclen = 1; - mlog_entry("%.*s\n", res->lockname.len, res->lockname.name); + mlog(0, "%.*s\n", res->lockname.len, res->lockname.name); if (owner == dlm->node_num) { /* ended up trying to contact ourself. this means @@ -588,8 +588,6 @@ enum dlm_status dlmunlock(struct dlm_ctxt *dlm, struct dlm_lockstatus *lksb, struct dlm_lock *lock = NULL; int call_ast, is_master; - mlog_entry_void(); - if (!lksb) { dlm_error(DLM_BADARGS); return DLM_BADARGS; diff --git a/fs/ocfs2/dlmglue.c b/fs/ocfs2/dlmglue.c index e8d94d722ecb8..c2f3fa1c47229 100644 --- a/fs/ocfs2/dlmglue.c +++ b/fs/ocfs2/dlmglue.c @@ -397,8 +397,6 @@ static void ocfs2_build_lock_name(enum ocfs2_lock_type type, { int len; - mlog_entry_void(); - BUG_ON(type >= OCFS2_NUM_LOCK_TYPES); len = snprintf(name, OCFS2_LOCK_ID_MAX_LEN, "%c%s%016llx%08x", @@ -729,8 +727,6 @@ void ocfs2_refcount_lock_res_init(struct ocfs2_lock_res *lockres, void ocfs2_lock_res_free(struct ocfs2_lock_res *res) { - mlog_entry_void(); - if (!(res->l_flags & OCFS2_LOCK_INITIALIZED)) return; @@ -762,8 +758,6 @@ void ocfs2_lock_res_free(struct ocfs2_lock_res *res) static inline void ocfs2_inc_holders(struct ocfs2_lock_res *lockres, int level) { - mlog_entry_void(); - BUG_ON(!lockres); switch(level) { @@ -783,8 +777,6 @@ static inline void ocfs2_inc_holders(struct ocfs2_lock_res *lockres, static inline void ocfs2_dec_holders(struct ocfs2_lock_res *lockres, int level) { - mlog_entry_void(); - BUG_ON(!lockres); switch(level) { @@ -846,8 +838,6 @@ static void lockres_clear_flags(struct ocfs2_lock_res *lockres, static inline void ocfs2_generic_handle_downconvert_action(struct ocfs2_lock_res *lockres) { - mlog_entry_void(); - BUG_ON(!(lockres->l_flags & OCFS2_LOCK_BUSY)); BUG_ON(!(lockres->l_flags & OCFS2_LOCK_ATTACHED)); BUG_ON(!(lockres->l_flags & OCFS2_LOCK_BLOCKED)); @@ -866,8 +856,6 @@ static inline void ocfs2_generic_handle_downconvert_action(struct ocfs2_lock_res static inline void ocfs2_generic_handle_convert_action(struct ocfs2_lock_res *lockres) { - mlog_entry_void(); - BUG_ON(!(lockres->l_flags & OCFS2_LOCK_BUSY)); BUG_ON(!(lockres->l_flags & OCFS2_LOCK_ATTACHED)); @@ -895,8 +883,6 @@ static inline void ocfs2_generic_handle_convert_action(struct ocfs2_lock_res *lo static inline void ocfs2_generic_handle_attach_action(struct ocfs2_lock_res *lockres) { - mlog_entry_void(); - BUG_ON((!(lockres->l_flags & OCFS2_LOCK_BUSY))); BUG_ON(lockres->l_flags & OCFS2_LOCK_ATTACHED); @@ -916,7 +902,6 @@ static int ocfs2_generic_handle_bast(struct ocfs2_lock_res *lockres, int level) { int needs_downconvert = 0; - mlog_entry_void(); assert_spin_locked(&lockres->l_lock); @@ -1151,8 +1136,6 @@ static void ocfs2_unlock_ast(struct ocfs2_dlm_lksb *lksb, int error) struct ocfs2_lock_res *lockres = ocfs2_lksb_to_lock_res(lksb); unsigned long flags; - mlog_entry_void(); - mlog(ML_BASTS, "UNLOCK AST fired for lockres %s, action = %d\n", lockres->l_name, lockres->l_unlock_action); @@ -1233,7 +1216,6 @@ static inline void ocfs2_recover_from_dlm_error(struct ocfs2_lock_res *lockres, { unsigned long flags; - mlog_entry_void(); spin_lock_irqsave(&lockres->l_lock, flags); lockres_clear_flags(lockres, OCFS2_LOCK_BUSY); lockres_clear_flags(lockres, OCFS2_LOCK_UPCONVERT_FINISHING); @@ -1260,8 +1242,6 @@ static int ocfs2_lock_create(struct ocfs2_super *osb, unsigned long flags; unsigned int gen; - mlog_entry_void(); - mlog(0, "lock %s, level = %d, flags = %u\n", lockres->l_name, level, dlm_flags); @@ -1416,8 +1396,6 @@ static int __ocfs2_cluster_lock(struct ocfs2_super *osb, unsigned int gen; int noqueue_attempted = 0; - mlog_entry_void(); - ocfs2_init_mask_waiter(&mw); if (lockres->l_ops->flags & LOCK_TYPE_USES_LVB) @@ -1605,7 +1583,6 @@ static void __ocfs2_cluster_unlock(struct ocfs2_super *osb, { unsigned long flags; - mlog_entry_void(); spin_lock_irqsave(&lockres->l_lock, flags); ocfs2_dec_holders(lockres, level); ocfs2_downconvert_on_unlock(osb, lockres); @@ -1648,8 +1625,6 @@ int ocfs2_create_new_inode_locks(struct inode *inode) BUG_ON(!inode); BUG_ON(!ocfs2_inode_is_new(inode)); - mlog_entry_void(); - mlog(0, "Inode %llu\n", (unsigned long long)OCFS2_I(inode)->ip_blkno); /* NOTE: That we don't increment any of the holder counts, nor @@ -1695,8 +1670,6 @@ int ocfs2_rw_lock(struct inode *inode, int write) BUG_ON(!inode); - mlog_entry_void(); - mlog(0, "inode %llu take %s RW lock\n", (unsigned long long)OCFS2_I(inode)->ip_blkno, write ? "EXMODE" : "PRMODE"); @@ -1725,8 +1698,6 @@ void ocfs2_rw_unlock(struct inode *inode, int write) struct ocfs2_lock_res *lockres = &OCFS2_I(inode)->ip_rw_lockres; struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); - mlog_entry_void(); - mlog(0, "inode %llu drop %s RW lock\n", (unsigned long long)OCFS2_I(inode)->ip_blkno, write ? "EXMODE" : "PRMODE"); @@ -1748,8 +1719,6 @@ int ocfs2_open_lock(struct inode *inode) BUG_ON(!inode); - mlog_entry_void(); - mlog(0, "inode %llu take PRMODE open lock\n", (unsigned long long)OCFS2_I(inode)->ip_blkno); @@ -1776,8 +1745,6 @@ int ocfs2_try_open_lock(struct inode *inode, int write) BUG_ON(!inode); - mlog_entry_void(); - mlog(0, "inode %llu try to take %s open lock\n", (unsigned long long)OCFS2_I(inode)->ip_blkno, write ? "EXMODE" : "PRMODE"); @@ -1811,8 +1778,6 @@ void ocfs2_open_unlock(struct inode *inode) struct ocfs2_lock_res *lockres = &OCFS2_I(inode)->ip_open_lockres; struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); - mlog_entry_void(); - mlog(0, "inode %llu drop open lock\n", (unsigned long long)OCFS2_I(inode)->ip_blkno); @@ -2043,8 +2008,6 @@ static void ocfs2_downconvert_on_unlock(struct ocfs2_super *osb, { int kick = 0; - mlog_entry_void(); - /* If we know that another node is waiting on our lock, kick * the downconvert thread * pre-emptively when we reach a release * condition. */ @@ -2095,8 +2058,6 @@ static void __ocfs2_stuff_meta_lvb(struct inode *inode) struct ocfs2_lock_res *lockres = &oi->ip_inode_lockres; struct ocfs2_meta_lvb *lvb; - mlog_entry_void(); - lvb = ocfs2_dlm_lvb(&lockres->l_lksb); /* @@ -2145,8 +2106,6 @@ static void ocfs2_refresh_inode_from_lvb(struct inode *inode) struct ocfs2_lock_res *lockres = &oi->ip_inode_lockres; struct ocfs2_meta_lvb *lvb; - mlog_entry_void(); - mlog_meta_lvb(0, lockres); lvb = ocfs2_dlm_lvb(&lockres->l_lksb); @@ -2205,8 +2164,6 @@ static int ocfs2_should_refresh_lock_res(struct ocfs2_lock_res *lockres) unsigned long flags; int status = 0; - mlog_entry_void(); - refresh_check: spin_lock_irqsave(&lockres->l_lock, flags); if (!(lockres->l_flags & OCFS2_LOCK_NEEDS_REFRESH)) { @@ -2237,7 +2194,6 @@ static inline void ocfs2_complete_lock_res_refresh(struct ocfs2_lock_res *lockre int status) { unsigned long flags; - mlog_entry_void(); spin_lock_irqsave(&lockres->l_lock, flags); lockres_clear_flags(lockres, OCFS2_LOCK_REFRESHING); @@ -2260,8 +2216,6 @@ static int ocfs2_inode_lock_update(struct inode *inode, struct ocfs2_dinode *fe; struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); - mlog_entry_void(); - if (ocfs2_mount_local(osb)) goto bail; @@ -2374,8 +2328,6 @@ int ocfs2_inode_lock_full_nested(struct inode *inode, BUG_ON(!inode); - mlog_entry_void(); - mlog(0, "inode %llu, take %s META lock\n", (unsigned long long)OCFS2_I(inode)->ip_blkno, ex ? "EXMODE" : "PRMODE"); @@ -2517,7 +2469,6 @@ int ocfs2_inode_lock_atime(struct inode *inode, { int ret; - mlog_entry_void(); ret = ocfs2_inode_lock(inode, NULL, 0); if (ret < 0) { mlog_errno(ret); @@ -2556,8 +2507,6 @@ void ocfs2_inode_unlock(struct inode *inode, struct ocfs2_lock_res *lockres = &OCFS2_I(inode)->ip_inode_lockres; struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); - mlog_entry_void(); - mlog(0, "inode %llu drop %s META lock\n", (unsigned long long)OCFS2_I(inode)->ip_blkno, ex ? "EXMODE" : "PRMODE"); @@ -2617,8 +2566,6 @@ int ocfs2_super_lock(struct ocfs2_super *osb, int level = ex ? DLM_LOCK_EX : DLM_LOCK_PR; struct ocfs2_lock_res *lockres = &osb->osb_super_lockres; - mlog_entry_void(); - if (ocfs2_is_hard_readonly(osb)) return -EROFS; @@ -3054,8 +3001,6 @@ int ocfs2_dlm_init(struct ocfs2_super *osb) int status = 0; struct ocfs2_cluster_connection *conn = NULL; - mlog_entry_void(); - if (ocfs2_mount_local(osb)) { osb->node_num = 0; goto local; @@ -3119,8 +3064,6 @@ bail: void ocfs2_dlm_shutdown(struct ocfs2_super *osb, int hangup_pending) { - mlog_entry_void(); - ocfs2_drop_osb_locks(osb); /* @@ -3284,8 +3227,6 @@ int ocfs2_drop_inode_locks(struct inode *inode) { int status, err; - mlog_entry_void(); - /* No need to call ocfs2_mark_lockres_freeing here - * ocfs2_clear_inode has done it for us. */ @@ -3352,8 +3293,6 @@ static int ocfs2_downconvert_lock(struct ocfs2_super *osb, int ret; u32 dlm_flags = DLM_LKF_CONVERT; - mlog_entry_void(); - mlog(ML_BASTS, "lockres %s, level %d => %d\n", lockres->l_name, lockres->l_level, new_level); @@ -3385,8 +3324,6 @@ static int ocfs2_prepare_cancel_convert(struct ocfs2_super *osb, { assert_spin_locked(&lockres->l_lock); - mlog_entry_void(); - if (lockres->l_unlock_action == OCFS2_UNLOCK_CANCEL_CONVERT) { /* If we're already trying to cancel a lock conversion * then just drop the spinlock and allow the caller to @@ -3416,8 +3353,6 @@ static int ocfs2_cancel_convert(struct ocfs2_super *osb, { int ret; - mlog_entry_void(); - ret = ocfs2_dlm_unlock(osb->cconn, &lockres->l_lksb, DLM_LKF_CANCEL); if (ret) { @@ -3443,8 +3378,6 @@ static int ocfs2_unblock_lock(struct ocfs2_super *osb, int set_lvb = 0; unsigned int gen; - mlog_entry_void(); - spin_lock_irqsave(&lockres->l_lock, flags); recheck: @@ -3859,8 +3792,6 @@ static void ocfs2_set_qinfo_lvb(struct ocfs2_lock_res *lockres) struct mem_dqinfo *info = sb_dqinfo(oinfo->dqi_gi.dqi_sb, oinfo->dqi_gi.dqi_type); - mlog_entry_void(); - lvb = ocfs2_dlm_lvb(&lockres->l_lksb); lvb->lvb_version = OCFS2_QINFO_LVB_VERSION; lvb->lvb_bgrace = cpu_to_be32(info->dqi_bgrace); @@ -3879,7 +3810,6 @@ void ocfs2_qinfo_unlock(struct ocfs2_mem_dqinfo *oinfo, int ex) struct ocfs2_super *osb = OCFS2_SB(oinfo->dqi_gi.dqi_sb); int level = ex ? DLM_LOCK_EX : DLM_LOCK_PR; - mlog_entry_void(); if (!ocfs2_is_hard_readonly(osb) && !ocfs2_mount_local(osb)) ocfs2_cluster_unlock(osb, lockres, level); mlog_exit_void(); @@ -3937,8 +3867,6 @@ int ocfs2_qinfo_lock(struct ocfs2_mem_dqinfo *oinfo, int ex) int level = ex ? DLM_LOCK_EX : DLM_LOCK_PR; int status = 0; - mlog_entry_void(); - /* On RO devices, locking really isn't needed... */ if (ocfs2_is_hard_readonly(osb)) { if (ex) @@ -4007,8 +3935,6 @@ static void ocfs2_process_blocked_lock(struct ocfs2_super *osb, * considered valid until we remove the OCFS2_LOCK_QUEUED * flag. */ - mlog_entry_void(); - BUG_ON(!lockres); BUG_ON(!lockres->l_ops); @@ -4049,8 +3975,6 @@ unqueue: static void ocfs2_schedule_blocked_lock(struct ocfs2_super *osb, struct ocfs2_lock_res *lockres) { - mlog_entry_void(); - assert_spin_locked(&lockres->l_lock); if (lockres->l_flags & OCFS2_LOCK_FREEING) { @@ -4080,8 +4004,6 @@ static void ocfs2_downconvert_thread_do_work(struct ocfs2_super *osb) unsigned long processed; struct ocfs2_lock_res *lockres; - mlog_entry_void(); - spin_lock(&osb->dc_task_lock); /* grab this early so we know to try again if a state change and * wake happens part-way through our work */ diff --git a/fs/ocfs2/export.c b/fs/ocfs2/export.c index 254652a9b5426..b90c751ba9385 100644 --- a/fs/ocfs2/export.c +++ b/fs/ocfs2/export.c @@ -56,7 +56,7 @@ static struct dentry *ocfs2_get_dentry(struct super_block *sb, int status, set; struct dentry *result; - mlog_entry("(0x%p, 0x%p)\n", sb, handle); + mlog(0, "(0x%p, 0x%p)\n", sb, handle); if (blkno == 0) { mlog(0, "nfs wants inode with blkno: 0\n"); @@ -152,8 +152,8 @@ static struct dentry *ocfs2_get_parent(struct dentry *child) struct dentry *parent; struct inode *dir = child->d_inode; - mlog_entry("(0x%p, '%.*s')\n", child, - child->d_name.len, child->d_name.name); + mlog(0, "(0x%p, '%.*s')\n", child, + child->d_name.len, child->d_name.name); mlog(0, "find parent of directory %llu\n", (unsigned long long)OCFS2_I(dir)->ip_blkno); @@ -193,9 +193,9 @@ static int ocfs2_encode_fh(struct dentry *dentry, u32 *fh_in, int *max_len, u32 generation; __le32 *fh = (__force __le32 *) fh_in; - mlog_entry("(0x%p, '%.*s', 0x%p, %d, %d)\n", dentry, - dentry->d_name.len, dentry->d_name.name, - fh, len, connectable); + mlog(0, "(0x%p, '%.*s', 0x%p, %d, %d)\n", dentry, + dentry->d_name.len, dentry->d_name.name, + fh, len, connectable); if (connectable && (len < 6)) { *max_len = 6; diff --git a/fs/ocfs2/extent_map.c b/fs/ocfs2/extent_map.c index 09e3fdfa6d33f..ed9916a9a2710 100644 --- a/fs/ocfs2/extent_map.c +++ b/fs/ocfs2/extent_map.c @@ -841,10 +841,10 @@ int ocfs2_read_virt_blocks(struct inode *inode, u64 v_block, int nr, u64 p_block, p_count; int i, count, done = 0; - mlog_entry("(inode = %p, v_block = %llu, nr = %d, bhs = %p, " - "flags = %x, validate = %p)\n", - inode, (unsigned long long)v_block, nr, bhs, flags, - validate); + mlog(0, "(inode = %p, v_block = %llu, nr = %d, bhs = %p, " + "flags = %x, validate = %p)\n", + inode, (unsigned long long)v_block, nr, bhs, flags, + validate); if (((v_block + nr - 1) << inode->i_sb->s_blocksize_bits) >= i_size_read(inode)) { diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c index a6651956482e1..71375d7b7bbe8 100644 --- a/fs/ocfs2/file.c +++ b/fs/ocfs2/file.c @@ -99,8 +99,8 @@ static int ocfs2_file_open(struct inode *inode, struct file *file) int mode = file->f_flags; struct ocfs2_inode_info *oi = OCFS2_I(inode); - mlog_entry("(0x%p, 0x%p, '%.*s')\n", inode, file, - file->f_path.dentry->d_name.len, file->f_path.dentry->d_name.name); + mlog(0, "(0x%p, 0x%p, '%.*s')\n", inode, file, + file->f_path.dentry->d_name.len, file->f_path.dentry->d_name.name); if (file->f_mode & FMODE_WRITE) dquot_initialize(inode); @@ -143,9 +143,9 @@ static int ocfs2_file_release(struct inode *inode, struct file *file) { struct ocfs2_inode_info *oi = OCFS2_I(inode); - mlog_entry("(0x%p, 0x%p, '%.*s')\n", inode, file, - file->f_path.dentry->d_name.len, - file->f_path.dentry->d_name.name); + mlog(0, "(0x%p, 0x%p, '%.*s')\n", inode, file, + file->f_path.dentry->d_name.len, + file->f_path.dentry->d_name.name); spin_lock(&oi->ip_lock); if (!--oi->ip_open_count) @@ -177,9 +177,9 @@ static int ocfs2_sync_file(struct file *file, int datasync) struct inode *inode = file->f_mapping->host; struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); - mlog_entry("(0x%p, %d, 0x%p, '%.*s')\n", file, datasync, - file->f_path.dentry, file->f_path.dentry->d_name.len, - file->f_path.dentry->d_name.name); + mlog(0, "(0x%p, %d, 0x%p, '%.*s')\n", file, datasync, + file->f_path.dentry, file->f_path.dentry->d_name.len, + file->f_path.dentry->d_name.name); if (datasync && !(inode->i_state & I_DIRTY_DATASYNC)) { /* @@ -251,8 +251,6 @@ int ocfs2_update_inode_atime(struct inode *inode, handle_t *handle; struct ocfs2_dinode *di = (struct ocfs2_dinode *) bh->b_data; - mlog_entry_void(); - handle = ocfs2_start_trans(osb, OCFS2_INODE_UPDATE_CREDITS); if (IS_ERR(handle)) { ret = PTR_ERR(handle); @@ -291,7 +289,6 @@ static int ocfs2_set_inode_size(handle_t *handle, { int status; - mlog_entry_void(); i_size_write(inode, new_i_size); inode->i_blocks = ocfs2_inode_sector_count(inode); inode->i_ctime = inode->i_mtime = CURRENT_TIME; @@ -375,8 +372,6 @@ static int ocfs2_orphan_for_truncate(struct ocfs2_super *osb, struct ocfs2_dinode *di; u64 cluster_bytes; - mlog_entry_void(); - /* * We need to CoW the cluster contains the offset if it is reflinked * since we will call ocfs2_zero_range_for_truncate later which will @@ -442,9 +437,9 @@ static int ocfs2_truncate_file(struct inode *inode, struct ocfs2_dinode *fe = NULL; struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); - mlog_entry("(inode = %llu, new_i_size = %llu\n", - (unsigned long long)OCFS2_I(inode)->ip_blkno, - (unsigned long long)new_i_size); + mlog(0, "(inode = %llu, new_i_size = %llu\n", + (unsigned long long)OCFS2_I(inode)->ip_blkno, + (unsigned long long)new_i_size); /* We trust di_bh because it comes from ocfs2_inode_lock(), which * already validated it */ @@ -578,7 +573,7 @@ static int __ocfs2_extend_allocation(struct inode *inode, u32 logical_start, struct ocfs2_extent_tree et; int did_quota = 0; - mlog_entry("(clusters_to_add = %u)\n", clusters_to_add); + mlog(0, "(clusters_to_add = %u)\n", clusters_to_add); /* * This function only exists for file systems which don't @@ -1113,8 +1108,8 @@ int ocfs2_setattr(struct dentry *dentry, struct iattr *attr) struct dquot *transfer_to[MAXQUOTAS] = { }; int qtype; - mlog_entry("(0x%p, '%.*s')\n", dentry, - dentry->d_name.len, dentry->d_name.name); + mlog(0, "(0x%p, '%.*s')\n", dentry, + dentry->d_name.len, dentry->d_name.name); /* ensuring we don't even attempt to truncate a symlink */ if (S_ISLNK(inode->i_mode)) @@ -1287,8 +1282,6 @@ int ocfs2_getattr(struct vfsmount *mnt, struct ocfs2_super *osb = sb->s_fs_info; int err; - mlog_entry_void(); - err = ocfs2_inode_revalidate(dentry); if (err) { if (err != -ENOENT) @@ -1314,8 +1307,6 @@ int ocfs2_permission(struct inode *inode, int mask, unsigned int flags) if (flags & IPERM_FLAG_RCU) return -ECHILD; - mlog_entry_void(); - ret = ocfs2_inode_lock(inode, NULL, 0); if (ret) { if (ret != -ENOENT) @@ -1339,8 +1330,8 @@ static int __ocfs2_write_remove_suid(struct inode *inode, struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); struct ocfs2_dinode *di; - mlog_entry("(Inode %llu, mode 0%o)\n", - (unsigned long long)OCFS2_I(inode)->ip_blkno, inode->i_mode); + mlog(0, "(Inode %llu, mode 0%o)\n", + (unsigned long long)OCFS2_I(inode)->ip_blkno, inode->i_mode); handle = ocfs2_start_trans(osb, OCFS2_INODE_UPDATE_CREDITS); if (IS_ERR(handle)) { @@ -2233,10 +2224,10 @@ static ssize_t ocfs2_file_aio_write(struct kiocb *iocb, int full_coherency = !(osb->s_mount_opt & OCFS2_MOUNT_COHERENCY_BUFFERED); - mlog_entry("(0x%p, %u, '%.*s')\n", file, - (unsigned int)nr_segs, - file->f_path.dentry->d_name.len, - file->f_path.dentry->d_name.name); + mlog(0, "(0x%p, %u, '%.*s')\n", file, + (unsigned int)nr_segs, + file->f_path.dentry->d_name.len, + file->f_path.dentry->d_name.name); if (iocb->ki_left == 0) return 0; @@ -2438,10 +2429,10 @@ static ssize_t ocfs2_file_splice_write(struct pipe_inode_info *pipe, .u.file = out, }; - mlog_entry("(0x%p, 0x%p, %u, '%.*s')\n", out, pipe, - (unsigned int)len, - out->f_path.dentry->d_name.len, - out->f_path.dentry->d_name.name); + mlog(0, "(0x%p, 0x%p, %u, '%.*s')\n", out, pipe, + (unsigned int)len, + out->f_path.dentry->d_name.len, + out->f_path.dentry->d_name.name); if (pipe->inode) mutex_lock_nested(&pipe->inode->i_mutex, I_MUTEX_PARENT); @@ -2498,10 +2489,10 @@ static ssize_t ocfs2_file_splice_read(struct file *in, int ret = 0, lock_level = 0; struct inode *inode = in->f_path.dentry->d_inode; - mlog_entry("(0x%p, 0x%p, %u, '%.*s')\n", in, pipe, - (unsigned int)len, - in->f_path.dentry->d_name.len, - in->f_path.dentry->d_name.name); + mlog(0, "(0x%p, 0x%p, %u, '%.*s')\n", in, pipe, + (unsigned int)len, + in->f_path.dentry->d_name.len, + in->f_path.dentry->d_name.name); /* * See the comment in ocfs2_file_aio_read() @@ -2529,10 +2520,10 @@ static ssize_t ocfs2_file_aio_read(struct kiocb *iocb, struct file *filp = iocb->ki_filp; struct inode *inode = filp->f_path.dentry->d_inode; - mlog_entry("(0x%p, %u, '%.*s')\n", filp, - (unsigned int)nr_segs, - filp->f_path.dentry->d_name.len, - filp->f_path.dentry->d_name.name); + mlog(0, "(0x%p, %u, '%.*s')\n", filp, + (unsigned int)nr_segs, + filp->f_path.dentry->d_name.len, + filp->f_path.dentry->d_name.name); if (!inode) { ret = -EINVAL; diff --git a/fs/ocfs2/inode.c b/fs/ocfs2/inode.c index 4068c6c4c6f64..16ee8e96f731f 100644 --- a/fs/ocfs2/inode.c +++ b/fs/ocfs2/inode.c @@ -131,7 +131,7 @@ struct inode *ocfs2_iget(struct ocfs2_super *osb, u64 blkno, unsigned flags, struct super_block *sb = osb->sb; struct ocfs2_find_inode_args args; - mlog_entry("(blkno = %llu)\n", (unsigned long long)blkno); + mlog(0, "(blkno = %llu)\n", (unsigned long long)blkno); /* Ok. By now we've either got the offsets passed to us by the * caller, or we just pulled them off the bh. Lets do some @@ -192,7 +192,7 @@ static int ocfs2_find_actor(struct inode *inode, void *opaque) struct ocfs2_inode_info *oi = OCFS2_I(inode); int ret = 0; - mlog_entry("(0x%p, %lu, 0x%p)\n", inode, inode->i_ino, opaque); + mlog(0, "(0x%p, %lu, 0x%p)\n", inode, inode->i_ino, opaque); args = opaque; @@ -218,7 +218,7 @@ static int ocfs2_init_locked_inode(struct inode *inode, void *opaque) static struct lock_class_key ocfs2_quota_ip_alloc_sem_key, ocfs2_file_ip_alloc_sem_key; - mlog_entry("inode = %p, opaque = %p\n", inode, opaque); + mlog(0, "inode = %p, opaque = %p\n", inode, opaque); inode->i_ino = args->fi_ino; OCFS2_I(inode)->ip_blkno = args->fi_blkno; @@ -246,8 +246,8 @@ void ocfs2_populate_inode(struct inode *inode, struct ocfs2_dinode *fe, struct ocfs2_super *osb; int use_plocks = 1; - mlog_entry("(0x%p, size:%llu)\n", inode, - (unsigned long long)le64_to_cpu(fe->i_size)); + mlog(0, "(0x%p, size:%llu)\n", inode, + (unsigned long long)le64_to_cpu(fe->i_size)); sb = inode->i_sb; osb = OCFS2_SB(sb); @@ -394,7 +394,7 @@ static int ocfs2_read_locked_inode(struct inode *inode, int status, can_lock; u32 generation = 0; - mlog_entry("(0x%p, 0x%p)\n", inode, args); + mlog(0, "(0x%p, 0x%p)\n", inode, args); status = -EINVAL; if (inode == NULL || inode->i_sb == NULL) { @@ -551,8 +551,6 @@ static int ocfs2_truncate_for_delete(struct ocfs2_super *osb, struct ocfs2_dinode *fe; handle_t *handle = NULL; - mlog_entry_void(); - fe = (struct ocfs2_dinode *) fe_bh->b_data; /* @@ -980,7 +978,7 @@ static void ocfs2_delete_inode(struct inode *inode) sigset_t oldset; struct buffer_head *di_bh = NULL; - mlog_entry("(inode->i_ino = %lu)\n", inode->i_ino); + mlog(0, "(inode->i_ino = %lu)\n", inode->i_ino); /* When we fail in read_inode() we mark inode as bad. The second test * catches the case when inode allocation fails before allocating @@ -1088,8 +1086,6 @@ static void ocfs2_clear_inode(struct inode *inode) int status; struct ocfs2_inode_info *oi = OCFS2_I(inode); - mlog_entry_void(); - end_writeback(inode); mlog(0, "Clearing inode: %llu, nlink = %u\n", (unsigned long long)OCFS2_I(inode)->ip_blkno, inode->i_nlink); @@ -1204,8 +1200,6 @@ int ocfs2_drop_inode(struct inode *inode) struct ocfs2_inode_info *oi = OCFS2_I(inode); int res; - mlog_entry_void(); - mlog(0, "Drop inode %llu, nlink = %u, ip_flags = 0x%x\n", (unsigned long long)oi->ip_blkno, inode->i_nlink, oi->ip_flags); @@ -1226,8 +1220,8 @@ int ocfs2_inode_revalidate(struct dentry *dentry) struct inode *inode = dentry->d_inode; int status = 0; - mlog_entry("(inode = 0x%p, ino = %llu)\n", inode, - inode ? (unsigned long long)OCFS2_I(inode)->ip_blkno : 0ULL); + mlog(0, "(inode = 0x%p, ino = %llu)\n", inode, + inode ? (unsigned long long)OCFS2_I(inode)->ip_blkno : 0ULL); if (!inode) { mlog(0, "eep, no inode!\n"); @@ -1271,8 +1265,8 @@ int ocfs2_mark_inode_dirty(handle_t *handle, int status; struct ocfs2_dinode *fe = (struct ocfs2_dinode *) bh->b_data; - mlog_entry("(inode %llu)\n", - (unsigned long long)OCFS2_I(inode)->ip_blkno); + mlog(0, "(inode %llu)\n", + (unsigned long long)OCFS2_I(inode)->ip_blkno); status = ocfs2_journal_access_di(handle, INODE_CACHE(inode), bh, OCFS2_JOURNAL_ACCESS_WRITE); diff --git a/fs/ocfs2/journal.c b/fs/ocfs2/journal.c index faa2303dbf0a4..7378277b17a47 100644 --- a/fs/ocfs2/journal.c +++ b/fs/ocfs2/journal.c @@ -303,8 +303,6 @@ static int ocfs2_commit_cache(struct ocfs2_super *osb) unsigned int flushed; struct ocfs2_journal *journal = NULL; - mlog_entry_void(); - journal = osb->journal; /* Flush all pending commits and checkpoint the journal. */ @@ -425,7 +423,6 @@ int ocfs2_extend_trans(handle_t *handle, int nblocks) return 0; old_nblocks = handle->h_buffer_credits; - mlog_entry_void(); mlog(0, "Trying to extend transaction by %d blocks\n", nblocks); @@ -622,12 +619,12 @@ static int __ocfs2_journal_access(handle_t *handle, BUG_ON(!handle); BUG_ON(!bh); - mlog_entry("bh->b_blocknr=%llu, type=%d (\"%s\"), bh->b_size = %zu\n", - (unsigned long long)bh->b_blocknr, type, - (type == OCFS2_JOURNAL_ACCESS_CREATE) ? - "OCFS2_JOURNAL_ACCESS_CREATE" : - "OCFS2_JOURNAL_ACCESS_WRITE", - bh->b_size); + mlog(0, "bh->b_blocknr=%llu, type=%d (\"%s\"), bh->b_size = %zu\n", + (unsigned long long)bh->b_blocknr, type, + (type == OCFS2_JOURNAL_ACCESS_CREATE) ? + "OCFS2_JOURNAL_ACCESS_CREATE" : + "OCFS2_JOURNAL_ACCESS_WRITE", + bh->b_size); /* we can safely remove this assertion after testing. */ if (!buffer_uptodate(bh)) { @@ -737,8 +734,8 @@ void ocfs2_journal_dirty(handle_t *handle, struct buffer_head *bh) { int status; - mlog_entry("(bh->b_blocknr=%llu)\n", - (unsigned long long)bh->b_blocknr); + mlog(0, "(bh->b_blocknr=%llu)\n", + (unsigned long long)bh->b_blocknr); status = jbd2_journal_dirty_metadata(handle, bh); BUG_ON(status); @@ -775,8 +772,6 @@ int ocfs2_journal_init(struct ocfs2_journal *journal, int *dirty) struct ocfs2_super *osb; int inode_lock = 0; - mlog_entry_void(); - BUG_ON(!journal); osb = journal->j_osb; @@ -882,8 +877,6 @@ static int ocfs2_journal_toggle_dirty(struct ocfs2_super *osb, struct buffer_head *bh = journal->j_bh; struct ocfs2_dinode *fe; - mlog_entry_void(); - fe = (struct ocfs2_dinode *)bh->b_data; /* The journal bh on the osb always comes from ocfs2_journal_init() @@ -921,8 +914,6 @@ void ocfs2_journal_shutdown(struct ocfs2_super *osb) struct inode *inode = NULL; int num_running_trans = 0; - mlog_entry_void(); - BUG_ON(!osb); journal = osb->journal; @@ -1024,8 +1015,6 @@ int ocfs2_journal_load(struct ocfs2_journal *journal, int local, int replayed) int status = 0; struct ocfs2_super *osb; - mlog_entry_void(); - BUG_ON(!journal); osb = journal->j_osb; @@ -1070,8 +1059,6 @@ int ocfs2_journal_wipe(struct ocfs2_journal *journal, int full) { int status; - mlog_entry_void(); - BUG_ON(!journal); status = jbd2_journal_wipe(journal->j_journal, full); @@ -1124,8 +1111,6 @@ static int ocfs2_force_read_journal(struct inode *inode) #define CONCURRENT_JOURNAL_FILL 32ULL struct buffer_head *bhs[CONCURRENT_JOURNAL_FILL]; - mlog_entry_void(); - memset(bhs, 0, sizeof(struct buffer_head *) * CONCURRENT_JOURNAL_FILL); num_blocks = ocfs2_blocks_for_bytes(inode->i_sb, inode->i_size); @@ -1194,8 +1179,6 @@ void ocfs2_complete_recovery(struct work_struct *work) struct ocfs2_quota_recovery *qrec; LIST_HEAD(tmp_la_list); - mlog_entry_void(); - mlog(0, "completing recovery from keventd\n"); spin_lock(&journal->j_lock); @@ -1339,8 +1322,6 @@ static int __ocfs2_recovery_thread(void *arg) int rm_quota_used = 0, i; struct ocfs2_quota_recovery *qrec; - mlog_entry_void(); - status = ocfs2_wait_on_mount(osb); if (status < 0) { goto bail; @@ -1461,8 +1442,8 @@ bail: void ocfs2_recovery_thread(struct ocfs2_super *osb, int node_num) { - mlog_entry("(node_num=%d, osb->node_num = %d)\n", - node_num, osb->node_num); + mlog(0, "(node_num=%d, osb->node_num = %d)\n", + node_num, osb->node_num); mutex_lock(&osb->recovery_lock); if (osb->disable_recovery) @@ -1688,8 +1669,8 @@ static int ocfs2_recover_node(struct ocfs2_super *osb, struct ocfs2_dinode *la_copy = NULL; struct ocfs2_dinode *tl_copy = NULL; - mlog_entry("(node_num=%d, slot_num=%d, osb->node_num = %d)\n", - node_num, slot_num, osb->node_num); + mlog(0, "(node_num=%d, slot_num=%d, osb->node_num = %d)\n", + node_num, slot_num, osb->node_num); /* Should not ever be called to recover ourselves -- in that * case we should've called ocfs2_journal_load instead. */ diff --git a/fs/ocfs2/localalloc.c b/fs/ocfs2/localalloc.c index ec6adbf8f5515..5f08c703f3541 100644 --- a/fs/ocfs2/localalloc.c +++ b/fs/ocfs2/localalloc.c @@ -291,8 +291,6 @@ int ocfs2_load_local_alloc(struct ocfs2_super *osb) struct inode *inode = NULL; struct ocfs2_local_alloc *la; - mlog_entry_void(); - if (osb->local_alloc_bits == 0) goto bail; @@ -388,8 +386,6 @@ void ocfs2_shutdown_local_alloc(struct ocfs2_super *osb) struct ocfs2_dinode *alloc_copy = NULL; struct ocfs2_dinode *alloc = NULL; - mlog_entry_void(); - cancel_delayed_work(&osb->la_enable_wq); flush_workqueue(ocfs2_wq); @@ -502,7 +498,7 @@ int ocfs2_begin_local_alloc_recovery(struct ocfs2_super *osb, struct inode *inode = NULL; struct ocfs2_dinode *alloc; - mlog_entry("(slot_num = %d)\n", slot_num); + mlog(0, "(slot_num = %d)\n", slot_num); *alloc_copy = NULL; @@ -570,8 +566,6 @@ int ocfs2_complete_local_alloc_recovery(struct ocfs2_super *osb, struct buffer_head *main_bm_bh = NULL; struct inode *main_bm_inode; - mlog_entry_void(); - main_bm_inode = ocfs2_get_system_file_inode(osb, GLOBAL_BITMAP_SYSTEM_INODE, OCFS2_INVALID_SLOT); @@ -640,8 +634,6 @@ int ocfs2_reserve_local_alloc_bits(struct ocfs2_super *osb, struct inode *local_alloc_inode; unsigned int free_bits; - mlog_entry_void(); - BUG_ON(!ac); local_alloc_inode = @@ -749,7 +741,6 @@ int ocfs2_claim_local_alloc_bits(struct ocfs2_super *osb, struct ocfs2_dinode *alloc; struct ocfs2_local_alloc *la; - mlog_entry_void(); BUG_ON(ac->ac_which != OCFS2_AC_USE_LOCAL); local_alloc_inode = ac->ac_inode; @@ -799,8 +790,6 @@ static u32 ocfs2_local_alloc_count_bits(struct ocfs2_dinode *alloc) u32 count = 0; struct ocfs2_local_alloc *la = OCFS2_LOCAL_ALLOC(alloc); - mlog_entry_void(); - buffer = la->la_bitmap; for (i = 0; i < le16_to_cpu(la->la_size); i++) count += hweight8(buffer[i]); @@ -820,7 +809,7 @@ static int ocfs2_local_alloc_find_clear_bits(struct ocfs2_super *osb, void *bitmap = NULL; struct ocfs2_reservation_map *resmap = &osb->osb_la_resmap; - mlog_entry("(numbits wanted = %u)\n", *numbits); + mlog(0, "(numbits wanted = %u)\n", *numbits); if (!alloc->id1.bitmap1.i_total) { mlog(0, "No bits in my window!\n"); @@ -903,7 +892,6 @@ static void ocfs2_clear_local_alloc(struct ocfs2_dinode *alloc) { struct ocfs2_local_alloc *la = OCFS2_LOCAL_ALLOC(alloc); int i; - mlog_entry_void(); alloc->id1.bitmap1.i_total = 0; alloc->id1.bitmap1.i_used = 0; @@ -952,9 +940,9 @@ static int ocfs2_sync_local_to_main(struct ocfs2_super *osb, void *bitmap; struct ocfs2_local_alloc *la = OCFS2_LOCAL_ALLOC(alloc); - mlog_entry("total = %u, used = %u\n", - le32_to_cpu(alloc->id1.bitmap1.i_total), - le32_to_cpu(alloc->id1.bitmap1.i_used)); + mlog(0, "total = %u, used = %u\n", + le32_to_cpu(alloc->id1.bitmap1.i_total), + le32_to_cpu(alloc->id1.bitmap1.i_used)); if (!alloc->id1.bitmap1.i_total) { mlog(0, "nothing to sync!\n"); @@ -1148,8 +1136,6 @@ static int ocfs2_local_alloc_new_window(struct ocfs2_super *osb, struct ocfs2_dinode *alloc = NULL; struct ocfs2_local_alloc *la; - mlog_entry_void(); - alloc = (struct ocfs2_dinode *) osb->local_alloc_bh->b_data; la = OCFS2_LOCAL_ALLOC(alloc); @@ -1243,8 +1229,6 @@ static int ocfs2_local_alloc_slide_window(struct ocfs2_super *osb, struct ocfs2_dinode *alloc_copy = NULL; struct ocfs2_alloc_context *ac = NULL; - mlog_entry_void(); - ocfs2_recalc_la_window(osb, OCFS2_LA_EVENT_SLIDE); /* This will lock the main bitmap for us. */ diff --git a/fs/ocfs2/mmap.c b/fs/ocfs2/mmap.c index 7e32db9c2c993..87438e178e118 100644 --- a/fs/ocfs2/mmap.c +++ b/fs/ocfs2/mmap.c @@ -49,7 +49,7 @@ static int ocfs2_fault(struct vm_area_struct *area, struct vm_fault *vmf) sigset_t oldset; int ret; - mlog_entry("(area=%p, page offset=%lu)\n", area, vmf->pgoff); + mlog(0, "(area=%p, page offset=%lu)\n", area, vmf->pgoff); ocfs2_block_signals(&oldset); ret = filemap_fault(area, vmf); diff --git a/fs/ocfs2/namei.c b/fs/ocfs2/namei.c index 849fb4a2e814a..fdf5c0b75caaf 100644 --- a/fs/ocfs2/namei.c +++ b/fs/ocfs2/namei.c @@ -106,8 +106,8 @@ static struct dentry *ocfs2_lookup(struct inode *dir, struct dentry *dentry, struct dentry *ret; struct ocfs2_inode_info *oi; - mlog_entry("(0x%p, 0x%p, '%.*s')\n", dir, dentry, - dentry->d_name.len, dentry->d_name.name); + mlog(0, "(0x%p, 0x%p, '%.*s')\n", dir, dentry, + dentry->d_name.len, dentry->d_name.name); if (dentry->d_name.len > OCFS2_MAX_FILENAME_LEN) { ret = ERR_PTR(-ENAMETOOLONG); @@ -235,9 +235,9 @@ static int ocfs2_mknod(struct inode *dir, sigset_t oldset; int did_block_signals = 0; - mlog_entry("(0x%p, 0x%p, %d, %lu, '%.*s')\n", dir, dentry, mode, - (unsigned long)dev, dentry->d_name.len, - dentry->d_name.name); + mlog(0, "(0x%p, 0x%p, %d, %lu, '%.*s')\n", dir, dentry, mode, + (unsigned long)dev, dentry->d_name.len, + dentry->d_name.name); dquot_initialize(dir); @@ -354,9 +354,9 @@ static int ocfs2_mknod(struct inode *dir, goto leave; did_quota_inode = 1; - mlog_entry("(0x%p, 0x%p, %d, %lu, '%.*s')\n", dir, dentry, - inode->i_mode, (unsigned long)dev, dentry->d_name.len, - dentry->d_name.name); + mlog(0, "(0x%p, 0x%p, %d, %lu, '%.*s')\n", dir, dentry, + inode->i_mode, (unsigned long)dev, dentry->d_name.len, + dentry->d_name.name); /* do the real work now. */ status = ocfs2_mknod_locked(osb, dir, inode, dev, @@ -615,8 +615,8 @@ static int ocfs2_mkdir(struct inode *dir, { int ret; - mlog_entry("(0x%p, 0x%p, %d, '%.*s')\n", dir, dentry, mode, - dentry->d_name.len, dentry->d_name.name); + mlog(0, "(0x%p, 0x%p, %d, '%.*s')\n", dir, dentry, mode, + dentry->d_name.len, dentry->d_name.name); ret = ocfs2_mknod(dir, dentry, mode | S_IFDIR, 0); mlog_exit(ret); @@ -630,8 +630,8 @@ static int ocfs2_create(struct inode *dir, { int ret; - mlog_entry("(0x%p, 0x%p, %d, '%.*s')\n", dir, dentry, mode, - dentry->d_name.len, dentry->d_name.name); + mlog(0, "(0x%p, 0x%p, %d, '%.*s')\n", dir, dentry, mode, + dentry->d_name.len, dentry->d_name.name); ret = ocfs2_mknod(dir, dentry, mode | S_IFREG, 0); mlog_exit(ret); @@ -652,9 +652,9 @@ static int ocfs2_link(struct dentry *old_dentry, struct ocfs2_dir_lookup_result lookup = { NULL, }; sigset_t oldset; - mlog_entry("(inode=%lu, old='%.*s' new='%.*s')\n", inode->i_ino, - old_dentry->d_name.len, old_dentry->d_name.name, - dentry->d_name.len, dentry->d_name.name); + mlog(0, "(inode=%lu, old='%.*s' new='%.*s')\n", inode->i_ino, + old_dentry->d_name.len, old_dentry->d_name.name, + dentry->d_name.len, dentry->d_name.name); if (S_ISDIR(inode->i_mode)) return -EPERM; @@ -809,8 +809,8 @@ static int ocfs2_unlink(struct inode *dir, struct ocfs2_dir_lookup_result lookup = { NULL, }; struct ocfs2_dir_lookup_result orphan_insert = { NULL, }; - mlog_entry("(0x%p, 0x%p, '%.*s')\n", dir, dentry, - dentry->d_name.len, dentry->d_name.name); + mlog(0, "(0x%p, 0x%p, '%.*s')\n", dir, dentry, + dentry->d_name.len, dentry->d_name.name); dquot_initialize(dir); @@ -975,9 +975,9 @@ static int ocfs2_double_lock(struct ocfs2_super *osb, struct buffer_head **tmpbh; struct inode *tmpinode; - mlog_entry("(inode1 = %llu, inode2 = %llu)\n", - (unsigned long long)oi1->ip_blkno, - (unsigned long long)oi2->ip_blkno); + mlog(0, "(inode1 = %llu, inode2 = %llu)\n", + (unsigned long long)oi1->ip_blkno, + (unsigned long long)oi2->ip_blkno); if (*bh1) *bh1 = NULL; @@ -1067,10 +1067,10 @@ static int ocfs2_rename(struct inode *old_dir, /* At some point it might be nice to break this function up a * bit. */ - mlog_entry("(0x%p, 0x%p, 0x%p, 0x%p, from='%.*s' to='%.*s')\n", - old_dir, old_dentry, new_dir, new_dentry, - old_dentry->d_name.len, old_dentry->d_name.name, - new_dentry->d_name.len, new_dentry->d_name.name); + mlog(0, "(0x%p, 0x%p, 0x%p, 0x%p, from='%.*s' to='%.*s')\n", + old_dir, old_dentry, new_dir, new_dentry, + old_dentry->d_name.len, old_dentry->d_name.name, + new_dentry->d_name.len, new_dentry->d_name.name); dquot_initialize(old_dir); dquot_initialize(new_dir); @@ -1501,9 +1501,9 @@ static int ocfs2_create_symlink_data(struct ocfs2_super *osb, * write i_size + 1 bytes. */ blocks = (bytes_left + sb->s_blocksize - 1) >> sb->s_blocksize_bits; - mlog_entry("i_blocks = %llu, i_size = %llu, blocks = %d\n", - (unsigned long long)inode->i_blocks, - i_size_read(inode), blocks); + mlog(0, "i_blocks = %llu, i_size = %llu, blocks = %d\n", + (unsigned long long)inode->i_blocks, + i_size_read(inode), blocks); /* Sanity check -- make sure we're going to fit. */ if (bytes_left > @@ -1610,8 +1610,8 @@ static int ocfs2_symlink(struct inode *dir, sigset_t oldset; int did_block_signals = 0; - mlog_entry("(0x%p, 0x%p, symname='%s' actual='%.*s')\n", dir, - dentry, symname, dentry->d_name.len, dentry->d_name.name); + mlog(0, "(0x%p, 0x%p, symname='%s' actual='%.*s')\n", dir, + dentry, symname, dentry->d_name.len, dentry->d_name.name); dquot_initialize(dir); @@ -1713,9 +1713,9 @@ static int ocfs2_symlink(struct inode *dir, goto bail; did_quota_inode = 1; - mlog_entry("(0x%p, 0x%p, %d, '%.*s')\n", dir, dentry, - inode->i_mode, dentry->d_name.len, - dentry->d_name.name); + mlog(0, "(0x%p, 0x%p, %d, '%.*s')\n", dir, dentry, + inode->i_mode, dentry->d_name.len, + dentry->d_name.name); status = ocfs2_mknod_locked(osb, dir, inode, 0, &new_fe_bh, parent_fe_bh, handle, @@ -1844,8 +1844,6 @@ static int ocfs2_blkno_stringify(u64 blkno, char *name) { int status, namelen; - mlog_entry_void(); - namelen = snprintf(name, OCFS2_ORPHAN_NAMELEN + 1, "%016llx", (long long)blkno); if (namelen <= 0) { @@ -1997,7 +1995,7 @@ static int ocfs2_orphan_add(struct ocfs2_super *osb, struct ocfs2_dinode *orphan_fe; struct ocfs2_dinode *fe = (struct ocfs2_dinode *) fe_bh->b_data; - mlog_entry("(inode->i_ino = %lu)\n", inode->i_ino); + mlog(0, "(inode->i_ino = %lu)\n", inode->i_ino); status = ocfs2_read_inode_block(orphan_dir_inode, &orphan_dir_bh); if (status < 0) { @@ -2078,8 +2076,6 @@ int ocfs2_orphan_del(struct ocfs2_super *osb, int status = 0; struct ocfs2_dir_lookup_result lookup = { NULL, }; - mlog_entry_void(); - status = ocfs2_blkno_stringify(OCFS2_I(inode)->ip_blkno, name); if (status < 0) { mlog_errno(status); @@ -2358,8 +2354,8 @@ int ocfs2_mv_orphaned_inode_to_new(struct inode *dir, struct buffer_head *di_bh = NULL; struct ocfs2_dir_lookup_result lookup = { NULL, }; - mlog_entry("(0x%p, 0x%p, %.*s')\n", dir, dentry, - dentry->d_name.len, dentry->d_name.name); + mlog(0, "(0x%p, 0x%p, %.*s')\n", dir, dentry, + dentry->d_name.len, dentry->d_name.name); status = ocfs2_inode_lock(dir, &parent_di_bh, 1); if (status < 0) { diff --git a/fs/ocfs2/quota_global.c b/fs/ocfs2/quota_global.c index 4607923eb24c1..33397bd7e1bc5 100644 --- a/fs/ocfs2/quota_global.c +++ b/fs/ocfs2/quota_global.c @@ -343,8 +343,6 @@ int ocfs2_global_read_info(struct super_block *sb, int type) u64 pcount; int status; - mlog_entry_void(); - /* Read global header */ gqinode = ocfs2_get_system_file_inode(OCFS2_SB(sb), ino[type], OCFS2_INVALID_SLOT); @@ -596,7 +594,7 @@ static int ocfs2_sync_dquot_helper(struct dquot *dquot, unsigned long type) struct ocfs2_super *osb = OCFS2_SB(sb); int status = 0; - mlog_entry("id=%u qtype=%u type=%lu device=%s\n", dquot->dq_id, + mlog(0, "id=%u qtype=%u type=%lu device=%s\n", dquot->dq_id, dquot->dq_type, type, sb->s_id); if (type != dquot->dq_type) goto out; @@ -649,7 +647,7 @@ static int ocfs2_write_dquot(struct dquot *dquot) struct ocfs2_super *osb = OCFS2_SB(dquot->dq_sb); int status = 0; - mlog_entry("id=%u, type=%d", dquot->dq_id, dquot->dq_type); + mlog(0, "id=%u, type=%d", dquot->dq_id, dquot->dq_type); handle = ocfs2_start_trans(osb, OCFS2_QWRITE_CREDITS); if (IS_ERR(handle)) { @@ -688,7 +686,7 @@ static int ocfs2_release_dquot(struct dquot *dquot) struct ocfs2_super *osb = OCFS2_SB(dquot->dq_sb); int status = 0; - mlog_entry("id=%u, type=%d", dquot->dq_id, dquot->dq_type); + mlog(0, "id=%u, type=%d", dquot->dq_id, dquot->dq_type); mutex_lock(&dquot->dq_lock); /* Check whether we are not racing with some other dqget() */ @@ -745,7 +743,7 @@ static int ocfs2_acquire_dquot(struct dquot *dquot) int need_alloc = ocfs2_global_qinit_alloc(sb, type); handle_t *handle; - mlog_entry("id=%u, type=%d", dquot->dq_id, type); + mlog(0, "id=%u, type=%d", dquot->dq_id, type); mutex_lock(&dquot->dq_lock); /* * We need an exclusive lock, because we're going to update use count @@ -831,7 +829,7 @@ static int ocfs2_mark_dquot_dirty(struct dquot *dquot) handle_t *handle; struct ocfs2_super *osb = OCFS2_SB(sb); - mlog_entry("id=%u, type=%d", dquot->dq_id, type); + mlog(0, "id=%u, type=%d", dquot->dq_id, type); /* In case user set some limits, sync dquot immediately to global * quota file so that information propagates quicker */ @@ -879,8 +877,6 @@ static int ocfs2_write_info(struct super_block *sb, int type) int status = 0; struct ocfs2_mem_dqinfo *oinfo = sb_dqinfo(sb, type)->dqi_priv; - mlog_entry_void(); - status = ocfs2_lock_global_qf(oinfo, 1); if (status < 0) goto out; diff --git a/fs/ocfs2/quota_local.c b/fs/ocfs2/quota_local.c index dc78764ccc4c6..a71d68d886673 100644 --- a/fs/ocfs2/quota_local.c +++ b/fs/ocfs2/quota_local.c @@ -475,7 +475,7 @@ static int ocfs2_recover_local_quota_file(struct inode *lqinode, struct ocfs2_recovery_chunk *rchunk, *next; qsize_t spacechange, inodechange; - mlog_entry("ino=%lu type=%u", (unsigned long)lqinode->i_ino, type); + mlog(0, "ino=%lu type=%u", (unsigned long)lqinode->i_ino, type); list_for_each_entry_safe(rchunk, next, &(rec->r_list[type]), rc_list) { chunk = rchunk->rc_chunk; diff --git a/fs/ocfs2/resize.c b/fs/ocfs2/resize.c index dacd553d86176..e4a50e3fcb801 100644 --- a/fs/ocfs2/resize.c +++ b/fs/ocfs2/resize.c @@ -103,8 +103,8 @@ static int ocfs2_update_last_group_and_inode(handle_t *handle, u16 cl_bpc = le16_to_cpu(cl->cl_bpc); u16 cl_cpg = le16_to_cpu(cl->cl_cpg); - mlog_entry("(new_clusters=%d, first_new_cluster = %u)\n", - new_clusters, first_new_cluster); + mlog(0, "(new_clusters=%d, first_new_cluster = %u)\n", + new_clusters, first_new_cluster); ret = ocfs2_journal_access_gd(handle, INODE_CACHE(bm_inode), group_bh, OCFS2_JOURNAL_ACCESS_WRITE); @@ -281,8 +281,6 @@ int ocfs2_group_extend(struct inode * inode, int new_clusters) u32 first_new_cluster; u64 lgd_blkno; - mlog_entry_void(); - if (ocfs2_is_hard_readonly(osb) || ocfs2_is_soft_readonly(osb)) return -EROFS; @@ -472,8 +470,6 @@ int ocfs2_group_add(struct inode *inode, struct ocfs2_new_group_input *input) struct ocfs2_chain_rec *cr; u16 cl_bpc; - mlog_entry_void(); - if (ocfs2_is_hard_readonly(osb) || ocfs2_is_soft_readonly(osb)) return -EROFS; diff --git a/fs/ocfs2/slot_map.c b/fs/ocfs2/slot_map.c index ab4e0172cc1d1..a6016e6b3ca2d 100644 --- a/fs/ocfs2/slot_map.c +++ b/fs/ocfs2/slot_map.c @@ -475,8 +475,6 @@ int ocfs2_find_slot(struct ocfs2_super *osb) int slot; struct ocfs2_slot_info *si; - mlog_entry_void(); - si = osb->slot_info; spin_lock(&osb->osb_lock); diff --git a/fs/ocfs2/suballoc.c b/fs/ocfs2/suballoc.c index 71998d4d61d5c..dd618496c2c63 100644 --- a/fs/ocfs2/suballoc.c +++ b/fs/ocfs2/suballoc.c @@ -389,8 +389,6 @@ static int ocfs2_block_group_fill(handle_t *handle, struct ocfs2_group_desc *bg = (struct ocfs2_group_desc *) bg_bh->b_data; struct super_block * sb = alloc_inode->i_sb; - mlog_entry_void(); - if (((unsigned long long) bg_bh->b_blocknr) != group_blkno) { ocfs2_error(alloc_inode->i_sb, "group block (%llu) != " "b_blocknr (%llu)", @@ -707,8 +705,6 @@ static int ocfs2_block_group_alloc(struct ocfs2_super *osb, BUG_ON(ocfs2_is_cluster_bitmap(alloc_inode)); - mlog_entry_void(); - cl = &fe->id2.i_chain; status = ocfs2_reserve_clusters_with_limit(osb, le16_to_cpu(cl->cl_cpg), @@ -814,8 +810,6 @@ static int ocfs2_reserve_suballoc_bits(struct ocfs2_super *osb, struct ocfs2_dinode *fe; u32 free_bits; - mlog_entry_void(); - alloc_inode = ocfs2_get_system_file_inode(osb, type, slot); if (!alloc_inode) { mlog_errno(-EINVAL); @@ -1189,8 +1183,6 @@ static int ocfs2_reserve_clusters_with_limit(struct ocfs2_super *osb, { int status; - mlog_entry_void(); - *ac = kzalloc(sizeof(struct ocfs2_alloc_context), GFP_KERNEL); if (!(*ac)) { status = -ENOMEM; @@ -1357,8 +1349,6 @@ static inline int ocfs2_block_group_set_bits(handle_t *handle, void *bitmap = bg->bg_bitmap; int journal_type = OCFS2_JOURNAL_ACCESS_WRITE; - mlog_entry_void(); - /* All callers get the descriptor via * ocfs2_read_group_descriptor(). Any corruption is a code bug. */ BUG_ON(!OCFS2_IS_VALID_GROUP_DESC(bg)); @@ -1888,8 +1878,6 @@ static int ocfs2_claim_suballoc_bits(struct ocfs2_alloc_context *ac, struct ocfs2_chain_list *cl; struct ocfs2_dinode *fe; - mlog_entry_void(); - BUG_ON(ac->ac_bits_given >= ac->ac_bits_wanted); BUG_ON(bits_wanted > (ac->ac_bits_wanted - ac->ac_bits_given)); BUG_ON(!ac->ac_bh); @@ -2201,8 +2189,6 @@ int ocfs2_claim_new_inode(handle_t *handle, int status; struct ocfs2_suballoc_result res; - mlog_entry_void(); - BUG_ON(!ac); BUG_ON(ac->ac_bits_given != 0); BUG_ON(ac->ac_bits_wanted != 1); @@ -2307,8 +2293,6 @@ int __ocfs2_claim_clusters(handle_t *handle, struct ocfs2_suballoc_result res = { .sr_blkno = 0, }; struct ocfs2_super *osb = OCFS2_SB(ac->ac_inode->i_sb); - mlog_entry_void(); - BUG_ON(ac->ac_bits_given >= ac->ac_bits_wanted); BUG_ON(ac->ac_which != OCFS2_AC_USE_LOCAL @@ -2392,8 +2376,6 @@ static int ocfs2_block_group_clear_bits(handle_t *handle, unsigned int tmp; struct ocfs2_group_desc *undo_bg = NULL; - mlog_entry_void(); - /* The caller got this descriptor from * ocfs2_read_group_descriptor(). Any corruption is a code bug. */ BUG_ON(!OCFS2_IS_VALID_GROUP_DESC(bg)); @@ -2463,8 +2445,6 @@ static int _ocfs2_free_suballoc_bits(handle_t *handle, struct buffer_head *group_bh = NULL; struct ocfs2_group_desc *group; - mlog_entry_void(); - /* The alloc_bh comes from ocfs2_free_dinode() or * ocfs2_free_clusters(). The callers have all locked the * allocator and gotten alloc_bh from the lock call. This @@ -2556,11 +2536,8 @@ static int _ocfs2_free_clusters(handle_t *handle, /* You can't ever have a contiguous set of clusters * bigger than a block group bitmap so we never have to worry - * about looping on them. */ - - mlog_entry_void(); - - /* This is expensive. We can safely remove once this stuff has + * about looping on them. + * This is expensive. We can safely remove once this stuff has * gotten tested really well. */ BUG_ON(start_blk != ocfs2_clusters_to_blocks(bitmap_inode->i_sb, ocfs2_blocks_to_clusters(bitmap_inode->i_sb, start_blk))); @@ -2756,7 +2733,7 @@ static int ocfs2_get_suballoc_slot_bit(struct ocfs2_super *osb, u64 blkno, struct buffer_head *inode_bh = NULL; struct ocfs2_dinode *inode_fe; - mlog_entry("blkno: %llu\n", (unsigned long long)blkno); + mlog(0, "blkno: %llu\n", (unsigned long long)blkno); /* dirty read disk */ status = ocfs2_read_blocks_sync(osb, blkno, 1, &inode_bh); @@ -2816,8 +2793,8 @@ static int ocfs2_test_suballoc_bit(struct ocfs2_super *osb, u64 bg_blkno; int status; - mlog_entry("blkno: %llu bit: %u\n", (unsigned long long)blkno, - (unsigned int)bit); + mlog(0, "blkno: %llu bit: %u\n", (unsigned long long)blkno, + (unsigned int)bit); alloc_di = (struct ocfs2_dinode *)alloc_bh->b_data; if ((bit + 1) > ocfs2_bits_per_group(&alloc_di->id2.i_chain)) { @@ -2869,7 +2846,7 @@ int ocfs2_test_inode_bit(struct ocfs2_super *osb, u64 blkno, int *res) struct inode *inode_alloc_inode; struct buffer_head *alloc_bh = NULL; - mlog_entry("blkno: %llu", (unsigned long long)blkno); + mlog(0, "blkno: %llu", (unsigned long long)blkno); status = ocfs2_get_suballoc_slot_bit(osb, blkno, &suballoc_slot, &group_blkno, &suballoc_bit); diff --git a/fs/ocfs2/super.c b/fs/ocfs2/super.c index 36c423fb06352..21c4bfdfd7391 100644 --- a/fs/ocfs2/super.c +++ b/fs/ocfs2/super.c @@ -441,8 +441,6 @@ static int ocfs2_init_global_system_inodes(struct ocfs2_super *osb) int status = 0; int i; - mlog_entry_void(); - new = ocfs2_iget(osb, osb->root_blkno, OCFS2_FI_FLAG_SYSFILE, 0); if (IS_ERR(new)) { status = PTR_ERR(new); @@ -488,8 +486,6 @@ static int ocfs2_init_local_system_inodes(struct ocfs2_super *osb) int status = 0; int i; - mlog_entry_void(); - for (i = OCFS2_LAST_GLOBAL_SYSTEM_INODE + 1; i < NUM_SYSTEM_INODES; i++) { @@ -517,8 +513,6 @@ static void ocfs2_release_system_inodes(struct ocfs2_super *osb) int i; struct inode *inode; - mlog_entry_void(); - for (i = 0; i < NUM_GLOBAL_SYSTEM_INODES; i++) { inode = osb->global_system_inodes[i]; if (inode) { @@ -1032,7 +1026,7 @@ static int ocfs2_fill_super(struct super_block *sb, void *data, int silent) char nodestr[8]; struct ocfs2_blockcheck_stats stats; - mlog_entry("%p, %p, %i", sb, data, silent); + mlog(0, "%p, %p, %i", sb, data, silent); if (!ocfs2_parse_options(sb, data, &parsed_options, 0)) { status = -EINVAL; @@ -1320,8 +1314,8 @@ static int ocfs2_parse_options(struct super_block *sb, char *p; u32 tmp; - mlog_entry("remount: %d, options: \"%s\"\n", is_remount, - options ? options : "(none)"); + mlog(0, "remount: %d, options: \"%s\"\n", is_remount, + options ? options : "(none)"); mopt->commit_interval = 0; mopt->mount_opt = OCFS2_MOUNT_NOINTR; @@ -1629,8 +1623,6 @@ static int __init ocfs2_init(void) { int status; - mlog_entry_void(); - ocfs2_print_version(); status = init_ocfs2_uptodate_cache(); @@ -1681,8 +1673,6 @@ leave: static void __exit ocfs2_exit(void) { - mlog_entry_void(); - ocfs2_quota_shutdown(); if (ocfs2_wq) { @@ -1705,7 +1695,7 @@ static void __exit ocfs2_exit(void) static void ocfs2_put_super(struct super_block *sb) { - mlog_entry("(0x%p)\n", sb); + mlog(0, "(0x%p)\n", sb); ocfs2_sync_blockdev(sb); ocfs2_dismount_volume(sb, 0); @@ -1722,7 +1712,7 @@ static int ocfs2_statfs(struct dentry *dentry, struct kstatfs *buf) struct buffer_head *bh = NULL; struct inode *inode = NULL; - mlog_entry("(%p, %p)\n", dentry->d_sb, buf); + mlog(0, "(%p, %p)\n", dentry->d_sb, buf); osb = OCFS2_SB(dentry->d_sb); @@ -1889,8 +1879,6 @@ static int ocfs2_mount_volume(struct super_block *sb) int unlock_super = 0; struct ocfs2_super *osb = OCFS2_SB(sb); - mlog_entry_void(); - if (ocfs2_is_hard_readonly(osb)) goto leave; @@ -1945,7 +1933,7 @@ static void ocfs2_dismount_volume(struct super_block *sb, int mnt_err) struct ocfs2_super *osb = NULL; char nodestr[8]; - mlog_entry("(0x%p)\n", sb); + mlog(0, "(0x%p)\n", sb); BUG_ON(!sb); osb = OCFS2_SB(sb); @@ -2097,8 +2085,6 @@ static int ocfs2_initialize_super(struct super_block *sb, struct ocfs2_super *osb; u64 total_blocks; - mlog_entry_void(); - osb = kzalloc(sizeof(struct ocfs2_super), GFP_KERNEL); if (!osb) { status = -ENOMEM; @@ -2403,8 +2389,6 @@ static int ocfs2_verify_volume(struct ocfs2_dinode *di, { int status = -EAGAIN; - mlog_entry_void(); - if (memcmp(di->i_signature, OCFS2_SUPER_BLOCK_SIGNATURE, strlen(OCFS2_SUPER_BLOCK_SIGNATURE)) == 0) { /* We have to do a raw check of the feature here */ @@ -2472,8 +2456,6 @@ static int ocfs2_check_volume(struct ocfs2_super *osb) * recover * ourselves. */ - mlog_entry_void(); - /* Init our journal object. */ status = ocfs2_journal_init(osb->journal, &dirty); if (status < 0) { @@ -2568,8 +2550,6 @@ finally: */ static void ocfs2_delete_osb(struct ocfs2_super *osb) { - mlog_entry_void(); - /* This function assumes that the caller has the main osb resource */ ocfs2_free_slot_info(osb); diff --git a/fs/ocfs2/symlink.c b/fs/ocfs2/symlink.c index 9975457c981f9..8a81688c57dfc 100644 --- a/fs/ocfs2/symlink.c +++ b/fs/ocfs2/symlink.c @@ -62,8 +62,6 @@ static char *ocfs2_fast_symlink_getlink(struct inode *inode, char *link = NULL; struct ocfs2_dinode *fe; - mlog_entry_void(); - status = ocfs2_read_inode_block(inode, bh); if (status < 0) { mlog_errno(status); @@ -88,8 +86,6 @@ static int ocfs2_readlink(struct dentry *dentry, struct buffer_head *bh = NULL; struct inode *inode = dentry->d_inode; - mlog_entry_void(); - link = ocfs2_fast_symlink_getlink(inode, &bh); if (IS_ERR(link)) { ret = PTR_ERR(link); @@ -117,8 +113,6 @@ static void *ocfs2_fast_follow_link(struct dentry *dentry, struct inode *inode = dentry->d_inode; struct buffer_head *bh = NULL; - mlog_entry_void(); - BUG_ON(!ocfs2_inode_is_fast_symlink(inode)); target = ocfs2_fast_symlink_getlink(inode, &bh); if (IS_ERR(target)) { diff --git a/fs/ocfs2/xattr.c b/fs/ocfs2/xattr.c index 67cd43914641f..81f98b7f75028 100644 --- a/fs/ocfs2/xattr.c +++ b/fs/ocfs2/xattr.c @@ -5538,7 +5538,7 @@ static int ocfs2_xattr_set_entry_bucket(struct inode *inode, int ret; struct ocfs2_xa_loc loc; - mlog_entry("Set xattr %s in xattr bucket\n", xi->xi_name); + mlog(0, "Set xattr %s in xattr bucket\n", xi->xi_name); ocfs2_init_xattr_bucket_xa_loc(&loc, xs->bucket, xs->not_found ? NULL : xs->here); @@ -5581,7 +5581,7 @@ static int ocfs2_xattr_set_entry_index_block(struct inode *inode, { int ret; - mlog_entry("Set xattr %s in xattr index block\n", xi->xi_name); + mlog(0, "Set xattr %s in xattr index block\n", xi->xi_name); ret = ocfs2_xattr_set_entry_bucket(inode, xi, xs, ctxt); if (!ret) -- GitLab From c1e8d35ef5ffb393b94a192034b5e3541e005d75 Mon Sep 17 00:00:00 2001 From: Tao Ma Date: Mon, 7 Mar 2011 16:43:21 +0800 Subject: [PATCH 0103/2822] ocfs2: Remove EXIT from masklog. mlog_exit is used to record the exit status of a function. But because it is added in so many functions, if we enable it, the system logs get filled up quickly and cause too much I/O. So actually no one can open it for a production system or even for a test. This patch just try to remove it or change it. So: 1. if all the error paths already use mlog_errno, it is just removed. Otherwise, it will be replaced by mlog_errno. 2. if it is used to print some return value, it is replaced with mlog(0,...). mlog_exit_ptr is changed to mlog(0. All those mlog(0,...) will be replaced with trace events later. Signed-off-by: Tao Ma --- fs/ocfs2/alloc.c | 26 +++---------- fs/ocfs2/aops.c | 19 ++-------- fs/ocfs2/buffer_head_io.c | 7 ++-- fs/ocfs2/cluster/heartbeat.c | 1 - fs/ocfs2/cluster/masklog.c | 3 +- fs/ocfs2/cluster/masklog.h | 44 ---------------------- fs/ocfs2/dcache.c | 3 +- fs/ocfs2/dir.c | 20 +++++----- fs/ocfs2/dlm/dlmrecovery.c | 5 +-- fs/ocfs2/dlmglue.c | 71 +++--------------------------------- fs/ocfs2/export.c | 6 +-- fs/ocfs2/extent_map.c | 1 - fs/ocfs2/file.c | 21 +---------- fs/ocfs2/inode.c | 15 +------- fs/ocfs2/ioctl.c | 2 - fs/ocfs2/journal.c | 19 ---------- fs/ocfs2/localalloc.c | 35 ++++++++++-------- fs/ocfs2/mmap.c | 2 +- fs/ocfs2/namei.c | 47 ++++++++++++++++-------- fs/ocfs2/quota_global.c | 17 +++++---- fs/ocfs2/quota_local.c | 3 +- fs/ocfs2/resize.c | 6 +-- fs/ocfs2/slot_map.c | 1 - fs/ocfs2/suballoc.c | 54 ++++++++++++++++++--------- fs/ocfs2/super.c | 37 +++++++------------ fs/ocfs2/symlink.c | 7 ++-- fs/ocfs2/xattr.c | 2 - 27 files changed, 159 insertions(+), 315 deletions(-) diff --git a/fs/ocfs2/alloc.c b/fs/ocfs2/alloc.c index 47a6ce84e67f3..80ffbe3dd32f4 100644 --- a/fs/ocfs2/alloc.c +++ b/fs/ocfs2/alloc.c @@ -985,7 +985,7 @@ int ocfs2_num_free_extents(struct ocfs2_super *osb, bail: brelse(eb_bh); - mlog_exit(retval); + mlog(0, "retval = %d\n", retval); return retval; } @@ -1070,8 +1070,8 @@ bail: brelse(bhs[i]); bhs[i] = NULL; } + mlog_errno(status); } - mlog_exit(status); return status; } @@ -1326,7 +1326,6 @@ bail: kfree(new_eb_bhs); } - mlog_exit(status); return status; } @@ -1407,7 +1406,6 @@ static int ocfs2_shift_tree_depth(handle_t *handle, bail: brelse(new_eb_bh); - mlog_exit(status); return status; } @@ -1493,7 +1491,6 @@ static int ocfs2_find_branch_target(struct ocfs2_extent_tree *et, bail: brelse(bh); - mlog_exit(status); return status; } @@ -4552,7 +4549,7 @@ static int ocfs2_figure_insert_type(struct ocfs2_extent_tree *et, ocfs2_et_get_last_eb_blk(et), &bh); if (ret) { - mlog_exit(ret); + mlog_errno(ret); goto out; } eb = (struct ocfs2_extent_block *) bh->b_data; @@ -4716,7 +4713,6 @@ int ocfs2_insert_extent(handle_t *handle, bail: brelse(last_eb_bh); - mlog_exit(status); return status; } @@ -4818,7 +4814,6 @@ int ocfs2_add_clusters_in_btree(handle_t *handle, } leave: - mlog_exit(status); if (reason_ret) *reason_ret = reason; return status; @@ -5029,7 +5024,7 @@ int ocfs2_split_extent(handle_t *handle, ocfs2_et_get_last_eb_blk(et), &last_eb_bh); if (ret) { - mlog_exit(ret); + mlog_errno(ret); goto out; } @@ -5849,7 +5844,6 @@ int ocfs2_truncate_log_append(struct ocfs2_super *osb, osb->truncated_clusters += num_clusters; bail: - mlog_exit(status); return status; } @@ -5920,7 +5914,6 @@ static int ocfs2_replay_truncate_records(struct ocfs2_super *osb, osb->truncated_clusters = 0; bail: - mlog_exit(status); return status; } @@ -5995,7 +5988,6 @@ out_mutex: iput(data_alloc_inode); out: - mlog_exit(status); return status; } @@ -6023,8 +6015,6 @@ static void ocfs2_truncate_log_worker(struct work_struct *work) mlog_errno(status); else ocfs2_init_steal_slots(osb); - - mlog_exit(status); } #define OCFS2_TRUNCATE_LOG_FLUSH_INTERVAL (2 * HZ) @@ -6070,7 +6060,6 @@ static int ocfs2_get_truncate_log_info(struct ocfs2_super *osb, *tl_inode = inode; *tl_bh = bh; bail: - mlog_exit(status); return status; } @@ -6141,9 +6130,9 @@ bail: if (status < 0 && (*tl_copy)) { kfree(*tl_copy); *tl_copy = NULL; + mlog_errno(status); } - mlog_exit(status); return status; } @@ -6201,7 +6190,6 @@ int ocfs2_complete_truncate_log_recovery(struct ocfs2_super *osb, bail_up: mutex_unlock(&tl_inode->i_mutex); - mlog_exit(status); return status; } @@ -6221,8 +6209,6 @@ void ocfs2_truncate_log_shutdown(struct ocfs2_super *osb) brelse(osb->osb_tl_bh); iput(osb->osb_tl_inode); } - - mlog_exit_void(); } int ocfs2_truncate_log_init(struct ocfs2_super *osb) @@ -6246,7 +6232,6 @@ int ocfs2_truncate_log_init(struct ocfs2_super *osb) osb->osb_tl_bh = tl_bh; osb->osb_tl_inode = tl_inode; - mlog_exit(status); return status; } @@ -7112,7 +7097,6 @@ bail: ocfs2_free_path(path); - mlog_exit(status); return status; } diff --git a/fs/ocfs2/aops.c b/fs/ocfs2/aops.c index 5dbfc9e45195c..9551518be4357 100644 --- a/fs/ocfs2/aops.c +++ b/fs/ocfs2/aops.c @@ -123,7 +123,6 @@ static int ocfs2_symlink_get_block(struct inode *inode, sector_t iblock, bail: brelse(bh); - mlog_exit(err); return err; } @@ -208,7 +207,6 @@ bail: if (err < 0) err = -EIO; - mlog_exit(err); return err; } @@ -323,7 +321,6 @@ out_inode_unlock: out: if (unlock) unlock_page(page); - mlog_exit(ret); return ret; } @@ -402,8 +399,6 @@ static int ocfs2_writepage(struct page *page, struct writeback_control *wbc) ret = block_write_full_page(page, ocfs2_get_block, wbc); - mlog_exit(ret); - return ret; } @@ -484,8 +479,6 @@ static sector_t ocfs2_bmap(struct address_space *mapping, sector_t block) bail: status = err ? 0 : p_blkno; - mlog_exit((int)status); - return status; } @@ -616,7 +609,6 @@ static ssize_t ocfs2_direct_IO(int rw, { struct file *file = iocb->ki_filp; struct inode *inode = file->f_path.dentry->d_inode->i_mapping->host; - int ret; /* * Fallback to buffered I/O if we see an inode without @@ -629,13 +621,10 @@ static ssize_t ocfs2_direct_IO(int rw, if (i_size_read(inode) <= offset) return 0; - ret = __blockdev_direct_IO(rw, iocb, inode, inode->i_sb->s_bdev, - iov, offset, nr_segs, - ocfs2_direct_IO_get_blocks, - ocfs2_dio_end_io, NULL, 0); - - mlog_exit(ret); - return ret; + return __blockdev_direct_IO(rw, iocb, inode, inode->i_sb->s_bdev, + iov, offset, nr_segs, + ocfs2_direct_IO_get_blocks, + ocfs2_dio_end_io, NULL, 0); } static void ocfs2_figure_cluster_boundaries(struct ocfs2_super *osb, diff --git a/fs/ocfs2/buffer_head_io.c b/fs/ocfs2/buffer_head_io.c index 024bd45b7a48d..c23846dbfc8f8 100644 --- a/fs/ocfs2/buffer_head_io.c +++ b/fs/ocfs2/buffer_head_io.c @@ -66,6 +66,7 @@ int ocfs2_write_block(struct ocfs2_super *osb, struct buffer_head *bh, * can get modified during recovery even if read-only. */ if (ocfs2_is_hard_readonly(osb)) { ret = -EROFS; + mlog_errno(ret); goto out; } @@ -91,11 +92,11 @@ int ocfs2_write_block(struct ocfs2_super *osb, struct buffer_head *bh, * uptodate. */ ret = -EIO; put_bh(bh); + mlog_errno(ret); } ocfs2_metadata_cache_io_unlock(ci); out: - mlog_exit(ret); return ret; } @@ -374,7 +375,6 @@ int ocfs2_read_blocks(struct ocfs2_caching_info *ci, u64 block, int nr, bail: - mlog_exit(status); return status; } @@ -413,6 +413,7 @@ int ocfs2_write_super_or_backup(struct ocfs2_super *osb, if (ocfs2_is_hard_readonly(osb) || ocfs2_is_soft_readonly(osb)) { ret = -EROFS; + mlog_errno(ret); goto out; } @@ -432,9 +433,9 @@ int ocfs2_write_super_or_backup(struct ocfs2_super *osb, if (!buffer_uptodate(bh)) { ret = -EIO; put_bh(bh); + mlog_errno(ret); } out: - mlog_exit(ret); return ret; } diff --git a/fs/ocfs2/cluster/heartbeat.c b/fs/ocfs2/cluster/heartbeat.c index 929178ce17a23..fc9e96a03a6b5 100644 --- a/fs/ocfs2/cluster/heartbeat.c +++ b/fs/ocfs2/cluster/heartbeat.c @@ -1679,7 +1679,6 @@ static int o2hb_populate_slot_data(struct o2hb_region *reg) } out: - mlog_exit(ret); return ret; } diff --git a/fs/ocfs2/cluster/masklog.c b/fs/ocfs2/cluster/masklog.c index bac64570c5259..fdc302ddafe82 100644 --- a/fs/ocfs2/cluster/masklog.c +++ b/fs/ocfs2/cluster/masklog.c @@ -30,7 +30,7 @@ struct mlog_bits mlog_and_bits = MLOG_BITS_RHS(MLOG_INITIAL_AND_MASK); EXPORT_SYMBOL_GPL(mlog_and_bits); -struct mlog_bits mlog_not_bits = MLOG_BITS_RHS(MLOG_INITIAL_NOT_MASK); +struct mlog_bits mlog_not_bits = MLOG_BITS_RHS(0); EXPORT_SYMBOL_GPL(mlog_not_bits); static ssize_t mlog_mask_show(u64 mask, char *buf) @@ -80,7 +80,6 @@ struct mlog_attribute { } static struct mlog_attribute mlog_attrs[MLOG_MAX_BITS] = { - define_mask(EXIT), define_mask(TCP), define_mask(MSG), define_mask(SOCKET), diff --git a/fs/ocfs2/cluster/masklog.h b/fs/ocfs2/cluster/masklog.h index 6e20877436b94..51ee790c7678f 100644 --- a/fs/ocfs2/cluster/masklog.h +++ b/fs/ocfs2/cluster/masklog.h @@ -82,7 +82,6 @@ /* bits that are frequently given and infrequently matched in the low word */ /* NOTE: If you add a flag, you need to also update masklog.c! */ -#define ML_EXIT 0x0000000000000002ULL /* func call exit */ #define ML_TCP 0x0000000000000004ULL /* net cluster/tcp.c */ #define ML_MSG 0x0000000000000008ULL /* net network messages */ #define ML_SOCKET 0x0000000000000010ULL /* net socket lifetime */ @@ -123,7 +122,6 @@ #define ML_KTHREAD 0x4000000000000000ULL /* kernel thread activity */ #define MLOG_INITIAL_AND_MASK (ML_ERROR|ML_NOTICE) -#define MLOG_INITIAL_NOT_MASK (ML_EXIT) #ifndef MLOG_MASK_PREFIX #define MLOG_MASK_PREFIX 0 #endif @@ -221,48 +219,6 @@ extern struct mlog_bits mlog_and_bits, mlog_not_bits; mlog(ML_ERROR, "status = %lld\n", (long long)_st); \ } while (0) -#if defined(CONFIG_OCFS2_DEBUG_MASKLOG) -/* - * We disable this for sparse. - */ -#if !defined(__CHECKER__) -#define mlog_exit(st) do { \ - if (__builtin_types_compatible_p(typeof(st), unsigned long)) \ - mlog(ML_EXIT, "EXIT: %lu\n", (unsigned long) (st)); \ - else if (__builtin_types_compatible_p(typeof(st), signed long)) \ - mlog(ML_EXIT, "EXIT: %ld\n", (signed long) (st)); \ - else if (__builtin_types_compatible_p(typeof(st), unsigned int) \ - || __builtin_types_compatible_p(typeof(st), unsigned short) \ - || __builtin_types_compatible_p(typeof(st), unsigned char)) \ - mlog(ML_EXIT, "EXIT: %u\n", (unsigned int) (st)); \ - else if (__builtin_types_compatible_p(typeof(st), signed int) \ - || __builtin_types_compatible_p(typeof(st), signed short) \ - || __builtin_types_compatible_p(typeof(st), signed char)) \ - mlog(ML_EXIT, "EXIT: %d\n", (signed int) (st)); \ - else if (__builtin_types_compatible_p(typeof(st), long long)) \ - mlog(ML_EXIT, "EXIT: %lld\n", (long long) (st)); \ - else \ - mlog(ML_EXIT, "EXIT: %llu\n", (unsigned long long) (st)); \ -} while (0) -#else -#define mlog_exit(st) do { \ - mlog(ML_EXIT, "EXIT: %lld\n", (long long) (st)); \ -} while (0) -#endif - -#define mlog_exit_ptr(ptr) do { \ - mlog(ML_EXIT, "EXIT: %p\n", ptr); \ -} while (0) - -#define mlog_exit_void() do { \ - mlog(ML_EXIT, "EXIT\n"); \ -} while (0) -#else -#define mlog_exit(...) do { } while (0) -#define mlog_exit_ptr(...) do { } while (0) -#define mlog_exit_void(...) do { } while (0) -#endif /* defined(CONFIG_OCFS2_DEBUG_MASKLOG) */ - #define mlog_bug_on_msg(cond, fmt, args...) do { \ if (cond) { \ mlog(ML_ERROR, "bug expression: " #cond "\n"); \ diff --git a/fs/ocfs2/dcache.c b/fs/ocfs2/dcache.c index 67d17a45773b0..c26551c25e8e8 100644 --- a/fs/ocfs2/dcache.c +++ b/fs/ocfs2/dcache.c @@ -123,8 +123,7 @@ valid: ret = 1; bail: - mlog_exit(ret); - + mlog(0, "ret = %d\n", ret); return ret; } diff --git a/fs/ocfs2/dir.c b/fs/ocfs2/dir.c index 2c983f083f8ac..2fc6c3673beaa 100644 --- a/fs/ocfs2/dir.c +++ b/fs/ocfs2/dir.c @@ -400,7 +400,7 @@ static int inline ocfs2_search_dirblock(struct buffer_head *bh, } bail: - mlog_exit(ret); + mlog(0, "ret = %d\n", ret); return ret; } @@ -784,7 +784,7 @@ cleanup_and_exit: for (; ra_ptr < ra_max; ra_ptr++) brelse(bh_use[ra_ptr]); - mlog_exit_ptr(ret); + mlog(0, "ret = %p\n", ret); return ret; } @@ -1198,7 +1198,6 @@ static int __ocfs2_delete_entry(handle_t *handle, struct inode *dir, de = (struct ocfs2_dir_entry *)((char *)de + le16_to_cpu(de->rec_len)); } bail: - mlog_exit(status); return status; } @@ -1759,8 +1758,9 @@ int __ocfs2_add_entry(handle_t *handle, * from ever getting here. */ retval = -ENOSPC; bail: + if (retval) + mlog_errno(retval); - mlog_exit(retval); return retval; } @@ -2045,9 +2045,10 @@ int ocfs2_readdir(struct file * filp, void * dirent, filldir_t filldir) dirent, filldir, NULL); ocfs2_inode_unlock(inode, lock_level); + if (error) + mlog_errno(error); bail_nolock: - mlog_exit(error); return error; } @@ -2119,7 +2120,8 @@ int ocfs2_check_dir_for_entry(struct inode *dir, bail: ocfs2_free_dir_lookup_result(&lookup); - mlog_exit(ret); + if (ret) + mlog_errno(ret); return ret; } @@ -2372,7 +2374,6 @@ static int ocfs2_fill_new_dir_el(struct ocfs2_super *osb, bail: brelse(new_bh); - mlog_exit(status); return status; } @@ -3227,7 +3228,6 @@ static int ocfs2_do_extend_dir(struct super_block *sb, bail: if (did_quota && status < 0) dquot_free_space_nodirty(dir, ocfs2_clusters_to_bytes(sb, 1)); - mlog_exit(status); return status; } @@ -3426,7 +3426,6 @@ bail: brelse(new_bh); - mlog_exit(status); return status; } @@ -3573,8 +3572,9 @@ next: status = 0; bail: brelse(bh); + if (status) + mlog_errno(status); - mlog_exit(status); return status; } diff --git a/fs/ocfs2/dlm/dlmrecovery.c b/fs/ocfs2/dlm/dlmrecovery.c index 6602b23c2ab3f..f1beb6fc254d1 100644 --- a/fs/ocfs2/dlm/dlmrecovery.c +++ b/fs/ocfs2/dlm/dlmrecovery.c @@ -727,7 +727,6 @@ static int dlm_remaster_locks(struct dlm_ctxt *dlm, u8 dead_node) if (destroy) dlm_destroy_recovery_area(dlm, dead_node); - mlog_exit(status); return status; } @@ -1496,9 +1495,9 @@ leave: kfree(buf); if (item) kfree(item); + mlog_errno(ret); } - mlog_exit(ret); return ret; } @@ -1567,7 +1566,6 @@ leave: dlm_lockres_put(res); } kfree(data); - mlog_exit(ret); } @@ -1986,7 +1984,6 @@ leave: dlm_lock_put(newlock); } - mlog_exit(ret); return ret; } diff --git a/fs/ocfs2/dlmglue.c b/fs/ocfs2/dlmglue.c index c2f3fa1c47229..7eb4b8da5cbc5 100644 --- a/fs/ocfs2/dlmglue.c +++ b/fs/ocfs2/dlmglue.c @@ -406,8 +406,6 @@ static void ocfs2_build_lock_name(enum ocfs2_lock_type type, BUG_ON(len != (OCFS2_LOCK_ID_MAX_LEN - 1)); mlog(0, "built lock resource with name: %s\n", name); - - mlog_exit_void(); } static DEFINE_SPINLOCK(ocfs2_dlm_tracking_lock); @@ -752,7 +750,6 @@ void ocfs2_lock_res_free(struct ocfs2_lock_res *res) memset(&res->l_lksb, 0, sizeof(res->l_lksb)); res->l_flags = 0UL; - mlog_exit_void(); } static inline void ocfs2_inc_holders(struct ocfs2_lock_res *lockres, @@ -770,8 +767,6 @@ static inline void ocfs2_inc_holders(struct ocfs2_lock_res *lockres, default: BUG(); } - - mlog_exit_void(); } static inline void ocfs2_dec_holders(struct ocfs2_lock_res *lockres, @@ -791,7 +786,6 @@ static inline void ocfs2_dec_holders(struct ocfs2_lock_res *lockres, default: BUG(); } - mlog_exit_void(); } /* WARNING: This function lives in a world where the only three lock @@ -850,8 +844,6 @@ static inline void ocfs2_generic_handle_downconvert_action(struct ocfs2_lock_res lockres_clear_flags(lockres, OCFS2_LOCK_BLOCKED); } lockres_clear_flags(lockres, OCFS2_LOCK_BUSY); - - mlog_exit_void(); } static inline void ocfs2_generic_handle_convert_action(struct ocfs2_lock_res *lockres) @@ -877,8 +869,6 @@ static inline void ocfs2_generic_handle_convert_action(struct ocfs2_lock_res *lo lockres_or_flags(lockres, OCFS2_LOCK_UPCONVERT_FINISHING); lockres_clear_flags(lockres, OCFS2_LOCK_BUSY); - - mlog_exit_void(); } static inline void ocfs2_generic_handle_attach_action(struct ocfs2_lock_res *lockres) @@ -894,8 +884,6 @@ static inline void ocfs2_generic_handle_attach_action(struct ocfs2_lock_res *loc lockres->l_level = lockres->l_requested; lockres_or_flags(lockres, OCFS2_LOCK_ATTACHED); lockres_clear_flags(lockres, OCFS2_LOCK_BUSY); - - mlog_exit_void(); } static int ocfs2_generic_handle_bast(struct ocfs2_lock_res *lockres, @@ -923,8 +911,7 @@ static int ocfs2_generic_handle_bast(struct ocfs2_lock_res *lockres, if (needs_downconvert) lockres_or_flags(lockres, OCFS2_LOCK_BLOCKED); - - mlog_exit(needs_downconvert); + mlog(0, "needs_downconvert = %d\n", needs_downconvert); return needs_downconvert; } @@ -1145,7 +1132,6 @@ static void ocfs2_unlock_ast(struct ocfs2_dlm_lksb *lksb, int error) "unlock_action %d\n", error, lockres->l_name, lockres->l_unlock_action); spin_unlock_irqrestore(&lockres->l_lock, flags); - mlog_exit_void(); return; } @@ -1169,8 +1155,6 @@ static void ocfs2_unlock_ast(struct ocfs2_dlm_lksb *lksb, int error) lockres->l_unlock_action = OCFS2_UNLOCK_INVALID; wake_up(&lockres->l_event); spin_unlock_irqrestore(&lockres->l_lock, flags); - - mlog_exit_void(); } /* @@ -1226,7 +1210,6 @@ static inline void ocfs2_recover_from_dlm_error(struct ocfs2_lock_res *lockres, spin_unlock_irqrestore(&lockres->l_lock, flags); wake_up(&lockres->l_event); - mlog_exit_void(); } /* Note: If we detect another process working on the lock (i.e., @@ -1273,7 +1256,6 @@ static int ocfs2_lock_create(struct ocfs2_super *osb, mlog(0, "lock %s, return from ocfs2_dlm_lock\n", lockres->l_name); bail: - mlog_exit(ret); return ret; } @@ -1561,7 +1543,6 @@ out: caller_ip); } #endif - mlog_exit(ret); return ret; } @@ -1591,7 +1572,6 @@ static void __ocfs2_cluster_unlock(struct ocfs2_super *osb, if (lockres->l_lockdep_map.key != NULL) rwsem_release(&lockres->l_lockdep_map, 1, caller_ip); #endif - mlog_exit_void(); } static int ocfs2_create_new_lock(struct ocfs2_super *osb, @@ -1658,7 +1638,6 @@ int ocfs2_create_new_inode_locks(struct inode *inode) } bail: - mlog_exit(ret); return ret; } @@ -1674,10 +1653,8 @@ int ocfs2_rw_lock(struct inode *inode, int write) (unsigned long long)OCFS2_I(inode)->ip_blkno, write ? "EXMODE" : "PRMODE"); - if (ocfs2_mount_local(osb)) { - mlog_exit(0); + if (ocfs2_mount_local(osb)) return 0; - } lockres = &OCFS2_I(inode)->ip_rw_lockres; @@ -1688,7 +1665,6 @@ int ocfs2_rw_lock(struct inode *inode, int write) if (status < 0) mlog_errno(status); - mlog_exit(status); return status; } @@ -1704,8 +1680,6 @@ void ocfs2_rw_unlock(struct inode *inode, int write) if (!ocfs2_mount_local(osb)) ocfs2_cluster_unlock(OCFS2_SB(inode->i_sb), lockres, level); - - mlog_exit_void(); } /* @@ -1733,7 +1707,6 @@ int ocfs2_open_lock(struct inode *inode) mlog_errno(status); out: - mlog_exit(status); return status; } @@ -1766,7 +1739,6 @@ int ocfs2_try_open_lock(struct inode *inode, int write) level, DLM_LKF_NOQUEUE, 0); out: - mlog_exit(status); return status; } @@ -1792,7 +1764,7 @@ void ocfs2_open_unlock(struct inode *inode) DLM_LOCK_EX); out: - mlog_exit_void(); + return; } static int ocfs2_flock_handle_signal(struct ocfs2_lock_res *lockres, @@ -2028,8 +2000,6 @@ static void ocfs2_downconvert_on_unlock(struct ocfs2_super *osb, if (kick) ocfs2_wake_downconvert_thread(osb); - - mlog_exit_void(); } #define OCFS2_SEC_BITS 34 @@ -2089,8 +2059,6 @@ static void __ocfs2_stuff_meta_lvb(struct inode *inode) out: mlog_meta_lvb(0, lockres); - - mlog_exit_void(); } static void ocfs2_unpack_timespec(struct timespec *spec, @@ -2136,8 +2104,6 @@ static void ocfs2_refresh_inode_from_lvb(struct inode *inode) ocfs2_unpack_timespec(&inode->i_ctime, be64_to_cpu(lvb->lvb_ictime_packed)); spin_unlock(&oi->ip_lock); - - mlog_exit_void(); } static inline int ocfs2_meta_lvb_is_trustable(struct inode *inode, @@ -2184,7 +2150,7 @@ refresh_check: status = 1; bail: - mlog_exit(status); + mlog(0, "status %d\n", status); return status; } @@ -2202,8 +2168,6 @@ static inline void ocfs2_complete_lock_res_refresh(struct ocfs2_lock_res *lockre spin_unlock_irqrestore(&lockres->l_lock, flags); wake_up(&lockres->l_event); - - mlog_exit_void(); } /* may or may not return a bh if it went to disk. */ @@ -2284,7 +2248,6 @@ static int ocfs2_inode_lock_update(struct inode *inode, bail_refresh: ocfs2_complete_lock_res_refresh(lockres, status); bail: - mlog_exit(status); return status; } @@ -2419,7 +2382,6 @@ bail: if (local_bh) brelse(local_bh); - mlog_exit(status); return status; } @@ -2496,7 +2458,6 @@ int ocfs2_inode_lock_atime(struct inode *inode, } else *level = 0; - mlog_exit(ret); return ret; } @@ -2514,8 +2475,6 @@ void ocfs2_inode_unlock(struct inode *inode, if (!ocfs2_is_hard_readonly(OCFS2_SB(inode->i_sb)) && !ocfs2_mount_local(osb)) ocfs2_cluster_unlock(OCFS2_SB(inode->i_sb), lockres, level); - - mlog_exit_void(); } int ocfs2_orphan_scan_lock(struct ocfs2_super *osb, u32 *seqno) @@ -2597,7 +2556,6 @@ int ocfs2_super_lock(struct ocfs2_super *osb, ocfs2_track_lock_refresh(lockres); } bail: - mlog_exit(status); return status; } @@ -3057,7 +3015,6 @@ bail: kthread_stop(osb->dc_task); } - mlog_exit(status); return status; } @@ -3086,8 +3043,6 @@ void ocfs2_dlm_shutdown(struct ocfs2_super *osb, osb->cconn = NULL; ocfs2_dlm_shutdown_debug(osb); - - mlog_exit_void(); } static int ocfs2_drop_lock(struct ocfs2_super *osb, @@ -3169,7 +3124,6 @@ static int ocfs2_drop_lock(struct ocfs2_super *osb, ocfs2_wait_on_busy_lock(lockres); out: - mlog_exit(0); return 0; } @@ -3251,7 +3205,6 @@ int ocfs2_drop_inode_locks(struct inode *inode) if (err < 0 && !status) status = err; - mlog_exit(status); return status; } @@ -3314,7 +3267,6 @@ static int ocfs2_downconvert_lock(struct ocfs2_super *osb, ret = 0; bail: - mlog_exit(ret); return ret; } @@ -3362,7 +3314,6 @@ static int ocfs2_cancel_convert(struct ocfs2_super *osb, mlog(ML_BASTS, "lockres %s\n", lockres->l_name); - mlog_exit(ret); return ret; } @@ -3552,14 +3503,14 @@ downconvert: gen); leave: - mlog_exit(ret); + if (ret) + mlog_errno(ret); return ret; leave_requeue: spin_unlock_irqrestore(&lockres->l_lock, flags); ctl->requeue = 1; - mlog_exit(0); return 0; } @@ -3800,8 +3751,6 @@ static void ocfs2_set_qinfo_lvb(struct ocfs2_lock_res *lockres) lvb->lvb_blocks = cpu_to_be32(oinfo->dqi_gi.dqi_blocks); lvb->lvb_free_blk = cpu_to_be32(oinfo->dqi_gi.dqi_free_blk); lvb->lvb_free_entry = cpu_to_be32(oinfo->dqi_gi.dqi_free_entry); - - mlog_exit_void(); } void ocfs2_qinfo_unlock(struct ocfs2_mem_dqinfo *oinfo, int ex) @@ -3812,7 +3761,6 @@ void ocfs2_qinfo_unlock(struct ocfs2_mem_dqinfo *oinfo, int ex) if (!ocfs2_is_hard_readonly(osb) && !ocfs2_mount_local(osb)) ocfs2_cluster_unlock(osb, lockres, level); - mlog_exit_void(); } static int ocfs2_refresh_qinfo(struct ocfs2_mem_dqinfo *oinfo) @@ -3889,7 +3837,6 @@ int ocfs2_qinfo_lock(struct ocfs2_mem_dqinfo *oinfo, int ex) ocfs2_qinfo_unlock(oinfo, ex); ocfs2_complete_lock_res_refresh(lockres, status); bail: - mlog_exit(status); return status; } @@ -3968,8 +3915,6 @@ unqueue: if (ctl.unblock_action != UNBLOCK_CONTINUE && lockres->l_ops->post_unlock) lockres->l_ops->post_unlock(osb, lockres); - - mlog_exit_void(); } static void ocfs2_schedule_blocked_lock(struct ocfs2_super *osb, @@ -3995,8 +3940,6 @@ static void ocfs2_schedule_blocked_lock(struct ocfs2_super *osb, osb->blocked_lock_count++; } spin_unlock(&osb->dc_task_lock); - - mlog_exit_void(); } static void ocfs2_downconvert_thread_do_work(struct ocfs2_super *osb) @@ -4027,8 +3970,6 @@ static void ocfs2_downconvert_thread_do_work(struct ocfs2_super *osb) spin_lock(&osb->dc_task_lock); } spin_unlock(&osb->dc_task_lock); - - mlog_exit_void(); } static int ocfs2_downconvert_thread_lists_empty(struct ocfs2_super *osb) diff --git a/fs/ocfs2/export.c b/fs/ocfs2/export.c index b90c751ba9385..96d7ed7f83057 100644 --- a/fs/ocfs2/export.c +++ b/fs/ocfs2/export.c @@ -141,7 +141,7 @@ check_gen: mlog_errno(PTR_ERR(result)); bail: - mlog_exit_ptr(result); + mlog(0, "result = %p\n", result); return result; } @@ -178,7 +178,7 @@ bail_unlock: ocfs2_inode_unlock(dir, 0); bail: - mlog_exit_ptr(parent); + mlog(0, "parent %p\n", parent); return parent; } @@ -243,7 +243,7 @@ static int ocfs2_encode_fh(struct dentry *dentry, u32 *fh_in, int *max_len, *max_len = len; bail: - mlog_exit(type); + mlog(0, "type = %d\n", type); return type; } diff --git a/fs/ocfs2/extent_map.c b/fs/ocfs2/extent_map.c index ed9916a9a2710..7d74d176706a4 100644 --- a/fs/ocfs2/extent_map.c +++ b/fs/ocfs2/extent_map.c @@ -897,7 +897,6 @@ int ocfs2_read_virt_blocks(struct inode *inode, u64 v_block, int nr, } out: - mlog_exit(rc); return rc; } diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c index 71375d7b7bbe8..1e1a93aa05264 100644 --- a/fs/ocfs2/file.c +++ b/fs/ocfs2/file.c @@ -135,7 +135,6 @@ static int ocfs2_file_open(struct inode *inode, struct file *file) } leave: - mlog_exit(status); return status; } @@ -154,8 +153,6 @@ static int ocfs2_file_release(struct inode *inode, struct file *file) ocfs2_free_file_private(inode, file); - mlog_exit(0); - return 0; } @@ -195,7 +192,8 @@ static int ocfs2_sync_file(struct file *file, int datasync) err = jbd2_journal_force_commit(journal); bail: - mlog_exit(err); + if (err) + mlog_errno(err); return (err < 0) ? -EIO : 0; } @@ -278,7 +276,6 @@ int ocfs2_update_inode_atime(struct inode *inode, out_commit: ocfs2_commit_trans(OCFS2_SB(inode->i_sb), handle); out: - mlog_exit(ret); return ret; } @@ -300,7 +297,6 @@ static int ocfs2_set_inode_size(handle_t *handle, } bail: - mlog_exit(status); return status; } @@ -424,8 +420,6 @@ static int ocfs2_orphan_for_truncate(struct ocfs2_super *osb, out_commit: ocfs2_commit_trans(osb, handle); out: - - mlog_exit(status); return status; } @@ -520,7 +514,6 @@ bail: if (!status && OCFS2_I(inode)->ip_clusters == 0) status = ocfs2_try_remove_refcount_tree(inode, di_bh); - mlog_exit(status); return status; } @@ -713,7 +706,6 @@ leave: brelse(bh); bh = NULL; - mlog_exit(status); return status; } @@ -1269,7 +1261,6 @@ bail: mlog_errno(status); } - mlog_exit(status); return status; } @@ -1295,8 +1286,6 @@ int ocfs2_getattr(struct vfsmount *mnt, stat->blksize = osb->s_clustersize; bail: - mlog_exit(err); - return err; } @@ -1318,7 +1307,6 @@ int ocfs2_permission(struct inode *inode, int mask, unsigned int flags) ocfs2_inode_unlock(inode, 0); out: - mlog_exit(ret); return ret; } @@ -1359,7 +1347,6 @@ static int __ocfs2_write_remove_suid(struct inode *inode, out_trans: ocfs2_commit_trans(osb, handle); out: - mlog_exit(ret); return ret; } @@ -2393,7 +2380,6 @@ out_sems: if (written) ret = written; - mlog_exit(ret); return ret; } @@ -2476,7 +2462,6 @@ static ssize_t ocfs2_file_splice_write(struct pipe_inode_info *pipe, balance_dirty_pages_ratelimited_nr(mapping, nr_pages); } - mlog_exit(ret); return ret; } @@ -2507,7 +2492,6 @@ static ssize_t ocfs2_file_splice_read(struct file *in, ret = generic_file_splice_read(in, ppos, pipe, len, flags); bail: - mlog_exit(ret); return ret; } @@ -2588,7 +2572,6 @@ bail: } if (rw_level != -1) ocfs2_rw_unlock(inode, rw_level); - mlog_exit(ret); return ret; } diff --git a/fs/ocfs2/inode.c b/fs/ocfs2/inode.c index 16ee8e96f731f..a96e56f127286 100644 --- a/fs/ocfs2/inode.c +++ b/fs/ocfs2/inode.c @@ -172,7 +172,7 @@ bail: if (!IS_ERR(inode)) { mlog(0, "returning inode with number %llu\n", (unsigned long long)OCFS2_I(inode)->ip_blkno); - mlog_exit_ptr(inode); + mlog(0, "inode %p\n", inode); } return inode; @@ -203,7 +203,6 @@ static int ocfs2_find_actor(struct inode *inode, void *opaque) ret = 1; bail: - mlog_exit(ret); return ret; } @@ -235,7 +234,6 @@ static int ocfs2_init_locked_inode(struct inode *inode, void *opaque) lockdep_set_class(&OCFS2_I(inode)->ip_alloc_sem, &ocfs2_file_ip_alloc_sem_key); - mlog_exit(0); return 0; } @@ -381,7 +379,6 @@ void ocfs2_populate_inode(struct inode *inode, struct ocfs2_dinode *fe, if (S_ISDIR(inode->i_mode)) ocfs2_resv_set_type(&OCFS2_I(inode)->ip_la_data_resv, OCFS2_RESV_FLAG_DIR); - mlog_exit_void(); } static int ocfs2_read_locked_inode(struct inode *inode, @@ -534,7 +531,6 @@ bail: if (args && bh) brelse(bh); - mlog_exit(status); return status; } @@ -598,7 +594,6 @@ static int ocfs2_truncate_for_delete(struct ocfs2_super *osb, out: if (handle) ocfs2_commit_trans(osb, handle); - mlog_exit(status); return status; } @@ -1078,7 +1073,7 @@ bail_unlock_nfs_sync: bail_unblock: ocfs2_unblock_signals(&oldset); bail: - mlog_exit_void(); + return; } static void ocfs2_clear_inode(struct inode *inode) @@ -1177,8 +1172,6 @@ static void ocfs2_clear_inode(struct inode *inode) */ jbd2_journal_release_jbd_inode(OCFS2_SB(inode->i_sb)->journal->j_journal, &oi->ip_jinode); - - mlog_exit_void(); } void ocfs2_evict_inode(struct inode *inode) @@ -1208,7 +1201,6 @@ int ocfs2_drop_inode(struct inode *inode) else res = generic_drop_inode(inode); - mlog_exit_void(); return res; } @@ -1248,8 +1240,6 @@ int ocfs2_inode_revalidate(struct dentry *dentry) } ocfs2_inode_unlock(inode, 0); bail: - mlog_exit(status); - return status; } @@ -1296,7 +1286,6 @@ int ocfs2_mark_inode_dirty(handle_t *handle, ocfs2_journal_dirty(handle, bh); leave: - mlog_exit(status); return status; } diff --git a/fs/ocfs2/ioctl.c b/fs/ocfs2/ioctl.c index 7a48681961521..b4f51e94c8f55 100644 --- a/fs/ocfs2/ioctl.c +++ b/fs/ocfs2/ioctl.c @@ -59,7 +59,6 @@ static int ocfs2_get_inode_attr(struct inode *inode, unsigned *flags) *flags = OCFS2_I(inode)->ip_attr; ocfs2_inode_unlock(inode, 0); - mlog_exit(status); return status; } @@ -125,7 +124,6 @@ bail: brelse(bh); - mlog_exit(status); return status; } diff --git a/fs/ocfs2/journal.c b/fs/ocfs2/journal.c index 7378277b17a47..956509167bf57 100644 --- a/fs/ocfs2/journal.c +++ b/fs/ocfs2/journal.c @@ -335,7 +335,6 @@ static int ocfs2_commit_cache(struct ocfs2_super *osb) ocfs2_wake_downconvert_thread(osb); wake_up(&journal->j_checkpointed); finally: - mlog_exit(status); return status; } @@ -450,8 +449,6 @@ int ocfs2_extend_trans(handle_t *handle, int nblocks) status = 0; bail: - - mlog_exit(status); return status; } @@ -665,7 +662,6 @@ static int __ocfs2_journal_access(handle_t *handle, mlog(ML_ERROR, "Error %d getting %d access to buffer!\n", status, type); - mlog_exit(status); return status; } @@ -739,8 +735,6 @@ void ocfs2_journal_dirty(handle_t *handle, struct buffer_head *bh) status = jbd2_journal_dirty_metadata(handle, bh); BUG_ON(status); - - mlog_exit_void(); } #define OCFS2_DEFAULT_COMMIT_INTERVAL (HZ * JBD2_DEFAULT_MAX_COMMIT_AGE) @@ -854,7 +848,6 @@ done: } } - mlog_exit(status); return status; } @@ -899,7 +892,6 @@ static int ocfs2_journal_toggle_dirty(struct ocfs2_super *osb, if (status < 0) mlog_errno(status); - mlog_exit(status); return status; } @@ -989,7 +981,6 @@ void ocfs2_journal_shutdown(struct ocfs2_super *osb) done: if (inode) iput(inode); - mlog_exit_void(); } static void ocfs2_clear_journal_error(struct super_block *sb, @@ -1048,7 +1039,6 @@ int ocfs2_journal_load(struct ocfs2_journal *journal, int local, int replayed) osb->commit_task = NULL; done: - mlog_exit(status); return status; } @@ -1072,7 +1062,6 @@ int ocfs2_journal_wipe(struct ocfs2_journal *journal, int full) mlog_errno(status); bail: - mlog_exit(status); return status; } @@ -1146,7 +1135,6 @@ static int ocfs2_force_read_journal(struct inode *inode) bail: for(i = 0; i < CONCURRENT_JOURNAL_FILL; i++) brelse(bhs[i]); - mlog_exit(status); return status; } @@ -1236,7 +1224,6 @@ void ocfs2_complete_recovery(struct work_struct *work) } mlog(0, "Recovery completion\n"); - mlog_exit_void(); } /* NOTE: This function always eats your references to la_dinode and @@ -1432,7 +1419,6 @@ bail: if (rm_quota) kfree(rm_quota); - mlog_exit(status); /* no one is callint kthread_stop() for us so the kthread() api * requires that we call do_exit(). And it isn't exported, but * complete_and_exit() seems to be a minimal wrapper around it. */ @@ -1469,8 +1455,6 @@ void ocfs2_recovery_thread(struct ocfs2_super *osb, int node_num) out: mutex_unlock(&osb->recovery_lock); wake_up(&osb->recovery_event); - - mlog_exit_void(); } static int ocfs2_read_journal_inode(struct ocfs2_super *osb, @@ -1646,7 +1630,6 @@ done: brelse(bh); - mlog_exit(status); return status; } @@ -1716,7 +1699,6 @@ static int ocfs2_recover_node(struct ocfs2_super *osb, status = 0; done: - mlog_exit(status); return status; } @@ -1826,7 +1808,6 @@ int ocfs2_mark_dead_nodes(struct ocfs2_super *osb) status = 0; bail: - mlog_exit(status); return status; } diff --git a/fs/ocfs2/localalloc.c b/fs/ocfs2/localalloc.c index 5f08c703f3541..36636e1c84e74 100644 --- a/fs/ocfs2/localalloc.c +++ b/fs/ocfs2/localalloc.c @@ -364,7 +364,8 @@ bail: mlog(0, "Local alloc window bits = %d\n", osb->local_alloc_bits); - mlog_exit(status); + if (status) + mlog_errno(status); return status; } @@ -478,8 +479,6 @@ out: if (alloc_copy) kfree(alloc_copy); - - mlog_exit_void(); } /* @@ -548,7 +547,8 @@ bail: iput(inode); } - mlog_exit(status); + if (status) + mlog_errno(status); return status; } @@ -614,7 +614,8 @@ out_mutex: out: if (!status) ocfs2_init_steal_slots(osb); - mlog_exit(status); + if (status) + mlog_errno(status); return status; } @@ -724,7 +725,8 @@ bail: mlog(0, "bits=%d, slot=%d, ret=%d\n", bits_wanted, osb->slot_num, status); - mlog_exit(status); + if (status) + mlog_errno(status); return status; } @@ -779,7 +781,8 @@ int ocfs2_claim_local_alloc_bits(struct ocfs2_super *osb, ocfs2_journal_dirty(handle, osb->local_alloc_bh); bail: - mlog_exit(status); + if (status) + mlog_errno(status); return status; } @@ -794,7 +797,7 @@ static u32 ocfs2_local_alloc_count_bits(struct ocfs2_dinode *alloc) for (i = 0; i < le16_to_cpu(la->la_size); i++) count += hweight8(buffer[i]); - mlog_exit(count); + mlog(0, "count %u\n", count); return count; } @@ -884,7 +887,7 @@ bail: if (local_resv) ocfs2_resv_discard(resmap, resv); - mlog_exit(bitoff); + mlog(0, "bitoff %d\n", bitoff); return bitoff; } @@ -898,8 +901,6 @@ static void ocfs2_clear_local_alloc(struct ocfs2_dinode *alloc) la->la_bm_off = 0; for(i = 0; i < le16_to_cpu(la->la_size); i++) la->la_bitmap[i] = 0; - - mlog_exit_void(); } #if 0 @@ -995,7 +996,8 @@ static int ocfs2_sync_local_to_main(struct ocfs2_super *osb, } bail: - mlog_exit(status); + if (status) + mlog_errno(status); return status; } @@ -1120,7 +1122,8 @@ bail: *ac = NULL; } - mlog_exit(status); + if (status) + mlog_errno(status); return status; } @@ -1212,7 +1215,8 @@ retry_enospc: mlog(0, "window bits = %u\n", le32_to_cpu(alloc->id1.bitmap1.i_total)); bail: - mlog_exit(status); + if (status) + mlog_errno(status); return status; } @@ -1308,7 +1312,8 @@ bail: if (ac) ocfs2_free_alloc_context(ac); - mlog_exit(status); + if (status) + mlog_errno(status); return status; } diff --git a/fs/ocfs2/mmap.c b/fs/ocfs2/mmap.c index 87438e178e118..49730b51ae451 100644 --- a/fs/ocfs2/mmap.c +++ b/fs/ocfs2/mmap.c @@ -55,7 +55,7 @@ static int ocfs2_fault(struct vm_area_struct *area, struct vm_fault *vmf) ret = filemap_fault(area, vmf); ocfs2_unblock_signals(&oldset); - mlog_exit_ptr(vmf->page); + mlog(0, "%p\n", vmf->page); return ret; } diff --git a/fs/ocfs2/namei.c b/fs/ocfs2/namei.c index fdf5c0b75caaf..8a13226eb1a25 100644 --- a/fs/ocfs2/namei.c +++ b/fs/ocfs2/namei.c @@ -182,7 +182,7 @@ bail_unlock: bail: - mlog_exit_ptr(ret); + mlog(0, "%p\n", ret); return ret; } @@ -466,7 +466,8 @@ leave: iput(inode); } - mlog_exit(status); + if (status) + mlog_errno(status); return status; } @@ -577,7 +578,8 @@ leave: } } - mlog_exit(status); + if (status) + mlog_errno(status); return status; } @@ -618,7 +620,8 @@ static int ocfs2_mkdir(struct inode *dir, mlog(0, "(0x%p, 0x%p, %d, '%.*s')\n", dir, dentry, mode, dentry->d_name.len, dentry->d_name.name); ret = ocfs2_mknod(dir, dentry, mode | S_IFDIR, 0); - mlog_exit(ret); + if (ret) + mlog_errno(ret); return ret; } @@ -633,7 +636,8 @@ static int ocfs2_create(struct inode *dir, mlog(0, "(0x%p, 0x%p, %d, '%.*s')\n", dir, dentry, mode, dentry->d_name.len, dentry->d_name.name); ret = ocfs2_mknod(dir, dentry, mode | S_IFREG, 0); - mlog_exit(ret); + if (ret) + mlog_errno(ret); return ret; } @@ -757,7 +761,8 @@ out: ocfs2_free_dir_lookup_result(&lookup); - mlog_exit(err); + if (err) + mlog_errno(err); return err; } @@ -954,7 +959,8 @@ leave: ocfs2_free_dir_lookup_result(&orphan_insert); ocfs2_free_dir_lookup_result(&lookup); - mlog_exit(status); + if (status) + mlog_errno(status); return status; } @@ -1025,7 +1031,8 @@ static int ocfs2_double_lock(struct ocfs2_super *osb, } bail: - mlog_exit(status); + if (status) + mlog_errno(status); return status; } @@ -1476,7 +1483,8 @@ bail: brelse(old_dir_bh); brelse(new_dir_bh); - mlog_exit(status); + if (status) + mlog_errno(status); return status; } @@ -1579,7 +1587,8 @@ bail: kfree(bhs); } - mlog_exit(status); + if (status) + mlog_errno(status); return status; } @@ -1835,7 +1844,8 @@ bail: iput(inode); } - mlog_exit(status); + if (status) + mlog_errno(status); return status; } @@ -1865,7 +1875,8 @@ static int ocfs2_blkno_stringify(u64 blkno, char *name) status = 0; bail: - mlog_exit(status); + if (status < 0) + mlog_errno(status); return status; } @@ -1978,7 +1989,8 @@ out: iput(orphan_dir_inode); } - mlog_exit(ret); + if (ret) + mlog_errno(ret); return ret; } @@ -2060,7 +2072,8 @@ static int ocfs2_orphan_add(struct ocfs2_super *osb, leave: brelse(orphan_dir_bh); - mlog_exit(status); + if (status) + mlog_errno(status); return status; } @@ -2120,7 +2133,8 @@ int ocfs2_orphan_del(struct ocfs2_super *osb, leave: ocfs2_free_dir_lookup_result(&lookup); - mlog_exit(status); + if (status) + mlog_errno(status); return status; } @@ -2472,7 +2486,8 @@ leave: ocfs2_free_dir_lookup_result(&lookup); - mlog_exit(status); + if (status) + mlog_errno(status); return status; } diff --git a/fs/ocfs2/quota_global.c b/fs/ocfs2/quota_global.c index 33397bd7e1bc5..10a49e8a5f03e 100644 --- a/fs/ocfs2/quota_global.c +++ b/fs/ocfs2/quota_global.c @@ -402,7 +402,8 @@ int ocfs2_global_read_info(struct super_block *sb, int type) msecs_to_jiffies(oinfo->dqi_syncms)); out_err: - mlog_exit(status); + if (status) + mlog_errno(status); return status; out_unlock: ocfs2_unlock_global_qf(oinfo, 0); @@ -621,7 +622,6 @@ static int ocfs2_sync_dquot_helper(struct dquot *dquot, unsigned long type) out_ilock: ocfs2_unlock_global_qf(oinfo, 1); out: - mlog_exit(status); return status; } @@ -660,7 +660,6 @@ static int ocfs2_write_dquot(struct dquot *dquot) mutex_unlock(&sb_dqopt(dquot->dq_sb)->dqio_mutex); ocfs2_commit_trans(osb, handle); out: - mlog_exit(status); return status; } @@ -722,7 +721,8 @@ out_ilock: ocfs2_unlock_global_qf(oinfo, 1); out: mutex_unlock(&dquot->dq_lock); - mlog_exit(status); + if (status) + mlog_errno(status); return status; } @@ -809,7 +809,8 @@ out_dq: set_bit(DQ_ACTIVE_B, &dquot->dq_flags); out: mutex_unlock(&dquot->dq_lock); - mlog_exit(status); + if (status) + mlog_errno(status); return status; } @@ -866,7 +867,8 @@ out_dlock: out_ilock: ocfs2_unlock_global_qf(oinfo, 1); out: - mlog_exit(status); + if (status) + mlog_errno(status); return status; } @@ -891,7 +893,8 @@ static int ocfs2_write_info(struct super_block *sb, int type) out_ilock: ocfs2_unlock_global_qf(oinfo, 1); out: - mlog_exit(status); + if (status) + mlog_errno(status); return status; } diff --git a/fs/ocfs2/quota_local.c b/fs/ocfs2/quota_local.c index a71d68d886673..88ec4516637b2 100644 --- a/fs/ocfs2/quota_local.c +++ b/fs/ocfs2/quota_local.c @@ -575,7 +575,8 @@ out_put_bh: } if (status < 0) free_recovery_list(&(rec->r_list[type])); - mlog_exit(status); + if (status) + mlog_errno(status); return status; } diff --git a/fs/ocfs2/resize.c b/fs/ocfs2/resize.c index e4a50e3fcb801..76b37909a4a1e 100644 --- a/fs/ocfs2/resize.c +++ b/fs/ocfs2/resize.c @@ -82,7 +82,6 @@ static u16 ocfs2_calc_new_backup_super(struct inode *inode, backups++; } - mlog_exit_void(); return backups; } @@ -176,7 +175,8 @@ out_rollback: le16_add_cpu(&group->bg_free_bits_count, -1 * num_bits); } out: - mlog_exit(ret); + if (ret) + mlog_errno(ret); return ret; } @@ -375,7 +375,6 @@ out_mutex: iput(main_bm_inode); out: - mlog_exit_void(); return ret; } @@ -585,6 +584,5 @@ out_mutex: iput(main_bm_inode); out: - mlog_exit_void(); return ret; } diff --git a/fs/ocfs2/slot_map.c b/fs/ocfs2/slot_map.c index a6016e6b3ca2d..93b449ed82f97 100644 --- a/fs/ocfs2/slot_map.c +++ b/fs/ocfs2/slot_map.c @@ -510,7 +510,6 @@ int ocfs2_find_slot(struct ocfs2_super *osb) mlog_errno(status); bail: - mlog_exit(status); return status; } diff --git a/fs/ocfs2/suballoc.c b/fs/ocfs2/suballoc.c index dd618496c2c63..2d722f1fbaa0d 100644 --- a/fs/ocfs2/suballoc.c +++ b/fs/ocfs2/suballoc.c @@ -434,7 +434,8 @@ static int ocfs2_block_group_fill(handle_t *handle, * allocation time. */ bail: - mlog_exit(status); + if (status) + mlog_errno(status); return status; } @@ -792,7 +793,8 @@ bail: brelse(bg_bh); - mlog_exit(status); + if (status) + mlog_errno(status); return status; } @@ -884,7 +886,8 @@ static int ocfs2_reserve_suballoc_bits(struct ocfs2_super *osb, bail: brelse(bh); - mlog_exit(status); + if (status) + mlog_errno(status); return status; } @@ -1046,7 +1049,8 @@ bail: *ac = NULL; } - mlog_exit(status); + if (status) + mlog_errno(status); return status; } @@ -1146,7 +1150,8 @@ bail: *ac = NULL; } - mlog_exit(status); + if (status) + mlog_errno(status); return status; } @@ -1221,7 +1226,8 @@ bail: *ac = NULL; } - mlog_exit(status); + if (status) + mlog_errno(status); return status; } @@ -1384,7 +1390,8 @@ static inline int ocfs2_block_group_set_bits(handle_t *handle, ocfs2_journal_dirty(handle, group_bh); bail: - mlog_exit(status); + if (status) + mlog_errno(status); return status; } @@ -1474,7 +1481,8 @@ out_rollback: prev_bg->bg_next_group = cpu_to_le64(prev_bg_ptr); } - mlog_exit(status); + if (status) + mlog_errno(status); return status; } @@ -1860,7 +1868,8 @@ bail: brelse(group_bh); brelse(prev_group_bh); - mlog_exit(status); + if (status) + mlog_errno(status); return status; } @@ -1972,7 +1981,8 @@ set_hint: } bail: - mlog_exit(status); + if (status) + mlog_errno(status); return status; } @@ -2009,7 +2019,8 @@ int ocfs2_claim_metadata(handle_t *handle, *num_bits = res.sr_bits; status = 0; bail: - mlog_exit(status); + if (status) + mlog_errno(status); return status; } @@ -2216,7 +2227,8 @@ int ocfs2_claim_new_inode(handle_t *handle, ocfs2_save_inode_ac_group(dir, ac); status = 0; bail: - mlog_exit(status); + if (status) + mlog_errno(status); return status; } @@ -2347,7 +2359,8 @@ int __ocfs2_claim_clusters(handle_t *handle, ac->ac_bits_given += *num_clusters; bail: - mlog_exit(status); + if (status) + mlog_errno(status); return status; } @@ -2491,7 +2504,8 @@ static int _ocfs2_free_suballoc_bits(handle_t *handle, bail: brelse(group_bh); - mlog_exit(status); + if (status) + mlog_errno(status); return status; } @@ -2563,7 +2577,8 @@ static int _ocfs2_free_clusters(handle_t *handle, num_clusters); out: - mlog_exit(status); + if (status) + mlog_errno(status); return status; } @@ -2770,7 +2785,8 @@ static int ocfs2_get_suballoc_slot_bit(struct ocfs2_super *osb, u64 blkno, bail: brelse(inode_bh); - mlog_exit(status); + if (status) + mlog_errno(status); return status; } @@ -2821,7 +2837,8 @@ static int ocfs2_test_suballoc_bit(struct ocfs2_super *osb, bail: brelse(group_bh); - mlog_exit(status); + if (status) + mlog_errno(status); return status; } @@ -2887,6 +2904,7 @@ int ocfs2_test_inode_bit(struct ocfs2_super *osb, u64 blkno, int *res) iput(inode_alloc_inode); brelse(alloc_bh); bail: - mlog_exit(status); + if (status) + mlog_errno(status); return status; } diff --git a/fs/ocfs2/super.c b/fs/ocfs2/super.c index 21c4bfdfd7391..b21b702c5603f 100644 --- a/fs/ocfs2/super.c +++ b/fs/ocfs2/super.c @@ -476,7 +476,8 @@ static int ocfs2_init_global_system_inodes(struct ocfs2_super *osb) } bail: - mlog_exit(status); + if (status) + mlog_errno(status); return status; } @@ -504,7 +505,8 @@ static int ocfs2_init_local_system_inodes(struct ocfs2_super *osb) } bail: - mlog_exit(status); + if (status) + mlog_errno(status); return status; } @@ -534,7 +536,7 @@ static void ocfs2_release_system_inodes(struct ocfs2_super *osb) } if (!osb->local_system_inodes) - goto out; + return; for (i = 0; i < NUM_LOCAL_SYSTEM_INODES * osb->max_slots; i++) { if (osb->local_system_inodes[i]) { @@ -545,9 +547,6 @@ static void ocfs2_release_system_inodes(struct ocfs2_super *osb) kfree(osb->local_system_inodes); osb->local_system_inodes = NULL; - -out: - mlog_exit(0); } /* We're allocating fs objects, use GFP_NOFS */ @@ -1202,7 +1201,6 @@ static int ocfs2_fill_super(struct super_block *sb, void *data, int silent) mlog_errno(status); atomic_set(&osb->vol_state, VOLUME_DISABLED); wake_up(&osb->osb_mount_event); - mlog_exit(status); return status; } } @@ -1216,7 +1214,6 @@ static int ocfs2_fill_super(struct super_block *sb, void *data, int silent) /* Start this when the mount is almost sure of being successful */ ocfs2_orphan_scan_start(osb); - mlog_exit(status); return status; read_super_error: @@ -1231,7 +1228,8 @@ read_super_error: ocfs2_dismount_volume(sb, 1); } - mlog_exit(status); + if (status) + mlog_errno(status); return status; } @@ -1532,7 +1530,6 @@ static int ocfs2_parse_options(struct super_block *sb, status = 1; bail: - mlog_exit(status); return status; } @@ -1661,10 +1658,9 @@ leave: ocfs2_quota_shutdown(); ocfs2_free_mem_caches(); exit_ocfs2_uptodate_cache(); + mlog_errno(status); } - mlog_exit(status); - if (status >= 0) { return register_filesystem(&ocfs2_fs_type); } else @@ -1689,8 +1685,6 @@ static void __exit ocfs2_exit(void) unregister_filesystem(&ocfs2_fs_type); exit_ocfs2_uptodate_cache(); - - mlog_exit_void(); } static void ocfs2_put_super(struct super_block *sb) @@ -1699,8 +1693,6 @@ static void ocfs2_put_super(struct super_block *sb) ocfs2_sync_blockdev(sb); ocfs2_dismount_volume(sb, 0); - - mlog_exit_void(); } static int ocfs2_statfs(struct dentry *dentry, struct kstatfs *buf) @@ -1759,7 +1751,8 @@ bail: if (inode) iput(inode); - mlog_exit(status); + if (status) + mlog_errno(status); return status; } @@ -1923,7 +1916,6 @@ leave: if (unlock_super) ocfs2_super_unlock(osb, 1); - mlog_exit(status); return status; } @@ -2373,7 +2365,6 @@ static int ocfs2_initialize_super(struct super_block *sb, } bail: - mlog_exit(status); return status; } @@ -2443,7 +2434,8 @@ static int ocfs2_verify_volume(struct ocfs2_dinode *di, } out: - mlog_exit(status); + if (status && status != -EAGAIN) + mlog_errno(status); return status; } @@ -2538,7 +2530,8 @@ finally: if (local_alloc) kfree(local_alloc); - mlog_exit(status); + if (status) + mlog_errno(status); return status; } @@ -2567,8 +2560,6 @@ static void ocfs2_delete_osb(struct ocfs2_super *osb) kfree(osb->uuid_str); ocfs2_put_dlm_debug(osb->osb_dlm_debug); memset(osb, 0, sizeof(struct ocfs2_super)); - - mlog_exit_void(); } /* Put OCFS2 into a readonly state, or (if the user specifies it), diff --git a/fs/ocfs2/symlink.c b/fs/ocfs2/symlink.c index 8a81688c57dfc..5485b19ec8f2b 100644 --- a/fs/ocfs2/symlink.c +++ b/fs/ocfs2/symlink.c @@ -72,7 +72,6 @@ static char *ocfs2_fast_symlink_getlink(struct inode *inode, fe = (struct ocfs2_dinode *) (*bh)->b_data; link = (char *) fe->id2.i_symlink; bail: - mlog_exit(status); return link; } @@ -100,7 +99,8 @@ static int ocfs2_readlink(struct dentry *dentry, brelse(bh); out: - mlog_exit(ret); + if (ret < 0) + mlog_errno(ret); return ret; } @@ -136,7 +136,8 @@ bail: nd_set_link(nd, status ? ERR_PTR(status) : link); brelse(bh); - mlog_exit(status); + if (status) + mlog_errno(status); return NULL; } diff --git a/fs/ocfs2/xattr.c b/fs/ocfs2/xattr.c index 81f98b7f75028..d57c7942e4dee 100644 --- a/fs/ocfs2/xattr.c +++ b/fs/ocfs2/xattr.c @@ -5570,7 +5570,6 @@ static int ocfs2_xattr_set_entry_bucket(struct inode *inode, out: - mlog_exit(ret); return ret; } @@ -5637,7 +5636,6 @@ static int ocfs2_xattr_set_entry_index_block(struct inode *inode, mlog_errno(ret); out: - mlog_exit(ret); return ret; } -- GitLab From 80a9a84da381087ed89f5fdfc40a513cf9768ac4 Mon Sep 17 00:00:00 2001 From: Wengang Wang Date: Mon, 21 Feb 2011 11:13:14 +0800 Subject: [PATCH 0104/2822] ocfs2: Add ocfs2_trace.h. About one year ago, Wengang Wang tried some first steps to add tracepoints to ocfs2. Hiss original patch is here: http://oss.oracle.com/pipermail/ocfs2-devel/2009-November/005512.html But as Steven Rostedt indicated in his article http://lwn.net/Articles/383362/, we'd better have our trace files resides in fs/ocfs2, so I rewrited the patch using the method Steven mentioned in that article. Signed-off-by: Wengang Wang Signed-off-by: Tao Ma --- fs/ocfs2/ocfs2_trace.h | 16 ++++++++++++++++ fs/ocfs2/super.c | 3 +++ 2 files changed, 19 insertions(+) create mode 100644 fs/ocfs2/ocfs2_trace.h diff --git a/fs/ocfs2/ocfs2_trace.h b/fs/ocfs2/ocfs2_trace.h new file mode 100644 index 0000000000000..8d4e49aef4915 --- /dev/null +++ b/fs/ocfs2/ocfs2_trace.h @@ -0,0 +1,16 @@ +#undef TRACE_SYSTEM +#define TRACE_SYSTEM ocfs2 + +#if !defined(_TRACE_OCFS2_H) || defined(TRACE_HEADER_MULTI_READ) +#define _TRACE_OCFS2_H + +#include + + +#endif /* _TRACE_OCFS2_H */ + +/* This part must be outside protection */ +#undef TRACE_INCLUDE_PATH +#define TRACE_INCLUDE_PATH . +#define TRACE_INCLUDE_FILE ocfs2_trace +#include diff --git a/fs/ocfs2/super.c b/fs/ocfs2/super.c index b21b702c5603f..f7e73a029844c 100644 --- a/fs/ocfs2/super.c +++ b/fs/ocfs2/super.c @@ -42,6 +42,9 @@ #include #include +#define CREATE_TRACE_POINTS +#include "ocfs2_trace.h" + #define MLOG_MASK_PREFIX ML_SUPER #include -- GitLab From a09d09b8f8d7c8acd46d96e3e9899bd1461fc036 Mon Sep 17 00:00:00 2001 From: Tao Ma Date: Tue, 22 Feb 2011 08:21:10 +0800 Subject: [PATCH 0105/2822] ocfs2: Remove mlog(0) from fs/ocfs2/alloc.c This is the first try of replacing debug mlog(0,...) to trace events. Wengang has did some work in his original patch http://oss.oracle.com/pipermail/ocfs2-devel/2009-November/005513.html But he didn't finished it. So this patch removes all mlog(0,...) from alloc.c and adds the corresponding trace events. Different mlogs have different solutions. 1. Some are replaced with trace event directly. 2. Some are replaced and some new parameters are added since I think we need to know the btree owner in that case. 3. Some are combined into one trace events. 4. Some redundant mlogs are removed. What's more, it defines some event classes so that we can use them later. Cc: Wengang Wang Signed-off-by: Tao Ma --- fs/ocfs2/alloc.c | 165 ++++++++++--------- fs/ocfs2/ocfs2_trace.h | 364 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 452 insertions(+), 77 deletions(-) diff --git a/fs/ocfs2/alloc.c b/fs/ocfs2/alloc.c index 80ffbe3dd32f4..f0e26c4adc94c 100644 --- a/fs/ocfs2/alloc.c +++ b/fs/ocfs2/alloc.c @@ -50,6 +50,7 @@ #include "uptodate.h" #include "xattr.h" #include "refcounttree.h" +#include "ocfs2_trace.h" #include "buffer_head_io.h" @@ -886,8 +887,7 @@ static int ocfs2_validate_extent_block(struct super_block *sb, struct ocfs2_extent_block *eb = (struct ocfs2_extent_block *)bh->b_data; - mlog(0, "Validating extent block %llu\n", - (unsigned long long)bh->b_blocknr); + trace_ocfs2_validate_extent_block((unsigned long long)bh->b_blocknr); BUG_ON(!buffer_uptodate(bh)); @@ -985,7 +985,7 @@ int ocfs2_num_free_extents(struct ocfs2_super *osb, bail: brelse(eb_bh); - mlog(0, "retval = %d\n", retval); + trace_ocfs2_num_free_extents(retval); return retval; } @@ -1194,8 +1194,11 @@ static int ocfs2_add_branch(handle_t *handle, * from new_cpos). */ if (root_end > new_cpos) { - mlog(0, "adjust the cluster end from %u to %u\n", - root_end, new_cpos); + trace_ocfs2_adjust_rightmost_branch( + (unsigned long long) + ocfs2_metadata_cache_owner(et->et_ci), + root_end, new_cpos); + status = ocfs2_adjust_rightmost_branch(handle, et); if (status) { mlog_errno(status); @@ -1527,7 +1530,10 @@ static int ocfs2_grow_tree(handle_t *handle, struct ocfs2_extent_tree *et, * another tree level */ if (shift) { BUG_ON(bh); - mlog(0, "need to shift tree depth (current = %d)\n", depth); + trace_ocfs2_grow_tree( + (unsigned long long) + ocfs2_metadata_cache_owner(et->et_ci), + depth); /* ocfs2_shift_tree_depth will return us a buffer with * the new extent block (so we can pass that to @@ -1557,7 +1563,6 @@ static int ocfs2_grow_tree(handle_t *handle, struct ocfs2_extent_tree *et, /* call ocfs2_add_branch to add the final part of the tree with * the new data. */ - mlog(0, "add branch. bh = %p\n", bh); ret = ocfs2_add_branch(handle, et, bh, last_eb_bh, meta_ac); if (ret < 0) { @@ -1632,8 +1637,9 @@ static void ocfs2_rotate_leaf(struct ocfs2_extent_list *el, } insert_index = i; - mlog(0, "ins %u: index %d, has_empty %d, next_free %d, count %d\n", - insert_cpos, insert_index, has_empty, next_free, le16_to_cpu(el->l_count)); + trace_ocfs2_rotate_leaf(insert_cpos, insert_index, + has_empty, next_free, + le16_to_cpu(el->l_count)); BUG_ON(insert_index < 0); BUG_ON(insert_index >= le16_to_cpu(el->l_count)); @@ -2046,7 +2052,7 @@ static void ocfs2_complete_edge_insert(handle_t *handle, left_el = path_leaf_el(left_path); right_el = path_leaf_el(right_path); for(i = left_path->p_tree_depth - 1; i > subtree_index; i--) { - mlog(0, "Adjust records at index %u\n", i); + trace_ocfs2_complete_edge_insert(i); /* * One nice property of knowing that all of these @@ -2376,7 +2382,9 @@ static int ocfs2_rotate_tree_right(handle_t *handle, goto out; } - mlog(0, "Insert: %u, first left path cpos: %u\n", insert_cpos, cpos); + trace_ocfs2_rotate_tree_right( + (unsigned long long)ocfs2_metadata_cache_owner(et->et_ci), + insert_cpos, cpos); /* * What we want to do here is: @@ -2405,8 +2413,10 @@ static int ocfs2_rotate_tree_right(handle_t *handle, * rotating subtrees. */ while (cpos && insert_cpos <= cpos) { - mlog(0, "Rotating a tree: ins. cpos: %u, left path cpos: %u\n", - insert_cpos, cpos); + trace_ocfs2_rotate_tree_right( + (unsigned long long) + ocfs2_metadata_cache_owner(et->et_ci), + insert_cpos, cpos); ret = ocfs2_find_path(et->et_ci, left_path, cpos); if (ret) { @@ -2448,10 +2458,10 @@ static int ocfs2_rotate_tree_right(handle_t *handle, start = ocfs2_find_subtree_root(et, left_path, right_path); - mlog(0, "Subtree root at index %d (blk %llu, depth %d)\n", - start, - (unsigned long long) right_path->p_node[start].bh->b_blocknr, - right_path->p_tree_depth); + trace_ocfs2_rotate_subtree(start, + (unsigned long long) + right_path->p_node[start].bh->b_blocknr, + right_path->p_tree_depth); ret = ocfs2_extend_rotate_transaction(handle, start, orig_credits, right_path); @@ -2951,8 +2961,7 @@ static int __ocfs2_rotate_tree_left(handle_t *handle, subtree_root = ocfs2_find_subtree_root(et, left_path, right_path); - mlog(0, "Subtree root at index %d (blk %llu, depth %d)\n", - subtree_root, + trace_ocfs2_rotate_subtree(subtree_root, (unsigned long long) right_path->p_node[subtree_root].bh->b_blocknr, right_path->p_tree_depth); @@ -3976,9 +3985,11 @@ static int ocfs2_append_rec_to_path(handle_t *handle, goto out; } - mlog(0, "Append may need a left path update. cpos: %u, " - "left_cpos: %u\n", le32_to_cpu(insert_rec->e_cpos), - left_cpos); + trace_ocfs2_append_rec_to_path( + (unsigned long long) + ocfs2_metadata_cache_owner(et->et_ci), + le32_to_cpu(insert_rec->e_cpos), + left_cpos); /* * No need to worry if the append is already in the @@ -4665,9 +4676,9 @@ int ocfs2_insert_extent(handle_t *handle, struct ocfs2_insert_type insert = {0, }; struct ocfs2_extent_rec rec; - mlog(0, "add %u clusters at position %u to owner %llu\n", - new_clusters, cpos, - (unsigned long long)ocfs2_metadata_cache_owner(et->et_ci)); + trace_ocfs2_insert_extent_start( + (unsigned long long)ocfs2_metadata_cache_owner(et->et_ci), + cpos, new_clusters); memset(&rec, 0, sizeof(rec)); rec.e_cpos = cpu_to_le32(cpos); @@ -4687,11 +4698,9 @@ int ocfs2_insert_extent(handle_t *handle, goto bail; } - mlog(0, "Insert.appending: %u, Insert.Contig: %u, " - "Insert.contig_index: %d, Insert.free_records: %d, " - "Insert.tree_depth: %d\n", - insert.ins_appending, insert.ins_contig, insert.ins_contig_index, - free_records, insert.ins_tree_depth); + trace_ocfs2_insert_extent(insert.ins_appending, insert.ins_contig, + insert.ins_contig_index, free_records, + insert.ins_tree_depth); if (insert.ins_contig == CONTIG_NONE && free_records == 0) { status = ocfs2_grow_tree(handle, et, @@ -4732,7 +4741,7 @@ int ocfs2_add_clusters_in_btree(handle_t *handle, struct ocfs2_alloc_context *meta_ac, enum ocfs2_alloc_restarted *reason_ret) { - int status = 0; + int status = 0, err = 0; int free_extents; enum ocfs2_alloc_restarted reason = RESTART_NONE; u32 bit_off, num_bits; @@ -4759,14 +4768,14 @@ int ocfs2_add_clusters_in_btree(handle_t *handle, * 2) we are so fragmented, we've needed to add metadata too * many times. */ if (!free_extents && !meta_ac) { - mlog(0, "we haven't reserved any metadata!\n"); + err = -1; status = -EAGAIN; reason = RESTART_META; goto leave; } else if ((!free_extents) && (ocfs2_alloc_context_bits_left(meta_ac) < ocfs2_extend_meta_needed(et->et_root_el))) { - mlog(0, "filesystem is really fragmented...\n"); + err = -2; status = -EAGAIN; reason = RESTART_META; goto leave; @@ -4791,9 +4800,9 @@ int ocfs2_add_clusters_in_btree(handle_t *handle, } block = ocfs2_clusters_to_blocks(osb->sb, bit_off); - mlog(0, "Allocating %u clusters at block %u for owner %llu\n", - num_bits, bit_off, - (unsigned long long)ocfs2_metadata_cache_owner(et->et_ci)); + trace_ocfs2_add_clusters_in_btree( + (unsigned long long)ocfs2_metadata_cache_owner(et->et_ci), + bit_off, num_bits); status = ocfs2_insert_extent(handle, et, *logical_offset, block, num_bits, flags, meta_ac); if (status < 0) { @@ -4807,8 +4816,7 @@ int ocfs2_add_clusters_in_btree(handle_t *handle, *logical_offset += num_bits; if (clusters_to_add) { - mlog(0, "need to alloc once more, wanted = %u\n", - clusters_to_add); + err = clusters_to_add; status = -EAGAIN; reason = RESTART_TRANS; } @@ -4816,6 +4824,7 @@ int ocfs2_add_clusters_in_btree(handle_t *handle, leave: if (reason_ret) *reason_ret = reason; + trace_ocfs2_add_clusters_in_btree_ret(status, reason, err); return status; } @@ -5041,9 +5050,9 @@ int ocfs2_split_extent(handle_t *handle, ctxt.c_has_empty_extent = ocfs2_is_empty_extent(&el->l_recs[0]); - mlog(0, "index: %d, contig: %u, has_empty: %u, split_covers: %u\n", - split_index, ctxt.c_contig_type, ctxt.c_has_empty_extent, - ctxt.c_split_covers_rec); + trace_ocfs2_split_extent(split_index, ctxt.c_contig_type, + ctxt.c_has_empty_extent, + ctxt.c_split_covers_rec); if (ctxt.c_contig_type == CONTIG_NONE) { if (ctxt.c_split_covers_rec) @@ -5177,8 +5186,9 @@ int ocfs2_mark_extent_written(struct inode *inode, { int ret; - mlog(0, "Inode %lu cpos %u, len %u, phys clusters %u\n", - inode->i_ino, cpos, len, phys); + trace_ocfs2_mark_extent_written( + (unsigned long long)OCFS2_I(inode)->ip_blkno, + cpos, len, phys); if (!ocfs2_writes_unwritten_extents(OCFS2_SB(inode->i_sb))) { ocfs2_error(inode->i_sb, "Inode %llu has unwritten extents " @@ -5497,11 +5507,10 @@ int ocfs2_remove_extent(handle_t *handle, BUG_ON(cpos < le32_to_cpu(rec->e_cpos) || trunc_range > rec_range); - mlog(0, "Owner %llu, remove (cpos %u, len %u). Existing index %d " - "(cpos %u, len %u)\n", - (unsigned long long)ocfs2_metadata_cache_owner(et->et_ci), - cpos, len, index, - le32_to_cpu(rec->e_cpos), ocfs2_rec_clusters(el, rec)); + trace_ocfs2_remove_extent( + (unsigned long long)ocfs2_metadata_cache_owner(et->et_ci), + cpos, len, index, le32_to_cpu(rec->e_cpos), + ocfs2_rec_clusters(el, rec)); if (le32_to_cpu(rec->e_cpos) == cpos || rec_range == trunc_range) { ret = ocfs2_truncate_rec(handle, et, path, index, dealloc, @@ -5780,9 +5789,6 @@ int ocfs2_truncate_log_append(struct ocfs2_super *osb, struct ocfs2_dinode *di; struct ocfs2_truncate_log *tl; - mlog(0, "start_blk = %llu, num_clusters = %u\n", - (unsigned long long)start_blk, num_clusters); - BUG_ON(mutex_trylock(&tl_inode->i_mutex)); start_cluster = ocfs2_blocks_to_clusters(osb->sb, start_blk); @@ -5819,10 +5825,9 @@ int ocfs2_truncate_log_append(struct ocfs2_super *osb, goto bail; } - mlog(0, "Log truncate of %u clusters starting at cluster %u to " - "%llu (index = %d)\n", num_clusters, start_cluster, - (unsigned long long)OCFS2_I(tl_inode)->ip_blkno, index); - + trace_ocfs2_truncate_log_append( + (unsigned long long)OCFS2_I(tl_inode)->ip_blkno, index, + start_cluster, num_clusters); if (ocfs2_truncate_log_can_coalesce(tl, start_cluster)) { /* * Move index back to the record we are coalescing with. @@ -5831,9 +5836,10 @@ int ocfs2_truncate_log_append(struct ocfs2_super *osb, index--; num_clusters += le32_to_cpu(tl->tl_recs[index].t_clusters); - mlog(0, "Coalesce with index %u (start = %u, clusters = %u)\n", - index, le32_to_cpu(tl->tl_recs[index].t_start), - num_clusters); + trace_ocfs2_truncate_log_append( + (unsigned long long)OCFS2_I(tl_inode)->ip_blkno, + index, le32_to_cpu(tl->tl_recs[index].t_start), + num_clusters); } else { tl->tl_recs[index].t_start = cpu_to_le32(start_cluster); tl->tl_used = cpu_to_le16(index + 1); @@ -5897,8 +5903,9 @@ static int ocfs2_replay_truncate_records(struct ocfs2_super *osb, /* if start_blk is not set, we ignore the record as * invalid. */ if (start_blk) { - mlog(0, "free record %d, start = %u, clusters = %u\n", - i, le32_to_cpu(rec.t_start), num_clusters); + trace_ocfs2_replay_truncate_records( + (unsigned long long)OCFS2_I(tl_inode)->ip_blkno, + i, le32_to_cpu(rec.t_start), num_clusters); status = ocfs2_free_clusters(handle, data_alloc_inode, data_alloc_bh, start_blk, @@ -5941,8 +5948,9 @@ int __ocfs2_flush_truncate_log(struct ocfs2_super *osb) tl = &di->id2.i_dealloc; num_to_flush = le16_to_cpu(tl->tl_used); - mlog(0, "Flush %u records from truncate log #%llu\n", - num_to_flush, (unsigned long long)OCFS2_I(tl_inode)->ip_blkno); + trace_ocfs2_flush_truncate_log( + (unsigned long long)OCFS2_I(tl_inode)->ip_blkno, + num_to_flush); if (!num_to_flush) { status = 0; goto out; @@ -6079,7 +6087,7 @@ int ocfs2_begin_truncate_log_recovery(struct ocfs2_super *osb, *tl_copy = NULL; - mlog(0, "recover truncate log from slot %d\n", slot_num); + trace_ocfs2_begin_truncate_log_recovery(slot_num); status = ocfs2_get_truncate_log_info(osb, slot_num, &tl_inode, &tl_bh); if (status < 0) { @@ -6096,8 +6104,7 @@ int ocfs2_begin_truncate_log_recovery(struct ocfs2_super *osb, tl = &di->id2.i_dealloc; if (le16_to_cpu(tl->tl_used)) { - mlog(0, "We'll have %u logs to recover\n", - le16_to_cpu(tl->tl_used)); + trace_ocfs2_truncate_log_recovery_num(le16_to_cpu(tl->tl_used)); *tl_copy = kmalloc(tl_bh->b_size, GFP_KERNEL); if (!(*tl_copy)) { @@ -6154,8 +6161,9 @@ int ocfs2_complete_truncate_log_recovery(struct ocfs2_super *osb, tl = &tl_copy->id2.i_dealloc; num_recs = le16_to_cpu(tl->tl_used); - mlog(0, "cleanup %u records from %llu\n", num_recs, - (unsigned long long)le64_to_cpu(tl_copy->i_blkno)); + trace_ocfs2_complete_truncate_log_recovery( + (unsigned long long)le64_to_cpu(tl_copy->i_blkno), + num_recs); mutex_lock(&tl_inode->i_mutex); for(i = 0; i < num_recs; i++) { @@ -6313,8 +6321,8 @@ static int ocfs2_free_cached_blocks(struct ocfs2_super *osb, else bg_blkno = ocfs2_which_suballoc_group(head->free_blk, head->free_bit); - mlog(0, "Free bit: (bit %u, blkno %llu)\n", - head->free_bit, (unsigned long long)head->free_blk); + trace_ocfs2_free_cached_blocks( + (unsigned long long)head->free_blk, head->free_bit); ret = ocfs2_free_suballoc_bits(handle, inode, di_bh, head->free_bit, bg_blkno, 1); @@ -6367,8 +6375,7 @@ int ocfs2_cache_cluster_dealloc(struct ocfs2_cached_dealloc_ctxt *ctxt, return ret; } - mlog(0, "Insert clusters: (bit %u, blk %llu)\n", - bit, (unsigned long long)blkno); + trace_ocfs2_cache_cluster_dealloc((unsigned long long)blkno, bit); item->free_blk = blkno; item->free_bit = bit; @@ -6443,8 +6450,8 @@ int ocfs2_run_deallocs(struct ocfs2_super *osb, fl = ctxt->c_first_suballocator; if (fl->f_first) { - mlog(0, "Free items: (type %u, slot %d)\n", - fl->f_inode_type, fl->f_slot); + trace_ocfs2_run_deallocs(fl->f_inode_type, + fl->f_slot); ret2 = ocfs2_free_cached_blocks(osb, fl->f_inode_type, fl->f_slot, @@ -6521,8 +6528,9 @@ int ocfs2_cache_block_dealloc(struct ocfs2_cached_dealloc_ctxt *ctxt, goto out; } - mlog(0, "Insert: (type %d, slot %u, bit %u, blk %llu)\n", - type, slot, bit, (unsigned long long)blkno); + trace_ocfs2_cache_block_dealloc(type, slot, + (unsigned long long)suballoc, + (unsigned long long)blkno, bit); item->free_bg = suballoc; item->free_blk = blkno; @@ -7002,8 +7010,11 @@ start: goto bail; } - mlog(0, "inode->ip_clusters = %u, tree_depth = %u\n", - OCFS2_I(inode)->ip_clusters, path->p_tree_depth); + trace_ocfs2_commit_truncate( + (unsigned long long)OCFS2_I(inode)->ip_blkno, + new_highest_cpos, + OCFS2_I(inode)->ip_clusters, + path->p_tree_depth); /* * By now, el will point to the extent list on the bottom most diff --git a/fs/ocfs2/ocfs2_trace.h b/fs/ocfs2/ocfs2_trace.h index 8d4e49aef4915..1793b1f718059 100644 --- a/fs/ocfs2/ocfs2_trace.h +++ b/fs/ocfs2/ocfs2_trace.h @@ -6,6 +6,370 @@ #include +DECLARE_EVENT_CLASS(ocfs2__int, + TP_PROTO(int num), + TP_ARGS(num), + TP_STRUCT__entry( + __field(int, num) + ), + TP_fast_assign( + __entry->num = num; + ), + TP_printk("%d", __entry->num) +); + +#define DEFINE_OCFS2_INT_EVENT(name) \ +DEFINE_EVENT(ocfs2__int, name, \ + TP_PROTO(int num), \ + TP_ARGS(num)) + +DECLARE_EVENT_CLASS(ocfs2__int_int, + TP_PROTO(int value1, int value2), + TP_ARGS(value1, value2), + TP_STRUCT__entry( + __field(int, value1) + __field(int, value2) + ), + TP_fast_assign( + __entry->value1 = value1; + __entry->value2 = value2; + ), + TP_printk("%d %d", __entry->value1, __entry->value2) +); + +#define DEFINE_OCFS2_INT_INT_EVENT(name) \ +DEFINE_EVENT(ocfs2__int_int, name, \ + TP_PROTO(int val1, int val2), \ + TP_ARGS(val1, val2)) + +DECLARE_EVENT_CLASS(ocfs2__ull_uint, + TP_PROTO(unsigned long long value1, unsigned int value2), + TP_ARGS(value1, value2), + TP_STRUCT__entry( + __field(unsigned long long, value1) + __field(unsigned int, value2) + ), + TP_fast_assign( + __entry->value1 = value1; + __entry->value2 = value2; + ), + TP_printk("%llu %u", __entry->value1, __entry->value2) +); + +#define DEFINE_OCFS2_ULL_UINT_EVENT(name) \ +DEFINE_EVENT(ocfs2__ull_uint, name, \ + TP_PROTO(unsigned long long val1, unsigned int val2), \ + TP_ARGS(val1, val2)) + +/* Trace events for fs/ocfs2/alloc.c. */ +DECLARE_EVENT_CLASS(ocfs2__btree_ops, + TP_PROTO(unsigned long long owner,\ + unsigned int value1, unsigned int value2), + TP_ARGS(owner, value1, value2), + TP_STRUCT__entry( + __field(unsigned long long, owner) + __field(unsigned int, value1) + __field(unsigned int, value2) + ), + TP_fast_assign( + __entry->owner = owner; + __entry->value1 = value1; + __entry->value2 = value2; + ), + TP_printk("%llu %u %u", + __entry->owner, __entry->value1, __entry->value2) +); + +#define DEFINE_OCFS2_BTREE_EVENT(name) \ +DEFINE_EVENT(ocfs2__btree_ops, name, \ + TP_PROTO(unsigned long long owner, \ + unsigned int value1, unsigned int value2), \ + TP_ARGS(owner, value1, value2)) + +DEFINE_OCFS2_BTREE_EVENT(ocfs2_adjust_rightmost_branch); + +DEFINE_OCFS2_BTREE_EVENT(ocfs2_rotate_tree_right); + +DEFINE_OCFS2_BTREE_EVENT(ocfs2_append_rec_to_path); + +DEFINE_OCFS2_BTREE_EVENT(ocfs2_insert_extent_start); + +DEFINE_OCFS2_BTREE_EVENT(ocfs2_add_clusters_in_btree); + +DEFINE_OCFS2_INT_EVENT(ocfs2_num_free_extents); + +DEFINE_OCFS2_INT_EVENT(ocfs2_complete_edge_insert); + +TRACE_EVENT(ocfs2_grow_tree, + TP_PROTO(unsigned long long owner, int depth), + TP_ARGS(owner, depth), + TP_STRUCT__entry( + __field(unsigned long long, owner) + __field(int, depth) + ), + TP_fast_assign( + __entry->owner = owner; + __entry->depth = depth; + ), + TP_printk("%llu %d", __entry->owner, __entry->depth) +); + +TRACE_EVENT(ocfs2_rotate_subtree, + TP_PROTO(int subtree_root, unsigned long long blkno, + int depth), + TP_ARGS(subtree_root, blkno, depth), + TP_STRUCT__entry( + __field(int, subtree_root) + __field(unsigned long long, blkno) + __field(int, depth) + ), + TP_fast_assign( + __entry->subtree_root = subtree_root; + __entry->blkno = blkno; + __entry->depth = depth; + ), + TP_printk("%d %llu %d", __entry->subtree_root, + __entry->blkno, __entry->depth) +); + +TRACE_EVENT(ocfs2_insert_extent, + TP_PROTO(unsigned int ins_appending, unsigned int ins_contig, + int ins_contig_index, int free_records, int ins_tree_depth), + TP_ARGS(ins_appending, ins_contig, ins_contig_index, free_records, + ins_tree_depth), + TP_STRUCT__entry( + __field(unsigned int, ins_appending) + __field(unsigned int, ins_contig) + __field(int, ins_contig_index) + __field(int, free_records) + __field(int, ins_tree_depth) + ), + TP_fast_assign( + __entry->ins_appending = ins_appending; + __entry->ins_contig = ins_contig; + __entry->ins_contig_index = ins_contig_index; + __entry->free_records = free_records; + __entry->ins_tree_depth = ins_tree_depth; + ), + TP_printk("%u %u %d %d %d", + __entry->ins_appending, __entry->ins_contig, + __entry->ins_contig_index, __entry->free_records, + __entry->ins_tree_depth) +); + +TRACE_EVENT(ocfs2_split_extent, + TP_PROTO(int split_index, unsigned int c_contig_type, + unsigned int c_has_empty_extent, + unsigned int c_split_covers_rec), + TP_ARGS(split_index, c_contig_type, + c_has_empty_extent, c_split_covers_rec), + TP_STRUCT__entry( + __field(int, split_index) + __field(unsigned int, c_contig_type) + __field(unsigned int, c_has_empty_extent) + __field(unsigned int, c_split_covers_rec) + ), + TP_fast_assign( + __entry->split_index = split_index; + __entry->c_contig_type = c_contig_type; + __entry->c_has_empty_extent = c_has_empty_extent; + __entry->c_split_covers_rec = c_split_covers_rec; + ), + TP_printk("%d %u %u %u", __entry->split_index, __entry->c_contig_type, + __entry->c_has_empty_extent, __entry->c_split_covers_rec) +); + +TRACE_EVENT(ocfs2_remove_extent, + TP_PROTO(unsigned long long owner, unsigned int cpos, + unsigned int len, int index, + unsigned int e_cpos, unsigned int clusters), + TP_ARGS(owner, cpos, len, index, e_cpos, clusters), + TP_STRUCT__entry( + __field(unsigned long long, owner) + __field(unsigned int, cpos) + __field(unsigned int, len) + __field(int, index) + __field(unsigned int, e_cpos) + __field(unsigned int, clusters) + ), + TP_fast_assign( + __entry->owner = owner; + __entry->cpos = cpos; + __entry->len = len; + __entry->index = index; + __entry->e_cpos = e_cpos; + __entry->clusters = clusters; + ), + TP_printk("%llu %u %u %d %u %u", + __entry->owner, __entry->cpos, __entry->len, __entry->index, + __entry->e_cpos, __entry->clusters) +); + +TRACE_EVENT(ocfs2_commit_truncate, + TP_PROTO(unsigned long long ino, unsigned int new_cpos, + unsigned int clusters, unsigned int depth), + TP_ARGS(ino, new_cpos, clusters, depth), + TP_STRUCT__entry( + __field(unsigned long long, ino) + __field(unsigned int, new_cpos) + __field(unsigned int, clusters) + __field(unsigned int, depth) + ), + TP_fast_assign( + __entry->ino = ino; + __entry->new_cpos = new_cpos; + __entry->clusters = clusters; + __entry->depth = depth; + ), + TP_printk("%llu %u %u %u", + __entry->ino, __entry->new_cpos, + __entry->clusters, __entry->depth) +); + +TRACE_EVENT(ocfs2_validate_extent_block, + TP_PROTO(unsigned long long blkno), + TP_ARGS(blkno), + TP_STRUCT__entry( + __field(unsigned long long, blkno) + ), + TP_fast_assign( + __entry->blkno = blkno; + ), + TP_printk("%llu ", __entry->blkno) +); + +TRACE_EVENT(ocfs2_rotate_leaf, + TP_PROTO(unsigned int insert_cpos, int insert_index, + int has_empty, int next_free, + unsigned int l_count), + TP_ARGS(insert_cpos, insert_index, has_empty, + next_free, l_count), + TP_STRUCT__entry( + __field(unsigned int, insert_cpos) + __field(int, insert_index) + __field(int, has_empty) + __field(int, next_free) + __field(unsigned int, l_count) + ), + TP_fast_assign( + __entry->insert_cpos = insert_cpos; + __entry->insert_index = insert_index; + __entry->has_empty = has_empty; + __entry->next_free = next_free; + __entry->l_count = l_count; + ), + TP_printk("%u %d %d %d %u", __entry->insert_cpos, + __entry->insert_index, __entry->has_empty, + __entry->next_free, __entry->l_count) +); + +TRACE_EVENT(ocfs2_add_clusters_in_btree_ret, + TP_PROTO(int status, int reason, int err), + TP_ARGS(status, reason, err), + TP_STRUCT__entry( + __field(int, status) + __field(int, reason) + __field(int, err) + ), + TP_fast_assign( + __entry->status = status; + __entry->reason = reason; + __entry->err = err; + ), + TP_printk("%d %d %d", __entry->status, + __entry->reason, __entry->err) +); + +TRACE_EVENT(ocfs2_mark_extent_written, + TP_PROTO(unsigned long long owner, unsigned int cpos, + unsigned int len, unsigned int phys), + TP_ARGS(owner, cpos, len, phys), + TP_STRUCT__entry( + __field(unsigned long long, owner) + __field(unsigned int, cpos) + __field(unsigned int, len) + __field(unsigned int, phys) + ), + TP_fast_assign( + __entry->owner = owner; + __entry->cpos = cpos; + __entry->len = len; + __entry->phys = phys; + ), + TP_printk("%llu %u %u %u", + __entry->owner, __entry->cpos, + __entry->len, __entry->phys) +); + +DECLARE_EVENT_CLASS(ocfs2__truncate_log_ops, + TP_PROTO(unsigned long long blkno, int index, + unsigned int start, unsigned int num), + TP_ARGS(blkno, index, start, num), + TP_STRUCT__entry( + __field(unsigned long long, blkno) + __field(int, index) + __field(unsigned int, start) + __field(unsigned int, num) + ), + TP_fast_assign( + __entry->blkno = blkno; + __entry->index = index; + __entry->start = start; + __entry->num = num; + ), + TP_printk("%llu %d %u %u", + __entry->blkno, __entry->index, + __entry->start, __entry->num) +); + +#define DEFINE_OCFS2_TRUNCATE_LOG_OPS_EVENT(name) \ +DEFINE_EVENT(ocfs2__truncate_log_ops, name, \ + TP_PROTO(unsigned long long blkno, int index, \ + unsigned int start, unsigned int num), \ + TP_ARGS(blkno, index, start, num)) + +DEFINE_OCFS2_TRUNCATE_LOG_OPS_EVENT(ocfs2_truncate_log_append); + +DEFINE_OCFS2_TRUNCATE_LOG_OPS_EVENT(ocfs2_replay_truncate_records); + +DEFINE_OCFS2_ULL_UINT_EVENT(ocfs2_flush_truncate_log); + +DEFINE_OCFS2_INT_EVENT(ocfs2_begin_truncate_log_recovery); + +DEFINE_OCFS2_INT_EVENT(ocfs2_truncate_log_recovery_num); + +DEFINE_OCFS2_ULL_UINT_EVENT(ocfs2_complete_truncate_log_recovery); + +DEFINE_OCFS2_ULL_UINT_EVENT(ocfs2_free_cached_blocks); + +DEFINE_OCFS2_ULL_UINT_EVENT(ocfs2_cache_cluster_dealloc); + +DEFINE_OCFS2_INT_INT_EVENT(ocfs2_run_deallocs); + +TRACE_EVENT(ocfs2_cache_block_dealloc, + TP_PROTO(int type, int slot, unsigned long long suballoc, + unsigned long long blkno, unsigned int bit), + TP_ARGS(type, slot, suballoc, blkno, bit), + TP_STRUCT__entry( + __field(int, type) + __field(int, slot) + __field(unsigned long long, suballoc) + __field(unsigned long long, blkno) + __field(unsigned int, bit) + ), + TP_fast_assign( + __entry->type = type; + __entry->slot = slot; + __entry->suballoc = suballoc; + __entry->blkno = blkno; + __entry->bit = bit; + ), + TP_printk("%d %d %llu %llu %u", + __entry->type, __entry->slot, __entry->suballoc, + __entry->blkno, __entry->bit) +); + +/* End of trace events for fs/ocfs2/alloc.c. */ #endif /* _TRACE_OCFS2_H */ -- GitLab From a04733d8afad9cd0bfb8269173e30d28fb96088e Mon Sep 17 00:00:00 2001 From: Tao Ma Date: Tue, 22 Feb 2011 07:56:45 +0800 Subject: [PATCH 0106/2822] ocfs2: Remove mlog(0) from fs/ocfs2/localalloc.c This is the 2nd step to remove the debug info of DISK_ALLOC. So this patch removes all mlog(0,...) from localalloc.c and adds the corresponding tracepoints. Different mlogs have different solutions. 1. Some are replaced with trace event directly. 2. Some are replaced while some new parameters are added. 3. Some are combined into one trace events. 4. Some redundant mlogs are removed. Signed-off-by: Tao Ma --- fs/ocfs2/localalloc.c | 57 +++++++++------------ fs/ocfs2/ocfs2_trace.h | 112 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 135 insertions(+), 34 deletions(-) diff --git a/fs/ocfs2/localalloc.c b/fs/ocfs2/localalloc.c index 36636e1c84e74..a311b1f658e23 100644 --- a/fs/ocfs2/localalloc.c +++ b/fs/ocfs2/localalloc.c @@ -43,6 +43,7 @@ #include "suballoc.h" #include "super.h" #include "sysfile.h" +#include "ocfs2_trace.h" #include "buffer_head_io.h" @@ -201,8 +202,7 @@ void ocfs2_la_set_sizes(struct ocfs2_super *osb, int requested_mb) la_max_mb = ocfs2_clusters_to_megabytes(sb, ocfs2_local_alloc_size(sb) * 8); - mlog(0, "requested: %dM, max: %uM, default: %uM\n", - requested_mb, la_max_mb, la_default_mb); + trace_ocfs2_la_set_sizes(requested_mb, la_max_mb, la_default_mb); if (requested_mb == -1) { /* No user request - use defaults */ @@ -276,8 +276,8 @@ int ocfs2_alloc_should_use_local(struct ocfs2_super *osb, u64 bits) ret = 1; bail: - mlog(0, "state=%d, bits=%llu, la_bits=%d, ret=%d\n", - osb->local_alloc_state, (unsigned long long)bits, la_bits, ret); + trace_ocfs2_alloc_should_use_local( + (unsigned long long)bits, osb->local_alloc_state, la_bits, ret); spin_unlock(&osb->osb_lock); return ret; } @@ -362,7 +362,7 @@ bail: if (inode) iput(inode); - mlog(0, "Local alloc window bits = %d\n", osb->local_alloc_bits); + trace_ocfs2_load_local_alloc(osb->local_alloc_bits); if (status) mlog_errno(status); @@ -497,7 +497,7 @@ int ocfs2_begin_local_alloc_recovery(struct ocfs2_super *osb, struct inode *inode = NULL; struct ocfs2_dinode *alloc; - mlog(0, "(slot_num = %d)\n", slot_num); + trace_ocfs2_begin_local_alloc_recovery(slot_num); *alloc_copy = NULL; @@ -705,10 +705,6 @@ int ocfs2_reserve_local_alloc_bits(struct ocfs2_super *osb, goto bail; } - if (ac->ac_max_block) - mlog(0, "Calling in_range for max block %llu\n", - (unsigned long long)ac->ac_max_block); - ac->ac_inode = local_alloc_inode; /* We should never use localalloc from another slot */ ac->ac_alloc_slot = osb->slot_num; @@ -722,8 +718,9 @@ bail: iput(local_alloc_inode); } - mlog(0, "bits=%d, slot=%d, ret=%d\n", bits_wanted, osb->slot_num, - status); + trace_ocfs2_reserve_local_alloc_bits( + (unsigned long long)ac->ac_max_block, + bits_wanted, osb->slot_num, status); if (status) mlog_errno(status); @@ -797,7 +794,7 @@ static u32 ocfs2_local_alloc_count_bits(struct ocfs2_dinode *alloc) for (i = 0; i < le16_to_cpu(la->la_size); i++) count += hweight8(buffer[i]); - mlog(0, "count %u\n", count); + trace_ocfs2_local_alloc_count_bits(count); return count; } @@ -812,10 +809,7 @@ static int ocfs2_local_alloc_find_clear_bits(struct ocfs2_super *osb, void *bitmap = NULL; struct ocfs2_reservation_map *resmap = &osb->osb_la_resmap; - mlog(0, "(numbits wanted = %u)\n", *numbits); - if (!alloc->id1.bitmap1.i_total) { - mlog(0, "No bits in my window!\n"); bitoff = -1; goto bail; } @@ -875,8 +869,7 @@ static int ocfs2_local_alloc_find_clear_bits(struct ocfs2_super *osb, } } - mlog(0, "Exiting loop, bitoff = %d, numfound = %d\n", bitoff, - numfound); + trace_ocfs2_local_alloc_find_clear_bits_search_bitmap(bitoff, numfound); if (numfound == *numbits) bitoff = startoff - numfound; @@ -887,7 +880,10 @@ bail: if (local_resv) ocfs2_resv_discard(resmap, resv); - mlog(0, "bitoff %d\n", bitoff); + trace_ocfs2_local_alloc_find_clear_bits(*numbits, + le32_to_cpu(alloc->id1.bitmap1.i_total), + bitoff, numfound); + return bitoff; } @@ -941,18 +937,16 @@ static int ocfs2_sync_local_to_main(struct ocfs2_super *osb, void *bitmap; struct ocfs2_local_alloc *la = OCFS2_LOCAL_ALLOC(alloc); - mlog(0, "total = %u, used = %u\n", + trace_ocfs2_sync_local_to_main( le32_to_cpu(alloc->id1.bitmap1.i_total), le32_to_cpu(alloc->id1.bitmap1.i_used)); if (!alloc->id1.bitmap1.i_total) { - mlog(0, "nothing to sync!\n"); goto bail; } if (le32_to_cpu(alloc->id1.bitmap1.i_used) == le32_to_cpu(alloc->id1.bitmap1.i_total)) { - mlog(0, "all bits were taken!\n"); goto bail; } @@ -974,8 +968,7 @@ static int ocfs2_sync_local_to_main(struct ocfs2_super *osb, ocfs2_clusters_to_blocks(osb->sb, start - count); - mlog(0, "freeing %u bits starting at local alloc bit " - "%u (la_start_blk = %llu, blkno = %llu)\n", + trace_ocfs2_sync_local_to_main_free( count, start - count, (unsigned long long)la_start_blk, (unsigned long long)blkno); @@ -1142,12 +1135,9 @@ static int ocfs2_local_alloc_new_window(struct ocfs2_super *osb, alloc = (struct ocfs2_dinode *) osb->local_alloc_bh->b_data; la = OCFS2_LOCAL_ALLOC(alloc); - if (alloc->id1.bitmap1.i_total) - mlog(0, "asking me to alloc a new window over a non-empty " - "one\n"); - - mlog(0, "Allocating %u clusters for a new window.\n", - osb->local_alloc_bits); + trace_ocfs2_local_alloc_new_window( + le32_to_cpu(alloc->id1.bitmap1.i_total), + osb->local_alloc_bits); /* Instruct the allocation code to try the most recently used * cluster group. We'll re-record the group used this pass @@ -1209,10 +1199,9 @@ retry_enospc: ocfs2_resmap_restart(&osb->osb_la_resmap, cluster_count, OCFS2_LOCAL_ALLOC(alloc)->la_bitmap); - mlog(0, "New window allocated:\n"); - mlog(0, "window la_bm_off = %u\n", - OCFS2_LOCAL_ALLOC(alloc)->la_bm_off); - mlog(0, "window bits = %u\n", le32_to_cpu(alloc->id1.bitmap1.i_total)); + trace_ocfs2_local_alloc_new_window_result( + OCFS2_LOCAL_ALLOC(alloc)->la_bm_off, + le32_to_cpu(alloc->id1.bitmap1.i_total)); bail: if (status) diff --git a/fs/ocfs2/ocfs2_trace.h b/fs/ocfs2/ocfs2_trace.h index 1793b1f718059..5bba629766cab 100644 --- a/fs/ocfs2/ocfs2_trace.h +++ b/fs/ocfs2/ocfs2_trace.h @@ -23,6 +23,23 @@ DEFINE_EVENT(ocfs2__int, name, \ TP_PROTO(int num), \ TP_ARGS(num)) +DECLARE_EVENT_CLASS(ocfs2__uint, + TP_PROTO(unsigned int num), + TP_ARGS(num), + TP_STRUCT__entry( + __field( unsigned int, num ) + ), + TP_fast_assign( + __entry->num = num; + ), + TP_printk("%u", __entry->num) +); + +#define DEFINE_OCFS2_UINT_EVENT(name) \ +DEFINE_EVENT(ocfs2__uint, name, \ + TP_PROTO(unsigned int num), \ + TP_ARGS(num)) + DECLARE_EVENT_CLASS(ocfs2__int_int, TP_PROTO(int value1, int value2), TP_ARGS(value1, value2), @@ -61,6 +78,55 @@ DEFINE_EVENT(ocfs2__ull_uint, name, \ TP_PROTO(unsigned long long val1, unsigned int val2), \ TP_ARGS(val1, val2)) +DECLARE_EVENT_CLASS(ocfs2__uint_uint_uint, + TP_PROTO(unsigned int value1, unsigned int value2, + unsigned int value3), + TP_ARGS(value1, value2, value3), + TP_STRUCT__entry( + __field( unsigned int, value1 ) + __field( unsigned int, value2 ) + __field( unsigned int, value3 ) + ), + TP_fast_assign( + __entry->value1 = value1; + __entry->value2 = value2; + __entry->value3 = value3; + ), + TP_printk("%u %u %u", __entry->value1, __entry->value2, __entry->value3) +); + +#define DEFINE_OCFS2_UINT_UINT_UINT_EVENT(name) \ +DEFINE_EVENT(ocfs2__uint_uint_uint, name, \ + TP_PROTO(unsigned int value1, unsigned int value2, \ + unsigned int value3), \ + TP_ARGS(value1, value2, value3)) + +DECLARE_EVENT_CLASS(ocfs2__ull_int_int_int, + TP_PROTO(unsigned long long ull, int value1, int value2, int value3), + TP_ARGS(ull, value1, value2, value3), + TP_STRUCT__entry( + __field( unsigned long long, ull ) + __field( int, value1 ) + __field( int, value2 ) + __field( int, value3 ) + ), + TP_fast_assign( + __entry->ull = ull; + __entry->value1 = value1; + __entry->value2 = value2; + __entry->value3 = value3; + ), + TP_printk("%llu %d %d %d", + __entry->ull, __entry->value1, + __entry->value2, __entry->value3) +); + +#define DEFINE_OCFS2_ULL_INT_INT_INT_EVENT(name) \ +DEFINE_EVENT(ocfs2__ull_int_int_int, name, \ + TP_PROTO(unsigned long long ull, int value1, \ + int value2, int value3), \ + TP_ARGS(ull, value1, value2, value3)) + /* Trace events for fs/ocfs2/alloc.c. */ DECLARE_EVENT_CLASS(ocfs2__btree_ops, TP_PROTO(unsigned long long owner,\ @@ -371,6 +437,52 @@ TRACE_EVENT(ocfs2_cache_block_dealloc, /* End of trace events for fs/ocfs2/alloc.c. */ +/* Trace events for fs/ocfs2/localalloc.c. */ + +DEFINE_OCFS2_UINT_UINT_UINT_EVENT(ocfs2_la_set_sizes); + +DEFINE_OCFS2_ULL_INT_INT_INT_EVENT(ocfs2_alloc_should_use_local); + +DEFINE_OCFS2_INT_EVENT(ocfs2_load_local_alloc); + +DEFINE_OCFS2_INT_EVENT(ocfs2_begin_local_alloc_recovery); + +DEFINE_OCFS2_ULL_INT_INT_INT_EVENT(ocfs2_reserve_local_alloc_bits); + +DEFINE_OCFS2_UINT_EVENT(ocfs2_local_alloc_count_bits); + +DEFINE_OCFS2_INT_INT_EVENT(ocfs2_local_alloc_find_clear_bits_search_bitmap); + +DEFINE_OCFS2_ULL_INT_INT_INT_EVENT(ocfs2_local_alloc_find_clear_bits); + +DEFINE_OCFS2_INT_INT_EVENT(ocfs2_sync_local_to_main); + +TRACE_EVENT(ocfs2_sync_local_to_main_free, + TP_PROTO(int count, int bit, unsigned long long start_blk, + unsigned long long blkno), + TP_ARGS(count, bit, start_blk, blkno), + TP_STRUCT__entry( + __field(int, count) + __field(int, bit) + __field(unsigned long long, start_blk) + __field(unsigned long long, blkno) + ), + TP_fast_assign( + __entry->count = count; + __entry->bit = bit; + __entry->start_blk = start_blk; + __entry->blkno = blkno; + ), + TP_printk("%d %d %llu %llu", + __entry->count, __entry->bit, __entry->start_blk, + __entry->blkno) +); + +DEFINE_OCFS2_INT_INT_EVENT(ocfs2_local_alloc_new_window); + +DEFINE_OCFS2_ULL_UINT_EVENT(ocfs2_local_alloc_new_window_result); + +/* End of trace events for fs/ocfs2/localalloc.c. */ #endif /* _TRACE_OCFS2_H */ /* This part must be outside protection */ -- GitLab From 2f73e135b83c5001dad84cbd1d445d23fd045b83 Mon Sep 17 00:00:00 2001 From: Tao Ma Date: Tue, 22 Feb 2011 08:22:33 +0800 Subject: [PATCH 0107/2822] ocfs2: Remove mlog(0) from fs/ocfs2/suballoc.c This is the 3rd step to remove the debug info of DISK_ALLOC. Signed-off-by: Tao Ma --- fs/ocfs2/ocfs2_trace.h | 212 +++++++++++++++++++++++++++++++++++++++++ fs/ocfs2/suballoc.c | 107 +++++++++++---------- 2 files changed, 265 insertions(+), 54 deletions(-) diff --git a/fs/ocfs2/ocfs2_trace.h b/fs/ocfs2/ocfs2_trace.h index 5bba629766cab..11980ecba5460 100644 --- a/fs/ocfs2/ocfs2_trace.h +++ b/fs/ocfs2/ocfs2_trace.h @@ -40,6 +40,23 @@ DEFINE_EVENT(ocfs2__uint, name, \ TP_PROTO(unsigned int num), \ TP_ARGS(num)) +DECLARE_EVENT_CLASS(ocfs2__ull, + TP_PROTO(unsigned long long blkno), + TP_ARGS(blkno), + TP_STRUCT__entry( + __field(unsigned long long, blkno) + ), + TP_fast_assign( + __entry->blkno = blkno; + ), + TP_printk("%llu", __entry->blkno) +); + +#define DEFINE_OCFS2_ULL_EVENT(name) \ +DEFINE_EVENT(ocfs2__ull, name, \ + TP_PROTO(unsigned long long num), \ + TP_ARGS(num)) + DECLARE_EVENT_CLASS(ocfs2__int_int, TP_PROTO(int value1, int value2), TP_ARGS(value1, value2), @@ -59,6 +76,25 @@ DEFINE_EVENT(ocfs2__int_int, name, \ TP_PROTO(int val1, int val2), \ TP_ARGS(val1, val2)) +DECLARE_EVENT_CLASS(ocfs2__uint_uint, + TP_PROTO(unsigned int value1, unsigned int value2), + TP_ARGS(value1, value2), + TP_STRUCT__entry( + __field(unsigned int, value1) + __field(unsigned int, value2) + ), + TP_fast_assign( + __entry->value1 = value1; + __entry->value2 = value2; + ), + TP_printk("%u %u", __entry->value1, __entry->value2) +); + +#define DEFINE_OCFS2_UINT_UINT_EVENT(name) \ +DEFINE_EVENT(ocfs2__uint_uint, name, \ + TP_PROTO(unsigned int val1, unsigned int val2), \ + TP_ARGS(val1, val2)) + DECLARE_EVENT_CLASS(ocfs2__ull_uint, TP_PROTO(unsigned long long value1, unsigned int value2), TP_ARGS(value1, value2), @@ -78,6 +114,49 @@ DEFINE_EVENT(ocfs2__ull_uint, name, \ TP_PROTO(unsigned long long val1, unsigned int val2), \ TP_ARGS(val1, val2)) +DECLARE_EVENT_CLASS(ocfs2__ull_ull, + TP_PROTO(unsigned long long value1, unsigned long long value2), + TP_ARGS(value1, value2), + TP_STRUCT__entry( + __field(unsigned long long, value1) + __field(unsigned long long, value2) + ), + TP_fast_assign( + __entry->value1 = value1; + __entry->value2 = value2; + ), + TP_printk("%llu %llu", __entry->value1, __entry->value2) +); + +#define DEFINE_OCFS2_ULL_ULL_EVENT(name) \ +DEFINE_EVENT(ocfs2__ull_ull, name, \ + TP_PROTO(unsigned long long val1, unsigned long long val2), \ + TP_ARGS(val1, val2)) + +DECLARE_EVENT_CLASS(ocfs2__ull_uint_uint, + TP_PROTO(unsigned long long value1, + unsigned int value2, unsigned int value3), + TP_ARGS(value1, value2, value3), + TP_STRUCT__entry( + __field(unsigned long long, value1) + __field(unsigned int, value2) + __field(unsigned int, value3) + ), + TP_fast_assign( + __entry->value1 = value1; + __entry->value2 = value2; + __entry->value3 = value3; + ), + TP_printk("%llu %u %u", __entry->value1, + __entry->value2, __entry->value3) +); + +#define DEFINE_OCFS2_ULL_UINT_UINT_EVENT(name) \ +DEFINE_EVENT(ocfs2__ull_uint_uint, name, \ + TP_PROTO(unsigned long long val1, \ + unsigned int val2, unsigned int val3), \ + TP_ARGS(val1, val2, val3)) + DECLARE_EVENT_CLASS(ocfs2__uint_uint_uint, TP_PROTO(unsigned int value1, unsigned int value2, unsigned int value3), @@ -127,6 +206,33 @@ DEFINE_EVENT(ocfs2__ull_int_int_int, name, \ int value2, int value3), \ TP_ARGS(ull, value1, value2, value3)) +DECLARE_EVENT_CLASS(ocfs2__ull_uint_uint_uint, + TP_PROTO(unsigned long long ull, unsigned int value1, + unsigned int value2, unsigned int value3), + TP_ARGS(ull, value1, value2, value3), + TP_STRUCT__entry( + __field(unsigned long long, ull) + __field(unsigned int, value1) + __field(unsigned int, value2) + __field(unsigned int, value3) + ), + TP_fast_assign( + __entry->ull = ull; + __entry->value1 = value1; + __entry->value2 = value2; + __entry->value3 = value3; + ), + TP_printk("%llu %u %u %u", + __entry->ull, __entry->value1, + __entry->value2, __entry->value3) +); + +#define DEFINE_OCFS2_ULL_UINT_UINT_UINT_EVENT(name) \ +DEFINE_EVENT(ocfs2__ull_uint_uint_uint, name, \ + TP_PROTO(unsigned long long ull, unsigned int value1, \ + unsigned int value2, unsigned int value3), \ + TP_ARGS(ull, value1, value2, value3)) + /* Trace events for fs/ocfs2/alloc.c. */ DECLARE_EVENT_CLASS(ocfs2__btree_ops, TP_PROTO(unsigned long long owner,\ @@ -483,6 +589,112 @@ DEFINE_OCFS2_INT_INT_EVENT(ocfs2_local_alloc_new_window); DEFINE_OCFS2_ULL_UINT_EVENT(ocfs2_local_alloc_new_window_result); /* End of trace events for fs/ocfs2/localalloc.c. */ + +/* Trace events for fs/ocfs2/suballoc.c. */ + +DEFINE_OCFS2_ULL_EVENT(ocfs2_validate_group_descriptor); + +DEFINE_OCFS2_ULL_UINT_EVENT(ocfs2_block_group_alloc_contig); + +DEFINE_OCFS2_ULL_UINT_EVENT(ocfs2_block_group_alloc_discontig); + +DEFINE_OCFS2_ULL_EVENT(ocfs2_block_group_alloc); + +DEFINE_OCFS2_UINT_UINT_EVENT(ocfs2_reserve_suballoc_bits_nospc); + +DEFINE_OCFS2_UINT_UINT_UINT_EVENT(ocfs2_reserve_suballoc_bits_no_new_group); + +DEFINE_OCFS2_ULL_EVENT(ocfs2_reserve_new_inode_new_group); + +DEFINE_OCFS2_UINT_UINT_EVENT(ocfs2_block_group_set_bits); + +TRACE_EVENT(ocfs2_relink_block_group, + TP_PROTO(unsigned long long i_blkno, unsigned int chain, + unsigned long long bg_blkno, + unsigned long long prev_blkno), + TP_ARGS(i_blkno, chain, bg_blkno, prev_blkno), + TP_STRUCT__entry( + __field(unsigned long long, i_blkno) + __field(unsigned int, chain) + __field(unsigned long long, bg_blkno) + __field(unsigned long long, prev_blkno) + ), + TP_fast_assign( + __entry->i_blkno = i_blkno; + __entry->chain = chain; + __entry->bg_blkno = bg_blkno; + __entry->prev_blkno = prev_blkno; + ), + TP_printk("%llu %u %llu %llu", + __entry->i_blkno, __entry->chain, __entry->bg_blkno, + __entry->prev_blkno) +); + +DEFINE_OCFS2_ULL_UINT_UINT_UINT_EVENT(ocfs2_cluster_group_search_wrong_max_bits); + +DEFINE_OCFS2_ULL_ULL_EVENT(ocfs2_cluster_group_search_max_block); + +DEFINE_OCFS2_ULL_ULL_EVENT(ocfs2_block_group_search_max_block); + +DEFINE_OCFS2_ULL_UINT_UINT_EVENT(ocfs2_search_chain_begin); + +DEFINE_OCFS2_ULL_UINT_EVENT(ocfs2_search_chain_succ); + +DEFINE_OCFS2_ULL_UINT_EVENT(ocfs2_search_chain_end); + +DEFINE_OCFS2_UINT_EVENT(ocfs2_claim_suballoc_bits); + +DEFINE_OCFS2_ULL_UINT_EVENT(ocfs2_claim_new_inode_at_loc); + +DEFINE_OCFS2_UINT_UINT_EVENT(ocfs2_block_group_clear_bits); + +TRACE_EVENT(ocfs2_free_suballoc_bits, + TP_PROTO(unsigned long long inode, unsigned long long group, + unsigned int start_bit, unsigned int count), + TP_ARGS(inode, group, start_bit, count), + TP_STRUCT__entry( + __field(unsigned long long, inode) + __field(unsigned long long, group) + __field(unsigned int, start_bit) + __field(unsigned int, count) + ), + TP_fast_assign( + __entry->inode = inode; + __entry->group = group; + __entry->start_bit = start_bit; + __entry->count = count; + ), + TP_printk("%llu %llu %u %u", __entry->inode, __entry->group, + __entry->start_bit, __entry->count) +); + +TRACE_EVENT(ocfs2_free_clusters, + TP_PROTO(unsigned long long bg_blkno, unsigned long long start_blk, + unsigned int start_bit, unsigned int count), + TP_ARGS(bg_blkno, start_blk, start_bit, count), + TP_STRUCT__entry( + __field(unsigned long long, bg_blkno) + __field(unsigned long long, start_blk) + __field(unsigned int, start_bit) + __field(unsigned int, count) + ), + TP_fast_assign( + __entry->bg_blkno = bg_blkno; + __entry->start_blk = start_blk; + __entry->start_bit = start_bit; + __entry->count = count; + ), + TP_printk("%llu %llu %u %u", __entry->bg_blkno, __entry->start_blk, + __entry->start_bit, __entry->count) +); + +DEFINE_OCFS2_ULL_EVENT(ocfs2_get_suballoc_slot_bit); + +DEFINE_OCFS2_ULL_UINT_EVENT(ocfs2_test_suballoc_bit); + +DEFINE_OCFS2_ULL_EVENT(ocfs2_test_inode_bit); + +/* End of trace events for fs/ocfs2/suballoc.c. */ #endif /* _TRACE_OCFS2_H */ /* This part must be outside protection */ diff --git a/fs/ocfs2/suballoc.c b/fs/ocfs2/suballoc.c index 2d722f1fbaa0d..94342bd9800db 100644 --- a/fs/ocfs2/suballoc.c +++ b/fs/ocfs2/suballoc.c @@ -44,6 +44,7 @@ #include "super.h" #include "sysfile.h" #include "uptodate.h" +#include "ocfs2_trace.h" #include "buffer_head_io.h" @@ -308,8 +309,8 @@ static int ocfs2_validate_group_descriptor(struct super_block *sb, int rc; struct ocfs2_group_desc *gd = (struct ocfs2_group_desc *)bh->b_data; - mlog(0, "Validating group descriptor %llu\n", - (unsigned long long)bh->b_blocknr); + trace_ocfs2_validate_group_descriptor( + (unsigned long long)bh->b_blocknr); BUG_ON(!buffer_uptodate(bh)); @@ -476,8 +477,8 @@ ocfs2_block_group_alloc_contig(struct ocfs2_super *osb, handle_t *handle, /* setup the group */ bg_blkno = ocfs2_clusters_to_blocks(osb->sb, bit_off); - mlog(0, "new descriptor, record %u, at block %llu\n", - alloc_rec, (unsigned long long)bg_blkno); + trace_ocfs2_block_group_alloc_contig( + (unsigned long long)bg_blkno, alloc_rec); bg_bh = sb_getblk(osb->sb, bg_blkno); if (!bg_bh) { @@ -656,8 +657,8 @@ ocfs2_block_group_alloc_discontig(handle_t *handle, /* setup the group */ bg_blkno = ocfs2_clusters_to_blocks(osb->sb, bit_off); - mlog(0, "new descriptor, record %u, at block %llu\n", - alloc_rec, (unsigned long long)bg_blkno); + trace_ocfs2_block_group_alloc_discontig( + (unsigned long long)bg_blkno, alloc_rec); bg_bh = sb_getblk(osb->sb, bg_blkno); if (!bg_bh) { @@ -727,8 +728,8 @@ static int ocfs2_block_group_alloc(struct ocfs2_super *osb, } if (last_alloc_group && *last_alloc_group != 0) { - mlog(0, "use old allocation group %llu for block group alloc\n", - (unsigned long long)*last_alloc_group); + trace_ocfs2_block_group_alloc( + (unsigned long long)*last_alloc_group); ac->ac_last_group = *last_alloc_group; } @@ -851,16 +852,15 @@ static int ocfs2_reserve_suballoc_bits(struct ocfs2_super *osb, if (bits_wanted > free_bits) { /* cluster bitmap never grows */ if (ocfs2_is_cluster_bitmap(alloc_inode)) { - mlog(0, "Disk Full: wanted=%u, free_bits=%u\n", - bits_wanted, free_bits); + trace_ocfs2_reserve_suballoc_bits_nospc(bits_wanted, + free_bits); status = -ENOSPC; goto bail; } if (!(flags & ALLOC_NEW_GROUP)) { - mlog(0, "Alloc File %u Full: wanted=%u, free_bits=%u, " - "and we don't alloc a new group for it.\n", - slot, bits_wanted, free_bits); + trace_ocfs2_reserve_suballoc_bits_no_new_group( + slot, bits_wanted, free_bits); status = -ENOSPC; goto bail; } @@ -1117,8 +1117,8 @@ int ocfs2_reserve_new_inode(struct ocfs2_super *osb, spin_lock(&osb->osb_lock); osb->osb_inode_alloc_group = alloc_group; spin_unlock(&osb->osb_lock); - mlog(0, "after reservation, new allocation group is " - "%llu\n", (unsigned long long)alloc_group); + trace_ocfs2_reserve_new_inode_new_group( + (unsigned long long)alloc_group); /* * Some inodes must be freed by us, so try to allocate @@ -1360,8 +1360,7 @@ static inline int ocfs2_block_group_set_bits(handle_t *handle, BUG_ON(!OCFS2_IS_VALID_GROUP_DESC(bg)); BUG_ON(le16_to_cpu(bg->bg_free_bits_count) < num_bits); - mlog(0, "block_group_set_bits: off = %u, num = %u\n", bit_off, - num_bits); + trace_ocfs2_block_group_set_bits(bit_off, num_bits); if (ocfs2_is_cluster_bitmap(alloc_inode)) journal_type = OCFS2_JOURNAL_ACCESS_UNDO; @@ -1434,10 +1433,10 @@ static int ocfs2_relink_block_group(handle_t *handle, BUG_ON(!OCFS2_IS_VALID_GROUP_DESC(bg)); BUG_ON(!OCFS2_IS_VALID_GROUP_DESC(prev_bg)); - mlog(0, "Suballoc %llu, chain %u, move group %llu to top, prev = %llu\n", - (unsigned long long)le64_to_cpu(fe->i_blkno), chain, - (unsigned long long)le64_to_cpu(bg->bg_blkno), - (unsigned long long)le64_to_cpu(prev_bg->bg_blkno)); + trace_ocfs2_relink_block_group( + (unsigned long long)le64_to_cpu(fe->i_blkno), chain, + (unsigned long long)le64_to_cpu(bg->bg_blkno), + (unsigned long long)le64_to_cpu(prev_bg->bg_blkno)); fe_ptr = le64_to_cpu(fe->id2.i_chain.cl_recs[chain].c_blkno); bg_ptr = le64_to_cpu(bg->bg_next_group); @@ -1523,10 +1522,10 @@ static int ocfs2_cluster_group_search(struct inode *inode, if ((gd_cluster_off + max_bits) > OCFS2_I(inode)->ip_clusters) { max_bits = OCFS2_I(inode)->ip_clusters - gd_cluster_off; - mlog(0, "Desc %llu, bg_bits %u, clusters %u, use %u\n", - (unsigned long long)le64_to_cpu(gd->bg_blkno), - le16_to_cpu(gd->bg_bits), - OCFS2_I(inode)->ip_clusters, max_bits); + trace_ocfs2_cluster_group_search_wrong_max_bits( + (unsigned long long)le64_to_cpu(gd->bg_blkno), + le16_to_cpu(gd->bg_bits), + OCFS2_I(inode)->ip_clusters, max_bits); } ret = ocfs2_block_group_find_clear_bits(OCFS2_SB(inode->i_sb), @@ -1540,9 +1539,9 @@ static int ocfs2_cluster_group_search(struct inode *inode, gd_cluster_off + res->sr_bit_offset + res->sr_bits); - mlog(0, "Checking %llu against %llu\n", - (unsigned long long)blkoff, - (unsigned long long)max_block); + trace_ocfs2_cluster_group_search_max_block( + (unsigned long long)blkoff, + (unsigned long long)max_block); if (blkoff > max_block) return -ENOSPC; } @@ -1586,9 +1585,9 @@ static int ocfs2_block_group_search(struct inode *inode, if (!ret && max_block) { blkoff = le64_to_cpu(bg->bg_blkno) + res->sr_bit_offset + res->sr_bits; - mlog(0, "Checking %llu against %llu\n", - (unsigned long long)blkoff, - (unsigned long long)max_block); + trace_ocfs2_block_group_search_max_block( + (unsigned long long)blkoff, + (unsigned long long)max_block); if (blkoff > max_block) ret = -ENOSPC; } @@ -1754,9 +1753,9 @@ static int ocfs2_search_chain(struct ocfs2_alloc_context *ac, struct ocfs2_group_desc *bg; chain = ac->ac_chain; - mlog(0, "trying to alloc %u bits from chain %u, inode %llu\n", - bits_wanted, chain, - (unsigned long long)OCFS2_I(alloc_inode)->ip_blkno); + trace_ocfs2_search_chain_begin( + (unsigned long long)OCFS2_I(alloc_inode)->ip_blkno, + bits_wanted, chain); status = ocfs2_read_group_descriptor(alloc_inode, fe, le64_to_cpu(cl->cl_recs[chain].c_blkno), @@ -1797,8 +1796,8 @@ static int ocfs2_search_chain(struct ocfs2_alloc_context *ac, goto bail; } - mlog(0, "alloc succeeds: we give %u bits from block group %llu\n", - res->sr_bits, (unsigned long long)le64_to_cpu(bg->bg_blkno)); + trace_ocfs2_search_chain_succ( + (unsigned long long)le64_to_cpu(bg->bg_blkno), res->sr_bits); res->sr_bg_blkno = le64_to_cpu(bg->bg_blkno); @@ -1859,8 +1858,9 @@ static int ocfs2_search_chain(struct ocfs2_alloc_context *ac, goto bail; } - mlog(0, "Allocated %u bits from suballocator %llu\n", res->sr_bits, - (unsigned long long)le64_to_cpu(fe->i_blkno)); + trace_ocfs2_search_chain_end( + (unsigned long long)le64_to_cpu(fe->i_blkno), + res->sr_bits); out_loc_only: *bits_left = le16_to_cpu(bg->bg_free_bits_count); @@ -1942,8 +1942,7 @@ static int ocfs2_claim_suballoc_bits(struct ocfs2_alloc_context *ac, goto bail; } - mlog(0, "Search of victim chain %u came up with nothing, " - "trying all chains now.\n", victim); + trace_ocfs2_claim_suballoc_bits(victim); /* If we didn't pick a good victim, then just default to * searching each chain in order. Don't allow chain relinking @@ -2171,8 +2170,8 @@ int ocfs2_claim_new_inode_at_loc(handle_t *handle, goto out; } - mlog(0, "Allocated %u bits from suballocator %llu\n", res->sr_bits, - (unsigned long long)di_blkno); + trace_ocfs2_claim_new_inode_at_loc((unsigned long long)di_blkno, + res->sr_bits); atomic_inc(&OCFS2_SB(ac->ac_inode->i_sb)->alloc_stats.bg_allocs); @@ -2393,7 +2392,7 @@ static int ocfs2_block_group_clear_bits(handle_t *handle, * ocfs2_read_group_descriptor(). Any corruption is a code bug. */ BUG_ON(!OCFS2_IS_VALID_GROUP_DESC(bg)); - mlog(0, "off = %u, num = %u\n", bit_off, num_bits); + trace_ocfs2_block_group_clear_bits(bit_off, num_bits); BUG_ON(undo_fn && !ocfs2_is_cluster_bitmap(alloc_inode)); status = ocfs2_journal_access_gd(handle, INODE_CACHE(alloc_inode), @@ -2466,9 +2465,10 @@ static int _ocfs2_free_suballoc_bits(handle_t *handle, BUG_ON(!OCFS2_IS_VALID_DINODE(fe)); BUG_ON((count + start_bit) > ocfs2_bits_per_group(cl)); - mlog(0, "%llu: freeing %u bits from group %llu, starting at %u\n", - (unsigned long long)OCFS2_I(alloc_inode)->ip_blkno, count, - (unsigned long long)bg_blkno, start_bit); + trace_ocfs2_free_suballoc_bits( + (unsigned long long)OCFS2_I(alloc_inode)->ip_blkno, + (unsigned long long)bg_blkno, + start_bit, count); status = ocfs2_read_group_descriptor(alloc_inode, fe, bg_blkno, &group_bh); @@ -2560,10 +2560,9 @@ static int _ocfs2_free_clusters(handle_t *handle, ocfs2_block_to_cluster_group(bitmap_inode, start_blk, &bg_blkno, &bg_start_bit); - mlog(0, "want to free %u clusters starting at block %llu\n", - num_clusters, (unsigned long long)start_blk); - mlog(0, "bg_blkno = %llu, bg_start_bit = %u\n", - (unsigned long long)bg_blkno, bg_start_bit); + trace_ocfs2_free_clusters((unsigned long long)bg_blkno, + (unsigned long long)start_blk, + bg_start_bit, num_clusters); status = _ocfs2_free_suballoc_bits(handle, bitmap_inode, bitmap_bh, bg_start_bit, bg_blkno, @@ -2748,7 +2747,7 @@ static int ocfs2_get_suballoc_slot_bit(struct ocfs2_super *osb, u64 blkno, struct buffer_head *inode_bh = NULL; struct ocfs2_dinode *inode_fe; - mlog(0, "blkno: %llu\n", (unsigned long long)blkno); + trace_ocfs2_get_suballoc_slot_bit((unsigned long long)blkno); /* dirty read disk */ status = ocfs2_read_blocks_sync(osb, blkno, 1, &inode_bh); @@ -2809,8 +2808,8 @@ static int ocfs2_test_suballoc_bit(struct ocfs2_super *osb, u64 bg_blkno; int status; - mlog(0, "blkno: %llu bit: %u\n", (unsigned long long)blkno, - (unsigned int)bit); + trace_ocfs2_test_suballoc_bit((unsigned long long)blkno, + (unsigned int)bit); alloc_di = (struct ocfs2_dinode *)alloc_bh->b_data; if ((bit + 1) > ocfs2_bits_per_group(&alloc_di->id2.i_chain)) { @@ -2863,7 +2862,7 @@ int ocfs2_test_inode_bit(struct ocfs2_super *osb, u64 blkno, int *res) struct inode *inode_alloc_inode; struct buffer_head *alloc_bh = NULL; - mlog(0, "blkno: %llu", (unsigned long long)blkno); + trace_ocfs2_test_inode_bit((unsigned long long)blkno); status = ocfs2_get_suballoc_slot_bit(osb, blkno, &suballoc_slot, &group_blkno, &suballoc_bit); -- GitLab From a5438702ee63b13710c497bb22c7952a7e5d6a52 Mon Sep 17 00:00:00 2001 From: Tao Ma Date: Tue, 22 Feb 2011 08:24:01 +0800 Subject: [PATCH 0108/2822] ocfs2: Remove mlog(0) from fs/ocfs2/suballoc.c This is the 4th step to remove the debug info of DISK_ALLOC. Signed-off-by: Tao Ma --- fs/ocfs2/ocfs2_trace.h | 10 ++++++++++ fs/ocfs2/resize.c | 12 +++++++----- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/fs/ocfs2/ocfs2_trace.h b/fs/ocfs2/ocfs2_trace.h index 11980ecba5460..335edc50f1320 100644 --- a/fs/ocfs2/ocfs2_trace.h +++ b/fs/ocfs2/ocfs2_trace.h @@ -590,6 +590,16 @@ DEFINE_OCFS2_ULL_UINT_EVENT(ocfs2_local_alloc_new_window_result); /* End of trace events for fs/ocfs2/localalloc.c. */ +/* Trace events for fs/ocfs2/resize.c. */ + +DEFINE_OCFS2_UINT_UINT_EVENT(ocfs2_update_last_group_and_inode); + +DEFINE_OCFS2_ULL_UINT_EVENT(ocfs2_group_extend); + +DEFINE_OCFS2_ULL_UINT_UINT_UINT_EVENT(ocfs2_group_add); + +/* End of trace events for fs/ocfs2/resize.c. */ + /* Trace events for fs/ocfs2/suballoc.c. */ DEFINE_OCFS2_ULL_EVENT(ocfs2_validate_group_descriptor); diff --git a/fs/ocfs2/resize.c b/fs/ocfs2/resize.c index 76b37909a4a1e..761d20da9dcd1 100644 --- a/fs/ocfs2/resize.c +++ b/fs/ocfs2/resize.c @@ -39,6 +39,7 @@ #include "super.h" #include "sysfile.h" #include "uptodate.h" +#include "ocfs2_trace.h" #include "buffer_head_io.h" #include "suballoc.h" @@ -102,8 +103,8 @@ static int ocfs2_update_last_group_and_inode(handle_t *handle, u16 cl_bpc = le16_to_cpu(cl->cl_bpc); u16 cl_cpg = le16_to_cpu(cl->cl_cpg); - mlog(0, "(new_clusters=%d, first_new_cluster = %u)\n", - new_clusters, first_new_cluster); + trace_ocfs2_update_last_group_and_inode(new_clusters, + first_new_cluster); ret = ocfs2_journal_access_gd(handle, INODE_CACHE(bm_inode), group_bh, OCFS2_JOURNAL_ACCESS_WRITE); @@ -340,7 +341,8 @@ int ocfs2_group_extend(struct inode * inode, int new_clusters) goto out_unlock; } - mlog(0, "extend the last group at %llu, new clusters = %d\n", + + trace_ocfs2_group_extend( (unsigned long long)le64_to_cpu(group->bg_blkno), new_clusters); handle = ocfs2_start_trans(osb, OCFS2_GROUP_EXTEND_CREDITS); @@ -515,8 +517,8 @@ int ocfs2_group_add(struct inode *inode, struct ocfs2_new_group_input *input) goto out_unlock; } - mlog(0, "Add a new group %llu in chain = %u, length = %u\n", - (unsigned long long)input->group, input->chain, input->clusters); + trace_ocfs2_group_add((unsigned long long)input->group, + input->chain, input->clusters, input->frees); handle = ocfs2_start_trans(osb, OCFS2_GROUP_ADD_CREDITS); if (IS_ERR(handle)) { -- GitLab From 81bad69749623062fae2f94e2d98dd43d95a36f4 Mon Sep 17 00:00:00 2001 From: Tao Ma Date: Tue, 22 Feb 2011 08:01:27 +0800 Subject: [PATCH 0109/2822] ocfs2: Remove DISK_ALLOC from masklog. Since all 4 files, localalloc.c, suballoc.c, alloc.c and resize.c, which use DISK_ALLOC are changed to trace events, Remove masklog DISK_ALLOC totally. Signed-off-by: Tao Ma --- fs/ocfs2/alloc.c | 1 - fs/ocfs2/cluster/masklog.c | 1 - fs/ocfs2/cluster/masklog.h | 1 - fs/ocfs2/localalloc.c | 1 - fs/ocfs2/resize.c | 1 - fs/ocfs2/suballoc.c | 1 - 6 files changed, 6 deletions(-) diff --git a/fs/ocfs2/alloc.c b/fs/ocfs2/alloc.c index f0e26c4adc94c..b27a0d86f8c58 100644 --- a/fs/ocfs2/alloc.c +++ b/fs/ocfs2/alloc.c @@ -30,7 +30,6 @@ #include #include -#define MLOG_MASK_PREFIX ML_DISK_ALLOC #include #include "ocfs2.h" diff --git a/fs/ocfs2/cluster/masklog.c b/fs/ocfs2/cluster/masklog.c index fdc302ddafe82..caba07c2dac6d 100644 --- a/fs/ocfs2/cluster/masklog.c +++ b/fs/ocfs2/cluster/masklog.c @@ -93,7 +93,6 @@ static struct mlog_attribute mlog_attrs[MLOG_MAX_BITS] = { define_mask(DLM_RECOVERY), define_mask(AIO), define_mask(JOURNAL), - define_mask(DISK_ALLOC), define_mask(SUPER), define_mask(FILE_IO), define_mask(EXTENT_MAP), diff --git a/fs/ocfs2/cluster/masklog.h b/fs/ocfs2/cluster/masklog.h index 51ee790c7678f..155835a6b1c3f 100644 --- a/fs/ocfs2/cluster/masklog.h +++ b/fs/ocfs2/cluster/masklog.h @@ -95,7 +95,6 @@ #define ML_DLM_RECOVERY 0x0000000000001000ULL /* dlm master functions */ #define ML_AIO 0x0000000000002000ULL /* ocfs2 aio read and write */ #define ML_JOURNAL 0x0000000000004000ULL /* ocfs2 journalling functions */ -#define ML_DISK_ALLOC 0x0000000000008000ULL /* ocfs2 disk allocation */ #define ML_SUPER 0x0000000000010000ULL /* ocfs2 mount / umount */ #define ML_FILE_IO 0x0000000000020000ULL /* ocfs2 file I/O */ #define ML_EXTENT_MAP 0x0000000000040000ULL /* ocfs2 extent map caching */ diff --git a/fs/ocfs2/localalloc.c b/fs/ocfs2/localalloc.c index a311b1f658e23..210c35237548b 100644 --- a/fs/ocfs2/localalloc.c +++ b/fs/ocfs2/localalloc.c @@ -29,7 +29,6 @@ #include #include -#define MLOG_MASK_PREFIX ML_DISK_ALLOC #include #include "ocfs2.h" diff --git a/fs/ocfs2/resize.c b/fs/ocfs2/resize.c index 761d20da9dcd1..ec55add7604a0 100644 --- a/fs/ocfs2/resize.c +++ b/fs/ocfs2/resize.c @@ -27,7 +27,6 @@ #include #include -#define MLOG_MASK_PREFIX ML_DISK_ALLOC #include #include "ocfs2.h" diff --git a/fs/ocfs2/suballoc.c b/fs/ocfs2/suballoc.c index 94342bd9800db..ab6e2061074fa 100644 --- a/fs/ocfs2/suballoc.c +++ b/fs/ocfs2/suballoc.c @@ -29,7 +29,6 @@ #include #include -#define MLOG_MASK_PREFIX ML_DISK_ALLOC #include #include "ocfs2.h" -- GitLab From 198aac2838731691ca67e15fd8a56f65307d3677 Mon Sep 17 00:00:00 2001 From: Tao Ma Date: Tue, 22 Feb 2011 08:20:04 +0800 Subject: [PATCH 0110/2822] ocfs2: Remove masklog ML_REFCOUNT. Change all the "mlog(0," in fs/ocfs2/refcounttree.c to trace events. And finally remove masklog ML_REFCOUNT. Signed-off-by: Tao Ma --- fs/ocfs2/cluster/masklog.c | 1 - fs/ocfs2/cluster/masklog.h | 1 - fs/ocfs2/ocfs2_trace.h | 263 +++++++++++++++++++++++++++++++++++++ fs/ocfs2/refcounttree.c | 158 +++++++++++----------- 4 files changed, 341 insertions(+), 82 deletions(-) diff --git a/fs/ocfs2/cluster/masklog.c b/fs/ocfs2/cluster/masklog.c index caba07c2dac6d..a961cca125290 100644 --- a/fs/ocfs2/cluster/masklog.c +++ b/fs/ocfs2/cluster/masklog.c @@ -108,7 +108,6 @@ static struct mlog_attribute mlog_attrs[MLOG_MAX_BITS] = { define_mask(EXPORT), define_mask(XATTR), define_mask(QUOTA), - define_mask(REFCOUNT), define_mask(BASTS), define_mask(RESERVATIONS), define_mask(CLUSTER), diff --git a/fs/ocfs2/cluster/masklog.h b/fs/ocfs2/cluster/masklog.h index 155835a6b1c3f..845ea2b02f0b1 100644 --- a/fs/ocfs2/cluster/masklog.h +++ b/fs/ocfs2/cluster/masklog.h @@ -110,7 +110,6 @@ #define ML_EXPORT 0x0000000010000000ULL /* ocfs2 export operations */ #define ML_XATTR 0x0000000020000000ULL /* ocfs2 extended attributes */ #define ML_QUOTA 0x0000000040000000ULL /* ocfs2 quota operations */ -#define ML_REFCOUNT 0x0000000080000000ULL /* refcount tree operations */ #define ML_BASTS 0x0000000100000000ULL /* dlmglue asts and basts */ #define ML_RESERVATIONS 0x0000000200000000ULL /* ocfs2 alloc reservations */ #define ML_CLUSTER 0x0000000400000000ULL /* cluster stack */ diff --git a/fs/ocfs2/ocfs2_trace.h b/fs/ocfs2/ocfs2_trace.h index 335edc50f1320..a8b57ca7bdb57 100644 --- a/fs/ocfs2/ocfs2_trace.h +++ b/fs/ocfs2/ocfs2_trace.h @@ -133,6 +133,30 @@ DEFINE_EVENT(ocfs2__ull_ull, name, \ TP_PROTO(unsigned long long val1, unsigned long long val2), \ TP_ARGS(val1, val2)) +DECLARE_EVENT_CLASS(ocfs2__ull_ull_uint, + TP_PROTO(unsigned long long value1, + unsigned long long value2, unsigned int value3), + TP_ARGS(value1, value2, value3), + TP_STRUCT__entry( + __field(unsigned long long, value1) + __field(unsigned long long, value2) + __field(unsigned int, value3) + ), + TP_fast_assign( + __entry->value1 = value1; + __entry->value2 = value2; + __entry->value3 = value3; + ), + TP_printk("%llu %llu %u", + __entry->value1, __entry->value2, __entry->value3) +); + +#define DEFINE_OCFS2_ULL_ULL_UINT_EVENT(name) \ +DEFINE_EVENT(ocfs2__ull_ull_uint, name, \ + TP_PROTO(unsigned long long val1, \ + unsigned long long val2, unsigned int val3), \ + TP_ARGS(val1, val2, val3)) + DECLARE_EVENT_CLASS(ocfs2__ull_uint_uint, TP_PROTO(unsigned long long value1, unsigned int value2, unsigned int value3), @@ -705,6 +729,245 @@ DEFINE_OCFS2_ULL_UINT_EVENT(ocfs2_test_suballoc_bit); DEFINE_OCFS2_ULL_EVENT(ocfs2_test_inode_bit); /* End of trace events for fs/ocfs2/suballoc.c. */ + +/* Trace events for fs/ocfs2/refcounttree.c. */ + +DEFINE_OCFS2_ULL_EVENT(ocfs2_validate_refcount_block); + +DEFINE_OCFS2_ULL_EVENT(ocfs2_purge_refcount_trees); + +DEFINE_OCFS2_ULL_EVENT(ocfs2_create_refcount_tree); + +DEFINE_OCFS2_ULL_EVENT(ocfs2_create_refcount_tree_blkno); + +DEFINE_OCFS2_ULL_INT_INT_INT_EVENT(ocfs2_change_refcount_rec); + +DEFINE_OCFS2_ULL_UINT_EVENT(ocfs2_expand_inline_ref_root); + +DEFINE_OCFS2_ULL_UINT_UINT_EVENT(ocfs2_divide_leaf_refcount_block); + +DEFINE_OCFS2_ULL_UINT_EVENT(ocfs2_new_leaf_refcount_block); + +DECLARE_EVENT_CLASS(ocfs2__refcount_tree_ops, + TP_PROTO(unsigned long long blkno, int index, + unsigned long long cpos, + unsigned int clusters, unsigned int refcount), + TP_ARGS(blkno, index, cpos, clusters, refcount), + TP_STRUCT__entry( + __field(unsigned long long, blkno) + __field(int, index) + __field(unsigned long long, cpos) + __field(unsigned int, clusters) + __field(unsigned int, refcount) + ), + TP_fast_assign( + __entry->blkno = blkno; + __entry->index = index; + __entry->cpos = cpos; + __entry->clusters = clusters; + __entry->refcount = refcount; + ), + TP_printk("%llu %d %llu %u %u", __entry->blkno, __entry->index, + __entry->cpos, __entry->clusters, __entry->refcount) +); + +#define DEFINE_OCFS2_REFCOUNT_TREE_OPS_EVENT(name) \ +DEFINE_EVENT(ocfs2__refcount_tree_ops, name, \ + TP_PROTO(unsigned long long blkno, int index, \ + unsigned long long cpos, \ + unsigned int count, unsigned int refcount), \ + TP_ARGS(blkno, index, cpos, count, refcount)) + +DEFINE_OCFS2_REFCOUNT_TREE_OPS_EVENT(ocfs2_insert_refcount_rec); + +TRACE_EVENT(ocfs2_split_refcount_rec, + TP_PROTO(unsigned long long cpos, + unsigned int clusters, unsigned int refcount, + unsigned long long split_cpos, + unsigned int split_clusters, unsigned int split_refcount), + TP_ARGS(cpos, clusters, refcount, + split_cpos, split_clusters, split_refcount), + TP_STRUCT__entry( + __field(unsigned long long, cpos) + __field(unsigned int, clusters) + __field(unsigned int, refcount) + __field(unsigned long long, split_cpos) + __field(unsigned int, split_clusters) + __field(unsigned int, split_refcount) + ), + TP_fast_assign( + __entry->cpos = cpos; + __entry->clusters = clusters; + __entry->refcount = refcount; + __entry->split_cpos = split_cpos; + __entry->split_clusters = split_clusters; + __entry->split_refcount = split_refcount; + ), + TP_printk("%llu %u %u %llu %u %u", + __entry->cpos, __entry->clusters, __entry->refcount, + __entry->split_cpos, __entry->split_clusters, + __entry->split_refcount) +); + +DEFINE_OCFS2_REFCOUNT_TREE_OPS_EVENT(ocfs2_split_refcount_rec_insert); + +DEFINE_OCFS2_ULL_ULL_UINT_EVENT(ocfs2_increase_refcount_begin); + +DEFINE_OCFS2_ULL_UINT_UINT_EVENT(ocfs2_increase_refcount_change); + +DEFINE_OCFS2_ULL_UINT_EVENT(ocfs2_increase_refcount_insert); + +DEFINE_OCFS2_ULL_UINT_UINT_EVENT(ocfs2_increase_refcount_split); + +DEFINE_OCFS2_ULL_ULL_UINT_EVENT(ocfs2_remove_refcount_extent); + +DEFINE_OCFS2_ULL_EVENT(ocfs2_restore_refcount_block); + +DEFINE_OCFS2_ULL_ULL_UINT_EVENT(ocfs2_decrease_refcount_rec); + +TRACE_EVENT(ocfs2_decrease_refcount, + TP_PROTO(unsigned long long owner, + unsigned long long cpos, + unsigned int len, int delete), + TP_ARGS(owner, cpos, len, delete), + TP_STRUCT__entry( + __field(unsigned long long, owner) + __field(unsigned long long, cpos) + __field(unsigned int, len) + __field(int, delete) + ), + TP_fast_assign( + __entry->owner = owner; + __entry->cpos = cpos; + __entry->len = len; + __entry->delete = delete; + ), + TP_printk("%llu %llu %u %d", + __entry->owner, __entry->cpos, __entry->len, __entry->delete) +); + +DEFINE_OCFS2_ULL_UINT_UINT_UINT_EVENT(ocfs2_mark_extent_refcounted); + +DEFINE_OCFS2_ULL_UINT_UINT_UINT_EVENT(ocfs2_calc_refcount_meta_credits); + +TRACE_EVENT(ocfs2_calc_refcount_meta_credits_iterate, + TP_PROTO(int recs_add, unsigned long long cpos, + unsigned int clusters, unsigned long long r_cpos, + unsigned int r_clusters, unsigned int refcount, int index), + TP_ARGS(recs_add, cpos, clusters, r_cpos, r_clusters, refcount, index), + TP_STRUCT__entry( + __field(int, recs_add) + __field(unsigned long long, cpos) + __field(unsigned int, clusters) + __field(unsigned long long, r_cpos) + __field(unsigned int, r_clusters) + __field(unsigned int, refcount) + __field(int, index) + ), + TP_fast_assign( + __entry->recs_add = recs_add; + __entry->cpos = cpos; + __entry->clusters = clusters; + __entry->r_cpos = r_cpos; + __entry->r_clusters = r_clusters; + __entry->refcount = refcount; + __entry->index = index; + ), + TP_printk("%d %llu %u %llu %u %u %d", + __entry->recs_add, __entry->cpos, __entry->clusters, + __entry->r_cpos, __entry->r_clusters, + __entry->refcount, __entry->index) +); + +DEFINE_OCFS2_INT_INT_EVENT(ocfs2_add_refcount_flag); + +DEFINE_OCFS2_INT_INT_EVENT(ocfs2_prepare_refcount_change_for_del); + +DEFINE_OCFS2_INT_INT_EVENT(ocfs2_lock_refcount_allocators); + +DEFINE_OCFS2_ULL_UINT_UINT_UINT_EVENT(ocfs2_duplicate_clusters_by_page); + +DEFINE_OCFS2_ULL_UINT_UINT_UINT_EVENT(ocfs2_duplicate_clusters_by_jbd); + +TRACE_EVENT(ocfs2_clear_ext_refcount, + TP_PROTO(unsigned long long ino, unsigned int cpos, + unsigned int len, unsigned int p_cluster, + unsigned int ext_flags), + TP_ARGS(ino, cpos, len, p_cluster, ext_flags), + TP_STRUCT__entry( + __field(unsigned long long, ino) + __field(unsigned int, cpos) + __field(unsigned int, len) + __field(unsigned int, p_cluster) + __field(unsigned int, ext_flags) + ), + TP_fast_assign( + __entry->ino = ino; + __entry->cpos = cpos; + __entry->len = len; + __entry->p_cluster = p_cluster; + __entry->ext_flags = ext_flags; + ), + TP_printk("%llu %u %u %u %u", + __entry->ino, __entry->cpos, __entry->len, + __entry->p_cluster, __entry->ext_flags) +); + +TRACE_EVENT(ocfs2_replace_clusters, + TP_PROTO(unsigned long long ino, unsigned int cpos, + unsigned int old, unsigned int new, unsigned int len, + unsigned int ext_flags), + TP_ARGS(ino, cpos, old, new, len, ext_flags), + TP_STRUCT__entry( + __field(unsigned long long, ino) + __field(unsigned int, cpos) + __field(unsigned int, old) + __field(unsigned int, new) + __field(unsigned int, len) + __field(unsigned int, ext_flags) + ), + TP_fast_assign( + __entry->ino = ino; + __entry->cpos = cpos; + __entry->old = old; + __entry->new = new; + __entry->len = len; + __entry->ext_flags = ext_flags; + ), + TP_printk("%llu %u %u %u %u %u", + __entry->ino, __entry->cpos, __entry->old, __entry->new, + __entry->len, __entry->ext_flags) +); + +DEFINE_OCFS2_ULL_UINT_UINT_UINT_EVENT(ocfs2_make_clusters_writable); + +TRACE_EVENT(ocfs2_refcount_cow_hunk, + TP_PROTO(unsigned long long ino, unsigned int cpos, + unsigned int write_len, unsigned int max_cpos, + unsigned int cow_start, unsigned int cow_len), + TP_ARGS(ino, cpos, write_len, max_cpos, cow_start, cow_len), + TP_STRUCT__entry( + __field(unsigned long long, ino) + __field(unsigned int, cpos) + __field(unsigned int, write_len) + __field(unsigned int, max_cpos) + __field(unsigned int, cow_start) + __field(unsigned int, cow_len) + ), + TP_fast_assign( + __entry->ino = ino; + __entry->cpos = cpos; + __entry->write_len = write_len; + __entry->max_cpos = max_cpos; + __entry->cow_start = cow_start; + __entry->cow_len = cow_len; + ), + TP_printk("%llu %u %u %u %u %u", + __entry->ino, __entry->cpos, __entry->write_len, + __entry->max_cpos, __entry->cow_start, __entry->cow_len) +); + +/* End of trace events for fs/ocfs2/refcounttree.c. */ #endif /* _TRACE_OCFS2_H */ /* This part must be outside protection */ diff --git a/fs/ocfs2/refcounttree.c b/fs/ocfs2/refcounttree.c index 29623da133ccb..93a81f853e66e 100644 --- a/fs/ocfs2/refcounttree.c +++ b/fs/ocfs2/refcounttree.c @@ -16,7 +16,6 @@ */ #include -#define MLOG_MASK_PREFIX ML_REFCOUNT #include #include "ocfs2.h" #include "inode.h" @@ -34,6 +33,7 @@ #include "aops.h" #include "xattr.h" #include "namei.h" +#include "ocfs2_trace.h" #include #include @@ -84,8 +84,7 @@ static int ocfs2_validate_refcount_block(struct super_block *sb, struct ocfs2_refcount_block *rb = (struct ocfs2_refcount_block *)bh->b_data; - mlog(0, "Validating refcount block %llu\n", - (unsigned long long)bh->b_blocknr); + trace_ocfs2_validate_refcount_block((unsigned long long)bh->b_blocknr); BUG_ON(!buffer_uptodate(bh)); @@ -545,8 +544,8 @@ void ocfs2_purge_refcount_trees(struct ocfs2_super *osb) while ((node = rb_last(root)) != NULL) { tree = rb_entry(node, struct ocfs2_refcount_tree, rf_node); - mlog(0, "Purge tree %llu\n", - (unsigned long long) tree->rf_blkno); + trace_ocfs2_purge_refcount_trees( + (unsigned long long) tree->rf_blkno); rb_erase(&tree->rf_node, root); ocfs2_free_refcount_tree(tree); @@ -575,7 +574,8 @@ static int ocfs2_create_refcount_tree(struct inode *inode, BUG_ON(oi->ip_dyn_features & OCFS2_HAS_REFCOUNT_FL); - mlog(0, "create tree for inode %lu\n", inode->i_ino); + trace_ocfs2_create_refcount_tree( + (unsigned long long)OCFS2_I(inode)->ip_blkno); ret = ocfs2_reserve_new_metadata_blocks(osb, 1, &meta_ac); if (ret) { @@ -646,8 +646,7 @@ static int ocfs2_create_refcount_tree(struct inode *inode, di->i_refcount_loc = cpu_to_le64(first_blkno); spin_unlock(&oi->ip_lock); - mlog(0, "created tree for inode %lu, refblock %llu\n", - inode->i_ino, (unsigned long long)first_blkno); + trace_ocfs2_create_refcount_tree_blkno((unsigned long long)first_blkno); ocfs2_journal_dirty(handle, di_bh); @@ -1256,8 +1255,9 @@ static int ocfs2_change_refcount_rec(handle_t *handle, goto out; } - mlog(0, "change index %d, old count %u, change %d\n", index, - le32_to_cpu(rec->r_refcount), change); + trace_ocfs2_change_refcount_rec( + (unsigned long long)ocfs2_metadata_cache_owner(ci), + index, le32_to_cpu(rec->r_refcount), change); le32_add_cpu(&rec->r_refcount, change); if (!rec->r_refcount) { @@ -1353,8 +1353,8 @@ static int ocfs2_expand_inline_ref_root(handle_t *handle, ocfs2_journal_dirty(handle, ref_root_bh); - mlog(0, "new leaf block %llu, used %u\n", (unsigned long long)blkno, - le16_to_cpu(new_rb->rf_records.rl_used)); + trace_ocfs2_expand_inline_ref_root((unsigned long long)blkno, + le16_to_cpu(new_rb->rf_records.rl_used)); *ref_leaf_bh = new_bh; new_bh = NULL; @@ -1466,9 +1466,9 @@ static int ocfs2_divide_leaf_refcount_block(struct buffer_head *ref_leaf_bh, (struct ocfs2_refcount_block *)new_bh->b_data; struct ocfs2_refcount_list *new_rl = &new_rb->rf_records; - mlog(0, "split old leaf refcount block %llu, count = %u, used = %u\n", - (unsigned long long)ref_leaf_bh->b_blocknr, - le32_to_cpu(rl->rl_count), le32_to_cpu(rl->rl_used)); + trace_ocfs2_divide_leaf_refcount_block( + (unsigned long long)ref_leaf_bh->b_blocknr, + le32_to_cpu(rl->rl_count), le32_to_cpu(rl->rl_used)); /* * XXX: Improvement later. @@ -1601,8 +1601,8 @@ static int ocfs2_new_leaf_refcount_block(handle_t *handle, ocfs2_init_refcount_extent_tree(&ref_et, ci, ref_root_bh); - mlog(0, "insert new leaf block %llu at %u\n", - (unsigned long long)new_bh->b_blocknr, new_cpos); + trace_ocfs2_new_leaf_refcount_block( + (unsigned long long)new_bh->b_blocknr, new_cpos); /* Insert the new leaf block with the specific offset cpos. */ ret = ocfs2_insert_extent(handle, &ref_et, new_cpos, new_bh->b_blocknr, @@ -1794,11 +1794,10 @@ static int ocfs2_insert_refcount_rec(handle_t *handle, (le16_to_cpu(rf_list->rl_used) - index) * sizeof(struct ocfs2_refcount_rec)); - mlog(0, "insert refcount record start %llu, len %u, count %u " - "to leaf block %llu at index %d\n", - (unsigned long long)le64_to_cpu(rec->r_cpos), - le32_to_cpu(rec->r_clusters), le32_to_cpu(rec->r_refcount), - (unsigned long long)ref_leaf_bh->b_blocknr, index); + trace_ocfs2_insert_refcount_rec( + (unsigned long long)ref_leaf_bh->b_blocknr, index, + (unsigned long long)le64_to_cpu(rec->r_cpos), + le32_to_cpu(rec->r_clusters), le32_to_cpu(rec->r_refcount)); rf_list->rl_recs[index] = *rec; @@ -1850,10 +1849,12 @@ static int ocfs2_split_refcount_rec(handle_t *handle, BUG_ON(le32_to_cpu(rb->rf_flags) & OCFS2_REFCOUNT_TREE_FL); - mlog(0, "original r_pos %llu, cluster %u, split %llu, cluster %u\n", - le64_to_cpu(orig_rec->r_cpos), le32_to_cpu(orig_rec->r_clusters), - le64_to_cpu(split_rec->r_cpos), - le32_to_cpu(split_rec->r_clusters)); + trace_ocfs2_split_refcount_rec(le64_to_cpu(orig_rec->r_cpos), + le32_to_cpu(orig_rec->r_clusters), + le32_to_cpu(orig_rec->r_refcount), + le64_to_cpu(split_rec->r_cpos), + le32_to_cpu(split_rec->r_clusters), + le32_to_cpu(split_rec->r_refcount)); /* * If we just need to split the header or tail clusters, @@ -1967,12 +1968,11 @@ static int ocfs2_split_refcount_rec(handle_t *handle, if (split_rec->r_refcount) { rf_list->rl_recs[index] = *split_rec; - mlog(0, "insert refcount record start %llu, len %u, count %u " - "to leaf block %llu at index %d\n", - (unsigned long long)le64_to_cpu(split_rec->r_cpos), - le32_to_cpu(split_rec->r_clusters), - le32_to_cpu(split_rec->r_refcount), - (unsigned long long)ref_leaf_bh->b_blocknr, index); + trace_ocfs2_split_refcount_rec_insert( + (unsigned long long)ref_leaf_bh->b_blocknr, index, + (unsigned long long)le64_to_cpu(split_rec->r_cpos), + le32_to_cpu(split_rec->r_clusters), + le32_to_cpu(split_rec->r_refcount)); if (merge) ocfs2_refcount_rec_merge(rb, index); @@ -1997,7 +1997,7 @@ static int __ocfs2_increase_refcount(handle_t *handle, struct ocfs2_refcount_rec rec; unsigned int set_len = 0; - mlog(0, "Tree owner %llu, add refcount start %llu, len %u\n", + trace_ocfs2_increase_refcount_begin( (unsigned long long)ocfs2_metadata_cache_owner(ci), (unsigned long long)cpos, len); @@ -2024,9 +2024,9 @@ static int __ocfs2_increase_refcount(handle_t *handle, */ if (rec.r_refcount && le64_to_cpu(rec.r_cpos) == cpos && set_len <= len) { - mlog(0, "increase refcount rec, start %llu, len %u, " - "count %u\n", (unsigned long long)cpos, set_len, - le32_to_cpu(rec.r_refcount)); + trace_ocfs2_increase_refcount_change( + (unsigned long long)cpos, set_len, + le32_to_cpu(rec.r_refcount)); ret = ocfs2_change_refcount_rec(handle, ci, ref_leaf_bh, index, merge, 1); @@ -2037,7 +2037,7 @@ static int __ocfs2_increase_refcount(handle_t *handle, } else if (!rec.r_refcount) { rec.r_refcount = cpu_to_le32(1); - mlog(0, "insert refcount rec, start %llu, len %u\n", + trace_ocfs2_increase_refcount_insert( (unsigned long long)le64_to_cpu(rec.r_cpos), set_len); ret = ocfs2_insert_refcount_rec(handle, ci, ref_root_bh, @@ -2055,8 +2055,7 @@ static int __ocfs2_increase_refcount(handle_t *handle, rec.r_clusters = cpu_to_le32(set_len); le32_add_cpu(&rec.r_refcount, 1); - mlog(0, "split refcount rec, start %llu, " - "len %u, count %u\n", + trace_ocfs2_increase_refcount_split( (unsigned long long)le64_to_cpu(rec.r_cpos), set_len, le32_to_cpu(rec.r_refcount)); ret = ocfs2_split_refcount_rec(handle, ci, @@ -2095,6 +2094,11 @@ static int ocfs2_remove_refcount_extent(handle_t *handle, BUG_ON(rb->rf_records.rl_used); + trace_ocfs2_remove_refcount_extent( + (unsigned long long)ocfs2_metadata_cache_owner(ci), + (unsigned long long)ref_leaf_bh->b_blocknr, + le32_to_cpu(rb->rf_cpos)); + ocfs2_init_refcount_extent_tree(&et, ci, ref_root_bh); ret = ocfs2_remove_extent(handle, &et, le32_to_cpu(rb->rf_cpos), 1, meta_ac, dealloc); @@ -2137,7 +2141,7 @@ static int ocfs2_remove_refcount_extent(handle_t *handle, if (!rb->rf_list.l_next_free_rec) { BUG_ON(rb->rf_clusters); - mlog(0, "reset refcount tree root %llu to be a record block.\n", + trace_ocfs2_restore_refcount_block( (unsigned long long)ref_root_bh->b_blocknr); rb->rf_flags = 0; @@ -2184,6 +2188,10 @@ static int ocfs2_decrease_refcount_rec(handle_t *handle, BUG_ON(cpos + len > le64_to_cpu(rec->r_cpos) + le32_to_cpu(rec->r_clusters)); + trace_ocfs2_decrease_refcount_rec( + (unsigned long long)ocfs2_metadata_cache_owner(ci), + (unsigned long long)cpos, len); + if (cpos == le64_to_cpu(rec->r_cpos) && len == le32_to_cpu(rec->r_clusters)) ret = ocfs2_change_refcount_rec(handle, ci, @@ -2195,12 +2203,6 @@ static int ocfs2_decrease_refcount_rec(handle_t *handle, le32_add_cpu(&split.r_refcount, -1); - mlog(0, "split refcount rec, start %llu, " - "len %u, count %u, original start %llu, len %u\n", - (unsigned long long)le64_to_cpu(split.r_cpos), - len, le32_to_cpu(split.r_refcount), - (unsigned long long)le64_to_cpu(rec->r_cpos), - le32_to_cpu(rec->r_clusters)); ret = ocfs2_split_refcount_rec(handle, ci, ref_root_bh, ref_leaf_bh, &split, index, 1, @@ -2239,10 +2241,9 @@ static int __ocfs2_decrease_refcount(handle_t *handle, struct super_block *sb = ocfs2_metadata_cache_get_super(ci); struct buffer_head *ref_leaf_bh = NULL; - mlog(0, "Tree owner %llu, decrease refcount start %llu, " - "len %u, delete %u\n", - (unsigned long long)ocfs2_metadata_cache_owner(ci), - (unsigned long long)cpos, len, delete); + trace_ocfs2_decrease_refcount( + (unsigned long long)ocfs2_metadata_cache_owner(ci), + (unsigned long long)cpos, len, delete); while (len) { ret = ocfs2_get_refcount_rec(ci, ref_root_bh, @@ -2352,8 +2353,8 @@ static int ocfs2_mark_extent_refcounted(struct inode *inode, { int ret; - mlog(0, "Inode %lu refcount tree cpos %u, len %u, phys cluster %u\n", - inode->i_ino, cpos, len, phys); + trace_ocfs2_mark_extent_refcounted(OCFS2_I(inode)->ip_blkno, + cpos, len, phys); if (!ocfs2_refcount_tree(OCFS2_SB(inode->i_sb))) { ocfs2_error(inode->i_sb, "Inode %lu want to use refcount " @@ -2392,8 +2393,6 @@ static int ocfs2_calc_refcount_meta_credits(struct super_block *sb, struct buffer_head *ref_leaf_bh = NULL, *prev_bh = NULL; u32 len; - mlog(0, "start_cpos %llu, clusters %u\n", - (unsigned long long)start_cpos, clusters); while (clusters) { ret = ocfs2_get_refcount_rec(ci, ref_root_bh, cpos, clusters, &rec, @@ -2427,12 +2426,11 @@ static int ocfs2_calc_refcount_meta_credits(struct super_block *sb, rb = (struct ocfs2_refcount_block *)ref_leaf_bh->b_data; - mlog(0, "recs_add %d,cpos %llu, clusters %u, rec->r_cpos %llu," - "rec->r_clusters %u, rec->r_refcount %u, index %d\n", - recs_add, (unsigned long long)cpos, clusters, - (unsigned long long)le64_to_cpu(rec.r_cpos), - le32_to_cpu(rec.r_clusters), - le32_to_cpu(rec.r_refcount), index); + trace_ocfs2_calc_refcount_meta_credits_iterate( + recs_add, (unsigned long long)cpos, clusters, + (unsigned long long)le64_to_cpu(rec.r_cpos), + le32_to_cpu(rec.r_clusters), + le32_to_cpu(rec.r_refcount), index); len = min((u64)cpos + clusters, le64_to_cpu(rec.r_cpos) + le32_to_cpu(rec.r_clusters)) - cpos; @@ -2488,7 +2486,6 @@ static int ocfs2_calc_refcount_meta_credits(struct super_block *sb, if (!ref_blocks) goto out; - mlog(0, "we need ref_blocks %d\n", ref_blocks); *meta_add += ref_blocks; *credits += ref_blocks; @@ -2514,6 +2511,10 @@ static int ocfs2_calc_refcount_meta_credits(struct super_block *sb, } out: + + trace_ocfs2_calc_refcount_meta_credits( + (unsigned long long)start_cpos, clusters, + *meta_add, *credits); brelse(ref_leaf_bh); brelse(prev_bh); return ret; @@ -2578,8 +2579,7 @@ int ocfs2_prepare_refcount_change_for_del(struct inode *inode, goto out; } - mlog(0, "reserve new metadata %d blocks, credits = %d\n", - *ref_blocks, *credits); + trace_ocfs2_prepare_refcount_change_for_del(*ref_blocks, *credits); out: brelse(ref_root_bh); @@ -2886,8 +2886,7 @@ static int ocfs2_lock_refcount_allocators(struct super_block *sb, goto out; } - mlog(0, "reserve new metadata %d, clusters %u, credits = %d\n", - meta_add, num_clusters, *credits); + trace_ocfs2_lock_refcount_allocators(meta_add, *credits); ret = ocfs2_reserve_new_metadata_blocks(OCFS2_SB(sb), meta_add, meta_ac); if (ret) { @@ -2937,8 +2936,8 @@ static int ocfs2_duplicate_clusters_by_page(handle_t *handle, loff_t offset, end, map_end; struct address_space *mapping = context->inode->i_mapping; - mlog(0, "old_cluster %u, new %u, len %u at offset %u\n", old_cluster, - new_cluster, new_len, cpos); + trace_ocfs2_duplicate_clusters_by_page(cpos, old_cluster, + new_cluster, new_len); readahead_pages = (ocfs2_cow_contig_clusters(sb) << @@ -3031,8 +3030,8 @@ static int ocfs2_duplicate_clusters_by_jbd(handle_t *handle, struct buffer_head *old_bh = NULL; struct buffer_head *new_bh = NULL; - mlog(0, "old_cluster %u, new %u, len %u\n", old_cluster, - new_cluster, new_len); + trace_ocfs2_duplicate_clusters_by_page(cpos, old_cluster, + new_cluster, new_len); for (i = 0; i < blocks; i++, old_block++, new_block++) { new_bh = sb_getblk(osb->sb, new_block); @@ -3085,8 +3084,8 @@ static int ocfs2_clear_ext_refcount(handle_t *handle, struct super_block *sb = ocfs2_metadata_cache_get_super(et->et_ci); u64 ino = ocfs2_metadata_cache_owner(et->et_ci); - mlog(0, "inode %llu cpos %u, len %u, p_cluster %u, ext_flags %u\n", - (unsigned long long)ino, cpos, len, p_cluster, ext_flags); + trace_ocfs2_clear_ext_refcount((unsigned long long)ino, + cpos, len, p_cluster, ext_flags); memset(&replace_rec, 0, sizeof(replace_rec)); replace_rec.e_cpos = cpu_to_le32(cpos); @@ -3141,8 +3140,8 @@ static int ocfs2_replace_clusters(handle_t *handle, struct ocfs2_caching_info *ci = context->data_et.et_ci; u64 ino = ocfs2_metadata_cache_owner(ci); - mlog(0, "inode %llu, cpos %u, old %u, new %u, len %u, ext_flags %u\n", - (unsigned long long)ino, cpos, old, new, len, ext_flags); + trace_ocfs2_replace_clusters((unsigned long long)ino, + cpos, old, new, len, ext_flags); /*If the old clusters is unwritten, no need to duplicate. */ if (!(ext_flags & OCFS2_EXT_UNWRITTEN)) { @@ -3236,8 +3235,8 @@ static int ocfs2_make_clusters_writable(struct super_block *sb, struct ocfs2_caching_info *ref_ci = &context->ref_tree->rf_ci; struct ocfs2_refcount_rec rec; - mlog(0, "cpos %u, p_cluster %u, num_clusters %u, e_flags %u\n", - cpos, p_cluster, num_clusters, e_flags); + trace_ocfs2_make_clusters_writable(cpos, p_cluster, + num_clusters, e_flags); ret = ocfs2_lock_refcount_allocators(sb, p_cluster, num_clusters, &context->data_et, @@ -3475,9 +3474,9 @@ static int ocfs2_refcount_cow_hunk(struct inode *inode, goto out; } - mlog(0, "CoW inode %lu, cpos %u, write_len %u, cow_start %u, " - "cow_len %u\n", inode->i_ino, - cpos, write_len, cow_start, cow_len); + trace_ocfs2_refcount_cow_hunk(OCFS2_I(inode)->ip_blkno, + cpos, write_len, max_cpos, + cow_start, cow_len); BUG_ON(cow_len == 0); @@ -3756,8 +3755,7 @@ int ocfs2_add_refcount_flag(struct inode *inode, goto out; } - mlog(0, "reserve new metadata %d, credits = %d\n", - ref_blocks, credits); + trace_ocfs2_add_refcount_flag(ref_blocks, credits); if (ref_blocks) { ret = ocfs2_reserve_new_metadata_blocks(OCFS2_SB(inode->i_sb), -- GitLab From 9558156bcf8e4750d20034e941213273743ed86a Mon Sep 17 00:00:00 2001 From: Tao Ma Date: Tue, 22 Feb 2011 21:33:59 +0800 Subject: [PATCH 0111/2822] ocfs2: Remove mlog(0) from fs/ocfs2/aops.c Remove all the "mlog(0," in fs/ocfs2/aops.c. Signed-off-by: Tao Ma --- fs/ocfs2/aops.c | 55 +++++++++--------- fs/ocfs2/ocfs2_trace.h | 124 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 153 insertions(+), 26 deletions(-) diff --git a/fs/ocfs2/aops.c b/fs/ocfs2/aops.c index 9551518be4357..0d44b77018442 100644 --- a/fs/ocfs2/aops.c +++ b/fs/ocfs2/aops.c @@ -29,7 +29,6 @@ #include #include -#define MLOG_MASK_PREFIX ML_FILE_IO #include #include "ocfs2.h" @@ -45,6 +44,7 @@ #include "super.h" #include "symlink.h" #include "refcounttree.h" +#include "ocfs2_trace.h" #include "buffer_head_io.h" @@ -59,8 +59,9 @@ static int ocfs2_symlink_get_block(struct inode *inode, sector_t iblock, struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); void *kaddr; - mlog(0, "(0x%p, %llu, 0x%p, %d)\n", inode, - (unsigned long long)iblock, bh_result, create); + trace_ocfs2_symlink_get_block( + (unsigned long long)OCFS2_I(inode)->ip_blkno, + (unsigned long long)iblock, bh_result, create); BUG_ON(ocfs2_inode_is_fast_symlink(inode)); @@ -135,8 +136,8 @@ int ocfs2_get_block(struct inode *inode, sector_t iblock, u64 p_blkno, count, past_eof; struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); - mlog(0, "(0x%p, %llu, 0x%p, %d)\n", inode, - (unsigned long long)iblock, bh_result, create); + trace_ocfs2_get_block((unsigned long long)OCFS2_I(inode)->ip_blkno, + (unsigned long long)iblock, bh_result, create); if (OCFS2_I(inode)->ip_flags & OCFS2_INODE_SYSTEM_FILE) mlog(ML_NOTICE, "get_block on system inode 0x%p (%lu)\n", @@ -198,8 +199,9 @@ int ocfs2_get_block(struct inode *inode, sector_t iblock, } past_eof = ocfs2_blocks_for_bytes(inode->i_sb, i_size_read(inode)); - mlog(0, "Inode %lu, past_eof = %llu\n", inode->i_ino, - (unsigned long long)past_eof); + + trace_ocfs2_get_block_end((unsigned long long)OCFS2_I(inode)->ip_blkno, + (unsigned long long)past_eof); if (create && (iblock >= past_eof)) set_buffer_new(bh_result); @@ -276,7 +278,8 @@ static int ocfs2_readpage(struct file *file, struct page *page) loff_t start = (loff_t)page->index << PAGE_CACHE_SHIFT; int ret, unlock = 1; - mlog(0, "(0x%p, %lu)\n", file, (page ? page->index : 0)); + trace_ocfs2_readpage((unsigned long long)oi->ip_blkno, + (page ? page->index : 0)); ret = ocfs2_inode_lock_with_page(inode, NULL, 0, page); if (ret != 0) { @@ -393,13 +396,11 @@ out_unlock: */ static int ocfs2_writepage(struct page *page, struct writeback_control *wbc) { - int ret; - - mlog(0, "(0x%p)\n", page); - - ret = block_write_full_page(page, ocfs2_get_block, wbc); + trace_ocfs2_writepage( + (unsigned long long)OCFS2_I(page->mapping->host)->ip_blkno, + page->index); - return ret; + return block_write_full_page(page, ocfs2_get_block, wbc); } /* Taken from ext3. We don't necessarily need the full blown @@ -445,7 +446,8 @@ static sector_t ocfs2_bmap(struct address_space *mapping, sector_t block) int err = 0; struct inode *inode = mapping->host; - mlog(0, "(block = %llu)\n", (unsigned long long)block); + trace_ocfs2_bmap((unsigned long long)OCFS2_I(inode)->ip_blkno, + (unsigned long long)block); /* We don't need to lock journal system files, since they aren't * accessed concurrently from multiple nodes. @@ -1521,9 +1523,9 @@ static int ocfs2_try_to_write_inline_data(struct address_space *mapping, struct ocfs2_inode_info *oi = OCFS2_I(inode); struct ocfs2_dinode *di = NULL; - mlog(0, "Inode %llu, write of %u bytes at off %llu. features: 0x%x\n", - (unsigned long long)oi->ip_blkno, len, (unsigned long long)pos, - oi->ip_dyn_features); + trace_ocfs2_try_to_write_inline_data((unsigned long long)oi->ip_blkno, + len, (unsigned long long)pos, + oi->ip_dyn_features); /* * Handle inodes which already have inline data 1st. @@ -1726,6 +1728,13 @@ try_again: di = (struct ocfs2_dinode *)wc->w_di_bh->b_data; + trace_ocfs2_write_begin_nolock( + (unsigned long long)OCFS2_I(inode)->ip_blkno, + (long long)i_size_read(inode), + le32_to_cpu(di->i_clusters), + pos, len, flags, mmap_page, + clusters_to_alloc, extents_to_split); + /* * We set w_target_from, w_target_to here so that * ocfs2_write_end() knows which range in the target page to @@ -1738,12 +1747,6 @@ try_again: * ocfs2_lock_allocators(). It greatly over-estimates * the work to be done. */ - mlog(0, "extend inode %llu, i_size = %lld, di->i_clusters = %u," - " clusters_to_add = %u, extents_to_split = %u\n", - (unsigned long long)OCFS2_I(inode)->ip_blkno, - (long long)i_size_read(inode), le32_to_cpu(di->i_clusters), - clusters_to_alloc, extents_to_split); - ocfs2_init_dinode_extent_tree(&et, INODE_CACHE(inode), wc->w_di_bh); ret = ocfs2_lock_allocators(inode, &et, @@ -1925,8 +1928,8 @@ static void ocfs2_write_end_inline(struct inode *inode, loff_t pos, memcpy(di->id2.i_data.id_data + pos, kaddr + pos, *copied); kunmap_atomic(kaddr, KM_USER0); - mlog(0, "Data written to inode at offset %llu. " - "id_count = %u, copied = %u, i_dyn_features = 0x%x\n", + trace_ocfs2_write_end_inline( + (unsigned long long)OCFS2_I(inode)->ip_blkno, (unsigned long long)pos, *copied, le16_to_cpu(di->id2.i_data.id_count), le16_to_cpu(di->i_dyn_features)); diff --git a/fs/ocfs2/ocfs2_trace.h b/fs/ocfs2/ocfs2_trace.h index a8b57ca7bdb57..5958da57f8ff3 100644 --- a/fs/ocfs2/ocfs2_trace.h +++ b/fs/ocfs2/ocfs2_trace.h @@ -968,6 +968,130 @@ TRACE_EVENT(ocfs2_refcount_cow_hunk, ); /* End of trace events for fs/ocfs2/refcounttree.c. */ + +/* Trace events for fs/ocfs2/aops.c. */ + +DECLARE_EVENT_CLASS(ocfs2__get_block, + TP_PROTO(unsigned long long ino, unsigned long long iblock, + void *bh_result, int create), + TP_ARGS(ino, iblock, bh_result, create), + TP_STRUCT__entry( + __field(unsigned long long, ino) + __field(unsigned long long, iblock) + __field(void *, bh_result) + __field(int, create) + ), + TP_fast_assign( + __entry->ino = ino; + __entry->iblock = iblock; + __entry->bh_result = bh_result; + __entry->create = create; + ), + TP_printk("%llu %llu %p %d", + __entry->ino, __entry->iblock, + __entry->bh_result, __entry->create) +); + +#define DEFINE_OCFS2_GET_BLOCK_EVENT(name) \ +DEFINE_EVENT(ocfs2__get_block, name, \ + TP_PROTO(unsigned long long ino, unsigned long long iblock, \ + void *bh_result, int create), \ + TP_ARGS(ino, iblock, bh_result, create)) + +DEFINE_OCFS2_GET_BLOCK_EVENT(ocfs2_symlink_get_block); + +DEFINE_OCFS2_GET_BLOCK_EVENT(ocfs2_get_block); + +DEFINE_OCFS2_ULL_ULL_EVENT(ocfs2_get_block_end); + +DEFINE_OCFS2_ULL_ULL_EVENT(ocfs2_readpage); + +DEFINE_OCFS2_ULL_ULL_EVENT(ocfs2_writepage); + +DEFINE_OCFS2_ULL_ULL_EVENT(ocfs2_bmap); + +TRACE_EVENT(ocfs2_try_to_write_inline_data, + TP_PROTO(unsigned long long ino, unsigned int len, + unsigned long long pos, unsigned int flags), + TP_ARGS(ino, len, pos, flags), + TP_STRUCT__entry( + __field(unsigned long long, ino) + __field(unsigned int, len) + __field(unsigned long long, pos) + __field(unsigned int, flags) + ), + TP_fast_assign( + __entry->ino = ino; + __entry->len = len; + __entry->pos = pos; + __entry->flags = flags; + ), + TP_printk("%llu %u %llu 0x%x", + __entry->ino, __entry->len, __entry->pos, __entry->flags) +); + +TRACE_EVENT(ocfs2_write_begin_nolock, + TP_PROTO(unsigned long long ino, + long long i_size, unsigned int i_clusters, + unsigned long long pos, unsigned int len, + unsigned int flags, void *page, + unsigned int clusters, unsigned int extents_to_split), + TP_ARGS(ino, i_size, i_clusters, pos, len, flags, + page, clusters, extents_to_split), + TP_STRUCT__entry( + __field(unsigned long long, ino) + __field(long long, i_size) + __field(unsigned int, i_clusters) + __field(unsigned long long, pos) + __field(unsigned int, len) + __field(unsigned int, flags) + __field(void *, page) + __field(unsigned int, clusters) + __field(unsigned int, extents_to_split) + ), + TP_fast_assign( + __entry->ino = ino; + __entry->i_size = i_size; + __entry->i_clusters = i_clusters; + __entry->pos = pos; + __entry->len = len; + __entry->flags = flags; + __entry->page = page; + __entry->clusters = clusters; + __entry->extents_to_split = extents_to_split; + ), + TP_printk("%llu %lld %u %llu %u %u %p %u %u", + __entry->ino, __entry->i_size, __entry->i_clusters, + __entry->pos, __entry->len, + __entry->flags, __entry->page, __entry->clusters, + __entry->extents_to_split) +); + +TRACE_EVENT(ocfs2_write_end_inline, + TP_PROTO(unsigned long long ino, + unsigned long long pos, unsigned int copied, + unsigned int id_count, unsigned int features), + TP_ARGS(ino, pos, copied, id_count, features), + TP_STRUCT__entry( + __field(unsigned long long, ino) + __field(unsigned long long, pos) + __field(unsigned int, copied) + __field(unsigned int, id_count) + __field(unsigned int, features) + ), + TP_fast_assign( + __entry->ino = ino; + __entry->pos = pos; + __entry->copied = copied; + __entry->id_count = id_count; + __entry->features = features; + ), + TP_printk("%llu %llu %u %u %u", + __entry->ino, __entry->pos, __entry->copied, + __entry->id_count, __entry->features) +); + +/* End of trace events for fs/ocfs2/aops.c. */ #endif /* _TRACE_OCFS2_H */ /* This part must be outside protection */ -- GitLab From 614a9e849ca6ea24843795251cb30af525d5336b Mon Sep 17 00:00:00 2001 From: Tao Ma Date: Tue, 22 Feb 2011 21:59:46 +0800 Subject: [PATCH 0112/2822] ocfs2: Remove FILE_IO from masklog. Change all the "mlog(0," in fs/ocfs2/mmap.c to trace events. And finally remove masklog FILE_IO. Signed-off-by: Tao Ma --- fs/ocfs2/cluster/masklog.c | 1 - fs/ocfs2/cluster/masklog.h | 1 - fs/ocfs2/mmap.c | 7 +++---- fs/ocfs2/ocfs2_trace.h | 25 +++++++++++++++++++++++++ 4 files changed, 28 insertions(+), 6 deletions(-) diff --git a/fs/ocfs2/cluster/masklog.c b/fs/ocfs2/cluster/masklog.c index a961cca125290..036e8b8814f79 100644 --- a/fs/ocfs2/cluster/masklog.c +++ b/fs/ocfs2/cluster/masklog.c @@ -94,7 +94,6 @@ static struct mlog_attribute mlog_attrs[MLOG_MAX_BITS] = { define_mask(AIO), define_mask(JOURNAL), define_mask(SUPER), - define_mask(FILE_IO), define_mask(EXTENT_MAP), define_mask(DLM_GLUE), define_mask(BH_IO), diff --git a/fs/ocfs2/cluster/masklog.h b/fs/ocfs2/cluster/masklog.h index 845ea2b02f0b1..d07780ab9f8f9 100644 --- a/fs/ocfs2/cluster/masklog.h +++ b/fs/ocfs2/cluster/masklog.h @@ -96,7 +96,6 @@ #define ML_AIO 0x0000000000002000ULL /* ocfs2 aio read and write */ #define ML_JOURNAL 0x0000000000004000ULL /* ocfs2 journalling functions */ #define ML_SUPER 0x0000000000010000ULL /* ocfs2 mount / umount */ -#define ML_FILE_IO 0x0000000000020000ULL /* ocfs2 file I/O */ #define ML_EXTENT_MAP 0x0000000000040000ULL /* ocfs2 extent map caching */ #define ML_DLM_GLUE 0x0000000000080000ULL /* ocfs2 dlm glue layer */ #define ML_BH_IO 0x0000000000100000ULL /* ocfs2 buffer I/O */ diff --git a/fs/ocfs2/mmap.c b/fs/ocfs2/mmap.c index 49730b51ae451..3e9393ca39ebd 100644 --- a/fs/ocfs2/mmap.c +++ b/fs/ocfs2/mmap.c @@ -31,7 +31,6 @@ #include #include -#define MLOG_MASK_PREFIX ML_FILE_IO #include #include "ocfs2.h" @@ -42,6 +41,7 @@ #include "inode.h" #include "mmap.h" #include "super.h" +#include "ocfs2_trace.h" static int ocfs2_fault(struct vm_area_struct *area, struct vm_fault *vmf) @@ -49,13 +49,12 @@ static int ocfs2_fault(struct vm_area_struct *area, struct vm_fault *vmf) sigset_t oldset; int ret; - mlog(0, "(area=%p, page offset=%lu)\n", area, vmf->pgoff); - ocfs2_block_signals(&oldset); ret = filemap_fault(area, vmf); ocfs2_unblock_signals(&oldset); - mlog(0, "%p\n", vmf->page); + trace_ocfs2_fault(OCFS2_I(area->vm_file->f_mapping->host)->ip_blkno, + area, vmf->page, vmf->pgoff); return ret; } diff --git a/fs/ocfs2/ocfs2_trace.h b/fs/ocfs2/ocfs2_trace.h index 5958da57f8ff3..77148e7a14f81 100644 --- a/fs/ocfs2/ocfs2_trace.h +++ b/fs/ocfs2/ocfs2_trace.h @@ -1092,6 +1092,31 @@ TRACE_EVENT(ocfs2_write_end_inline, ); /* End of trace events for fs/ocfs2/aops.c. */ + +/* Trace events for fs/ocfs2/mmap.c. */ + +TRACE_EVENT(ocfs2_fault, + TP_PROTO(unsigned long long ino, + void *area, void *page, unsigned long pgoff), + TP_ARGS(ino, area, page, pgoff), + TP_STRUCT__entry( + __field(unsigned long long, ino) + __field(void *, area) + __field(void *, page) + __field(unsigned long, pgoff) + ), + TP_fast_assign( + __entry->ino = ino; + __entry->area = area; + __entry->page = page; + __entry->pgoff = pgoff; + ), + TP_printk("%llu %p %p %lu", + __entry->ino, __entry->area, __entry->page, __entry->pgoff) +); + +/* End of trace events for fs/ocfs2/mmap.c. */ + #endif /* _TRACE_OCFS2_H */ /* This part must be outside protection */ -- GitLab From da561c9cfa3022f6134ef52686d52931d3d1df3d Mon Sep 17 00:00:00 2001 From: Tao Ma Date: Mon, 21 Feb 2011 11:18:23 +0800 Subject: [PATCH 0113/2822] ocfs2: remove INODE from unused files. As there are no such debug information in fs/ocfs2/ioctl.c, fs/ocfs2/locks.c and fs/ocfs2/sysfile.c, ML_INODE are also removed. Signed-off-by: Tao Ma --- fs/ocfs2/acl.c | 1 - fs/ocfs2/ioctl.c | 1 - fs/ocfs2/locks.c | 1 - 3 files changed, 3 deletions(-) diff --git a/fs/ocfs2/acl.c b/fs/ocfs2/acl.c index 704f6b1742f32..69786e3eb43cd 100644 --- a/fs/ocfs2/acl.c +++ b/fs/ocfs2/acl.c @@ -24,7 +24,6 @@ #include #include -#define MLOG_MASK_PREFIX ML_INODE #include #include "ocfs2.h" diff --git a/fs/ocfs2/ioctl.c b/fs/ocfs2/ioctl.c index b4f51e94c8f55..d9bfa904d006a 100644 --- a/fs/ocfs2/ioctl.c +++ b/fs/ocfs2/ioctl.c @@ -9,7 +9,6 @@ #include #include -#define MLOG_MASK_PREFIX ML_INODE #include #include "ocfs2.h" diff --git a/fs/ocfs2/locks.c b/fs/ocfs2/locks.c index b5cb3ede94089..e57c804069ea6 100644 --- a/fs/ocfs2/locks.c +++ b/fs/ocfs2/locks.c @@ -26,7 +26,6 @@ #include #include -#define MLOG_MASK_PREFIX ML_INODE #include #include "ocfs2.h" -- GitLab From 468eedde23d6c9335935773f4f5764267d5a7763 Mon Sep 17 00:00:00 2001 From: Tao Ma Date: Tue, 22 Feb 2011 22:14:41 +0800 Subject: [PATCH 0114/2822] ocfs2: Remove mlog(0) from fs/ocfs2/file.c This is the 2nd step to remove the debug info of INODE. Signed-off-by: Tao Ma --- fs/ocfs2/file.c | 190 ++++++++++++++++----------------- fs/ocfs2/ocfs2_trace.h | 237 +++++++++++++++++++++++++++++++++++++++++ fs/ocfs2/sysfile.c | 1 - 3 files changed, 330 insertions(+), 98 deletions(-) diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c index 1e1a93aa05264..41565ae528566 100644 --- a/fs/ocfs2/file.c +++ b/fs/ocfs2/file.c @@ -38,7 +38,6 @@ #include #include -#define MLOG_MASK_PREFIX ML_INODE #include #include "ocfs2.h" @@ -61,6 +60,7 @@ #include "acl.h" #include "quota.h" #include "refcounttree.h" +#include "ocfs2_trace.h" #include "buffer_head_io.h" @@ -99,8 +99,10 @@ static int ocfs2_file_open(struct inode *inode, struct file *file) int mode = file->f_flags; struct ocfs2_inode_info *oi = OCFS2_I(inode); - mlog(0, "(0x%p, 0x%p, '%.*s')\n", inode, file, - file->f_path.dentry->d_name.len, file->f_path.dentry->d_name.name); + trace_ocfs2_file_open(inode, file, file->f_path.dentry, + (unsigned long long)OCFS2_I(inode)->ip_blkno, + file->f_path.dentry->d_name.len, + file->f_path.dentry->d_name.name, mode); if (file->f_mode & FMODE_WRITE) dquot_initialize(inode); @@ -142,13 +144,15 @@ static int ocfs2_file_release(struct inode *inode, struct file *file) { struct ocfs2_inode_info *oi = OCFS2_I(inode); - mlog(0, "(0x%p, 0x%p, '%.*s')\n", inode, file, - file->f_path.dentry->d_name.len, - file->f_path.dentry->d_name.name); - spin_lock(&oi->ip_lock); if (!--oi->ip_open_count) oi->ip_flags &= ~OCFS2_INODE_OPEN_DIRECT; + + trace_ocfs2_file_release(inode, file, file->f_path.dentry, + oi->ip_blkno, + file->f_path.dentry->d_name.len, + file->f_path.dentry->d_name.name, + oi->ip_open_count); spin_unlock(&oi->ip_lock); ocfs2_free_file_private(inode, file); @@ -174,9 +178,11 @@ static int ocfs2_sync_file(struct file *file, int datasync) struct inode *inode = file->f_mapping->host; struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); - mlog(0, "(0x%p, %d, 0x%p, '%.*s')\n", file, datasync, - file->f_path.dentry, file->f_path.dentry->d_name.len, - file->f_path.dentry->d_name.name); + trace_ocfs2_sync_file(inode, file, file->f_path.dentry, + OCFS2_I(inode)->ip_blkno, + file->f_path.dentry->d_name.len, + file->f_path.dentry->d_name.name, + (unsigned long long)datasync); if (datasync && !(inode->i_state & I_DIRTY_DATASYNC)) { /* @@ -431,14 +437,14 @@ static int ocfs2_truncate_file(struct inode *inode, struct ocfs2_dinode *fe = NULL; struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); - mlog(0, "(inode = %llu, new_i_size = %llu\n", - (unsigned long long)OCFS2_I(inode)->ip_blkno, - (unsigned long long)new_i_size); - /* We trust di_bh because it comes from ocfs2_inode_lock(), which * already validated it */ fe = (struct ocfs2_dinode *) di_bh->b_data; + trace_ocfs2_truncate_file((unsigned long long)OCFS2_I(inode)->ip_blkno, + (unsigned long long)le64_to_cpu(fe->i_size), + (unsigned long long)new_i_size); + mlog_bug_on_msg(le64_to_cpu(fe->i_size) != i_size_read(inode), "Inode %llu, inode i_size = %lld != di " "i_size = %llu, i_flags = 0x%x\n", @@ -448,19 +454,14 @@ static int ocfs2_truncate_file(struct inode *inode, le32_to_cpu(fe->i_flags)); if (new_i_size > le64_to_cpu(fe->i_size)) { - mlog(0, "asked to truncate file with size (%llu) to size (%llu)!\n", - (unsigned long long)le64_to_cpu(fe->i_size), - (unsigned long long)new_i_size); + trace_ocfs2_truncate_file_error( + (unsigned long long)le64_to_cpu(fe->i_size), + (unsigned long long)new_i_size); status = -EINVAL; mlog_errno(status); goto bail; } - mlog(0, "inode %llu, i_size = %llu, new_i_size = %llu\n", - (unsigned long long)le64_to_cpu(fe->i_blkno), - (unsigned long long)le64_to_cpu(fe->i_size), - (unsigned long long)new_i_size); - /* lets handle the simple truncate cases before doing any more * cluster locking. */ if (new_i_size == le64_to_cpu(fe->i_size)) @@ -566,8 +567,6 @@ static int __ocfs2_extend_allocation(struct inode *inode, u32 logical_start, struct ocfs2_extent_tree et; int did_quota = 0; - mlog(0, "(clusters_to_add = %u)\n", clusters_to_add); - /* * This function only exists for file systems which don't * support holes. @@ -584,11 +583,6 @@ static int __ocfs2_extend_allocation(struct inode *inode, u32 logical_start, restart_all: BUG_ON(le32_to_cpu(fe->i_clusters) != OCFS2_I(inode)->ip_clusters); - mlog(0, "extend inode %llu, i_size = %lld, di->i_clusters = %u, " - "clusters_to_add = %u\n", - (unsigned long long)OCFS2_I(inode)->ip_blkno, - (long long)i_size_read(inode), le32_to_cpu(fe->i_clusters), - clusters_to_add); ocfs2_init_dinode_extent_tree(&et, INODE_CACHE(inode), bh); status = ocfs2_lock_allocators(inode, &et, clusters_to_add, 0, &data_ac, &meta_ac); @@ -608,6 +602,12 @@ restart_all: } restarted_transaction: + trace_ocfs2_extend_allocation( + (unsigned long long)OCFS2_I(inode)->ip_blkno, + (unsigned long long)i_size_read(inode), + le32_to_cpu(fe->i_clusters), clusters_to_add, + why, restart_func); + status = dquot_alloc_space_nodirty(inode, ocfs2_clusters_to_bytes(osb->sb, clusters_to_add)); if (status) @@ -654,13 +654,11 @@ restarted_transaction: if (why != RESTART_NONE && clusters_to_add) { if (why == RESTART_META) { - mlog(0, "restarting function.\n"); restart_func = 1; status = 0; } else { BUG_ON(why != RESTART_TRANS); - mlog(0, "restarting transaction.\n"); /* TODO: This can be more intelligent. */ credits = ocfs2_calc_extend_credits(osb->sb, &fe->id2.i_list, @@ -677,11 +675,11 @@ restarted_transaction: } } - mlog(0, "fe: i_clusters = %u, i_size=%llu\n", + trace_ocfs2_extend_allocation_end(OCFS2_I(inode)->ip_blkno, le32_to_cpu(fe->i_clusters), - (unsigned long long)le64_to_cpu(fe->i_size)); - mlog(0, "inode: ip_clusters=%u, i_size=%lld\n", - OCFS2_I(inode)->ip_clusters, (long long)i_size_read(inode)); + (unsigned long long)le64_to_cpu(fe->i_size), + OCFS2_I(inode)->ip_clusters, + (unsigned long long)i_size_read(inode)); leave: if (status < 0 && did_quota) @@ -772,10 +770,11 @@ static int ocfs2_write_zero_page(struct inode *inode, u64 abs_from, if (!zero_to) zero_to = PAGE_CACHE_SIZE; - mlog(0, - "abs_from = %llu, abs_to = %llu, index = %lu, zero_from = %u, zero_to = %u\n", - (unsigned long long)abs_from, (unsigned long long)abs_to, - index, zero_from, zero_to); + trace_ocfs2_write_zero_page( + (unsigned long long)OCFS2_I(inode)->ip_blkno, + (unsigned long long)abs_from, + (unsigned long long)abs_to, + index, zero_from, zero_to); /* We know that zero_from is block aligned */ for (block_start = zero_from; block_start < zero_to; @@ -915,9 +914,10 @@ static int ocfs2_zero_extend_range(struct inode *inode, u64 range_start, u64 next_pos; u64 zero_pos = range_start; - mlog(0, "range_start = %llu, range_end = %llu\n", - (unsigned long long)range_start, - (unsigned long long)range_end); + trace_ocfs2_zero_extend_range( + (unsigned long long)OCFS2_I(inode)->ip_blkno, + (unsigned long long)range_start, + (unsigned long long)range_end); BUG_ON(range_start >= range_end); while (zero_pos < range_end) { @@ -949,9 +949,9 @@ int ocfs2_zero_extend(struct inode *inode, struct buffer_head *di_bh, struct super_block *sb = inode->i_sb; zero_start = ocfs2_align_bytes_to_blocks(sb, i_size_read(inode)); - mlog(0, "zero_start %llu for i_size %llu\n", - (unsigned long long)zero_start, - (unsigned long long)i_size_read(inode)); + trace_ocfs2_zero_extend((unsigned long long)OCFS2_I(inode)->ip_blkno, + (unsigned long long)zero_start, + (unsigned long long)i_size_read(inode)); while (zero_start < zero_to_size) { ret = ocfs2_zero_extend_get_range(inode, di_bh, zero_start, zero_to_size, @@ -1100,30 +1100,20 @@ int ocfs2_setattr(struct dentry *dentry, struct iattr *attr) struct dquot *transfer_to[MAXQUOTAS] = { }; int qtype; - mlog(0, "(0x%p, '%.*s')\n", dentry, - dentry->d_name.len, dentry->d_name.name); + trace_ocfs2_setattr(inode, dentry, + (unsigned long long)OCFS2_I(inode)->ip_blkno, + dentry->d_name.len, dentry->d_name.name, + attr->ia_valid, attr->ia_mode, + attr->ia_uid, attr->ia_gid); /* ensuring we don't even attempt to truncate a symlink */ if (S_ISLNK(inode->i_mode)) attr->ia_valid &= ~ATTR_SIZE; - if (attr->ia_valid & ATTR_MODE) - mlog(0, "mode change: %d\n", attr->ia_mode); - if (attr->ia_valid & ATTR_UID) - mlog(0, "uid change: %d\n", attr->ia_uid); - if (attr->ia_valid & ATTR_GID) - mlog(0, "gid change: %d\n", attr->ia_gid); - if (attr->ia_valid & ATTR_SIZE) - mlog(0, "size change...\n"); - if (attr->ia_valid & (ATTR_ATIME | ATTR_MTIME | ATTR_CTIME)) - mlog(0, "time change...\n"); - #define OCFS2_VALID_ATTRS (ATTR_ATIME | ATTR_MTIME | ATTR_CTIME | ATTR_SIZE \ | ATTR_GID | ATTR_UID | ATTR_MODE) - if (!(attr->ia_valid & OCFS2_VALID_ATTRS)) { - mlog(0, "can't handle attrs: 0x%x\n", attr->ia_valid); + if (!(attr->ia_valid & OCFS2_VALID_ATTRS)) return 0; - } status = inode_change_ok(inode, attr); if (status) @@ -1318,8 +1308,9 @@ static int __ocfs2_write_remove_suid(struct inode *inode, struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); struct ocfs2_dinode *di; - mlog(0, "(Inode %llu, mode 0%o)\n", - (unsigned long long)OCFS2_I(inode)->ip_blkno, inode->i_mode); + trace_ocfs2_write_remove_suid( + (unsigned long long)OCFS2_I(inode)->ip_blkno, + inode->i_mode); handle = ocfs2_start_trans(osb, OCFS2_INODE_UPDATE_CREDITS); if (IS_ERR(handle)) { @@ -1525,8 +1516,9 @@ static int ocfs2_zero_partial_clusters(struct inode *inode, * partial clusters here. There's no need to worry about * physical allocation - the zeroing code knows to skip holes. */ - mlog(0, "byte start: %llu, end: %llu\n", - (unsigned long long)start, (unsigned long long)end); + trace_ocfs2_zero_partial_clusters( + (unsigned long long)OCFS2_I(inode)->ip_blkno, + (unsigned long long)start, (unsigned long long)end); /* * If both edges are on a cluster boundary then there's no @@ -1550,8 +1542,8 @@ static int ocfs2_zero_partial_clusters(struct inode *inode, if (tmpend > end) tmpend = end; - mlog(0, "1st range: start: %llu, tmpend: %llu\n", - (unsigned long long)start, (unsigned long long)tmpend); + trace_ocfs2_zero_partial_clusters_range1((unsigned long long)start, + (unsigned long long)tmpend); ret = ocfs2_zero_range_for_truncate(inode, handle, start, tmpend); if (ret) @@ -1565,8 +1557,8 @@ static int ocfs2_zero_partial_clusters(struct inode *inode, */ start = end & ~(osb->s_clustersize - 1); - mlog(0, "2nd range: start: %llu, end: %llu\n", - (unsigned long long)start, (unsigned long long)end); + trace_ocfs2_zero_partial_clusters_range2( + (unsigned long long)start, (unsigned long long)end); ret = ocfs2_zero_range_for_truncate(inode, handle, start, end); if (ret) @@ -1666,6 +1658,11 @@ static int ocfs2_remove_inode_range(struct inode *inode, ocfs2_init_dinode_extent_tree(&et, INODE_CACHE(inode), di_bh); ocfs2_init_dealloc_ctxt(&dealloc); + trace_ocfs2_remove_inode_range( + (unsigned long long)OCFS2_I(inode)->ip_blkno, + (unsigned long long)byte_start, + (unsigned long long)byte_len); + if (byte_len == 0) return 0; @@ -1712,11 +1709,6 @@ static int ocfs2_remove_inode_range(struct inode *inode, trunc_end = (byte_start + byte_len) >> osb->s_clustersize_bits; cluster_in_el = trunc_end; - mlog(0, "Inode: %llu, start: %llu, len: %llu, cstart: %u, cend: %u\n", - (unsigned long long)OCFS2_I(inode)->ip_blkno, - (unsigned long long)byte_start, - (unsigned long long)byte_len, trunc_start, trunc_end); - ret = ocfs2_zero_partial_clusters(inode, byte_start, byte_len); if (ret) { mlog_errno(ret); @@ -2071,7 +2063,7 @@ static int ocfs2_prepare_inode_for_write(struct file *file, int ret = 0, meta_level = 0; struct dentry *dentry = file->f_path.dentry; struct inode *inode = dentry->d_inode; - loff_t saved_pos, end; + loff_t saved_pos = 0, end; /* * We start with a read level meta lock and only jump to an ex @@ -2110,12 +2102,10 @@ static int ocfs2_prepare_inode_for_write(struct file *file, /* work on a copy of ppos until we're sure that we won't have * to recalculate it due to relocking. */ - if (appending) { + if (appending) saved_pos = i_size_read(inode); - mlog(0, "O_APPEND: inode->i_size=%llu\n", saved_pos); - } else { + else saved_pos = *ppos; - } end = saved_pos + count; @@ -2186,6 +2176,10 @@ static int ocfs2_prepare_inode_for_write(struct file *file, *ppos = saved_pos; out_unlock: + trace_ocfs2_prepare_inode_for_write(OCFS2_I(inode)->ip_blkno, + saved_pos, appending, count, + direct_io, has_refcount); + if (meta_level >= 0) ocfs2_inode_unlock(inode, meta_level); @@ -2211,10 +2205,11 @@ static ssize_t ocfs2_file_aio_write(struct kiocb *iocb, int full_coherency = !(osb->s_mount_opt & OCFS2_MOUNT_COHERENCY_BUFFERED); - mlog(0, "(0x%p, %u, '%.*s')\n", file, - (unsigned int)nr_segs, - file->f_path.dentry->d_name.len, - file->f_path.dentry->d_name.name); + trace_ocfs2_file_aio_write(inode, file, file->f_path.dentry, + (unsigned long long)OCFS2_I(inode)->ip_blkno, + file->f_path.dentry->d_name.len, + file->f_path.dentry->d_name.name, + (unsigned int)nr_segs); if (iocb->ki_left == 0) return 0; @@ -2415,10 +2410,11 @@ static ssize_t ocfs2_file_splice_write(struct pipe_inode_info *pipe, .u.file = out, }; - mlog(0, "(0x%p, 0x%p, %u, '%.*s')\n", out, pipe, - (unsigned int)len, - out->f_path.dentry->d_name.len, - out->f_path.dentry->d_name.name); + + trace_ocfs2_file_splice_write(inode, out, out->f_path.dentry, + (unsigned long long)OCFS2_I(inode)->ip_blkno, + out->f_path.dentry->d_name.len, + out->f_path.dentry->d_name.name, len); if (pipe->inode) mutex_lock_nested(&pipe->inode->i_mutex, I_MUTEX_PARENT); @@ -2474,10 +2470,10 @@ static ssize_t ocfs2_file_splice_read(struct file *in, int ret = 0, lock_level = 0; struct inode *inode = in->f_path.dentry->d_inode; - mlog(0, "(0x%p, 0x%p, %u, '%.*s')\n", in, pipe, - (unsigned int)len, - in->f_path.dentry->d_name.len, - in->f_path.dentry->d_name.name); + trace_ocfs2_file_splice_read(inode, in, in->f_path.dentry, + (unsigned long long)OCFS2_I(inode)->ip_blkno, + in->f_path.dentry->d_name.len, + in->f_path.dentry->d_name.name, len); /* * See the comment in ocfs2_file_aio_read() @@ -2504,10 +2500,11 @@ static ssize_t ocfs2_file_aio_read(struct kiocb *iocb, struct file *filp = iocb->ki_filp; struct inode *inode = filp->f_path.dentry->d_inode; - mlog(0, "(0x%p, %u, '%.*s')\n", filp, - (unsigned int)nr_segs, - filp->f_path.dentry->d_name.len, - filp->f_path.dentry->d_name.name); + trace_ocfs2_file_aio_read(inode, filp, filp->f_path.dentry, + (unsigned long long)OCFS2_I(inode)->ip_blkno, + filp->f_path.dentry->d_name.len, + filp->f_path.dentry->d_name.name, nr_segs); + if (!inode) { ret = -EINVAL; @@ -2553,8 +2550,7 @@ static ssize_t ocfs2_file_aio_read(struct kiocb *iocb, ocfs2_inode_unlock(inode, lock_level); ret = generic_file_aio_read(iocb, iov, nr_segs, iocb->ki_pos); - if (ret == -EINVAL) - mlog(0, "generic_file_aio_read returned -EINVAL\n"); + trace_generic_file_aio_read_ret(ret); /* buffered aio wouldn't have proper lock coverage today */ BUG_ON(ret == -EIOCBQUEUED && !(filp->f_flags & O_DIRECT)); diff --git a/fs/ocfs2/ocfs2_trace.h b/fs/ocfs2/ocfs2_trace.h index 77148e7a14f81..16013b5588c6e 100644 --- a/fs/ocfs2/ocfs2_trace.h +++ b/fs/ocfs2/ocfs2_trace.h @@ -204,6 +204,30 @@ DEFINE_EVENT(ocfs2__uint_uint_uint, name, \ unsigned int value3), \ TP_ARGS(value1, value2, value3)) +DECLARE_EVENT_CLASS(ocfs2__ull_ull_ull, + TP_PROTO(unsigned long long value1, + unsigned long long value2, unsigned long long value3), + TP_ARGS(value1, value2, value3), + TP_STRUCT__entry( + __field(unsigned long long, value1) + __field(unsigned long long, value2) + __field(unsigned long long, value3) + ), + TP_fast_assign( + __entry->value1 = value1; + __entry->value2 = value2; + __entry->value3 = value3; + ), + TP_printk("%llu %llu %llu", + __entry->value1, __entry->value2, __entry->value3) +); + +#define DEFINE_OCFS2_ULL_ULL_ULL_EVENT(name) \ +DEFINE_EVENT(ocfs2__ull_ull_ull, name, \ + TP_PROTO(unsigned long long value1, unsigned long long value2, \ + unsigned long long value3), \ + TP_ARGS(value1, value2, value3)) + DECLARE_EVENT_CLASS(ocfs2__ull_int_int_int, TP_PROTO(unsigned long long ull, int value1, int value2, int value3), TP_ARGS(ull, value1, value2, value3), @@ -1117,6 +1141,219 @@ TRACE_EVENT(ocfs2_fault, /* End of trace events for fs/ocfs2/mmap.c. */ +/* Trace events for fs/ocfs2/file.c. */ + +DECLARE_EVENT_CLASS(ocfs2__file_ops, + TP_PROTO(void *inode, void *file, void *dentry, + unsigned long long ino, + unsigned int d_len, const unsigned char *d_name, + unsigned long long para), + TP_ARGS(inode, file, dentry, ino, d_len, d_name, para), + TP_STRUCT__entry( + __field(void *, inode) + __field(void *, file) + __field(void *, dentry) + __field(unsigned long long, ino) + __field(unsigned int, d_len) + __string(d_name, d_name) + __field(unsigned long long, para) + ), + TP_fast_assign( + __entry->inode = inode; + __entry->file = file; + __entry->dentry = dentry; + __entry->ino = ino; + __entry->d_len = d_len; + __assign_str(d_name, d_name); + __entry->para = para; + ), + TP_printk("%p %p %p %llu %llu %.*s", __entry->inode, __entry->file, + __entry->dentry, __entry->ino, __entry->para, + __entry->d_len, __get_str(d_name)) +); + +#define DEFINE_OCFS2_FILE_OPS(name) \ +DEFINE_EVENT(ocfs2__file_ops, name, \ +TP_PROTO(void *inode, void *file, void *dentry, \ + unsigned long long ino, \ + unsigned int d_len, const unsigned char *d_name, \ + unsigned long long mode), \ + TP_ARGS(inode, file, dentry, ino, d_len, d_name, mode)) + +DEFINE_OCFS2_FILE_OPS(ocfs2_file_open); + +DEFINE_OCFS2_FILE_OPS(ocfs2_file_release); + +DEFINE_OCFS2_FILE_OPS(ocfs2_sync_file); + +DEFINE_OCFS2_FILE_OPS(ocfs2_file_aio_write); + +DEFINE_OCFS2_FILE_OPS(ocfs2_file_splice_write); + +DEFINE_OCFS2_FILE_OPS(ocfs2_file_splice_read); + +DEFINE_OCFS2_FILE_OPS(ocfs2_file_aio_read); + +DEFINE_OCFS2_ULL_ULL_ULL_EVENT(ocfs2_truncate_file); + +DEFINE_OCFS2_ULL_ULL_EVENT(ocfs2_truncate_file_error); + +TRACE_EVENT(ocfs2_extend_allocation, + TP_PROTO(unsigned long long ip_blkno, unsigned long long size, + unsigned int clusters, unsigned int clusters_to_add, + int why, int restart_func), + TP_ARGS(ip_blkno, size, clusters, clusters_to_add, why, restart_func), + TP_STRUCT__entry( + __field(unsigned long long, ip_blkno) + __field(unsigned long long, size) + __field(unsigned int, clusters) + __field(unsigned int, clusters_to_add) + __field(int, why) + __field(int, restart_func) + ), + TP_fast_assign( + __entry->ip_blkno = ip_blkno; + __entry->size = size; + __entry->clusters = clusters; + __entry->clusters_to_add = clusters_to_add; + __entry->why = why; + __entry->restart_func = restart_func; + ), + TP_printk("%llu %llu %u %u %d %d", + __entry->ip_blkno, __entry->size, __entry->clusters, + __entry->clusters_to_add, __entry->why, __entry->restart_func) +); + +TRACE_EVENT(ocfs2_extend_allocation_end, + TP_PROTO(unsigned long long ino, + unsigned int di_clusters, unsigned long long di_size, + unsigned int ip_clusters, unsigned long long i_size), + TP_ARGS(ino, di_clusters, di_size, ip_clusters, i_size), + TP_STRUCT__entry( + __field(unsigned long long, ino) + __field(unsigned int, di_clusters) + __field(unsigned long long, di_size) + __field(unsigned int, ip_clusters) + __field(unsigned long long, i_size) + ), + TP_fast_assign( + __entry->ino = ino; + __entry->di_clusters = di_clusters; + __entry->di_size = di_size; + __entry->ip_clusters = ip_clusters; + __entry->i_size = i_size; + ), + TP_printk("%llu %u %llu %u %llu", __entry->ino, __entry->di_clusters, + __entry->di_size, __entry->ip_clusters, __entry->i_size) +); + +TRACE_EVENT(ocfs2_write_zero_page, + TP_PROTO(unsigned long long ino, + unsigned long long abs_from, unsigned long long abs_to, + unsigned long index, unsigned int zero_from, + unsigned int zero_to), + TP_ARGS(ino, abs_from, abs_to, index, zero_from, zero_to), + TP_STRUCT__entry( + __field(unsigned long long, ino) + __field(unsigned long long, abs_from) + __field(unsigned long long, abs_to) + __field(unsigned long, index) + __field(unsigned int, zero_from) + __field(unsigned int, zero_to) + ), + TP_fast_assign( + __entry->ino = ino; + __entry->abs_from = abs_from; + __entry->abs_to = abs_to; + __entry->index = index; + __entry->zero_from = zero_from; + __entry->zero_to = zero_to; + ), + TP_printk("%llu %llu %llu %lu %u %u", __entry->ino, + __entry->abs_from, __entry->abs_to, + __entry->index, __entry->zero_from, __entry->zero_to) +); + +DEFINE_OCFS2_ULL_ULL_ULL_EVENT(ocfs2_zero_extend_range); + +DEFINE_OCFS2_ULL_ULL_ULL_EVENT(ocfs2_zero_extend); + +TRACE_EVENT(ocfs2_setattr, + TP_PROTO(void *inode, void *dentry, + unsigned long long ino, + unsigned int d_len, const unsigned char *d_name, + unsigned int ia_valid, unsigned int ia_mode, + unsigned int ia_uid, unsigned int ia_gid), + TP_ARGS(inode, dentry, ino, d_len, d_name, + ia_valid, ia_mode, ia_uid, ia_gid), + TP_STRUCT__entry( + __field(void *, inode) + __field(void *, dentry) + __field(unsigned long long, ino) + __field(unsigned int, d_len) + __string(d_name, d_name) + __field(unsigned int, ia_valid) + __field(unsigned int, ia_mode) + __field(unsigned int, ia_uid) + __field(unsigned int, ia_gid) + ), + TP_fast_assign( + __entry->inode = inode; + __entry->dentry = dentry; + __entry->ino = ino; + __entry->d_len = d_len; + __assign_str(d_name, d_name); + __entry->ia_valid = ia_valid; + __entry->ia_mode = ia_mode; + __entry->ia_uid = ia_uid; + __entry->ia_gid = ia_gid; + ), + TP_printk("%p %p %llu %.*s %u %u %u %u", __entry->inode, + __entry->dentry, __entry->ino, __entry->d_len, + __get_str(d_name), __entry->ia_valid, __entry->ia_mode, + __entry->ia_uid, __entry->ia_gid) +); + +DEFINE_OCFS2_ULL_UINT_EVENT(ocfs2_write_remove_suid); + +DEFINE_OCFS2_ULL_ULL_ULL_EVENT(ocfs2_zero_partial_clusters); + +DEFINE_OCFS2_ULL_ULL_EVENT(ocfs2_zero_partial_clusters_range1); + +DEFINE_OCFS2_ULL_ULL_EVENT(ocfs2_zero_partial_clusters_range2); + +DEFINE_OCFS2_ULL_ULL_ULL_EVENT(ocfs2_remove_inode_range); + +TRACE_EVENT(ocfs2_prepare_inode_for_write, + TP_PROTO(unsigned long long ino, unsigned long long saved_pos, + int appending, unsigned long count, + int *direct_io, int *has_refcount), + TP_ARGS(ino, saved_pos, appending, count, direct_io, has_refcount), + TP_STRUCT__entry( + __field(unsigned long long, ino) + __field(unsigned long long, saved_pos) + __field(int, appending) + __field(unsigned long, count) + __field(int, direct_io) + __field(int, has_refcount) + ), + TP_fast_assign( + __entry->ino = ino; + __entry->saved_pos = saved_pos; + __entry->appending = appending; + __entry->count = count; + __entry->direct_io = direct_io ? *direct_io : -1; + __entry->has_refcount = has_refcount ? *has_refcount : -1; + ), + TP_printk("%llu %llu %d %lu %d %d", __entry->ino, + __entry->saved_pos, __entry->appending, __entry->count, + __entry->direct_io, __entry->has_refcount) +); + +DEFINE_OCFS2_INT_EVENT(generic_file_aio_read_ret); + +/* End of trace events for fs/ocfs2/file.c. */ + #endif /* _TRACE_OCFS2_H */ /* This part must be outside protection */ diff --git a/fs/ocfs2/sysfile.c b/fs/ocfs2/sysfile.c index 902efb23b6a66..3d635f4bbb201 100644 --- a/fs/ocfs2/sysfile.c +++ b/fs/ocfs2/sysfile.c @@ -27,7 +27,6 @@ #include #include -#define MLOG_MASK_PREFIX ML_INODE #include #include "ocfs2.h" -- GitLab From 6218b90e7669d83cb8ad744f3400205d260597f2 Mon Sep 17 00:00:00 2001 From: Tao Ma Date: Mon, 21 Feb 2011 11:18:30 +0800 Subject: [PATCH 0115/2822] ocfs2: Little refactoring against ocfs2_iget. ocfs2_iget is used to get/create inode. Only iget5_locked will give us an inode = NULL. So move this check ahead of ocfs2_read_locked_inode so that we don't need to check inode before we read and unlock inode. This is also helpful for trace event(see the next patch). Signed-off-by: Tao Ma --- fs/ocfs2/inode.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/fs/ocfs2/inode.c b/fs/ocfs2/inode.c index a96e56f127286..8ec0cb01cb7c9 100644 --- a/fs/ocfs2/inode.c +++ b/fs/ocfs2/inode.c @@ -152,16 +152,16 @@ struct inode *ocfs2_iget(struct ocfs2_super *osb, u64 blkno, unsigned flags, /* inode was *not* in the inode cache. 2.6.x requires * us to do our own read_inode call and unlock it * afterwards. */ - if (inode && inode->i_state & I_NEW) { - mlog(0, "Inode was not in inode cache, reading it.\n"); - ocfs2_read_locked_inode(inode, &args); - unlock_new_inode(inode); - } if (inode == NULL) { inode = ERR_PTR(-ENOMEM); mlog_errno(PTR_ERR(inode)); goto bail; } + if (inode->i_state & I_NEW) { + mlog(0, "Inode was not in inode cache, reading it.\n"); + ocfs2_read_locked_inode(inode, &args); + unlock_new_inode(inode); + } if (is_bad_inode(inode)) { iput(inode); inode = ERR_PTR(-ESTALE); -- GitLab From 64f3b2692724fdbe72697b77887685b5bd3f4a3c Mon Sep 17 00:00:00 2001 From: Tao Ma Date: Tue, 22 Feb 2011 22:24:57 +0800 Subject: [PATCH 0116/2822] ocfs2: Remove masklog ML_INODE. Remove mlog(0) from fs/ocfs2/inode.c and the masklog INODE. Signed-off-by: Tao Ma --- fs/ocfs2/cluster/masklog.c | 1 - fs/ocfs2/cluster/masklog.h | 1 - fs/ocfs2/inode.c | 107 +++++++++++++---------------- fs/ocfs2/ocfs2_trace.h | 136 +++++++++++++++++++++++++++++++++++++ 4 files changed, 182 insertions(+), 63 deletions(-) diff --git a/fs/ocfs2/cluster/masklog.c b/fs/ocfs2/cluster/masklog.c index 036e8b8814f79..e18fb801633ea 100644 --- a/fs/ocfs2/cluster/masklog.c +++ b/fs/ocfs2/cluster/masklog.c @@ -99,7 +99,6 @@ static struct mlog_attribute mlog_attrs[MLOG_MAX_BITS] = { define_mask(BH_IO), define_mask(UPTODATE), define_mask(NAMEI), - define_mask(INODE), define_mask(VOTE), define_mask(DCACHE), define_mask(CONN), diff --git a/fs/ocfs2/cluster/masklog.h b/fs/ocfs2/cluster/masklog.h index d07780ab9f8f9..b76d077861077 100644 --- a/fs/ocfs2/cluster/masklog.h +++ b/fs/ocfs2/cluster/masklog.h @@ -101,7 +101,6 @@ #define ML_BH_IO 0x0000000000100000ULL /* ocfs2 buffer I/O */ #define ML_UPTODATE 0x0000000000200000ULL /* ocfs2 caching sequence #'s */ #define ML_NAMEI 0x0000000000400000ULL /* ocfs2 directory / namespace */ -#define ML_INODE 0x0000000000800000ULL /* ocfs2 inode manipulation */ #define ML_VOTE 0x0000000001000000ULL /* ocfs2 node messaging */ #define ML_DCACHE 0x0000000002000000ULL /* ocfs2 dcache operations */ #define ML_CONN 0x0000000004000000ULL /* net connection management */ diff --git a/fs/ocfs2/inode.c b/fs/ocfs2/inode.c index 8ec0cb01cb7c9..177d3a6c2a5f4 100644 --- a/fs/ocfs2/inode.c +++ b/fs/ocfs2/inode.c @@ -31,7 +31,6 @@ #include -#define MLOG_MASK_PREFIX ML_INODE #include #include "ocfs2.h" @@ -53,6 +52,7 @@ #include "uptodate.h" #include "xattr.h" #include "refcounttree.h" +#include "ocfs2_trace.h" #include "buffer_head_io.h" @@ -131,7 +131,8 @@ struct inode *ocfs2_iget(struct ocfs2_super *osb, u64 blkno, unsigned flags, struct super_block *sb = osb->sb; struct ocfs2_find_inode_args args; - mlog(0, "(blkno = %llu)\n", (unsigned long long)blkno); + trace_ocfs2_iget_begin((unsigned long long)blkno, flags, + sysfile_type); /* Ok. By now we've either got the offsets passed to us by the * caller, or we just pulled them off the bh. Lets do some @@ -157,8 +158,8 @@ struct inode *ocfs2_iget(struct ocfs2_super *osb, u64 blkno, unsigned flags, mlog_errno(PTR_ERR(inode)); goto bail; } + trace_ocfs2_iget5_locked(inode->i_state); if (inode->i_state & I_NEW) { - mlog(0, "Inode was not in inode cache, reading it.\n"); ocfs2_read_locked_inode(inode, &args); unlock_new_inode(inode); } @@ -170,9 +171,8 @@ struct inode *ocfs2_iget(struct ocfs2_super *osb, u64 blkno, unsigned flags, bail: if (!IS_ERR(inode)) { - mlog(0, "returning inode with number %llu\n", - (unsigned long long)OCFS2_I(inode)->ip_blkno); - mlog(0, "inode %p\n", inode); + trace_ocfs2_iget_end(inode, + (unsigned long long)OCFS2_I(inode)->ip_blkno); } return inode; @@ -192,12 +192,12 @@ static int ocfs2_find_actor(struct inode *inode, void *opaque) struct ocfs2_inode_info *oi = OCFS2_I(inode); int ret = 0; - mlog(0, "(0x%p, %lu, 0x%p)\n", inode, inode->i_ino, opaque); - args = opaque; mlog_bug_on_msg(!inode, "No inode in find actor!\n"); + trace_ocfs2_find_actor(inode, inode->i_ino, opaque, args->fi_blkno); + if (oi->ip_blkno != args->fi_blkno) goto bail; @@ -217,8 +217,6 @@ static int ocfs2_init_locked_inode(struct inode *inode, void *opaque) static struct lock_class_key ocfs2_quota_ip_alloc_sem_key, ocfs2_file_ip_alloc_sem_key; - mlog(0, "inode = %p, opaque = %p\n", inode, opaque); - inode->i_ino = args->fi_ino; OCFS2_I(inode)->ip_blkno = args->fi_blkno; if (args->fi_sysfile_type != 0) @@ -244,9 +242,6 @@ void ocfs2_populate_inode(struct inode *inode, struct ocfs2_dinode *fe, struct ocfs2_super *osb; int use_plocks = 1; - mlog(0, "(0x%p, size:%llu)\n", inode, - (unsigned long long)le64_to_cpu(fe->i_size)); - sb = inode->i_sb; osb = OCFS2_SB(sb); @@ -298,20 +293,20 @@ void ocfs2_populate_inode(struct inode *inode, struct ocfs2_dinode *fe, inode->i_nlink = ocfs2_read_links_count(fe); + trace_ocfs2_populate_inode(OCFS2_I(inode)->ip_blkno, + le32_to_cpu(fe->i_flags)); if (fe->i_flags & cpu_to_le32(OCFS2_SYSTEM_FL)) { OCFS2_I(inode)->ip_flags |= OCFS2_INODE_SYSTEM_FILE; inode->i_flags |= S_NOQUOTA; } - + if (fe->i_flags & cpu_to_le32(OCFS2_LOCAL_ALLOC_FL)) { OCFS2_I(inode)->ip_flags |= OCFS2_INODE_BITMAP; - mlog(0, "local alloc inode: i_ino=%lu\n", inode->i_ino); } else if (fe->i_flags & cpu_to_le32(OCFS2_BITMAP_FL)) { OCFS2_I(inode)->ip_flags |= OCFS2_INODE_BITMAP; } else if (fe->i_flags & cpu_to_le32(OCFS2_QUOTA_FL)) { inode->i_flags |= S_NOQUOTA; } else if (fe->i_flags & cpu_to_le32(OCFS2_SUPER_BLOCK_FL)) { - mlog(0, "superblock inode: i_ino=%lu\n", inode->i_ino); /* we can't actually hit this as read_inode can't * handle superblocks today ;-) */ BUG(); @@ -391,8 +386,6 @@ static int ocfs2_read_locked_inode(struct inode *inode, int status, can_lock; u32 generation = 0; - mlog(0, "(0x%p, 0x%p)\n", inode, args); - status = -EINVAL; if (inode == NULL || inode->i_sb == NULL) { mlog(ML_ERROR, "bad inode\n"); @@ -440,6 +433,9 @@ static int ocfs2_read_locked_inode(struct inode *inode, && !(args->fi_flags & OCFS2_FI_FLAG_ORPHAN_RECOVERY) && !ocfs2_mount_local(osb); + trace_ocfs2_read_locked_inode( + (unsigned long long)OCFS2_I(inode)->ip_blkno, can_lock); + /* * To maintain backwards compatibility with older versions of * ocfs2-tools, we still store the generation value for system @@ -689,8 +685,6 @@ static int ocfs2_check_orphan_recovery_state(struct ocfs2_super *osb, spin_lock(&osb->osb_lock); if (ocfs2_node_map_test_bit(osb, &osb->osb_recovering_orphan_dirs, slot)) { - mlog(0, "Recovery is happening on orphan dir %d, will skip " - "this inode\n", slot); ret = -EDEADLK; goto out; } @@ -699,6 +693,7 @@ static int ocfs2_check_orphan_recovery_state(struct ocfs2_super *osb, osb->osb_orphan_wipes[slot]++; out: spin_unlock(&osb->osb_lock); + trace_ocfs2_check_orphan_recovery_state(slot, ret); return ret; } @@ -809,6 +804,10 @@ static int ocfs2_inode_is_valid_to_delete(struct inode *inode) struct ocfs2_inode_info *oi = OCFS2_I(inode); struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); + trace_ocfs2_inode_is_valid_to_delete(current, osb->dc_task, + (unsigned long long)oi->ip_blkno, + oi->ip_flags); + /* We shouldn't be getting here for the root directory * inode.. */ if (inode == osb->root_inode) { @@ -821,11 +820,8 @@ static int ocfs2_inode_is_valid_to_delete(struct inode *inode) * have to skip deleting this guy. That's OK though because * the node who's doing the actual deleting should handle it * anyway. */ - if (current == osb->dc_task) { - mlog(0, "Skipping delete of %lu because we're currently " - "in downconvert\n", inode->i_ino); + if (current == osb->dc_task) goto bail; - } spin_lock(&oi->ip_lock); /* OCFS2 *never* deletes system files. This should technically @@ -840,11 +836,8 @@ static int ocfs2_inode_is_valid_to_delete(struct inode *inode) /* If we have allowd wipe of this inode for another node, it * will be marked here so we can safely skip it. Recovery will * cleanup any inodes we might inadvertantly skip here. */ - if (oi->ip_flags & OCFS2_INODE_SKIP_DELETE) { - mlog(0, "Skipping delete of %lu because another node " - "has done this for us.\n", inode->i_ino); + if (oi->ip_flags & OCFS2_INODE_SKIP_DELETE) goto bail_unlock; - } ret = 1; bail_unlock: @@ -861,28 +854,27 @@ static int ocfs2_query_inode_wipe(struct inode *inode, struct buffer_head *di_bh, int *wipe) { - int status = 0; + int status = 0, reason = 0; struct ocfs2_inode_info *oi = OCFS2_I(inode); struct ocfs2_dinode *di; *wipe = 0; + trace_ocfs2_query_inode_wipe_begin((unsigned long long)oi->ip_blkno, + inode->i_nlink); + /* While we were waiting for the cluster lock in * ocfs2_delete_inode, another node might have asked to delete * the inode. Recheck our flags to catch this. */ if (!ocfs2_inode_is_valid_to_delete(inode)) { - mlog(0, "Skipping delete of %llu because flags changed\n", - (unsigned long long)oi->ip_blkno); + reason = 1; goto bail; } /* Now that we have an up to date inode, we can double check * the link count. */ - if (inode->i_nlink) { - mlog(0, "Skipping delete of %llu because nlink = %u\n", - (unsigned long long)oi->ip_blkno, inode->i_nlink); + if (inode->i_nlink) goto bail; - } /* Do some basic inode verification... */ di = (struct ocfs2_dinode *) di_bh->b_data; @@ -897,9 +889,7 @@ static int ocfs2_query_inode_wipe(struct inode *inode, * ORPHANED_FL not. */ if (di->i_dyn_features & cpu_to_le16(OCFS2_HAS_REFCOUNT_FL)) { - mlog(0, "Reflinked inode %llu is no longer orphaned. " - "it shouldn't be deleted\n", - (unsigned long long)oi->ip_blkno); + reason = 2; goto bail; } @@ -936,8 +926,7 @@ static int ocfs2_query_inode_wipe(struct inode *inode, status = ocfs2_try_open_lock(inode, 1); if (status == -EAGAIN) { status = 0; - mlog(0, "Skipping delete of %llu because it is in use on " - "other nodes\n", (unsigned long long)oi->ip_blkno); + reason = 3; goto bail; } if (status < 0) { @@ -946,11 +935,10 @@ static int ocfs2_query_inode_wipe(struct inode *inode, } *wipe = 1; - mlog(0, "Inode %llu is ok to wipe from orphan dir %u\n", - (unsigned long long)oi->ip_blkno, - le16_to_cpu(di->i_orphaned_slot)); + trace_ocfs2_query_inode_wipe_succ(le16_to_cpu(di->i_orphaned_slot)); bail: + trace_ocfs2_query_inode_wipe_end(status, reason); return status; } @@ -960,8 +948,8 @@ bail: static void ocfs2_cleanup_delete_inode(struct inode *inode, int sync_data) { - mlog(0, "Cleanup inode %llu, sync = %d\n", - (unsigned long long)OCFS2_I(inode)->ip_blkno, sync_data); + trace_ocfs2_cleanup_delete_inode( + (unsigned long long)OCFS2_I(inode)->ip_blkno, sync_data); if (sync_data) write_inode_now(inode, 1); truncate_inode_pages(&inode->i_data, 0); @@ -973,15 +961,15 @@ static void ocfs2_delete_inode(struct inode *inode) sigset_t oldset; struct buffer_head *di_bh = NULL; - mlog(0, "(inode->i_ino = %lu)\n", inode->i_ino); + trace_ocfs2_delete_inode(inode->i_ino, + (unsigned long long)OCFS2_I(inode)->ip_blkno, + is_bad_inode(inode)); /* When we fail in read_inode() we mark inode as bad. The second test * catches the case when inode allocation fails before allocating * a block for inode. */ - if (is_bad_inode(inode) || !OCFS2_I(inode)->ip_blkno) { - mlog(0, "Skipping delete of bad inode\n"); + if (is_bad_inode(inode) || !OCFS2_I(inode)->ip_blkno) goto bail; - } dquot_initialize(inode); @@ -1082,8 +1070,8 @@ static void ocfs2_clear_inode(struct inode *inode) struct ocfs2_inode_info *oi = OCFS2_I(inode); end_writeback(inode); - mlog(0, "Clearing inode: %llu, nlink = %u\n", - (unsigned long long)OCFS2_I(inode)->ip_blkno, inode->i_nlink); + trace_ocfs2_clear_inode((unsigned long long)oi->ip_blkno, + inode->i_nlink); mlog_bug_on_msg(OCFS2_SB(inode->i_sb) == NULL, "Inode=%lu\n", inode->i_ino); @@ -1193,8 +1181,8 @@ int ocfs2_drop_inode(struct inode *inode) struct ocfs2_inode_info *oi = OCFS2_I(inode); int res; - mlog(0, "Drop inode %llu, nlink = %u, ip_flags = 0x%x\n", - (unsigned long long)oi->ip_blkno, inode->i_nlink, oi->ip_flags); + trace_ocfs2_drop_inode((unsigned long long)oi->ip_blkno, + inode->i_nlink, oi->ip_flags); if (oi->ip_flags & OCFS2_INODE_MAYBE_ORPHANED) res = 1; @@ -1212,11 +1200,11 @@ int ocfs2_inode_revalidate(struct dentry *dentry) struct inode *inode = dentry->d_inode; int status = 0; - mlog(0, "(inode = 0x%p, ino = %llu)\n", inode, - inode ? (unsigned long long)OCFS2_I(inode)->ip_blkno : 0ULL); + trace_ocfs2_inode_revalidate(inode, + inode ? (unsigned long long)OCFS2_I(inode)->ip_blkno : 0ULL, + inode ? (unsigned long long)OCFS2_I(inode)->ip_flags : 0); if (!inode) { - mlog(0, "eep, no inode!\n"); status = -ENOENT; goto bail; } @@ -1224,7 +1212,6 @@ int ocfs2_inode_revalidate(struct dentry *dentry) spin_lock(&OCFS2_I(inode)->ip_lock); if (OCFS2_I(inode)->ip_flags & OCFS2_INODE_DELETED) { spin_unlock(&OCFS2_I(inode)->ip_lock); - mlog(0, "inode deleted!\n"); status = -ENOENT; goto bail; } @@ -1255,8 +1242,7 @@ int ocfs2_mark_inode_dirty(handle_t *handle, int status; struct ocfs2_dinode *fe = (struct ocfs2_dinode *) bh->b_data; - mlog(0, "(inode %llu)\n", - (unsigned long long)OCFS2_I(inode)->ip_blkno); + trace_ocfs2_mark_inode_dirty((unsigned long long)OCFS2_I(inode)->ip_blkno); status = ocfs2_journal_access_di(handle, INODE_CACHE(inode), bh, OCFS2_JOURNAL_ACCESS_WRITE); @@ -1328,8 +1314,7 @@ int ocfs2_validate_inode_block(struct super_block *sb, int rc; struct ocfs2_dinode *di = (struct ocfs2_dinode *)bh->b_data; - mlog(0, "Validating dinode %llu\n", - (unsigned long long)bh->b_blocknr); + trace_ocfs2_validate_inode_block((unsigned long long)bh->b_blocknr); BUG_ON(!buffer_uptodate(bh)); diff --git a/fs/ocfs2/ocfs2_trace.h b/fs/ocfs2/ocfs2_trace.h index 16013b5588c6e..052057a01ea8d 100644 --- a/fs/ocfs2/ocfs2_trace.h +++ b/fs/ocfs2/ocfs2_trace.h @@ -114,6 +114,25 @@ DEFINE_EVENT(ocfs2__ull_uint, name, \ TP_PROTO(unsigned long long val1, unsigned int val2), \ TP_ARGS(val1, val2)) +DECLARE_EVENT_CLASS(ocfs2__ull_int, + TP_PROTO(unsigned long long value1, int value2), + TP_ARGS(value1, value2), + TP_STRUCT__entry( + __field(unsigned long long, value1) + __field(int, value2) + ), + TP_fast_assign( + __entry->value1 = value1; + __entry->value2 = value2; + ), + TP_printk("%llu %d", __entry->value1, __entry->value2) +); + +#define DEFINE_OCFS2_ULL_INT_EVENT(name) \ +DEFINE_EVENT(ocfs2__ull_int, name, \ + TP_PROTO(unsigned long long val1, int val2), \ + TP_ARGS(val1, val2)) + DECLARE_EVENT_CLASS(ocfs2__ull_ull, TP_PROTO(unsigned long long value1, unsigned long long value2), TP_ARGS(value1, value2), @@ -1354,6 +1373,123 @@ DEFINE_OCFS2_INT_EVENT(generic_file_aio_read_ret); /* End of trace events for fs/ocfs2/file.c. */ +/* Trace events for fs/ocfs2/inode.c. */ + +TRACE_EVENT(ocfs2_iget_begin, + TP_PROTO(unsigned long long ino, unsigned int flags, int sysfile_type), + TP_ARGS(ino, flags, sysfile_type), + TP_STRUCT__entry( + __field(unsigned long long, ino) + __field(unsigned int, flags) + __field(int, sysfile_type) + ), + TP_fast_assign( + __entry->ino = ino; + __entry->flags = flags; + __entry->sysfile_type = sysfile_type; + ), + TP_printk("%llu %u %d", __entry->ino, + __entry->flags, __entry->sysfile_type) +); + +DEFINE_OCFS2_ULL_EVENT(ocfs2_iget5_locked); + +TRACE_EVENT(ocfs2_iget_end, + TP_PROTO(void *inode, unsigned long long ino), + TP_ARGS(inode, ino), + TP_STRUCT__entry( + __field(void *, inode) + __field(unsigned long long, ino) + ), + TP_fast_assign( + __entry->inode = inode; + __entry->ino = ino; + ), + TP_printk("%p %llu", __entry->inode, __entry->ino) +); + +TRACE_EVENT(ocfs2_find_actor, + TP_PROTO(void *inode, unsigned long long ino, + void *args, unsigned long long fi_blkno), + TP_ARGS(inode, ino, args, fi_blkno), + TP_STRUCT__entry( + __field(void *, inode) + __field(unsigned long long, ino) + __field(void *, args) + __field(unsigned long long, fi_blkno) + ), + TP_fast_assign( + __entry->inode = inode; + __entry->ino = ino; + __entry->args = args; + __entry->fi_blkno = fi_blkno; + ), + TP_printk("%p %llu %p %llu", __entry->inode, __entry->ino, + __entry->args, __entry->fi_blkno) +); + +DEFINE_OCFS2_ULL_UINT_EVENT(ocfs2_populate_inode); + +DEFINE_OCFS2_ULL_INT_EVENT(ocfs2_read_locked_inode); + +DEFINE_OCFS2_INT_INT_EVENT(ocfs2_check_orphan_recovery_state); + +DEFINE_OCFS2_ULL_EVENT(ocfs2_validate_inode_block); + +TRACE_EVENT(ocfs2_inode_is_valid_to_delete, + TP_PROTO(void *task, void *dc_task, unsigned long long ino, + unsigned int flags), + TP_ARGS(task, dc_task, ino, flags), + TP_STRUCT__entry( + __field(void *, task) + __field(void *, dc_task) + __field(unsigned long long, ino) + __field(unsigned int, flags) + ), + TP_fast_assign( + __entry->task = task; + __entry->dc_task = dc_task; + __entry->ino = ino; + __entry->flags = flags; + ), + TP_printk("%p %p %llu %u", __entry->task, __entry->dc_task, + __entry->ino, __entry->flags) +); + +DEFINE_OCFS2_ULL_UINT_EVENT(ocfs2_query_inode_wipe_begin); + +DEFINE_OCFS2_UINT_EVENT(ocfs2_query_inode_wipe_succ); + +DEFINE_OCFS2_INT_INT_EVENT(ocfs2_query_inode_wipe_end); + +DEFINE_OCFS2_ULL_INT_EVENT(ocfs2_cleanup_delete_inode); + +DEFINE_OCFS2_ULL_ULL_UINT_EVENT(ocfs2_delete_inode); + +DEFINE_OCFS2_ULL_UINT_EVENT(ocfs2_clear_inode); + +DEFINE_OCFS2_ULL_UINT_UINT_EVENT(ocfs2_drop_inode); + +TRACE_EVENT(ocfs2_inode_revalidate, + TP_PROTO(void *inode, unsigned long long ino, + unsigned int flags), + TP_ARGS(inode, ino, flags), + TP_STRUCT__entry( + __field(void *, inode) + __field(unsigned long long, ino) + __field(unsigned int, flags) + ), + TP_fast_assign( + __entry->inode = inode; + __entry->ino = ino; + __entry->flags = flags; + ), + TP_printk("%p %llu %u", __entry->inode, __entry->ino, __entry->flags) +); + +DEFINE_OCFS2_ULL_EVENT(ocfs2_mark_inode_dirty); + +/* End of trace events for fs/ocfs2/inode.c. */ #endif /* _TRACE_OCFS2_H */ /* This part must be outside protection */ -- GitLab From a716357c47ea1cc4f535356cff2c39edd327136b Mon Sep 17 00:00:00 2001 From: Tao Ma Date: Tue, 22 Feb 2011 22:27:33 +0800 Subject: [PATCH 0117/2822] ocfs2: Remove masklog ML_EXTENT_MAP. Remove mlog(0) from fs/ocfs2/extent_map.c and the masklog EXTENT_MAP. Signed-off-by: Tao Ma --- fs/ocfs2/cluster/masklog.c | 1 - fs/ocfs2/cluster/masklog.h | 1 - fs/ocfs2/extent_map.c | 5 ++--- fs/ocfs2/ocfs2_trace.h | 29 +++++++++++++++++++++++++++++ 4 files changed, 31 insertions(+), 5 deletions(-) diff --git a/fs/ocfs2/cluster/masklog.c b/fs/ocfs2/cluster/masklog.c index e18fb801633ea..c5ba4373d8638 100644 --- a/fs/ocfs2/cluster/masklog.c +++ b/fs/ocfs2/cluster/masklog.c @@ -94,7 +94,6 @@ static struct mlog_attribute mlog_attrs[MLOG_MAX_BITS] = { define_mask(AIO), define_mask(JOURNAL), define_mask(SUPER), - define_mask(EXTENT_MAP), define_mask(DLM_GLUE), define_mask(BH_IO), define_mask(UPTODATE), diff --git a/fs/ocfs2/cluster/masklog.h b/fs/ocfs2/cluster/masklog.h index b76d077861077..e4ca487078b32 100644 --- a/fs/ocfs2/cluster/masklog.h +++ b/fs/ocfs2/cluster/masklog.h @@ -96,7 +96,6 @@ #define ML_AIO 0x0000000000002000ULL /* ocfs2 aio read and write */ #define ML_JOURNAL 0x0000000000004000ULL /* ocfs2 journalling functions */ #define ML_SUPER 0x0000000000010000ULL /* ocfs2 mount / umount */ -#define ML_EXTENT_MAP 0x0000000000040000ULL /* ocfs2 extent map caching */ #define ML_DLM_GLUE 0x0000000000080000ULL /* ocfs2 dlm glue layer */ #define ML_BH_IO 0x0000000000100000ULL /* ocfs2 buffer I/O */ #define ML_UPTODATE 0x0000000000200000ULL /* ocfs2 caching sequence #'s */ diff --git a/fs/ocfs2/extent_map.c b/fs/ocfs2/extent_map.c index 7d74d176706a4..23457b491e8ce 100644 --- a/fs/ocfs2/extent_map.c +++ b/fs/ocfs2/extent_map.c @@ -28,7 +28,6 @@ #include #include -#define MLOG_MASK_PREFIX ML_EXTENT_MAP #include #include "ocfs2.h" @@ -39,6 +38,7 @@ #include "inode.h" #include "super.h" #include "symlink.h" +#include "ocfs2_trace.h" #include "buffer_head_io.h" @@ -841,8 +841,7 @@ int ocfs2_read_virt_blocks(struct inode *inode, u64 v_block, int nr, u64 p_block, p_count; int i, count, done = 0; - mlog(0, "(inode = %p, v_block = %llu, nr = %d, bhs = %p, " - "flags = %x, validate = %p)\n", + trace_ocfs2_read_virt_blocks( inode, (unsigned long long)v_block, nr, bhs, flags, validate); diff --git a/fs/ocfs2/ocfs2_trace.h b/fs/ocfs2/ocfs2_trace.h index 052057a01ea8d..a7938505227b9 100644 --- a/fs/ocfs2/ocfs2_trace.h +++ b/fs/ocfs2/ocfs2_trace.h @@ -1490,6 +1490,35 @@ TRACE_EVENT(ocfs2_inode_revalidate, DEFINE_OCFS2_ULL_EVENT(ocfs2_mark_inode_dirty); /* End of trace events for fs/ocfs2/inode.c. */ + +/* Trace events for fs/ocfs2/extent_map.c. */ + +TRACE_EVENT(ocfs2_read_virt_blocks, + TP_PROTO(void *inode, unsigned long long vblock, int nr, + void *bhs, unsigned int flags, void *validate), + TP_ARGS(inode, vblock, nr, bhs, flags, validate), + TP_STRUCT__entry( + __field(void *, inode) + __field(unsigned long long, vblock) + __field(int, nr) + __field(void *, bhs) + __field(unsigned int, flags) + __field(void *, validate) + ), + TP_fast_assign( + __entry->inode = inode; + __entry->vblock = vblock; + __entry->nr = nr; + __entry->bhs = bhs; + __entry->flags = flags; + __entry->validate = validate; + ), + TP_printk("%p %llu %d %p %x %p", __entry->inode, __entry->vblock, + __entry->nr, __entry->bhs, __entry->flags, __entry->validate) +); + +/* End of trace events for fs/ocfs2/extent_map.c. */ + #endif /* _TRACE_OCFS2_H */ /* This part must be outside protection */ -- GitLab From a8731086eff053b430cddbf5783654dfd700ea06 Mon Sep 17 00:00:00 2001 From: Tao Ma Date: Tue, 22 Feb 2011 22:29:08 +0800 Subject: [PATCH 0118/2822] ocfs2: Remove mlog(0) from fs/ocfs2/slot_map.c This is the 1st step to remove the debug info of SUPER. Signed-off-by: Tao Ma --- fs/ocfs2/ocfs2_trace.h | 11 +++++++++++ fs/ocfs2/slot_map.c | 13 +++++-------- 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/fs/ocfs2/ocfs2_trace.h b/fs/ocfs2/ocfs2_trace.h index a7938505227b9..d70471f8ad046 100644 --- a/fs/ocfs2/ocfs2_trace.h +++ b/fs/ocfs2/ocfs2_trace.h @@ -1519,6 +1519,17 @@ TRACE_EVENT(ocfs2_read_virt_blocks, /* End of trace events for fs/ocfs2/extent_map.c. */ +/* Trace events for fs/ocfs2/slot_map.c. */ + +DEFINE_OCFS2_UINT_EVENT(ocfs2_refresh_slot_info); + +DEFINE_OCFS2_ULL_UINT_EVENT(ocfs2_map_slot_buffers); + +DEFINE_OCFS2_ULL_UINT_EVENT(ocfs2_map_slot_buffers_block); + +DEFINE_OCFS2_INT_EVENT(ocfs2_find_slot); + +/* End of trace events for fs/ocfs2/slot_map.c. */ #endif /* _TRACE_OCFS2_H */ /* This part must be outside protection */ diff --git a/fs/ocfs2/slot_map.c b/fs/ocfs2/slot_map.c index 93b449ed82f97..26fc0014d5093 100644 --- a/fs/ocfs2/slot_map.c +++ b/fs/ocfs2/slot_map.c @@ -27,7 +27,6 @@ #include #include -#define MLOG_MASK_PREFIX ML_SUPER #include #include "ocfs2.h" @@ -39,6 +38,7 @@ #include "slot_map.h" #include "super.h" #include "sysfile.h" +#include "ocfs2_trace.h" #include "buffer_head_io.h" @@ -142,8 +142,7 @@ int ocfs2_refresh_slot_info(struct ocfs2_super *osb) BUG_ON(si->si_blocks == 0); BUG_ON(si->si_bh == NULL); - mlog(0, "Refreshing slot map, reading %u block(s)\n", - si->si_blocks); + trace_ocfs2_refresh_slot_info(si->si_blocks); /* * We pass -1 as blocknr because we expect all of si->si_bh to @@ -381,8 +380,7 @@ static int ocfs2_map_slot_buffers(struct ocfs2_super *osb, /* The size checks above should ensure this */ BUG_ON((osb->max_slots / si->si_slots_per_block) > blocks); - mlog(0, "Slot map needs %u buffers for %llu bytes\n", - si->si_blocks, bytes); + trace_ocfs2_map_slot_buffers(bytes, si->si_blocks); si->si_bh = kzalloc(sizeof(struct buffer_head *) * si->si_blocks, GFP_KERNEL); @@ -400,8 +398,7 @@ static int ocfs2_map_slot_buffers(struct ocfs2_super *osb, goto bail; } - mlog(0, "Reading slot map block %u at %llu\n", i, - (unsigned long long)blkno); + trace_ocfs2_map_slot_buffers_block((unsigned long long)blkno, i); bh = NULL; /* Acquire a fresh bh */ status = ocfs2_read_blocks(INODE_CACHE(si->si_inode), blkno, @@ -503,7 +500,7 @@ int ocfs2_find_slot(struct ocfs2_super *osb) osb->slot_num = slot; spin_unlock(&osb->osb_lock); - mlog(0, "taking node slot %d\n", osb->slot_num); + trace_ocfs2_find_slot(osb->slot_num); status = ocfs2_update_disk_slot(osb, si, osb->slot_num); if (status < 0) -- GitLab From b5770f98b00e94dd573e3438427de09733fe2039 Mon Sep 17 00:00:00 2001 From: Tao Ma Date: Wed, 23 Feb 2011 21:17:39 +0800 Subject: [PATCH 0119/2822] ocfs2: Remove mlog(0) from fs/ocfs2/heartbeat.c This is the 2nd step to remove the debug info of SUPER. Signed-off-by: Tao Ma --- fs/ocfs2/heartbeat.c | 4 ++-- fs/ocfs2/ocfs2_trace.h | 7 +++++++ 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/fs/ocfs2/heartbeat.c b/fs/ocfs2/heartbeat.c index 1aa863dd901f7..d8208b20dc532 100644 --- a/fs/ocfs2/heartbeat.c +++ b/fs/ocfs2/heartbeat.c @@ -28,7 +28,6 @@ #include #include -#define MLOG_MASK_PREFIX ML_SUPER #include #include "ocfs2.h" @@ -37,6 +36,7 @@ #include "heartbeat.h" #include "inode.h" #include "journal.h" +#include "ocfs2_trace.h" #include "buffer_head_io.h" @@ -66,7 +66,7 @@ void ocfs2_do_node_down(int node_num, void *data) BUG_ON(osb->node_num == node_num); - mlog(0, "ocfs2: node down event for %d\n", node_num); + trace_ocfs2_do_node_down(node_num); if (!osb->cconn) { /* diff --git a/fs/ocfs2/ocfs2_trace.h b/fs/ocfs2/ocfs2_trace.h index d70471f8ad046..876b119d3656f 100644 --- a/fs/ocfs2/ocfs2_trace.h +++ b/fs/ocfs2/ocfs2_trace.h @@ -1530,6 +1530,13 @@ DEFINE_OCFS2_ULL_UINT_EVENT(ocfs2_map_slot_buffers_block); DEFINE_OCFS2_INT_EVENT(ocfs2_find_slot); /* End of trace events for fs/ocfs2/slot_map.c. */ + +/* Trace events for fs/ocfs2/heartbeat.c. */ + +DEFINE_OCFS2_INT_EVENT(ocfs2_do_node_down); + +/* End of trace events for fs/ocfs2/heartbeat.c. */ + #endif /* _TRACE_OCFS2_H */ /* This part must be outside protection */ -- GitLab From 32a42d392bf9b8f90f41434ccb3605e958b16251 Mon Sep 17 00:00:00 2001 From: Tao Ma Date: Wed, 23 Feb 2011 21:29:08 +0800 Subject: [PATCH 0120/2822] ocfs2: Remove masklog ML_SUPER. Remove mlog(0) from fs/ocfs2/super.c and the masklog SUPER. Signed-off-by: Tao Ma --- fs/ocfs2/cluster/masklog.c | 1 - fs/ocfs2/cluster/masklog.h | 1 - fs/ocfs2/ocfs2_trace.h | 108 +++++++++++++++++++++++++++++++++++++ fs/ocfs2/super.c | 29 ++++------ 4 files changed, 118 insertions(+), 21 deletions(-) diff --git a/fs/ocfs2/cluster/masklog.c b/fs/ocfs2/cluster/masklog.c index c5ba4373d8638..ffc0de62a031a 100644 --- a/fs/ocfs2/cluster/masklog.c +++ b/fs/ocfs2/cluster/masklog.c @@ -93,7 +93,6 @@ static struct mlog_attribute mlog_attrs[MLOG_MAX_BITS] = { define_mask(DLM_RECOVERY), define_mask(AIO), define_mask(JOURNAL), - define_mask(SUPER), define_mask(DLM_GLUE), define_mask(BH_IO), define_mask(UPTODATE), diff --git a/fs/ocfs2/cluster/masklog.h b/fs/ocfs2/cluster/masklog.h index e4ca487078b32..98d4af95c8fe5 100644 --- a/fs/ocfs2/cluster/masklog.h +++ b/fs/ocfs2/cluster/masklog.h @@ -95,7 +95,6 @@ #define ML_DLM_RECOVERY 0x0000000000001000ULL /* dlm master functions */ #define ML_AIO 0x0000000000002000ULL /* ocfs2 aio read and write */ #define ML_JOURNAL 0x0000000000004000ULL /* ocfs2 journalling functions */ -#define ML_SUPER 0x0000000000010000ULL /* ocfs2 mount / umount */ #define ML_DLM_GLUE 0x0000000000080000ULL /* ocfs2 dlm glue layer */ #define ML_BH_IO 0x0000000000100000ULL /* ocfs2 buffer I/O */ #define ML_UPTODATE 0x0000000000200000ULL /* ocfs2 caching sequence #'s */ diff --git a/fs/ocfs2/ocfs2_trace.h b/fs/ocfs2/ocfs2_trace.h index 876b119d3656f..75900635109bc 100644 --- a/fs/ocfs2/ocfs2_trace.h +++ b/fs/ocfs2/ocfs2_trace.h @@ -57,6 +57,23 @@ DEFINE_EVENT(ocfs2__ull, name, \ TP_PROTO(unsigned long long num), \ TP_ARGS(num)) +DECLARE_EVENT_CLASS(ocfs2__pointer, + TP_PROTO(void *pointer), + TP_ARGS(pointer), + TP_STRUCT__entry( + __field(void *, pointer) + ), + TP_fast_assign( + __entry->pointer = pointer; + ), + TP_printk("%p", __entry->pointer) +); + +#define DEFINE_OCFS2_POINTER_EVENT(name) \ +DEFINE_EVENT(ocfs2__pointer, name, \ + TP_PROTO(void *pointer), \ + TP_ARGS(pointer)) + DECLARE_EVENT_CLASS(ocfs2__int_int, TP_PROTO(int value1, int value2), TP_ARGS(value1, value2), @@ -1537,6 +1554,97 @@ DEFINE_OCFS2_INT_EVENT(ocfs2_do_node_down); /* End of trace events for fs/ocfs2/heartbeat.c. */ +/* Trace events for fs/ocfs2/super.c. */ + +TRACE_EVENT(ocfs2_remount, + TP_PROTO(unsigned long s_flags, unsigned long osb_flags, int flags), + TP_ARGS(s_flags, osb_flags, flags), + TP_STRUCT__entry( + __field(unsigned long, s_flags) + __field(unsigned long, osb_flags) + __field(int, flags) + ), + TP_fast_assign( + __entry->s_flags = s_flags; + __entry->osb_flags = osb_flags; + __entry->flags = flags; + ), + TP_printk("%lu %lu %d", __entry->s_flags, + __entry->osb_flags, __entry->flags) +); + +TRACE_EVENT(ocfs2_fill_super, + TP_PROTO(void *sb, void *data, int silent), + TP_ARGS(sb, data, silent), + TP_STRUCT__entry( + __field(void *, sb) + __field(void *, data) + __field(int, silent) + ), + TP_fast_assign( + __entry->sb = sb; + __entry->data = data; + __entry->silent = silent; + ), + TP_printk("%p %p %d", __entry->sb, + __entry->data, __entry->silent) +); + +TRACE_EVENT(ocfs2_parse_options, + TP_PROTO(int is_remount, char *options), + TP_ARGS(is_remount, options), + TP_STRUCT__entry( + __field(int, is_remount) + __string(options, options) + ), + TP_fast_assign( + __entry->is_remount = is_remount; + __assign_str(options, options); + ), + TP_printk("%d %s", __entry->is_remount, __get_str(options)) +); + +DEFINE_OCFS2_POINTER_EVENT(ocfs2_put_super); + +TRACE_EVENT(ocfs2_statfs, + TP_PROTO(void *sb, void *buf), + TP_ARGS(sb, buf), + TP_STRUCT__entry( + __field(void *, sb) + __field(void *, buf) + ), + TP_fast_assign( + __entry->sb = sb; + __entry->buf = buf; + ), + TP_printk("%p %p", __entry->sb, __entry->buf) +); + +DEFINE_OCFS2_POINTER_EVENT(ocfs2_dismount_volume); + +TRACE_EVENT(ocfs2_initialize_super, + TP_PROTO(char *label, char *uuid_str, unsigned long long root_dir, + unsigned long long system_dir, int cluster_bits), + TP_ARGS(label, uuid_str, root_dir, system_dir, cluster_bits), + TP_STRUCT__entry( + __string(label, label) + __string(uuid_str, uuid_str) + __field(unsigned long long, root_dir) + __field(unsigned long long, system_dir) + __field(int, cluster_bits) + ), + TP_fast_assign( + __assign_str(label, label); + __assign_str(uuid_str, uuid_str); + __entry->root_dir = root_dir; + __entry->system_dir = system_dir; + __entry->cluster_bits = cluster_bits; + ), + TP_printk("%s %s %llu %llu %d", __get_str(label), __get_str(uuid_str), + __entry->root_dir, __entry->system_dir, __entry->cluster_bits) +); + +/* End of trace events for fs/ocfs2/super.c. */ #endif /* _TRACE_OCFS2_H */ /* This part must be outside protection */ diff --git a/fs/ocfs2/super.c b/fs/ocfs2/super.c index f7e73a029844c..0e4083987d2bf 100644 --- a/fs/ocfs2/super.c +++ b/fs/ocfs2/super.c @@ -45,7 +45,6 @@ #define CREATE_TRACE_POINTS #include "ocfs2_trace.h" -#define MLOG_MASK_PREFIX ML_SUPER #include #include "ocfs2.h" @@ -680,12 +679,9 @@ static int ocfs2_remount(struct super_block *sb, int *flags, char *data) } if (*flags & MS_RDONLY) { - mlog(0, "Going to ro mode.\n"); sb->s_flags |= MS_RDONLY; osb->osb_flags |= OCFS2_OSB_SOFT_RO; } else { - mlog(0, "Making ro filesystem writeable.\n"); - if (osb->osb_flags & OCFS2_OSB_ERROR_FS) { mlog(ML_ERROR, "Cannot remount RDWR " "filesystem due to previous errors.\n"); @@ -703,6 +699,7 @@ static int ocfs2_remount(struct super_block *sb, int *flags, char *data) sb->s_flags &= ~MS_RDONLY; osb->osb_flags &= ~OCFS2_OSB_SOFT_RO; } + trace_ocfs2_remount(sb->s_flags, osb->osb_flags, *flags); unlock_osb: spin_unlock(&osb->osb_lock); /* Enable quota accounting after remounting RW */ @@ -1028,7 +1025,7 @@ static int ocfs2_fill_super(struct super_block *sb, void *data, int silent) char nodestr[8]; struct ocfs2_blockcheck_stats stats; - mlog(0, "%p, %p, %i", sb, data, silent); + trace_ocfs2_fill_super(sb, data, silent); if (!ocfs2_parse_options(sb, data, &parsed_options, 0)) { status = -EINVAL; @@ -1315,8 +1312,7 @@ static int ocfs2_parse_options(struct super_block *sb, char *p; u32 tmp; - mlog(0, "remount: %d, options: \"%s\"\n", is_remount, - options ? options : "(none)"); + trace_ocfs2_parse_options(is_remount, options ? options : "(none)"); mopt->commit_interval = 0; mopt->mount_opt = OCFS2_MOUNT_NOINTR; @@ -1692,7 +1688,7 @@ static void __exit ocfs2_exit(void) static void ocfs2_put_super(struct super_block *sb) { - mlog(0, "(0x%p)\n", sb); + trace_ocfs2_put_super(sb); ocfs2_sync_blockdev(sb); ocfs2_dismount_volume(sb, 0); @@ -1707,7 +1703,7 @@ static int ocfs2_statfs(struct dentry *dentry, struct kstatfs *buf) struct buffer_head *bh = NULL; struct inode *inode = NULL; - mlog(0, "(%p, %p)\n", dentry->d_sb, buf); + trace_ocfs2_statfs(dentry->d_sb, buf); osb = OCFS2_SB(dentry->d_sb); @@ -1928,7 +1924,7 @@ static void ocfs2_dismount_volume(struct super_block *sb, int mnt_err) struct ocfs2_super *osb = NULL; char nodestr[8]; - mlog(0, "(0x%p)\n", sb); + trace_ocfs2_dismount_volume(sb); BUG_ON(!sb); osb = OCFS2_SB(sb); @@ -2143,7 +2139,6 @@ static int ocfs2_initialize_super(struct super_block *sb, status = -EINVAL; goto bail; } - mlog(0, "max_slots for this device: %u\n", osb->max_slots); ocfs2_orphan_scan_init(osb); @@ -2282,7 +2277,6 @@ static int ocfs2_initialize_super(struct super_block *sb, osb->s_clustersize_bits = le32_to_cpu(di->id2.i_super.s_clustersize_bits); osb->s_clustersize = 1 << osb->s_clustersize_bits; - mlog(0, "clusterbits=%d\n", osb->s_clustersize_bits); if (osb->s_clustersize < OCFS2_MIN_CLUSTERSIZE || osb->s_clustersize > OCFS2_MAX_CLUSTERSIZE) { @@ -2321,11 +2315,10 @@ static int ocfs2_initialize_super(struct super_block *sb, le64_to_cpu(di->id2.i_super.s_first_cluster_group); osb->fs_generation = le32_to_cpu(di->i_fs_generation); osb->uuid_hash = le32_to_cpu(di->id2.i_super.s_uuid_hash); - mlog(0, "vol_label: %s\n", osb->vol_label); - mlog(0, "uuid: %s\n", osb->uuid_str); - mlog(0, "root_blkno=%llu, system_dir_blkno=%llu\n", - (unsigned long long)osb->root_blkno, - (unsigned long long)osb->system_dir_blkno); + trace_ocfs2_initialize_super(osb->vol_label, osb->uuid_str, + (unsigned long long)osb->root_blkno, + (unsigned long long)osb->system_dir_blkno, + osb->s_clustersize_bits); osb->osb_dlm_debug = ocfs2_new_dlm_debug(); if (!osb->osb_dlm_debug) { @@ -2500,8 +2493,6 @@ static int ocfs2_check_volume(struct ocfs2_super *osb) * ourselves as mounted. */ } - mlog(0, "Journal loaded.\n"); - status = ocfs2_load_local_alloc(osb); if (status < 0) { mlog_errno(status); -- GitLab From 402b418311f0d20a71451770d764a2e37b08dbcf Mon Sep 17 00:00:00 2001 From: Tao Ma Date: Wed, 23 Feb 2011 22:01:17 +0800 Subject: [PATCH 0121/2822] ocfs2: Remove masklog ML_XATTR. Remove mlog(0) from fs/ocfs2/xattr.c and the masklog ML_XATTR. Signed-off-by: Tao Ma --- fs/ocfs2/cluster/masklog.c | 1 - fs/ocfs2/cluster/masklog.h | 1 - fs/ocfs2/ocfs2_trace.h | 164 +++++++++++++++++++++++++++++++++++++ fs/ocfs2/xattr.c | 153 +++++++++++++++++----------------- 4 files changed, 239 insertions(+), 80 deletions(-) diff --git a/fs/ocfs2/cluster/masklog.c b/fs/ocfs2/cluster/masklog.c index ffc0de62a031a..ef140ab7dcf84 100644 --- a/fs/ocfs2/cluster/masklog.c +++ b/fs/ocfs2/cluster/masklog.c @@ -102,7 +102,6 @@ static struct mlog_attribute mlog_attrs[MLOG_MAX_BITS] = { define_mask(CONN), define_mask(QUORUM), define_mask(EXPORT), - define_mask(XATTR), define_mask(QUOTA), define_mask(BASTS), define_mask(RESERVATIONS), diff --git a/fs/ocfs2/cluster/masklog.h b/fs/ocfs2/cluster/masklog.h index 98d4af95c8fe5..f574b167e8dc6 100644 --- a/fs/ocfs2/cluster/masklog.h +++ b/fs/ocfs2/cluster/masklog.h @@ -104,7 +104,6 @@ #define ML_CONN 0x0000000004000000ULL /* net connection management */ #define ML_QUORUM 0x0000000008000000ULL /* net connection quorum */ #define ML_EXPORT 0x0000000010000000ULL /* ocfs2 export operations */ -#define ML_XATTR 0x0000000020000000ULL /* ocfs2 extended attributes */ #define ML_QUOTA 0x0000000040000000ULL /* ocfs2 quota operations */ #define ML_BASTS 0x0000000100000000ULL /* dlmglue asts and basts */ #define ML_RESERVATIONS 0x0000000200000000ULL /* ocfs2 alloc reservations */ diff --git a/fs/ocfs2/ocfs2_trace.h b/fs/ocfs2/ocfs2_trace.h index 75900635109bc..0fc2840d6fb1a 100644 --- a/fs/ocfs2/ocfs2_trace.h +++ b/fs/ocfs2/ocfs2_trace.h @@ -74,6 +74,23 @@ DEFINE_EVENT(ocfs2__pointer, name, \ TP_PROTO(void *pointer), \ TP_ARGS(pointer)) +DECLARE_EVENT_CLASS(ocfs2__string, + TP_PROTO(const char *name), + TP_ARGS(name), + TP_STRUCT__entry( + __string(name,name) + ), + TP_fast_assign( + __assign_str(name, name); + ), + TP_printk("%s", __get_str(name)) +); + +#define DEFINE_OCFS2_STRING_EVENT(name) \ +DEFINE_EVENT(ocfs2__string, name, \ + TP_PROTO(const char *name), \ + TP_ARGS(name)) + DECLARE_EVENT_CLASS(ocfs2__int_int, TP_PROTO(int value1, int value2), TP_ARGS(value1, value2), @@ -317,6 +334,33 @@ DEFINE_EVENT(ocfs2__ull_uint_uint_uint, name, \ unsigned int value2, unsigned int value3), \ TP_ARGS(ull, value1, value2, value3)) +DECLARE_EVENT_CLASS(ocfs2__ull_ull_uint_uint, + TP_PROTO(unsigned long long value1, unsigned long long value2, + unsigned int value3, unsigned int value4), + TP_ARGS(value1, value2, value3, value4), + TP_STRUCT__entry( + __field(unsigned long long, value1) + __field(unsigned long long, value2) + __field(unsigned int, value3) + __field(unsigned int, value4) + ), + TP_fast_assign( + __entry->value1 = value1; + __entry->value2 = value2; + __entry->value3 = value3; + __entry->value4 = value4; + ), + TP_printk("%llu %llu %u %u", + __entry->value1, __entry->value2, + __entry->value3, __entry->value4) +); + +#define DEFINE_OCFS2_ULL_ULL_UINT_UINT_EVENT(name) \ +DEFINE_EVENT(ocfs2__ull_ull_uint_uint, name, \ + TP_PROTO(unsigned long long ull, unsigned long long ull1, \ + unsigned int value2, unsigned int value3), \ + TP_ARGS(ull, ull1, value2, value3)) + /* Trace events for fs/ocfs2/alloc.c. */ DECLARE_EVENT_CLASS(ocfs2__btree_ops, TP_PROTO(unsigned long long owner,\ @@ -1645,6 +1689,126 @@ TRACE_EVENT(ocfs2_initialize_super, ); /* End of trace events for fs/ocfs2/super.c. */ + +/* Trace events for fs/ocfs2/xattr.c. */ + +DEFINE_OCFS2_ULL_EVENT(ocfs2_validate_xattr_block); + +DEFINE_OCFS2_UINT_EVENT(ocfs2_xattr_extend_allocation); + +TRACE_EVENT(ocfs2_init_xattr_set_ctxt, + TP_PROTO(const char *name, int meta, int clusters, int credits), + TP_ARGS(name, meta, clusters, credits), + TP_STRUCT__entry( + __string(name, name) + __field(int, meta) + __field(int, clusters) + __field(int, credits) + ), + TP_fast_assign( + __assign_str(name, name); + __entry->meta = meta; + __entry->clusters = clusters; + __entry->credits = credits; + ), + TP_printk("%s %d %d %d", __get_str(name), __entry->meta, + __entry->clusters, __entry->credits) +); + +DECLARE_EVENT_CLASS(ocfs2__xattr_find, + TP_PROTO(unsigned long long ino, const char *name, int name_index, + unsigned int hash, unsigned long long location, + int xe_index), + TP_ARGS(ino, name, name_index, hash, location, xe_index), + TP_STRUCT__entry( + __field(unsigned long long, ino) + __string(name, name) + __field(int, name_index) + __field(unsigned int, hash) + __field(unsigned long long, location) + __field(int, xe_index) + ), + TP_fast_assign( + __entry->ino = ino; + __assign_str(name, name); + __entry->name_index = name_index; + __entry->hash = hash; + __entry->location = location; + __entry->xe_index = xe_index; + ), + TP_printk("%llu %s %d %u %llu %d", __entry->ino, __get_str(name), + __entry->name_index, __entry->hash, __entry->location, + __entry->xe_index) +); + +#define DEFINE_OCFS2_XATTR_FIND_EVENT(name) \ +DEFINE_EVENT(ocfs2__xattr_find, name, \ +TP_PROTO(unsigned long long ino, const char *name, int name_index, \ + unsigned int hash, unsigned long long bucket, \ + int xe_index), \ + TP_ARGS(ino, name, name_index, hash, bucket, xe_index)) + +DEFINE_OCFS2_XATTR_FIND_EVENT(ocfs2_xattr_bucket_find); + +DEFINE_OCFS2_XATTR_FIND_EVENT(ocfs2_xattr_index_block_find); + +DEFINE_OCFS2_XATTR_FIND_EVENT(ocfs2_xattr_index_block_find_rec); + +DEFINE_OCFS2_ULL_ULL_UINT_EVENT(ocfs2_iterate_xattr_buckets); + +DEFINE_OCFS2_ULL_UINT_EVENT(ocfs2_iterate_xattr_bucket); + +DEFINE_OCFS2_ULL_ULL_EVENT(ocfs2_cp_xattr_block_to_bucket_begin); + +DEFINE_OCFS2_UINT_UINT_UINT_EVENT(ocfs2_cp_xattr_block_to_bucket_end); + +DEFINE_OCFS2_ULL_EVENT(ocfs2_xattr_create_index_block_begin); + +DEFINE_OCFS2_ULL_EVENT(ocfs2_xattr_create_index_block); + +DEFINE_OCFS2_ULL_UINT_UINT_UINT_EVENT(ocfs2_defrag_xattr_bucket); + +DEFINE_OCFS2_ULL_ULL_EVENT(ocfs2_mv_xattr_bucket_cross_cluster); + +DEFINE_OCFS2_ULL_ULL_EVENT(ocfs2_divide_xattr_bucket_begin); + +DEFINE_OCFS2_UINT_UINT_UINT_EVENT(ocfs2_divide_xattr_bucket_move); + +DEFINE_OCFS2_ULL_ULL_UINT_EVENT(ocfs2_cp_xattr_bucket); + +DEFINE_OCFS2_ULL_ULL_EVENT(ocfs2_mv_xattr_buckets); + +DEFINE_OCFS2_ULL_ULL_UINT_EVENT(ocfs2_adjust_xattr_cross_cluster); + +DEFINE_OCFS2_ULL_ULL_UINT_UINT_EVENT(ocfs2_add_new_xattr_cluster_begin); + +DEFINE_OCFS2_ULL_UINT_EVENT(ocfs2_add_new_xattr_cluster); + +DEFINE_OCFS2_ULL_UINT_UINT_EVENT(ocfs2_add_new_xattr_cluster_insert); + +DEFINE_OCFS2_ULL_ULL_UINT_UINT_EVENT(ocfs2_extend_xattr_bucket); + +DEFINE_OCFS2_ULL_EVENT(ocfs2_add_new_xattr_bucket); + +DEFINE_OCFS2_ULL_UINT_UINT_EVENT(ocfs2_xattr_bucket_value_truncate); + +DEFINE_OCFS2_ULL_ULL_UINT_UINT_EVENT(ocfs2_rm_xattr_cluster); + +DEFINE_OCFS2_ULL_UINT_EVENT(ocfs2_reflink_xattr_header); + +DEFINE_OCFS2_ULL_INT_EVENT(ocfs2_create_empty_xattr_block); + +DEFINE_OCFS2_STRING_EVENT(ocfs2_xattr_set_entry_bucket); + +DEFINE_OCFS2_STRING_EVENT(ocfs2_xattr_set_entry_index_block); + +DEFINE_OCFS2_ULL_UINT_EVENT(ocfs2_xattr_bucket_value_refcount); + +DEFINE_OCFS2_ULL_UINT_UINT_EVENT(ocfs2_reflink_xattr_buckets); + +DEFINE_OCFS2_ULL_UINT_EVENT(ocfs2_reflink_xattr_rec); + +/* End of trace events for fs/ocfs2/xattr.c. */ #endif /* _TRACE_OCFS2_H */ /* This part must be outside protection */ diff --git a/fs/ocfs2/xattr.c b/fs/ocfs2/xattr.c index d57c7942e4dee..52e3dadd36428 100644 --- a/fs/ocfs2/xattr.c +++ b/fs/ocfs2/xattr.c @@ -37,7 +37,6 @@ #include #include -#define MLOG_MASK_PREFIX ML_XATTR #include #include "ocfs2.h" @@ -57,6 +56,7 @@ #include "xattr.h" #include "refcounttree.h" #include "acl.h" +#include "ocfs2_trace.h" struct ocfs2_xattr_def_value_root { struct ocfs2_xattr_value_root xv; @@ -474,8 +474,7 @@ static int ocfs2_validate_xattr_block(struct super_block *sb, struct ocfs2_xattr_block *xb = (struct ocfs2_xattr_block *)bh->b_data; - mlog(0, "Validating xattr block %llu\n", - (unsigned long long)bh->b_blocknr); + trace_ocfs2_validate_xattr_block((unsigned long long)bh->b_blocknr); BUG_ON(!buffer_uptodate(bh)); @@ -715,11 +714,11 @@ static int ocfs2_xattr_extend_allocation(struct inode *inode, u32 prev_clusters, logical_start = le32_to_cpu(vb->vb_xv->xr_clusters); struct ocfs2_extent_tree et; - mlog(0, "(clusters_to_add for xattr= %u)\n", clusters_to_add); - ocfs2_init_xattr_value_extent_tree(&et, INODE_CACHE(inode), vb); while (clusters_to_add) { + trace_ocfs2_xattr_extend_allocation(clusters_to_add); + status = vb->vb_access(handle, INODE_CACHE(inode), vb->vb_bh, OCFS2_JOURNAL_ACCESS_WRITE); if (status < 0) { @@ -754,8 +753,6 @@ static int ocfs2_xattr_extend_allocation(struct inode *inode, */ BUG_ON(why == RESTART_META); - mlog(0, "restarting xattr value extension for %u" - " clusters,.\n", clusters_to_add); credits = ocfs2_calc_extend_credits(inode->i_sb, &vb->vb_xv->xr_list, clusters_to_add); @@ -3246,8 +3243,8 @@ static int ocfs2_init_xattr_set_ctxt(struct inode *inode, } meta_add += extra_meta; - mlog(0, "Set xattr %s, reserve meta blocks = %d, clusters = %d, " - "credits = %d\n", xi->xi_name, meta_add, clusters_add, *credits); + trace_ocfs2_init_xattr_set_ctxt(xi->xi_name, meta_add, + clusters_add, *credits); if (meta_add) { ret = ocfs2_reserve_new_metadata_blocks(osb, meta_add, @@ -3887,8 +3884,10 @@ static int ocfs2_xattr_bucket_find(struct inode *inode, if (found) { xs->here = &xs->header->xh_entries[index]; - mlog(0, "find xattr %s in bucket %llu, entry = %u\n", name, - (unsigned long long)bucket_blkno(xs->bucket), index); + trace_ocfs2_xattr_bucket_find(OCFS2_I(inode)->ip_blkno, + name, name_index, name_hash, + (unsigned long long)bucket_blkno(xs->bucket), + index); } else ret = -ENODATA; @@ -3915,8 +3914,10 @@ static int ocfs2_xattr_index_block_find(struct inode *inode, if (le16_to_cpu(el->l_next_free_rec) == 0) return -ENODATA; - mlog(0, "find xattr %s, hash = %u, index = %d in xattr tree\n", - name, name_hash, name_index); + trace_ocfs2_xattr_index_block_find(OCFS2_I(inode)->ip_blkno, + name, name_index, name_hash, + (unsigned long long)root_bh->b_blocknr, + -1); ret = ocfs2_xattr_get_rec(inode, name_hash, &p_blkno, &first_hash, &num_clusters, el); @@ -3927,9 +3928,10 @@ static int ocfs2_xattr_index_block_find(struct inode *inode, BUG_ON(p_blkno == 0 || num_clusters == 0 || first_hash > name_hash); - mlog(0, "find xattr extent rec %u clusters from %llu, the first hash " - "in the rec is %u\n", num_clusters, (unsigned long long)p_blkno, - first_hash); + trace_ocfs2_xattr_index_block_find_rec(OCFS2_I(inode)->ip_blkno, + name, name_index, first_hash, + (unsigned long long)p_blkno, + num_clusters); ret = ocfs2_xattr_bucket_find(inode, name_index, name, name_hash, p_blkno, first_hash, num_clusters, xs); @@ -3955,8 +3957,9 @@ static int ocfs2_iterate_xattr_buckets(struct inode *inode, return -ENOMEM; } - mlog(0, "iterating xattr buckets in %u clusters starting from %llu\n", - clusters, (unsigned long long)blkno); + trace_ocfs2_iterate_xattr_buckets( + (unsigned long long)OCFS2_I(inode)->ip_blkno, + (unsigned long long)blkno, clusters); for (i = 0; i < num_buckets; i++, blkno += bucket->bu_blocks) { ret = ocfs2_read_xattr_bucket(bucket, blkno); @@ -3972,8 +3975,7 @@ static int ocfs2_iterate_xattr_buckets(struct inode *inode, if (i == 0) num_buckets = le16_to_cpu(bucket_xh(bucket)->xh_num_buckets); - mlog(0, "iterating xattr bucket %llu, first hash %u\n", - (unsigned long long)blkno, + trace_ocfs2_iterate_xattr_bucket((unsigned long long)blkno, le32_to_cpu(bucket_xh(bucket)->xh_entries[0].xe_name_hash)); if (func) { ret = func(inode, bucket, para); @@ -4173,9 +4175,9 @@ static void ocfs2_cp_xattr_block_to_bucket(struct inode *inode, char *src = xb_bh->b_data; char *target = bucket_block(bucket, blks - 1); - mlog(0, "cp xattr from block %llu to bucket %llu\n", - (unsigned long long)xb_bh->b_blocknr, - (unsigned long long)bucket_blkno(bucket)); + trace_ocfs2_cp_xattr_block_to_bucket_begin( + (unsigned long long)xb_bh->b_blocknr, + (unsigned long long)bucket_blkno(bucket)); for (i = 0; i < blks; i++) memset(bucket_block(bucket, i), 0, blocksize); @@ -4211,8 +4213,7 @@ static void ocfs2_cp_xattr_block_to_bucket(struct inode *inode, for (i = 0; i < count; i++) le16_add_cpu(&xh->xh_entries[i].xe_name_offset, off_change); - mlog(0, "copy entry: start = %u, size = %u, offset_change = %u\n", - offset, size, off_change); + trace_ocfs2_cp_xattr_block_to_bucket_end(offset, size, off_change); sort(target + offset, count, sizeof(struct ocfs2_xattr_entry), cmp_xe, swap_xe); @@ -4261,8 +4262,8 @@ static int ocfs2_xattr_create_index_block(struct inode *inode, struct ocfs2_xattr_tree_root *xr; u16 xb_flags = le16_to_cpu(xb->xb_flags); - mlog(0, "create xattr index block for %llu\n", - (unsigned long long)xb_bh->b_blocknr); + trace_ocfs2_xattr_create_index_block_begin( + (unsigned long long)xb_bh->b_blocknr); BUG_ON(xb_flags & OCFS2_XATTR_INDEXED); BUG_ON(!xs->bucket); @@ -4295,8 +4296,7 @@ static int ocfs2_xattr_create_index_block(struct inode *inode, */ blkno = ocfs2_clusters_to_blocks(inode->i_sb, bit_off); - mlog(0, "allocate 1 cluster from %llu to xattr block\n", - (unsigned long long)blkno); + trace_ocfs2_xattr_create_index_block((unsigned long long)blkno); ret = ocfs2_init_xattr_bucket(xs->bucket, blkno); if (ret) { @@ -4400,8 +4400,7 @@ static int ocfs2_defrag_xattr_bucket(struct inode *inode, entries = (char *)xh->xh_entries; xh_free_start = le16_to_cpu(xh->xh_free_start); - mlog(0, "adjust xattr bucket in %llu, count = %u, " - "xh_free_start = %u, xh_name_value_len = %u.\n", + trace_ocfs2_defrag_xattr_bucket( (unsigned long long)blkno, le16_to_cpu(xh->xh_count), xh_free_start, le16_to_cpu(xh->xh_name_value_len)); @@ -4503,8 +4502,9 @@ static int ocfs2_mv_xattr_bucket_cross_cluster(struct inode *inode, BUG_ON(le16_to_cpu(bucket_xh(first)->xh_num_buckets) < num_buckets); BUG_ON(OCFS2_XATTR_BUCKET_SIZE == OCFS2_SB(sb)->s_clustersize); - mlog(0, "move half of xattrs in cluster %llu to %llu\n", - (unsigned long long)last_cluster_blkno, (unsigned long long)new_blkno); + trace_ocfs2_mv_xattr_bucket_cross_cluster( + (unsigned long long)last_cluster_blkno, + (unsigned long long)new_blkno); ret = ocfs2_mv_xattr_buckets(inode, handle, bucket_blkno(first), last_cluster_blkno, new_blkno, @@ -4614,8 +4614,8 @@ static int ocfs2_divide_xattr_bucket(struct inode *inode, struct ocfs2_xattr_entry *xe; int blocksize = inode->i_sb->s_blocksize; - mlog(0, "move some of xattrs from bucket %llu to %llu\n", - (unsigned long long)blk, (unsigned long long)new_blk); + trace_ocfs2_divide_xattr_bucket_begin((unsigned long long)blk, + (unsigned long long)new_blk); s_bucket = ocfs2_xattr_bucket_new(inode); t_bucket = ocfs2_xattr_bucket_new(inode); @@ -4714,9 +4714,9 @@ static int ocfs2_divide_xattr_bucket(struct inode *inode, */ xe = &xh->xh_entries[start]; len = sizeof(struct ocfs2_xattr_entry) * (count - start); - mlog(0, "mv xattr entry len %d from %d to %d\n", len, - (int)((char *)xe - (char *)xh), - (int)((char *)xh->xh_entries - (char *)xh)); + trace_ocfs2_divide_xattr_bucket_move(len, + (int)((char *)xe - (char *)xh), + (int)((char *)xh->xh_entries - (char *)xh)); memmove((char *)xh->xh_entries, (char *)xe, len); xe = &xh->xh_entries[count - start]; len = sizeof(struct ocfs2_xattr_entry) * start; @@ -4788,9 +4788,9 @@ static int ocfs2_cp_xattr_bucket(struct inode *inode, BUG_ON(s_blkno == t_blkno); - mlog(0, "cp bucket %llu to %llu, target is %d\n", - (unsigned long long)s_blkno, (unsigned long long)t_blkno, - t_is_new); + trace_ocfs2_cp_xattr_bucket((unsigned long long)s_blkno, + (unsigned long long)t_blkno, + t_is_new); s_bucket = ocfs2_xattr_bucket_new(inode); t_bucket = ocfs2_xattr_bucket_new(inode); @@ -4862,8 +4862,8 @@ static int ocfs2_mv_xattr_buckets(struct inode *inode, handle_t *handle, int num_buckets = ocfs2_xattr_buckets_per_cluster(osb); struct ocfs2_xattr_bucket *old_first, *new_first; - mlog(0, "mv xattrs from cluster %llu to %llu\n", - (unsigned long long)last_blk, (unsigned long long)to_blk); + trace_ocfs2_mv_xattr_buckets((unsigned long long)last_blk, + (unsigned long long)to_blk); BUG_ON(start_bucket >= num_buckets); if (start_bucket) { @@ -5013,9 +5013,9 @@ static int ocfs2_adjust_xattr_cross_cluster(struct inode *inode, { int ret; - mlog(0, "adjust xattrs from cluster %llu len %u to %llu\n", - (unsigned long long)bucket_blkno(first), prev_clusters, - (unsigned long long)new_blk); + trace_ocfs2_adjust_xattr_cross_cluster( + (unsigned long long)bucket_blkno(first), + (unsigned long long)new_blk, prev_clusters); if (ocfs2_xattr_buckets_per_cluster(OCFS2_SB(inode->i_sb)) > 1) { ret = ocfs2_mv_xattr_bucket_cross_cluster(inode, @@ -5088,10 +5088,10 @@ static int ocfs2_add_new_xattr_cluster(struct inode *inode, struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); struct ocfs2_extent_tree et; - mlog(0, "Add new xattr cluster for %llu, previous xattr hash = %u, " - "previous xattr blkno = %llu\n", - (unsigned long long)OCFS2_I(inode)->ip_blkno, - prev_cpos, (unsigned long long)bucket_blkno(first)); + trace_ocfs2_add_new_xattr_cluster_begin( + (unsigned long long)OCFS2_I(inode)->ip_blkno, + (unsigned long long)bucket_blkno(first), + prev_cpos, prev_clusters); ocfs2_init_xattr_tree_extent_tree(&et, INODE_CACHE(inode), root_bh); @@ -5113,8 +5113,7 @@ static int ocfs2_add_new_xattr_cluster(struct inode *inode, BUG_ON(num_bits > clusters_to_add); block = ocfs2_clusters_to_blocks(osb->sb, bit_off); - mlog(0, "Allocating %u clusters at block %u for xattr in inode %llu\n", - num_bits, bit_off, (unsigned long long)OCFS2_I(inode)->ip_blkno); + trace_ocfs2_add_new_xattr_cluster((unsigned long long)block, num_bits); if (bucket_blkno(first) + (prev_clusters * bpc) == block && (prev_clusters + num_bits) << osb->s_clustersize_bits <= @@ -5130,8 +5129,6 @@ static int ocfs2_add_new_xattr_cluster(struct inode *inode, */ v_start = prev_cpos + prev_clusters; *num_clusters = prev_clusters + num_bits; - mlog(0, "Add contiguous %u clusters to previous extent rec.\n", - num_bits); } else { ret = ocfs2_adjust_xattr_cross_cluster(inode, handle, @@ -5147,8 +5144,8 @@ static int ocfs2_add_new_xattr_cluster(struct inode *inode, } } - mlog(0, "Insert %u clusters at block %llu for xattr at %u\n", - num_bits, (unsigned long long)block, v_start); + trace_ocfs2_add_new_xattr_cluster_insert((unsigned long long)block, + v_start, num_bits); ret = ocfs2_insert_extent(handle, &et, v_start, block, num_bits, 0, ctxt->meta_ac); if (ret < 0) { @@ -5183,9 +5180,9 @@ static int ocfs2_extend_xattr_bucket(struct inode *inode, u64 end_blk; u16 new_bucket = le16_to_cpu(bucket_xh(first)->xh_num_buckets); - mlog(0, "extend xattr bucket in %llu, xattr extend rec starting " - "from %llu, len = %u\n", (unsigned long long)target_blk, - (unsigned long long)bucket_blkno(first), num_clusters); + trace_ocfs2_extend_xattr_bucket((unsigned long long)target_blk, + (unsigned long long)bucket_blkno(first), + num_clusters, new_bucket); /* The extent must have room for an additional bucket */ BUG_ON(new_bucket >= @@ -5265,8 +5262,8 @@ static int ocfs2_add_new_xattr_bucket(struct inode *inode, /* The bucket at the front of the extent */ struct ocfs2_xattr_bucket *first; - mlog(0, "Add new xattr bucket starting from %llu\n", - (unsigned long long)bucket_blkno(target)); + trace_ocfs2_add_new_xattr_bucket( + (unsigned long long)bucket_blkno(target)); /* The first bucket of the original extent */ first = ocfs2_xattr_bucket_new(inode); @@ -5382,8 +5379,8 @@ static int ocfs2_xattr_bucket_value_truncate(struct inode *inode, * modified something. We have to assume they did, and dirty * the whole bucket. This leaves us in a consistent state. */ - mlog(0, "truncate %u in xattr bucket %llu to %d bytes.\n", - xe_off, (unsigned long long)bucket_blkno(bucket), len); + trace_ocfs2_xattr_bucket_value_truncate( + (unsigned long long)bucket_blkno(bucket), xe_off, len); ret = ocfs2_xattr_value_truncate(inode, &vb, len, ctxt); if (ret) { mlog_errno(ret); @@ -5433,8 +5430,9 @@ static int ocfs2_rm_xattr_cluster(struct inode *inode, ocfs2_init_dealloc_ctxt(&dealloc); - mlog(0, "rm xattr extent rec at %u len = %u, start from %llu\n", - cpos, len, (unsigned long long)blkno); + trace_ocfs2_rm_xattr_cluster( + (unsigned long long)OCFS2_I(inode)->ip_blkno, + (unsigned long long)blkno, cpos, len); ocfs2_remove_xattr_clusters_from_cache(INODE_CACHE(inode), blkno, len); @@ -5538,7 +5536,7 @@ static int ocfs2_xattr_set_entry_bucket(struct inode *inode, int ret; struct ocfs2_xa_loc loc; - mlog(0, "Set xattr %s in xattr bucket\n", xi->xi_name); + trace_ocfs2_xattr_set_entry_bucket(xi->xi_name); ocfs2_init_xattr_bucket_xa_loc(&loc, xs->bucket, xs->not_found ? NULL : xs->here); @@ -5580,7 +5578,7 @@ static int ocfs2_xattr_set_entry_index_block(struct inode *inode, { int ret; - mlog(0, "Set xattr %s in xattr index block\n", xi->xi_name); + trace_ocfs2_xattr_set_entry_index_block(xi->xi_name); ret = ocfs2_xattr_set_entry_bucket(inode, xi, xs, ctxt); if (!ret) @@ -6039,9 +6037,9 @@ static int ocfs2_xattr_bucket_value_refcount(struct inode *inode, if (ocfs2_meta_ecc(OCFS2_SB(inode->i_sb))) p = &refcount; - mlog(0, "refcount bucket %llu, count = %u\n", - (unsigned long long)bucket_blkno(bucket), - le16_to_cpu(xh->xh_count)); + trace_ocfs2_xattr_bucket_value_refcount( + (unsigned long long)bucket_blkno(bucket), + le16_to_cpu(xh->xh_count)); for (i = 0; i < le16_to_cpu(xh->xh_count); i++) { xe = &xh->xh_entries[i]; @@ -6337,8 +6335,8 @@ static int ocfs2_reflink_xattr_header(handle_t *handle, u32 clusters, cpos, p_cluster, num_clusters; unsigned int ext_flags = 0; - mlog(0, "reflink xattr in container %llu, count = %u\n", - (unsigned long long)old_bh->b_blocknr, le16_to_cpu(xh->xh_count)); + trace_ocfs2_reflink_xattr_header((unsigned long long)old_bh->b_blocknr, + le16_to_cpu(xh->xh_count)); last = &new_xh->xh_entries[le16_to_cpu(new_xh->xh_count)]; for (i = 0, j = 0; i < le16_to_cpu(xh->xh_count); i++, j++) { @@ -6538,8 +6536,8 @@ static int ocfs2_create_empty_xattr_block(struct inode *inode, goto out; } - mlog(0, "create new xattr block for inode %llu, index = %d\n", - (unsigned long long)fe_bh->b_blocknr, indexed); + trace_ocfs2_create_empty_xattr_block( + (unsigned long long)fe_bh->b_blocknr, indexed); ret = ocfs2_create_xattr_block(inode, fe_bh, &ctxt, indexed, ret_bh); if (ret) @@ -6950,8 +6948,8 @@ static int ocfs2_reflink_xattr_buckets(handle_t *handle, if (ret) mlog_errno(ret); - mlog(0, "insert new xattr extent rec start %llu len %u to %u\n", - (unsigned long long)new_blkno, num_clusters, reflink_cpos); + trace_ocfs2_reflink_xattr_buckets((unsigned long long)new_blkno, + num_clusters, reflink_cpos); len -= num_clusters; blkno += ocfs2_clusters_to_blocks(inode->i_sb, num_clusters); @@ -6980,8 +6978,7 @@ static int ocfs2_reflink_xattr_rec(struct inode *inode, struct ocfs2_alloc_context *data_ac = NULL; struct ocfs2_extent_tree et; - mlog(0, "reflink xattr buckets %llu len %u\n", - (unsigned long long)blkno, len); + trace_ocfs2_reflink_xattr_rec((unsigned long long)blkno, len); ocfs2_init_xattr_tree_extent_tree(&et, INODE_CACHE(args->reflink->new_inode), -- GitLab From 2661836e0ca07f57505563ec31aeee20b1758987 Mon Sep 17 00:00:00 2001 From: Tao Ma Date: Wed, 23 Feb 2011 22:10:56 +0800 Subject: [PATCH 0122/2822] ocfs2: Remove masklog ML_RESERVATIONS. Remove mlog(0) from fs/ocfs2/reservations.c and the masklog RESERVATIONS. Signed-off-by: Tao Ma --- fs/ocfs2/cluster/masklog.c | 1 - fs/ocfs2/cluster/masklog.h | 1 - fs/ocfs2/ocfs2_trace.h | 116 +++++++++++++++++++++++++++++++++++++ fs/ocfs2/reservations.c | 57 +++++++++--------- 4 files changed, 142 insertions(+), 33 deletions(-) diff --git a/fs/ocfs2/cluster/masklog.c b/fs/ocfs2/cluster/masklog.c index ef140ab7dcf84..39f2a46810d13 100644 --- a/fs/ocfs2/cluster/masklog.c +++ b/fs/ocfs2/cluster/masklog.c @@ -104,7 +104,6 @@ static struct mlog_attribute mlog_attrs[MLOG_MAX_BITS] = { define_mask(EXPORT), define_mask(QUOTA), define_mask(BASTS), - define_mask(RESERVATIONS), define_mask(CLUSTER), define_mask(ERROR), define_mask(NOTICE), diff --git a/fs/ocfs2/cluster/masklog.h b/fs/ocfs2/cluster/masklog.h index f574b167e8dc6..c36b4d8d5aa97 100644 --- a/fs/ocfs2/cluster/masklog.h +++ b/fs/ocfs2/cluster/masklog.h @@ -106,7 +106,6 @@ #define ML_EXPORT 0x0000000010000000ULL /* ocfs2 export operations */ #define ML_QUOTA 0x0000000040000000ULL /* ocfs2 quota operations */ #define ML_BASTS 0x0000000100000000ULL /* dlmglue asts and basts */ -#define ML_RESERVATIONS 0x0000000200000000ULL /* ocfs2 alloc reservations */ #define ML_CLUSTER 0x0000000400000000ULL /* cluster stack */ /* bits that are infrequently given and frequently matched in the high word */ diff --git a/fs/ocfs2/ocfs2_trace.h b/fs/ocfs2/ocfs2_trace.h index 0fc2840d6fb1a..1c040fcbd6e7d 100644 --- a/fs/ocfs2/ocfs2_trace.h +++ b/fs/ocfs2/ocfs2_trace.h @@ -1809,6 +1809,122 @@ DEFINE_OCFS2_ULL_UINT_UINT_EVENT(ocfs2_reflink_xattr_buckets); DEFINE_OCFS2_ULL_UINT_EVENT(ocfs2_reflink_xattr_rec); /* End of trace events for fs/ocfs2/xattr.c. */ + +/* Trace events for fs/ocfs2/reservations.c. */ + +DEFINE_OCFS2_UINT_UINT_EVENT(ocfs2_resv_insert); + +DEFINE_OCFS2_ULL_UINT_UINT_UINT_EVENT(ocfs2_resmap_find_free_bits_begin); + +DEFINE_OCFS2_UINT_UINT_EVENT(ocfs2_resmap_find_free_bits_end); + +TRACE_EVENT(ocfs2_resv_find_window_begin, + TP_PROTO(unsigned int r_start, unsigned int r_end, unsigned int goal, + unsigned int wanted, int empty_root), + TP_ARGS(r_start, r_end, goal, wanted, empty_root), + TP_STRUCT__entry( + __field(unsigned int, r_start) + __field(unsigned int, r_end) + __field(unsigned int, goal) + __field(unsigned int, wanted) + __field(int, empty_root) + ), + TP_fast_assign( + __entry->r_start = r_start; + __entry->r_end = r_end; + __entry->goal = goal; + __entry->wanted = wanted; + __entry->empty_root = empty_root; + ), + TP_printk("%u %u %u %u %d", __entry->r_start, __entry->r_end, + __entry->goal, __entry->wanted, __entry->empty_root) +); + +DEFINE_OCFS2_UINT_UINT_EVENT(ocfs2_resv_find_window_prev); + +DEFINE_OCFS2_INT_INT_EVENT(ocfs2_resv_find_window_next); + +DEFINE_OCFS2_UINT_UINT_UINT_EVENT(ocfs2_cannibalize_resv_begin); + +TRACE_EVENT(ocfs2_cannibalize_resv_end, + TP_PROTO(unsigned int start, unsigned int end, unsigned int len, + unsigned int last_start, unsigned int last_len), + TP_ARGS(start, end, len, last_start, last_len), + TP_STRUCT__entry( + __field(unsigned int, start) + __field(unsigned int, end) + __field(unsigned int, len) + __field(unsigned int, last_start) + __field(unsigned int, last_len) + ), + TP_fast_assign( + __entry->start = start; + __entry->end = end; + __entry->len = len; + __entry->last_start = last_start; + __entry->last_len = last_len; + ), + TP_printk("%u %u %u %u %u", __entry->start, __entry->end, + __entry->len, __entry->last_start, __entry->last_len) +); + +DEFINE_OCFS2_UINT_UINT_EVENT(ocfs2_resmap_resv_bits); + +TRACE_EVENT(ocfs2_resmap_claimed_bits_begin, + TP_PROTO(unsigned int cstart, unsigned int cend, unsigned int clen, + unsigned int r_start, unsigned int r_end, unsigned int r_len, + unsigned int last_start, unsigned int last_len), + TP_ARGS(cstart, cend, clen, r_start, r_end, + r_len, last_start, last_len), + TP_STRUCT__entry( + __field(unsigned int, cstart) + __field(unsigned int, cend) + __field(unsigned int, clen) + __field(unsigned int, r_start) + __field(unsigned int, r_end) + __field(unsigned int, r_len) + __field(unsigned int, last_start) + __field(unsigned int, last_len) + ), + TP_fast_assign( + __entry->cstart = cstart; + __entry->cend = cend; + __entry->clen = clen; + __entry->r_start = r_start; + __entry->r_end = r_end; + __entry->r_len = r_len; + __entry->last_start = last_start; + __entry->last_len = last_len; + ), + TP_printk("%u %u %u %u %u %u %u %u", + __entry->cstart, __entry->cend, __entry->clen, + __entry->r_start, __entry->r_end, __entry->r_len, + __entry->last_start, __entry->last_len) +); + +TRACE_EVENT(ocfs2_resmap_claimed_bits_end, + TP_PROTO(unsigned int start, unsigned int end, unsigned int len, + unsigned int last_start, unsigned int last_len), + TP_ARGS(start, end, len, last_start, last_len), + TP_STRUCT__entry( + __field(unsigned int, start) + __field(unsigned int, end) + __field(unsigned int, len) + __field(unsigned int, last_start) + __field(unsigned int, last_len) + ), + TP_fast_assign( + __entry->start = start; + __entry->end = end; + __entry->len = len; + __entry->last_start = last_start; + __entry->last_len = last_len; + ), + TP_printk("%u %u %u %u %u", __entry->start, __entry->end, + __entry->len, __entry->last_start, __entry->last_len) +); + +/* End of trace events for fs/ocfs2/reservations.c. */ #endif /* _TRACE_OCFS2_H */ /* This part must be outside protection */ diff --git a/fs/ocfs2/reservations.c b/fs/ocfs2/reservations.c index 3e78db361bc70..41ffd36c689c2 100644 --- a/fs/ocfs2/reservations.c +++ b/fs/ocfs2/reservations.c @@ -30,10 +30,10 @@ #include #include -#define MLOG_MASK_PREFIX ML_RESERVATIONS #include #include "ocfs2.h" +#include "ocfs2_trace.h" #ifdef CONFIG_OCFS2_DEBUG_FS #define OCFS2_CHECK_RESERVATIONS @@ -321,8 +321,7 @@ static void ocfs2_resv_insert(struct ocfs2_reservation_map *resmap, assert_spin_locked(&resv_lock); - mlog(0, "Insert reservation start: %u len: %u\n", new->r_start, - new->r_len); + trace_ocfs2_resv_insert(new->r_start, new->r_len); while (*p) { parent = *p; @@ -423,8 +422,8 @@ static int ocfs2_resmap_find_free_bits(struct ocfs2_reservation_map *resmap, unsigned int best_start, best_len = 0; int offset, start, found; - mlog(0, "Find %u bits within range (%u, len %u) resmap len: %u\n", - wanted, search_start, search_len, resmap->m_bitmap_len); + trace_ocfs2_resmap_find_free_bits_begin(search_start, search_len, + wanted, resmap->m_bitmap_len); found = best_start = best_len = 0; @@ -463,7 +462,7 @@ static int ocfs2_resmap_find_free_bits(struct ocfs2_reservation_map *resmap, *rlen = best_len; *rstart = best_start; - mlog(0, "Found start: %u len: %u\n", best_start, best_len); + trace_ocfs2_resmap_find_free_bits_end(best_start, best_len); return *rlen; } @@ -487,9 +486,8 @@ static void __ocfs2_resv_find_window(struct ocfs2_reservation_map *resmap, * - our window should be last in all reservations * - need to make sure we don't go past end of bitmap */ - - mlog(0, "resv start: %u resv end: %u goal: %u wanted: %u\n", - resv->r_start, ocfs2_resv_end(resv), goal, wanted); + trace_ocfs2_resv_find_window_begin(resv->r_start, ocfs2_resv_end(resv), + goal, wanted, RB_EMPTY_ROOT(root)); assert_spin_locked(&resv_lock); @@ -498,9 +496,6 @@ static void __ocfs2_resv_find_window(struct ocfs2_reservation_map *resmap, * Easiest case - empty tree. We can just take * whatever window of free bits we want. */ - - mlog(0, "Empty root\n"); - clen = ocfs2_resmap_find_free_bits(resmap, wanted, goal, resmap->m_bitmap_len - goal, &cstart, &clen); @@ -524,8 +519,6 @@ static void __ocfs2_resv_find_window(struct ocfs2_reservation_map *resmap, prev_resv = ocfs2_find_resv_lhs(resmap, goal); if (prev_resv == NULL) { - mlog(0, "Goal on LHS of leftmost window\n"); - /* * A NULL here means that the search code couldn't * find a window that starts before goal. @@ -570,13 +563,15 @@ static void __ocfs2_resv_find_window(struct ocfs2_reservation_map *resmap, next_resv = NULL; } + trace_ocfs2_resv_find_window_prev(prev_resv->r_start, + ocfs2_resv_end(prev_resv)); + prev = &prev_resv->r_node; /* Now we do a linear search for a window, starting at 'prev_rsv' */ while (1) { next = rb_next(prev); if (next) { - mlog(0, "One more resv found in linear search\n"); next_resv = rb_entry(next, struct ocfs2_alloc_reservation, r_node); @@ -585,7 +580,6 @@ static void __ocfs2_resv_find_window(struct ocfs2_reservation_map *resmap, gap_end = next_resv->r_start - 1; gap_len = gap_end - gap_start + 1; } else { - mlog(0, "No next node\n"); /* * We're at the rightmost edge of the * tree. See if a reservation between this @@ -596,6 +590,8 @@ static void __ocfs2_resv_find_window(struct ocfs2_reservation_map *resmap, gap_end = resmap->m_bitmap_len - 1; } + trace_ocfs2_resv_find_window_next(next ? next_resv->r_start: -1, + next ? ocfs2_resv_end(next_resv) : -1); /* * No need to check this gap if we have already found * a larger region of free bits. @@ -654,8 +650,9 @@ static void ocfs2_cannibalize_resv(struct ocfs2_reservation_map *resmap, lru_resv = list_first_entry(&resmap->m_lru, struct ocfs2_alloc_reservation, r_lru); - mlog(0, "lru resv: start: %u len: %u end: %u\n", lru_resv->r_start, - lru_resv->r_len, ocfs2_resv_end(lru_resv)); + trace_ocfs2_cannibalize_resv_begin(lru_resv->r_start, + lru_resv->r_len, + ocfs2_resv_end(lru_resv)); /* * Cannibalize (some or all) of the target reservation and @@ -684,10 +681,9 @@ static void ocfs2_cannibalize_resv(struct ocfs2_reservation_map *resmap, resv->r_len = shrink; } - mlog(0, "Reservation now looks like: r_start: %u r_end: %u " - "r_len: %u r_last_start: %u r_last_len: %u\n", - resv->r_start, ocfs2_resv_end(resv), resv->r_len, - resv->r_last_start, resv->r_last_len); + trace_ocfs2_cannibalize_resv_end(resv->r_start, ocfs2_resv_end(resv), + resv->r_len, resv->r_last_start, + resv->r_last_len); ocfs2_resv_insert(resmap, resv); } @@ -748,7 +744,6 @@ int ocfs2_resmap_resv_bits(struct ocfs2_reservation_map *resmap, if ((resv->r_flags & OCFS2_RESV_FLAG_TMP) || wanted < *clen) wanted = *clen; - mlog(0, "empty reservation, find new window\n"); /* * Try to get a window here. If it works, we must fall * through and test the bitmap . This avoids some @@ -757,6 +752,7 @@ int ocfs2_resmap_resv_bits(struct ocfs2_reservation_map *resmap, * that inode. */ ocfs2_resv_find_window(resmap, resv, wanted); + trace_ocfs2_resmap_resv_bits(resv->r_start, resv->r_len); } BUG_ON(ocfs2_resv_empty(resv)); @@ -813,10 +809,10 @@ void ocfs2_resmap_claimed_bits(struct ocfs2_reservation_map *resmap, spin_lock(&resv_lock); - mlog(0, "claim bits: cstart: %u cend: %u clen: %u r_start: %u " - "r_end: %u r_len: %u, r_last_start: %u r_last_len: %u\n", - cstart, cend, clen, resv->r_start, ocfs2_resv_end(resv), - resv->r_len, resv->r_last_start, resv->r_last_len); + trace_ocfs2_resmap_claimed_bits_begin(cstart, cend, clen, resv->r_start, + ocfs2_resv_end(resv), resv->r_len, + resv->r_last_start, + resv->r_last_len); BUG_ON(cstart < resv->r_start); BUG_ON(cstart > ocfs2_resv_end(resv)); @@ -833,10 +829,9 @@ void ocfs2_resmap_claimed_bits(struct ocfs2_reservation_map *resmap, if (!ocfs2_resv_empty(resv)) ocfs2_resv_mark_lru(resmap, resv); - mlog(0, "Reservation now looks like: r_start: %u r_end: %u " - "r_len: %u r_last_start: %u r_last_len: %u\n", - resv->r_start, ocfs2_resv_end(resv), resv->r_len, - resv->r_last_start, resv->r_last_len); + trace_ocfs2_resmap_claimed_bits_end(resv->r_start, ocfs2_resv_end(resv), + resv->r_len, resv->r_last_start, + resv->r_last_len); ocfs2_check_resmap(resmap); -- GitLab From 38877a43795d3a834fad827f3d6532ff649e5c45 Mon Sep 17 00:00:00 2001 From: Tao Ma Date: Wed, 23 Feb 2011 22:12:48 +0800 Subject: [PATCH 0123/2822] ocfs2: Remove mlog(0) from quota_local.c. Remove mlog(0) from fs/ocfs2/quota_local.c. Signed-off-by: Tao Ma --- fs/ocfs2/ocfs2_trace.h | 10 ++++++++++ fs/ocfs2/quota_local.c | 13 +++++++------ 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/fs/ocfs2/ocfs2_trace.h b/fs/ocfs2/ocfs2_trace.h index 1c040fcbd6e7d..dbd1812f51615 100644 --- a/fs/ocfs2/ocfs2_trace.h +++ b/fs/ocfs2/ocfs2_trace.h @@ -1925,6 +1925,16 @@ TRACE_EVENT(ocfs2_resmap_claimed_bits_end, ); /* End of trace events for fs/ocfs2/reservations.c. */ + +/* Trace events for fs/ocfs2/quota_local.c. */ + +DEFINE_OCFS2_ULL_UINT_EVENT(ocfs2_recover_local_quota_file); + +DEFINE_OCFS2_INT_EVENT(ocfs2_finish_quota_recovery); + +DEFINE_OCFS2_ULL_ULL_UINT_EVENT(olq_set_dquot); + +/* End of trace events for fs/ocfs2/quota_local.c. */ #endif /* _TRACE_OCFS2_H */ /* This part must be outside protection */ diff --git a/fs/ocfs2/quota_local.c b/fs/ocfs2/quota_local.c index 88ec4516637b2..dc8007fc92471 100644 --- a/fs/ocfs2/quota_local.c +++ b/fs/ocfs2/quota_local.c @@ -8,7 +8,6 @@ #include #include -#define MLOG_MASK_PREFIX ML_QUOTA #include #include "ocfs2_fs.h" @@ -23,6 +22,7 @@ #include "quota.h" #include "uptodate.h" #include "super.h" +#include "ocfs2_trace.h" /* Number of local quota structures per block */ static inline unsigned int ol_quota_entries_per_block(struct super_block *sb) @@ -475,7 +475,7 @@ static int ocfs2_recover_local_quota_file(struct inode *lqinode, struct ocfs2_recovery_chunk *rchunk, *next; qsize_t spacechange, inodechange; - mlog(0, "ino=%lu type=%u", (unsigned long)lqinode->i_ino, type); + trace_ocfs2_recover_local_quota_file((unsigned long)lqinode->i_ino, type); list_for_each_entry_safe(rchunk, next, &(rec->r_list[type]), rc_list) { chunk = rchunk->rc_chunk; @@ -601,7 +601,7 @@ int ocfs2_finish_quota_recovery(struct ocfs2_super *osb, for (type = 0; type < MAXQUOTAS; type++) { if (list_empty(&(rec->r_list[type]))) continue; - mlog(0, "Recovering quota in slot %d\n", slot_num); + trace_ocfs2_finish_quota_recovery(slot_num); lqinode = ocfs2_get_system_file_inode(osb, ino[type], slot_num); if (!lqinode) { status = -ENOENT; @@ -883,9 +883,10 @@ static void olq_set_dquot(struct buffer_head *bh, void *private) dqblk->dqb_inodemod = cpu_to_le64(od->dq_dquot.dq_dqb.dqb_curinodes - od->dq_originodes); spin_unlock(&dq_data_lock); - mlog(0, "Writing local dquot %u space %lld inodes %lld\n", - od->dq_dquot.dq_id, (long long)le64_to_cpu(dqblk->dqb_spacemod), - (long long)le64_to_cpu(dqblk->dqb_inodemod)); + trace_olq_set_dquot( + (unsigned long long)le64_to_cpu(dqblk->dqb_spacemod), + (unsigned long long)le64_to_cpu(dqblk->dqb_inodemod), + od->dq_dquot.dq_id); } /* Write dquot to local quota file */ -- GitLab From 1db986a839d8acf8ad809c876f1154f2e672d3af Mon Sep 17 00:00:00 2001 From: Tao Ma Date: Wed, 23 Feb 2011 22:19:12 +0800 Subject: [PATCH 0124/2822] ocfs2: Remove masklog ML_QUOTA. Remove mlog(0) from fs/ocfs2/quota_global.c and the masklog QUOTA. Signed-off-by: Tao Ma --- fs/ocfs2/cluster/masklog.c | 1 - fs/ocfs2/cluster/masklog.h | 1 - fs/ocfs2/ocfs2_trace.h | 78 ++++++++++++++++++++++++++++++++++++++ fs/ocfs2/quota_global.c | 24 ++++++------ 4 files changed, 90 insertions(+), 14 deletions(-) diff --git a/fs/ocfs2/cluster/masklog.c b/fs/ocfs2/cluster/masklog.c index 39f2a46810d13..90ed4c0ce1805 100644 --- a/fs/ocfs2/cluster/masklog.c +++ b/fs/ocfs2/cluster/masklog.c @@ -102,7 +102,6 @@ static struct mlog_attribute mlog_attrs[MLOG_MAX_BITS] = { define_mask(CONN), define_mask(QUORUM), define_mask(EXPORT), - define_mask(QUOTA), define_mask(BASTS), define_mask(CLUSTER), define_mask(ERROR), diff --git a/fs/ocfs2/cluster/masklog.h b/fs/ocfs2/cluster/masklog.h index c36b4d8d5aa97..0e65bae257d6a 100644 --- a/fs/ocfs2/cluster/masklog.h +++ b/fs/ocfs2/cluster/masklog.h @@ -104,7 +104,6 @@ #define ML_CONN 0x0000000004000000ULL /* net connection management */ #define ML_QUORUM 0x0000000008000000ULL /* net connection quorum */ #define ML_EXPORT 0x0000000010000000ULL /* ocfs2 export operations */ -#define ML_QUOTA 0x0000000040000000ULL /* ocfs2 quota operations */ #define ML_BASTS 0x0000000100000000ULL /* dlmglue asts and basts */ #define ML_CLUSTER 0x0000000400000000ULL /* cluster stack */ diff --git a/fs/ocfs2/ocfs2_trace.h b/fs/ocfs2/ocfs2_trace.h index dbd1812f51615..0f7165914401f 100644 --- a/fs/ocfs2/ocfs2_trace.h +++ b/fs/ocfs2/ocfs2_trace.h @@ -110,6 +110,25 @@ DEFINE_EVENT(ocfs2__int_int, name, \ TP_PROTO(int val1, int val2), \ TP_ARGS(val1, val2)) +DECLARE_EVENT_CLASS(ocfs2__uint_int, + TP_PROTO(unsigned int value1, int value2), + TP_ARGS(value1, value2), + TP_STRUCT__entry( + __field(unsigned int, value1) + __field(int, value2) + ), + TP_fast_assign( + __entry->value1 = value1; + __entry->value2 = value2; + ), + TP_printk("%u %d", __entry->value1, __entry->value2) +); + +#define DEFINE_OCFS2_UINT_INT_EVENT(name) \ +DEFINE_EVENT(ocfs2__uint_int, name, \ + TP_PROTO(unsigned int val1, int val2), \ + TP_ARGS(val1, val2)) + DECLARE_EVENT_CLASS(ocfs2__uint_uint, TP_PROTO(unsigned int value1, unsigned int value2), TP_ARGS(value1, value2), @@ -1935,6 +1954,65 @@ DEFINE_OCFS2_INT_EVENT(ocfs2_finish_quota_recovery); DEFINE_OCFS2_ULL_ULL_UINT_EVENT(olq_set_dquot); /* End of trace events for fs/ocfs2/quota_local.c. */ + +/* Trace events for fs/ocfs2/quota_global.c. */ + +DEFINE_OCFS2_ULL_EVENT(ocfs2_validate_quota_block); + +TRACE_EVENT(ocfs2_sync_dquot, + TP_PROTO(unsigned int dq_id, long long dqb_curspace, + long long spacechange, long long curinodes, + long long inodechange), + TP_ARGS(dq_id, dqb_curspace, spacechange, curinodes, inodechange), + TP_STRUCT__entry( + __field(unsigned int, dq_id) + __field(long long, dqb_curspace) + __field(long long, spacechange) + __field(long long, curinodes) + __field(long long, inodechange) + ), + TP_fast_assign( + __entry->dq_id = dq_id; + __entry->dqb_curspace = dqb_curspace; + __entry->spacechange = spacechange; + __entry->curinodes = curinodes; + __entry->inodechange = inodechange; + ), + TP_printk("%u %lld %lld %lld %lld", __entry->dq_id, + __entry->dqb_curspace, __entry->spacechange, + __entry->curinodes, __entry->inodechange) +); + +TRACE_EVENT(ocfs2_sync_dquot_helper, + TP_PROTO(unsigned int dq_id, unsigned int dq_type, unsigned long type, + const char *s_id), + TP_ARGS(dq_id, dq_type, type, s_id), + + TP_STRUCT__entry( + __field(unsigned int, dq_id) + __field(unsigned int, dq_type) + __field(unsigned long, type) + __string(s_id, s_id) + ), + TP_fast_assign( + __entry->dq_id = dq_id; + __entry->dq_type = dq_type; + __entry->type = type; + __assign_str(s_id, s_id); + ), + TP_printk("%u %u %lu %s", __entry->dq_id, __entry->dq_type, + __entry->type, __get_str(s_id)) +); + +DEFINE_OCFS2_UINT_INT_EVENT(ocfs2_write_dquot); + +DEFINE_OCFS2_UINT_INT_EVENT(ocfs2_release_dquot); + +DEFINE_OCFS2_UINT_INT_EVENT(ocfs2_acquire_dquot); + +DEFINE_OCFS2_UINT_INT_EVENT(ocfs2_mark_dquot_dirty); + +/* End of trace events for fs/ocfs2/quota_global.c. */ #endif /* _TRACE_OCFS2_H */ /* This part must be outside protection */ diff --git a/fs/ocfs2/quota_global.c b/fs/ocfs2/quota_global.c index 10a49e8a5f03e..64346f836c091 100644 --- a/fs/ocfs2/quota_global.c +++ b/fs/ocfs2/quota_global.c @@ -11,7 +11,6 @@ #include #include -#define MLOG_MASK_PREFIX ML_QUOTA #include #include "ocfs2_fs.h" @@ -27,6 +26,7 @@ #include "super.h" #include "buffer_head_io.h" #include "quota.h" +#include "ocfs2_trace.h" /* * Locking of quotas with OCFS2 is rather complex. Here are rules that @@ -132,8 +132,7 @@ int ocfs2_validate_quota_block(struct super_block *sb, struct buffer_head *bh) struct ocfs2_disk_dqtrailer *dqt = ocfs2_block_dqtrailer(sb->s_blocksize, bh->b_data); - mlog(0, "Validating quota block %llu\n", - (unsigned long long)bh->b_blocknr); + trace_ocfs2_validate_quota_block((unsigned long long)bh->b_blocknr); BUG_ON(!buffer_uptodate(bh)); @@ -509,9 +508,10 @@ int __ocfs2_sync_dquot(struct dquot *dquot, int freeing) olditime = dquot->dq_dqb.dqb_itime; oldbtime = dquot->dq_dqb.dqb_btime; ocfs2_global_disk2memdqb(dquot, &dqblk); - mlog(0, "Syncing global dquot %u space %lld+%lld, inodes %lld+%lld\n", - dquot->dq_id, dquot->dq_dqb.dqb_curspace, (long long)spacechange, - dquot->dq_dqb.dqb_curinodes, (long long)inodechange); + trace_ocfs2_sync_dquot(dquot->dq_id, dquot->dq_dqb.dqb_curspace, + (long long)spacechange, + dquot->dq_dqb.dqb_curinodes, + (long long)inodechange); if (!test_bit(DQ_LASTSET_B + QIF_SPACE_B, &dquot->dq_flags)) dquot->dq_dqb.dqb_curspace += spacechange; if (!test_bit(DQ_LASTSET_B + QIF_INODES_B, &dquot->dq_flags)) @@ -595,8 +595,8 @@ static int ocfs2_sync_dquot_helper(struct dquot *dquot, unsigned long type) struct ocfs2_super *osb = OCFS2_SB(sb); int status = 0; - mlog(0, "id=%u qtype=%u type=%lu device=%s\n", dquot->dq_id, - dquot->dq_type, type, sb->s_id); + trace_ocfs2_sync_dquot_helper(dquot->dq_id, dquot->dq_type, + type, sb->s_id); if (type != dquot->dq_type) goto out; status = ocfs2_lock_global_qf(oinfo, 1); @@ -647,7 +647,7 @@ static int ocfs2_write_dquot(struct dquot *dquot) struct ocfs2_super *osb = OCFS2_SB(dquot->dq_sb); int status = 0; - mlog(0, "id=%u, type=%d", dquot->dq_id, dquot->dq_type); + trace_ocfs2_write_dquot(dquot->dq_id, dquot->dq_type); handle = ocfs2_start_trans(osb, OCFS2_QWRITE_CREDITS); if (IS_ERR(handle)) { @@ -685,7 +685,7 @@ static int ocfs2_release_dquot(struct dquot *dquot) struct ocfs2_super *osb = OCFS2_SB(dquot->dq_sb); int status = 0; - mlog(0, "id=%u, type=%d", dquot->dq_id, dquot->dq_type); + trace_ocfs2_release_dquot(dquot->dq_id, dquot->dq_type); mutex_lock(&dquot->dq_lock); /* Check whether we are not racing with some other dqget() */ @@ -743,7 +743,7 @@ static int ocfs2_acquire_dquot(struct dquot *dquot) int need_alloc = ocfs2_global_qinit_alloc(sb, type); handle_t *handle; - mlog(0, "id=%u, type=%d", dquot->dq_id, type); + trace_ocfs2_acquire_dquot(dquot->dq_id, type); mutex_lock(&dquot->dq_lock); /* * We need an exclusive lock, because we're going to update use count @@ -830,7 +830,7 @@ static int ocfs2_mark_dquot_dirty(struct dquot *dquot) handle_t *handle; struct ocfs2_super *osb = OCFS2_SB(sb); - mlog(0, "id=%u, type=%d", dquot->dq_id, type); + trace_ocfs2_mark_dquot_dirty(dquot->dq_id, type); /* In case user set some limits, sync dquot immediately to global * quota file so that information propagates quicker */ -- GitLab From f32037d9bda37ca9a7a179cc1546033d374a8541 Mon Sep 17 00:00:00 2001 From: Tao Ma Date: Mon, 21 Feb 2011 11:19:02 +0800 Subject: [PATCH 0125/2822] ocfs2: remove NAMEI from symlink.c No mlog(0,...) in symlink.c, so just remove NAMEI. Signed-off-by: Tao Ma --- fs/ocfs2/symlink.c | 1 - 1 file changed, 1 deletion(-) diff --git a/fs/ocfs2/symlink.c b/fs/ocfs2/symlink.c index 5485b19ec8f2b..5d22872e2bb36 100644 --- a/fs/ocfs2/symlink.c +++ b/fs/ocfs2/symlink.c @@ -40,7 +40,6 @@ #include #include -#define MLOG_MASK_PREFIX ML_NAMEI #include #include "ocfs2.h" -- GitLab From f1088d471f8d846e817eb4d673212d18d9820c61 Mon Sep 17 00:00:00 2001 From: Tao Ma Date: Wed, 23 Feb 2011 22:30:23 +0800 Subject: [PATCH 0126/2822] ocfs2: Remove mlog(0) from fs/ocfs2/dir.c This is the 2nd step to remove the debug info of NAMEI. Signed-off-by: Tao Ma --- fs/ocfs2/dir.c | 83 +++++++++++++---------------- fs/ocfs2/ocfs2_trace.h | 116 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 153 insertions(+), 46 deletions(-) diff --git a/fs/ocfs2/dir.c b/fs/ocfs2/dir.c index 2fc6c3673beaa..0740752ca31eb 100644 --- a/fs/ocfs2/dir.c +++ b/fs/ocfs2/dir.c @@ -43,7 +43,6 @@ #include #include -#define MLOG_MASK_PREFIX ML_NAMEI #include #include "ocfs2.h" @@ -61,6 +60,7 @@ #include "super.h" #include "sysfile.h" #include "uptodate.h" +#include "ocfs2_trace.h" #include "buffer_head_io.h" @@ -400,7 +400,7 @@ static int inline ocfs2_search_dirblock(struct buffer_head *bh, } bail: - mlog(0, "ret = %d\n", ret); + trace_ocfs2_search_dirblock(ret); return ret; } @@ -445,8 +445,7 @@ static int ocfs2_validate_dir_block(struct super_block *sb, * We don't validate dirents here, that's handled * in-place when the code walks them. */ - mlog(0, "Validating dirblock %llu\n", - (unsigned long long)bh->b_blocknr); + trace_ocfs2_validate_dir_block((unsigned long long)bh->b_blocknr); BUG_ON(!buffer_uptodate(bh)); @@ -784,7 +783,7 @@ cleanup_and_exit: for (; ra_ptr < ra_max; ra_ptr++) brelse(bh_use[ra_ptr]); - mlog(0, "ret = %p\n", ret); + trace_ocfs2_find_entry_el(ret); return ret; } @@ -946,11 +945,9 @@ static int ocfs2_dx_dir_search(const char *name, int namelen, goto out; } - mlog(0, "Dir %llu: name: \"%.*s\", lookup of hash: %u.0x%x " - "returns: %llu\n", - (unsigned long long)OCFS2_I(dir)->ip_blkno, - namelen, name, hinfo->major_hash, hinfo->minor_hash, - (unsigned long long)phys); + trace_ocfs2_dx_dir_search((unsigned long long)OCFS2_I(dir)->ip_blkno, + namelen, name, hinfo->major_hash, + hinfo->minor_hash, (unsigned long long)phys); ret = ocfs2_read_dx_leaf(dir, phys, &dx_leaf_bh); if (ret) { @@ -960,9 +957,9 @@ static int ocfs2_dx_dir_search(const char *name, int namelen, dx_leaf = (struct ocfs2_dx_leaf *) dx_leaf_bh->b_data; - mlog(0, "leaf info: num_used: %d, count: %d\n", - le16_to_cpu(dx_leaf->dl_list.de_num_used), - le16_to_cpu(dx_leaf->dl_list.de_count)); + trace_ocfs2_dx_dir_search_leaf_info( + le16_to_cpu(dx_leaf->dl_list.de_num_used), + le16_to_cpu(dx_leaf->dl_list.de_count)); entry_list = &dx_leaf->dl_list; @@ -1162,8 +1159,6 @@ static int __ocfs2_delete_entry(handle_t *handle, struct inode *dir, int i, status = -ENOENT; ocfs2_journal_access_func access = ocfs2_journal_access_db; - mlog(0, "(0x%p, 0x%p, 0x%p, 0x%p)\n", handle, dir, de_del, bh); - if (OCFS2_I(dir)->ip_dyn_features & OCFS2_INLINE_DATA_FL) access = ocfs2_journal_access_di; @@ -1343,8 +1338,8 @@ static int ocfs2_delete_entry_dx(handle_t *handle, struct inode *dir, } } - mlog(0, "Dir %llu: delete entry at index: %d\n", - (unsigned long long)OCFS2_I(dir)->ip_blkno, index); + trace_ocfs2_delete_entry_dx((unsigned long long)OCFS2_I(dir)->ip_blkno, + index); ret = __ocfs2_delete_entry(handle, dir, lookup->dl_entry, leaf_bh, leaf_bh->b_data, leaf_bh->b_size); @@ -2022,8 +2017,7 @@ int ocfs2_readdir(struct file * filp, void * dirent, filldir_t filldir) struct inode *inode = filp->f_path.dentry->d_inode; int lock_level = 0; - mlog(0, "dirino=%llu\n", - (unsigned long long)OCFS2_I(inode)->ip_blkno); + trace_ocfs2_readdir((unsigned long long)OCFS2_I(inode)->ip_blkno); error = ocfs2_inode_lock_atime(inode, filp->f_vfsmnt, &lock_level); if (lock_level && error >= 0) { @@ -2064,8 +2058,8 @@ int ocfs2_find_files_on_disk(const char *name, { int status = -ENOENT; - mlog(0, "name=%.*s, blkno=%p, inode=%llu\n", namelen, name, blkno, - (unsigned long long)OCFS2_I(inode)->ip_blkno); + trace_ocfs2_find_files_on_disk(namelen, name, blkno, + (unsigned long long)OCFS2_I(inode)->ip_blkno); status = ocfs2_find_entry(name, namelen, inode, lookup); if (status) @@ -2109,8 +2103,8 @@ int ocfs2_check_dir_for_entry(struct inode *dir, int ret; struct ocfs2_dir_lookup_result lookup = { NULL, }; - mlog(0, "dir %llu, name '%.*s'\n", - (unsigned long long)OCFS2_I(dir)->ip_blkno, namelen, name); + trace_ocfs2_check_dir_for_entry( + (unsigned long long)OCFS2_I(dir)->ip_blkno, namelen, name); ret = -EEXIST; if (ocfs2_find_entry(name, namelen, dir, &lookup) == 0) @@ -2402,9 +2396,9 @@ static int ocfs2_dx_dir_attach_index(struct ocfs2_super *osb, goto out; } - mlog(0, "Dir %llu, attach new index block: %llu\n", - (unsigned long long)OCFS2_I(dir)->ip_blkno, - (unsigned long long)dr_blkno); + trace_ocfs2_dx_dir_attach_index( + (unsigned long long)OCFS2_I(dir)->ip_blkno, + (unsigned long long)dr_blkno); dx_root_bh = sb_getblk(osb->sb, dr_blkno); if (dx_root_bh == NULL) { @@ -2504,11 +2498,10 @@ static int ocfs2_dx_dir_format_cluster(struct ocfs2_super *osb, dx_leaf->dl_list.de_count = cpu_to_le16(ocfs2_dx_entries_per_leaf(osb->sb)); - mlog(0, - "Dir %llu, format dx_leaf: %llu, entry count: %u\n", - (unsigned long long)OCFS2_I(dir)->ip_blkno, - (unsigned long long)bh->b_blocknr, - le16_to_cpu(dx_leaf->dl_list.de_count)); + trace_ocfs2_dx_dir_format_cluster( + (unsigned long long)OCFS2_I(dir)->ip_blkno, + (unsigned long long)bh->b_blocknr, + le16_to_cpu(dx_leaf->dl_list.de_count)); ocfs2_journal_dirty(handle, bh); } @@ -2752,12 +2745,11 @@ static void ocfs2_dx_dir_index_root_block(struct inode *dir, ocfs2_dx_dir_name_hash(dir, de->name, de->name_len, &hinfo); - mlog(0, - "dir: %llu, major: 0x%x minor: 0x%x, index: %u, name: %.*s\n", - (unsigned long long)dir->i_ino, hinfo.major_hash, - hinfo.minor_hash, - le16_to_cpu(dx_root->dr_entries.de_num_used), - de->name_len, de->name); + trace_ocfs2_dx_dir_index_root_block( + (unsigned long long)dir->i_ino, + hinfo.major_hash, hinfo.minor_hash, + de->name_len, de->name, + le16_to_cpu(dx_root->dr_entries.de_num_used)); ocfs2_dx_entry_list_insert(&dx_root->dr_entries, &hinfo, dirent_blk); @@ -3310,8 +3302,8 @@ static int ocfs2_extend_dir(struct ocfs2_super *osb, down_write(&OCFS2_I(dir)->ip_alloc_sem); drop_alloc_sem = 1; dir_i_size = i_size_read(dir); - mlog(0, "extending dir %llu (i_size = %lld)\n", - (unsigned long long)OCFS2_I(dir)->ip_blkno, dir_i_size); + trace_ocfs2_extend_dir((unsigned long long)OCFS2_I(dir)->ip_blkno, + dir_i_size); /* dir->i_size is always block aligned. */ spin_lock(&OCFS2_I(dir)->ip_lock); @@ -3805,9 +3797,9 @@ static int ocfs2_dx_dir_rebalance(struct ocfs2_super *osb, struct inode *dir, struct ocfs2_dx_root_block *dx_root; struct ocfs2_dx_leaf *tmp_dx_leaf = NULL; - mlog(0, "DX Dir: %llu, rebalance leaf leaf_blkno: %llu insert: %u\n", - (unsigned long long)OCFS2_I(dir)->ip_blkno, - (unsigned long long)leaf_blkno, insert_hash); + trace_ocfs2_dx_dir_rebalance((unsigned long long)OCFS2_I(dir)->ip_blkno, + (unsigned long long)leaf_blkno, + insert_hash); ocfs2_init_dx_root_extent_tree(&et, INODE_CACHE(dir), dx_root_bh); @@ -3887,8 +3879,7 @@ static int ocfs2_dx_dir_rebalance(struct ocfs2_super *osb, struct inode *dir, goto out_commit; } - mlog(0, "Split leaf (%u) at %u, insert major hash is %u\n", - leaf_cpos, split_hash, insert_hash); + trace_ocfs2_dx_dir_rebalance_split(leaf_cpos, split_hash, insert_hash); /* * We have to carefully order operations here. There are items @@ -4345,8 +4336,8 @@ int ocfs2_prepare_dir_for_insert(struct ocfs2_super *osb, unsigned int blocks_wanted = 1; struct buffer_head *bh = NULL; - mlog(0, "getting ready to insert namelen %d into dir %llu\n", - namelen, (unsigned long long)OCFS2_I(dir)->ip_blkno); + trace_ocfs2_prepare_dir_for_insert( + (unsigned long long)OCFS2_I(dir)->ip_blkno, namelen); if (!namelen) { ret = -EINVAL; diff --git a/fs/ocfs2/ocfs2_trace.h b/fs/ocfs2/ocfs2_trace.h index 0f7165914401f..25e057e9d14d3 100644 --- a/fs/ocfs2/ocfs2_trace.h +++ b/fs/ocfs2/ocfs2_trace.h @@ -2013,6 +2013,122 @@ DEFINE_OCFS2_UINT_INT_EVENT(ocfs2_acquire_dquot); DEFINE_OCFS2_UINT_INT_EVENT(ocfs2_mark_dquot_dirty); /* End of trace events for fs/ocfs2/quota_global.c. */ + +/* Trace events for fs/ocfs2/dir.c. */ +DEFINE_OCFS2_INT_EVENT(ocfs2_search_dirblock); + +DEFINE_OCFS2_ULL_EVENT(ocfs2_validate_dir_block); + +DEFINE_OCFS2_POINTER_EVENT(ocfs2_find_entry_el); + +TRACE_EVENT(ocfs2_dx_dir_search, + TP_PROTO(unsigned long long ino, int namelen, const char *name, + unsigned int major_hash, unsigned int minor_hash, + unsigned long long blkno), + TP_ARGS(ino, namelen, name, major_hash, minor_hash, blkno), + TP_STRUCT__entry( + __field(unsigned long long, ino) + __field(int, namelen) + __string(name, name) + __field(unsigned int, major_hash) + __field(unsigned int,minor_hash) + __field(unsigned long long, blkno) + ), + TP_fast_assign( + __entry->ino = ino; + __entry->namelen = namelen; + __assign_str(name, name); + __entry->major_hash = major_hash; + __entry->minor_hash = minor_hash; + __entry->blkno = blkno; + ), + TP_printk("%llu %.*s %u %u %llu", __entry->ino, + __entry->namelen, __get_str(name), + __entry->major_hash, __entry->minor_hash, __entry->blkno) +); + +DEFINE_OCFS2_UINT_UINT_EVENT(ocfs2_dx_dir_search_leaf_info); + +DEFINE_OCFS2_ULL_INT_EVENT(ocfs2_delete_entry_dx); + +DEFINE_OCFS2_ULL_EVENT(ocfs2_readdir); + +TRACE_EVENT(ocfs2_find_files_on_disk, + TP_PROTO(int namelen, const char *name, void *blkno, + unsigned long long dir), + TP_ARGS(namelen, name, blkno, dir), + TP_STRUCT__entry( + __field(int, namelen) + __string(name, name) + __field(void *, blkno) + __field(unsigned long long, dir) + ), + TP_fast_assign( + __entry->namelen = namelen; + __assign_str(name, name); + __entry->blkno = blkno; + __entry->dir = dir; + ), + TP_printk("%.*s %p %llu", __entry->namelen, __get_str(name), + __entry->blkno, __entry->dir) +); + +TRACE_EVENT(ocfs2_check_dir_for_entry, + TP_PROTO(unsigned long long dir, int namelen, const char *name), + TP_ARGS(dir, namelen, name), + TP_STRUCT__entry( + __field(unsigned long long, dir) + __field(int, namelen) + __string(name, name) + ), + TP_fast_assign( + __entry->dir = dir; + __entry->namelen = namelen; + __assign_str(name, name); + ), + TP_printk("%llu %.*s", __entry->dir, + __entry->namelen, __get_str(name)) +); + +DEFINE_OCFS2_ULL_ULL_EVENT(ocfs2_dx_dir_attach_index); + +DEFINE_OCFS2_ULL_ULL_UINT_EVENT(ocfs2_dx_dir_format_cluster); + +TRACE_EVENT(ocfs2_dx_dir_index_root_block, + TP_PROTO(unsigned long long dir, + unsigned int major_hash, unsigned int minor_hash, + int namelen, const char *name, unsigned int num_used), + TP_ARGS(dir, major_hash, minor_hash, namelen, name, num_used), + TP_STRUCT__entry( + __field(unsigned long long, dir) + __field(unsigned int, major_hash) + __field(unsigned int, minor_hash) + __field(int, namelen) + __string(name, name) + __field(unsigned int, num_used) + ), + TP_fast_assign( + __entry->dir = dir; + __entry->major_hash = major_hash; + __entry->minor_hash = minor_hash; + __entry->namelen = namelen; + __assign_str(name, name); + __entry->num_used = num_used; + ), + TP_printk("%llu %x %x %.*s %u", __entry->dir, + __entry->major_hash, __entry->minor_hash, + __entry->namelen, __get_str(name), __entry->num_used) +); + +DEFINE_OCFS2_ULL_ULL_EVENT(ocfs2_extend_dir); + +DEFINE_OCFS2_ULL_ULL_UINT_EVENT(ocfs2_dx_dir_rebalance); + +DEFINE_OCFS2_UINT_UINT_UINT_EVENT(ocfs2_dx_dir_rebalance_split); + +DEFINE_OCFS2_ULL_INT_EVENT(ocfs2_prepare_dir_for_insert); + +/* End of trace events for fs/ocfs2/dir.c. */ #endif /* _TRACE_OCFS2_H */ /* This part must be outside protection */ -- GitLab From 8990e44a2bceaa68018fb13000e3a4497d78a53c Mon Sep 17 00:00:00 2001 From: Tao Ma Date: Wed, 23 Feb 2011 22:45:26 +0800 Subject: [PATCH 0127/2822] ocfs2: Remove masklog ML_NAMEI. Remove mlog(0) from fs/ocfs2/namei.c and the masklog NAMEI finally. Signed-off-by: Tao Ma --- fs/ocfs2/cluster/masklog.c | 1 - fs/ocfs2/cluster/masklog.h | 1 - fs/ocfs2/namei.c | 126 +++++++++----------- fs/ocfs2/ocfs2_trace.h | 235 +++++++++++++++++++++++++++++++++++++ 4 files changed, 292 insertions(+), 71 deletions(-) diff --git a/fs/ocfs2/cluster/masklog.c b/fs/ocfs2/cluster/masklog.c index 90ed4c0ce1805..0668eb6e05d6e 100644 --- a/fs/ocfs2/cluster/masklog.c +++ b/fs/ocfs2/cluster/masklog.c @@ -96,7 +96,6 @@ static struct mlog_attribute mlog_attrs[MLOG_MAX_BITS] = { define_mask(DLM_GLUE), define_mask(BH_IO), define_mask(UPTODATE), - define_mask(NAMEI), define_mask(VOTE), define_mask(DCACHE), define_mask(CONN), diff --git a/fs/ocfs2/cluster/masklog.h b/fs/ocfs2/cluster/masklog.h index 0e65bae257d6a..a815b55d87a7f 100644 --- a/fs/ocfs2/cluster/masklog.h +++ b/fs/ocfs2/cluster/masklog.h @@ -98,7 +98,6 @@ #define ML_DLM_GLUE 0x0000000000080000ULL /* ocfs2 dlm glue layer */ #define ML_BH_IO 0x0000000000100000ULL /* ocfs2 buffer I/O */ #define ML_UPTODATE 0x0000000000200000ULL /* ocfs2 caching sequence #'s */ -#define ML_NAMEI 0x0000000000400000ULL /* ocfs2 directory / namespace */ #define ML_VOTE 0x0000000001000000ULL /* ocfs2 node messaging */ #define ML_DCACHE 0x0000000002000000ULL /* ocfs2 dcache operations */ #define ML_CONN 0x0000000004000000ULL /* net connection management */ diff --git a/fs/ocfs2/namei.c b/fs/ocfs2/namei.c index 8a13226eb1a25..b6fa9eb2d2985 100644 --- a/fs/ocfs2/namei.c +++ b/fs/ocfs2/namei.c @@ -42,7 +42,6 @@ #include #include -#define MLOG_MASK_PREFIX ML_NAMEI #include #include "ocfs2.h" @@ -63,6 +62,7 @@ #include "uptodate.h" #include "xattr.h" #include "acl.h" +#include "ocfs2_trace.h" #include "buffer_head_io.h" @@ -106,17 +106,15 @@ static struct dentry *ocfs2_lookup(struct inode *dir, struct dentry *dentry, struct dentry *ret; struct ocfs2_inode_info *oi; - mlog(0, "(0x%p, 0x%p, '%.*s')\n", dir, dentry, - dentry->d_name.len, dentry->d_name.name); + trace_ocfs2_lookup(dir, dentry, dentry->d_name.len, + dentry->d_name.name, + (unsigned long long)OCFS2_I(dir)->ip_blkno, 0); if (dentry->d_name.len > OCFS2_MAX_FILENAME_LEN) { ret = ERR_PTR(-ENAMETOOLONG); goto bail; } - mlog(0, "find name %.*s in directory %llu\n", dentry->d_name.len, - dentry->d_name.name, (unsigned long long)OCFS2_I(dir)->ip_blkno); - status = ocfs2_inode_lock_nested(dir, NULL, 0, OI_LS_PARENT); if (status < 0) { if (status != -ENOENT) @@ -182,7 +180,7 @@ bail_unlock: bail: - mlog(0, "%p\n", ret); + trace_ocfs2_lookup_ret(ret); return ret; } @@ -235,9 +233,9 @@ static int ocfs2_mknod(struct inode *dir, sigset_t oldset; int did_block_signals = 0; - mlog(0, "(0x%p, 0x%p, %d, %lu, '%.*s')\n", dir, dentry, mode, - (unsigned long)dev, dentry->d_name.len, - dentry->d_name.name); + trace_ocfs2_mknod(dir, dentry, dentry->d_name.len, dentry->d_name.name, + (unsigned long long)OCFS2_I(dir)->ip_blkno, + (unsigned long)dev, mode); dquot_initialize(dir); @@ -354,10 +352,6 @@ static int ocfs2_mknod(struct inode *dir, goto leave; did_quota_inode = 1; - mlog(0, "(0x%p, 0x%p, %d, %lu, '%.*s')\n", dir, dentry, - inode->i_mode, (unsigned long)dev, dentry->d_name.len, - dentry->d_name.name); - /* do the real work now. */ status = ocfs2_mknod_locked(osb, dir, inode, dev, &new_fe_bh, parent_fe_bh, handle, @@ -436,9 +430,6 @@ leave: if (did_block_signals) ocfs2_unblock_signals(&oldset); - if (status == -ENOSPC) - mlog(0, "Disk is full\n"); - brelse(new_fe_bh); brelse(parent_fe_bh); kfree(si.name); @@ -617,8 +608,8 @@ static int ocfs2_mkdir(struct inode *dir, { int ret; - mlog(0, "(0x%p, 0x%p, %d, '%.*s')\n", dir, dentry, mode, - dentry->d_name.len, dentry->d_name.name); + trace_ocfs2_mkdir(dir, dentry, dentry->d_name.len, dentry->d_name.name, + OCFS2_I(dir)->ip_blkno, mode); ret = ocfs2_mknod(dir, dentry, mode | S_IFDIR, 0); if (ret) mlog_errno(ret); @@ -633,8 +624,8 @@ static int ocfs2_create(struct inode *dir, { int ret; - mlog(0, "(0x%p, 0x%p, %d, '%.*s')\n", dir, dentry, mode, - dentry->d_name.len, dentry->d_name.name); + trace_ocfs2_create(dir, dentry, dentry->d_name.len, dentry->d_name.name, + (unsigned long long)OCFS2_I(dir)->ip_blkno, mode); ret = ocfs2_mknod(dir, dentry, mode | S_IFREG, 0); if (ret) mlog_errno(ret); @@ -656,9 +647,9 @@ static int ocfs2_link(struct dentry *old_dentry, struct ocfs2_dir_lookup_result lookup = { NULL, }; sigset_t oldset; - mlog(0, "(inode=%lu, old='%.*s' new='%.*s')\n", inode->i_ino, - old_dentry->d_name.len, old_dentry->d_name.name, - dentry->d_name.len, dentry->d_name.name); + trace_ocfs2_link((unsigned long long)OCFS2_I(inode)->ip_blkno, + old_dentry->d_name.len, old_dentry->d_name.name, + dentry->d_name.len, dentry->d_name.name); if (S_ISDIR(inode->i_mode)) return -EPERM; @@ -814,19 +805,17 @@ static int ocfs2_unlink(struct inode *dir, struct ocfs2_dir_lookup_result lookup = { NULL, }; struct ocfs2_dir_lookup_result orphan_insert = { NULL, }; - mlog(0, "(0x%p, 0x%p, '%.*s')\n", dir, dentry, - dentry->d_name.len, dentry->d_name.name); + trace_ocfs2_unlink(dir, dentry, dentry->d_name.len, + dentry->d_name.name, + (unsigned long long)OCFS2_I(dir)->ip_blkno, + (unsigned long long)OCFS2_I(inode)->ip_blkno); dquot_initialize(dir); BUG_ON(dentry->d_parent->d_inode != dir); - mlog(0, "ino = %llu\n", (unsigned long long)OCFS2_I(inode)->ip_blkno); - - if (inode == osb->root_inode) { - mlog(0, "Cannot delete the root directory\n"); + if (inode == osb->root_inode) return -EPERM; - } status = ocfs2_inode_lock_nested(dir, &parent_node_bh, 1, OI_LS_PARENT); @@ -848,9 +837,10 @@ static int ocfs2_unlink(struct inode *dir, if (OCFS2_I(inode)->ip_blkno != blkno) { status = -ENOENT; - mlog(0, "ip_blkno %llu != dirent blkno %llu ip_flags = %x\n", - (unsigned long long)OCFS2_I(inode)->ip_blkno, - (unsigned long long)blkno, OCFS2_I(inode)->ip_flags); + trace_ocfs2_unlink_noent( + (unsigned long long)OCFS2_I(inode)->ip_blkno, + (unsigned long long)blkno, + OCFS2_I(inode)->ip_flags); goto leave; } @@ -981,9 +971,8 @@ static int ocfs2_double_lock(struct ocfs2_super *osb, struct buffer_head **tmpbh; struct inode *tmpinode; - mlog(0, "(inode1 = %llu, inode2 = %llu)\n", - (unsigned long long)oi1->ip_blkno, - (unsigned long long)oi2->ip_blkno); + trace_ocfs2_double_lock((unsigned long long)oi1->ip_blkno, + (unsigned long long)oi2->ip_blkno); if (*bh1) *bh1 = NULL; @@ -994,7 +983,6 @@ static int ocfs2_double_lock(struct ocfs2_super *osb, if (oi1->ip_blkno != oi2->ip_blkno) { if (oi1->ip_blkno < oi2->ip_blkno) { /* switch id1 and id2 around */ - mlog(0, "switching them around...\n"); tmpbh = bh2; bh2 = bh1; bh1 = tmpbh; @@ -1030,6 +1018,10 @@ static int ocfs2_double_lock(struct ocfs2_super *osb, mlog_errno(status); } + trace_ocfs2_double_lock_end( + (unsigned long long)OCFS2_I(inode1)->ip_blkno, + (unsigned long long)OCFS2_I(inode2)->ip_blkno); + bail: if (status) mlog_errno(status); @@ -1074,10 +1066,9 @@ static int ocfs2_rename(struct inode *old_dir, /* At some point it might be nice to break this function up a * bit. */ - mlog(0, "(0x%p, 0x%p, 0x%p, 0x%p, from='%.*s' to='%.*s')\n", - old_dir, old_dentry, new_dir, new_dentry, - old_dentry->d_name.len, old_dentry->d_name.name, - new_dentry->d_name.len, new_dentry->d_name.name); + trace_ocfs2_rename(old_dir, old_dentry, new_dir, new_dentry, + old_dentry->d_name.len, old_dentry->d_name.name, + new_dentry->d_name.len, new_dentry->d_name.name); dquot_initialize(old_dir); dquot_initialize(new_dir); @@ -1234,16 +1225,15 @@ static int ocfs2_rename(struct inode *old_dir, if (!new_inode) { status = -EACCES; - mlog(0, "We found an inode for name %.*s but VFS " - "didn't give us one.\n", new_dentry->d_name.len, - new_dentry->d_name.name); + trace_ocfs2_rename_target_exists(new_dentry->d_name.len, + new_dentry->d_name.name); goto bail; } if (OCFS2_I(new_inode)->ip_blkno != newfe_blkno) { status = -EACCES; - mlog(0, "Inode %llu and dir %llu disagree. flags = %x\n", + trace_ocfs2_rename_disagree( (unsigned long long)OCFS2_I(new_inode)->ip_blkno, (unsigned long long)newfe_blkno, OCFS2_I(new_inode)->ip_flags); @@ -1266,8 +1256,7 @@ static int ocfs2_rename(struct inode *old_dir, newfe = (struct ocfs2_dinode *) newfe_bh->b_data; - mlog(0, "aha rename over existing... new_blkno=%llu " - "newfebh=%p bhblocknr=%llu\n", + trace_ocfs2_rename_over_existing( (unsigned long long)newfe_blkno, newfe_bh, newfe_bh ? (unsigned long long)newfe_bh->b_blocknr : 0ULL); @@ -1509,9 +1498,8 @@ static int ocfs2_create_symlink_data(struct ocfs2_super *osb, * write i_size + 1 bytes. */ blocks = (bytes_left + sb->s_blocksize - 1) >> sb->s_blocksize_bits; - mlog(0, "i_blocks = %llu, i_size = %llu, blocks = %d\n", - (unsigned long long)inode->i_blocks, - i_size_read(inode), blocks); + trace_ocfs2_create_symlink_data((unsigned long long)inode->i_blocks, + i_size_read(inode), blocks); /* Sanity check -- make sure we're going to fit. */ if (bytes_left > @@ -1619,8 +1607,8 @@ static int ocfs2_symlink(struct inode *dir, sigset_t oldset; int did_block_signals = 0; - mlog(0, "(0x%p, 0x%p, symname='%s' actual='%.*s')\n", dir, - dentry, symname, dentry->d_name.len, dentry->d_name.name); + trace_ocfs2_symlink_begin(dir, dentry, symname, + dentry->d_name.len, dentry->d_name.name); dquot_initialize(dir); @@ -1722,9 +1710,10 @@ static int ocfs2_symlink(struct inode *dir, goto bail; did_quota_inode = 1; - mlog(0, "(0x%p, 0x%p, %d, '%.*s')\n", dir, dentry, - inode->i_mode, dentry->d_name.len, - dentry->d_name.name); + trace_ocfs2_symlink_create(dir, dentry, dentry->d_name.len, + dentry->d_name.name, + (unsigned long long)OCFS2_I(dir)->ip_blkno, + inode->i_mode); status = ocfs2_mknod_locked(osb, dir, inode, 0, &new_fe_bh, parent_fe_bh, handle, @@ -1870,8 +1859,7 @@ static int ocfs2_blkno_stringify(u64 blkno, char *name) goto bail; } - mlog(0, "built filename '%s' for orphan dir (len=%d)\n", name, - namelen); + trace_ocfs2_blkno_stringify(blkno, name, namelen); status = 0; bail: @@ -2007,7 +1995,8 @@ static int ocfs2_orphan_add(struct ocfs2_super *osb, struct ocfs2_dinode *orphan_fe; struct ocfs2_dinode *fe = (struct ocfs2_dinode *) fe_bh->b_data; - mlog(0, "(inode->i_ino = %lu)\n", inode->i_ino); + trace_ocfs2_orphan_add_begin( + (unsigned long long)OCFS2_I(inode)->ip_blkno); status = ocfs2_read_inode_block(orphan_dir_inode, &orphan_dir_bh); if (status < 0) { @@ -2066,8 +2055,8 @@ static int ocfs2_orphan_add(struct ocfs2_super *osb, ocfs2_journal_dirty(handle, fe_bh); - mlog(0, "Inode %llu orphaned in slot %d\n", - (unsigned long long)OCFS2_I(inode)->ip_blkno, osb->slot_num); + trace_ocfs2_orphan_add_end((unsigned long long)OCFS2_I(inode)->ip_blkno, + osb->slot_num); leave: brelse(orphan_dir_bh); @@ -2095,9 +2084,9 @@ int ocfs2_orphan_del(struct ocfs2_super *osb, goto leave; } - mlog(0, "removing '%s' from orphan dir %llu (namelen=%d)\n", - name, (unsigned long long)OCFS2_I(orphan_dir_inode)->ip_blkno, - OCFS2_ORPHAN_NAMELEN); + trace_ocfs2_orphan_del( + (unsigned long long)OCFS2_I(orphan_dir_inode)->ip_blkno, + name, OCFS2_ORPHAN_NAMELEN); /* find it's spot in the orphan directory */ status = ocfs2_find_entry(name, OCFS2_ORPHAN_NAMELEN, orphan_dir_inode, @@ -2331,9 +2320,6 @@ leave: iput(orphan_dir); } - if (status == -ENOSPC) - mlog(0, "Disk is full\n"); - if ((status < 0) && inode) { clear_nlink(inode); iput(inode); @@ -2368,8 +2354,10 @@ int ocfs2_mv_orphaned_inode_to_new(struct inode *dir, struct buffer_head *di_bh = NULL; struct ocfs2_dir_lookup_result lookup = { NULL, }; - mlog(0, "(0x%p, 0x%p, %.*s')\n", dir, dentry, - dentry->d_name.len, dentry->d_name.name); + trace_ocfs2_mv_orphaned_inode_to_new(dir, dentry, + dentry->d_name.len, dentry->d_name.name, + (unsigned long long)OCFS2_I(dir)->ip_blkno, + (unsigned long long)OCFS2_I(inode)->ip_blkno); status = ocfs2_inode_lock(dir, &parent_di_bh, 1); if (status < 0) { diff --git a/fs/ocfs2/ocfs2_trace.h b/fs/ocfs2/ocfs2_trace.h index 25e057e9d14d3..a98e52ae06ee9 100644 --- a/fs/ocfs2/ocfs2_trace.h +++ b/fs/ocfs2/ocfs2_trace.h @@ -2129,6 +2129,241 @@ DEFINE_OCFS2_UINT_UINT_UINT_EVENT(ocfs2_dx_dir_rebalance_split); DEFINE_OCFS2_ULL_INT_EVENT(ocfs2_prepare_dir_for_insert); /* End of trace events for fs/ocfs2/dir.c. */ + +/* Trace events for fs/ocfs2/namei.c. */ + +DECLARE_EVENT_CLASS(ocfs2__dentry_ops, + TP_PROTO(void *dir, void *dentry, int name_len, const char *name, + unsigned long long dir_blkno, unsigned long long extra), + TP_ARGS(dir, dentry, name_len, name, dir_blkno, extra), + TP_STRUCT__entry( + __field(void *, dir) + __field(void *, dentry) + __field(int, name_len) + __string(name, name) + __field(unsigned long long, dir_blkno) + __field(unsigned long long, extra) + ), + TP_fast_assign( + __entry->dir = dir; + __entry->dentry = dentry; + __entry->name_len = name_len; + __assign_str(name, name); + __entry->dir_blkno = dir_blkno; + __entry->extra = extra; + ), + TP_printk("%p %p %.*s %llu %llu", __entry->dir, __entry->dentry, + __entry->name_len, __get_str(name), + __entry->dir_blkno, __entry->extra) +); + +#define DEFINE_OCFS2_DENTRY_OPS(name) \ +DEFINE_EVENT(ocfs2__dentry_ops, name, \ +TP_PROTO(void *dir, void *dentry, int name_len, const char *name, \ + unsigned long long dir_blkno, unsigned long long extra), \ + TP_ARGS(dir, dentry, name_len, name, dir_blkno, extra)) + +DEFINE_OCFS2_DENTRY_OPS(ocfs2_lookup); + +DEFINE_OCFS2_DENTRY_OPS(ocfs2_mkdir); + +DEFINE_OCFS2_DENTRY_OPS(ocfs2_create); + +DEFINE_OCFS2_DENTRY_OPS(ocfs2_unlink); + +DEFINE_OCFS2_DENTRY_OPS(ocfs2_symlink_create); + +DEFINE_OCFS2_DENTRY_OPS(ocfs2_mv_orphaned_inode_to_new); + +DEFINE_OCFS2_POINTER_EVENT(ocfs2_lookup_ret); + +TRACE_EVENT(ocfs2_mknod, + TP_PROTO(void *dir, void *dentry, int name_len, const char *name, + unsigned long long dir_blkno, unsigned long dev, int mode), + TP_ARGS(dir, dentry, name_len, name, dir_blkno, dev, mode), + TP_STRUCT__entry( + __field(void *, dir) + __field(void *, dentry) + __field(int, name_len) + __string(name, name) + __field(unsigned long long, dir_blkno) + __field(unsigned long, dev) + __field(int, mode) + ), + TP_fast_assign( + __entry->dir = dir; + __entry->dentry = dentry; + __entry->name_len = name_len; + __assign_str(name, name); + __entry->dir_blkno = dir_blkno; + __entry->dev = dev; + __entry->mode = mode; + ), + TP_printk("%p %p %.*s %llu %lu %d", __entry->dir, __entry->dentry, + __entry->name_len, __get_str(name), + __entry->dir_blkno, __entry->dev, __entry->mode) +); + +TRACE_EVENT(ocfs2_link, + TP_PROTO(unsigned long long ino, int old_len, const char *old_name, + int name_len, const char *name), + TP_ARGS(ino, old_len, old_name, name_len, name), + TP_STRUCT__entry( + __field(unsigned long long, ino) + __field(int, old_len) + __string(old_name, old_name) + __field(int, name_len) + __string(name, name) + ), + TP_fast_assign( + __entry->ino = ino; + __entry->old_len = old_len; + __assign_str(old_name, old_name); + __entry->name_len = name_len; + __assign_str(name, name); + ), + TP_printk("%llu %.*s %.*s", __entry->ino, + __entry->old_len, __get_str(old_name), + __entry->name_len, __get_str(name)) +); + +DEFINE_OCFS2_ULL_ULL_UINT_EVENT(ocfs2_unlink_noent); + +DEFINE_OCFS2_ULL_ULL_EVENT(ocfs2_double_lock); + +DEFINE_OCFS2_ULL_ULL_EVENT(ocfs2_double_lock_end); + +TRACE_EVENT(ocfs2_rename, + TP_PROTO(void *old_dir, void *old_dentry, + void *new_dir, void *new_dentry, + int old_len, const char *old_name, + int new_len, const char *new_name), + TP_ARGS(old_dir, old_dentry, new_dir, new_dentry, + old_len, old_name, new_len, new_name), + TP_STRUCT__entry( + __field(void *, old_dir) + __field(void *, old_dentry) + __field(void *, new_dir) + __field(void *, new_dentry) + __field(int, old_len) + __string(old_name, old_name) + __field(int, new_len) + __string(new_name, new_name) + ), + TP_fast_assign( + __entry->old_dir = old_dir; + __entry->old_dentry = old_dentry; + __entry->new_dir = new_dir; + __entry->new_dentry = new_dentry; + __entry->old_len = old_len; + __assign_str(old_name, old_name); + __entry->new_len = new_len; + __assign_str(new_name, new_name); + ), + TP_printk("%p %p %p %p %.*s %.*s", + __entry->old_dir, __entry->old_dentry, + __entry->new_dir, __entry->new_dentry, + __entry->old_len, __get_str(old_name), + __entry->new_len, __get_str(new_name)) +); + +TRACE_EVENT(ocfs2_rename_target_exists, + TP_PROTO(int new_len, const char *new_name), + TP_ARGS(new_len, new_name), + TP_STRUCT__entry( + __field(int, new_len) + __string(new_name, new_name) + ), + TP_fast_assign( + __entry->new_len = new_len; + __assign_str(new_name, new_name); + ), + TP_printk("%.*s", __entry->new_len, __get_str(new_name)) +); + +DEFINE_OCFS2_ULL_ULL_UINT_EVENT(ocfs2_rename_disagree); + +TRACE_EVENT(ocfs2_rename_over_existing, + TP_PROTO(unsigned long long new_blkno, void *new_bh, + unsigned long long newdi_blkno), + TP_ARGS(new_blkno, new_bh, newdi_blkno), + TP_STRUCT__entry( + __field(unsigned long long, new_blkno) + __field(void *, new_bh) + __field(unsigned long long, newdi_blkno) + ), + TP_fast_assign( + __entry->new_blkno = new_blkno; + __entry->new_bh = new_bh; + __entry->newdi_blkno = newdi_blkno; + ), + TP_printk("%llu %p %llu", __entry->new_blkno, __entry->new_bh, + __entry->newdi_blkno) +); + +DEFINE_OCFS2_ULL_ULL_UINT_EVENT(ocfs2_create_symlink_data); + +TRACE_EVENT(ocfs2_symlink_begin, + TP_PROTO(void *dir, void *dentry, const char *symname, + int len, const char *name), + TP_ARGS(dir, dentry, symname, len, name), + TP_STRUCT__entry( + __field(void *, dir) + __field(void *, dentry) + __field(const char *, symname) + __field(int, len) + __string(name, name) + ), + TP_fast_assign( + __entry->dir = dir; + __entry->dentry = dentry; + __entry->symname = symname; + __entry->len = len; + __assign_str(name, name); + ), + TP_printk("%p %p %s %.*s", __entry->dir, __entry->dentry, + __entry->symname, __entry->len, __get_str(name)) +); + +TRACE_EVENT(ocfs2_blkno_stringify, + TP_PROTO(unsigned long long blkno, const char *name, int namelen), + TP_ARGS(blkno, name, namelen), + TP_STRUCT__entry( + __field(unsigned long long, blkno) + __string(name, name) + __field(int, namelen) + ), + TP_fast_assign( + __entry->blkno = blkno; + __assign_str(name, name); + __entry->namelen = namelen; + ), + TP_printk("%llu %s %d", __entry->blkno, __get_str(name), + __entry->namelen) +); + +DEFINE_OCFS2_ULL_EVENT(ocfs2_orphan_add_begin); + +DEFINE_OCFS2_ULL_UINT_EVENT(ocfs2_orphan_add_end); + +TRACE_EVENT(ocfs2_orphan_del, + TP_PROTO(unsigned long long dir, const char *name, int namelen), + TP_ARGS(dir, name, namelen), + TP_STRUCT__entry( + __field(unsigned long long, dir) + __string(name, name) + __field(int, namelen) + ), + TP_fast_assign( + __entry->dir = dir; + __assign_str(name, name); + __entry->namelen = namelen; + ), + TP_printk("%llu %s %d", __entry->dir, __get_str(name), + __entry->namelen) +); + +/* End of trace events for fs/ocfs2/namei.c. */ #endif /* _TRACE_OCFS2_H */ /* This part must be outside protection */ -- GitLab From a5b8443b34d57c6c6e3f8180d9f88890f3625a4b Mon Sep 17 00:00:00 2001 From: Tao Ma Date: Wed, 23 Feb 2011 22:51:49 +0800 Subject: [PATCH 0128/2822] ocfs2: Remove masklog ML_DCACHE. Remove mlog(0) from fs/ocfs2/dcache.c and the masklog DCACHE. Signed-off-by: Tao Ma --- fs/ocfs2/cluster/masklog.c | 1 - fs/ocfs2/cluster/masklog.h | 1 - fs/ocfs2/dcache.c | 44 ++++++++--------- fs/ocfs2/ocfs2_trace.h | 99 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 121 insertions(+), 24 deletions(-) diff --git a/fs/ocfs2/cluster/masklog.c b/fs/ocfs2/cluster/masklog.c index 0668eb6e05d6e..91df3e2571a0c 100644 --- a/fs/ocfs2/cluster/masklog.c +++ b/fs/ocfs2/cluster/masklog.c @@ -97,7 +97,6 @@ static struct mlog_attribute mlog_attrs[MLOG_MAX_BITS] = { define_mask(BH_IO), define_mask(UPTODATE), define_mask(VOTE), - define_mask(DCACHE), define_mask(CONN), define_mask(QUORUM), define_mask(EXPORT), diff --git a/fs/ocfs2/cluster/masklog.h b/fs/ocfs2/cluster/masklog.h index a815b55d87a7f..c64b0aa59e9d9 100644 --- a/fs/ocfs2/cluster/masklog.h +++ b/fs/ocfs2/cluster/masklog.h @@ -99,7 +99,6 @@ #define ML_BH_IO 0x0000000000100000ULL /* ocfs2 buffer I/O */ #define ML_UPTODATE 0x0000000000200000ULL /* ocfs2 caching sequence #'s */ #define ML_VOTE 0x0000000001000000ULL /* ocfs2 node messaging */ -#define ML_DCACHE 0x0000000002000000ULL /* ocfs2 dcache operations */ #define ML_CONN 0x0000000004000000ULL /* net connection management */ #define ML_QUORUM 0x0000000008000000ULL /* net connection quorum */ #define ML_EXPORT 0x0000000010000000ULL /* ocfs2 export operations */ diff --git a/fs/ocfs2/dcache.c b/fs/ocfs2/dcache.c index c26551c25e8e8..e5ba348183321 100644 --- a/fs/ocfs2/dcache.c +++ b/fs/ocfs2/dcache.c @@ -28,7 +28,6 @@ #include #include -#define MLOG_MASK_PREFIX ML_DCACHE #include #include "ocfs2.h" @@ -39,6 +38,7 @@ #include "file.h" #include "inode.h" #include "super.h" +#include "ocfs2_trace.h" void ocfs2_dentry_attach_gen(struct dentry *dentry) { @@ -62,8 +62,8 @@ static int ocfs2_dentry_revalidate(struct dentry *dentry, inode = dentry->d_inode; osb = OCFS2_SB(dentry->d_sb); - mlog(0, "(0x%p, '%.*s')\n", dentry, - dentry->d_name.len, dentry->d_name.name); + trace_ocfs2_dentry_revalidate(dentry, dentry->d_name.len, + dentry->d_name.name); /* For a negative dentry - * check the generation number of the parent and compare with the @@ -73,9 +73,10 @@ static int ocfs2_dentry_revalidate(struct dentry *dentry, unsigned long gen = (unsigned long) dentry->d_fsdata; unsigned long pgen = OCFS2_I(dentry->d_parent->d_inode)->ip_dir_lock_gen; - mlog(0, "negative dentry: %.*s parent gen: %lu " - "dentry gen: %lu\n", - dentry->d_name.len, dentry->d_name.name, pgen, gen); + + trace_ocfs2_dentry_revalidate_negative(dentry->d_name.len, + dentry->d_name.name, + pgen, gen); if (gen != pgen) goto bail; goto valid; @@ -90,8 +91,8 @@ static int ocfs2_dentry_revalidate(struct dentry *dentry, /* did we or someone else delete this inode? */ if (OCFS2_I(inode)->ip_flags & OCFS2_INODE_DELETED) { spin_unlock(&OCFS2_I(inode)->ip_lock); - mlog(0, "inode (%llu) deleted, returning false\n", - (unsigned long long)OCFS2_I(inode)->ip_blkno); + trace_ocfs2_dentry_revalidate_delete( + (unsigned long long)OCFS2_I(inode)->ip_blkno); goto bail; } spin_unlock(&OCFS2_I(inode)->ip_lock); @@ -101,10 +102,9 @@ static int ocfs2_dentry_revalidate(struct dentry *dentry, * inode nlink hits zero, it never goes back. */ if (inode->i_nlink == 0) { - mlog(0, "Inode %llu orphaned, returning false " - "dir = %d\n", - (unsigned long long)OCFS2_I(inode)->ip_blkno, - S_ISDIR(inode->i_mode)); + trace_ocfs2_dentry_revalidate_orphaned( + (unsigned long long)OCFS2_I(inode)->ip_blkno, + S_ISDIR(inode->i_mode)); goto bail; } @@ -113,9 +113,8 @@ static int ocfs2_dentry_revalidate(struct dentry *dentry, * redo it. */ if (!dentry->d_fsdata) { - mlog(0, "Inode %llu doesn't have dentry lock, " - "returning false\n", - (unsigned long long)OCFS2_I(inode)->ip_blkno); + trace_ocfs2_dentry_revalidate_nofsdata( + (unsigned long long)OCFS2_I(inode)->ip_blkno); goto bail; } @@ -123,7 +122,7 @@ valid: ret = 1; bail: - mlog(0, "ret = %d\n", ret); + trace_ocfs2_dentry_revalidate_ret(ret); return ret; } @@ -180,8 +179,8 @@ struct dentry *ocfs2_find_local_alias(struct inode *inode, spin_lock(&dentry->d_lock); if (ocfs2_match_dentry(dentry, parent_blkno, skip_unhashed)) { - mlog(0, "dentry found: %.*s\n", - dentry->d_name.len, dentry->d_name.name); + trace_ocfs2_find_local_alias(dentry->d_name.len, + dentry->d_name.name); dget_dlock(dentry); spin_unlock(&dentry->d_lock); @@ -239,9 +238,8 @@ int ocfs2_dentry_attach_lock(struct dentry *dentry, struct dentry *alias; struct ocfs2_dentry_lock *dl = dentry->d_fsdata; - mlog(0, "Attach \"%.*s\", parent %llu, fsdata: %p\n", - dentry->d_name.len, dentry->d_name.name, - (unsigned long long)parent_blkno, dl); + trace_ocfs2_dentry_attach_lock(dentry->d_name.len, dentry->d_name.name, + (unsigned long long)parent_blkno, dl); /* * Negative dentry. We ignore these for now. @@ -291,7 +289,9 @@ int ocfs2_dentry_attach_lock(struct dentry *dentry, (unsigned long long)parent_blkno, (unsigned long long)dl->dl_parent_blkno); - mlog(0, "Found: %s\n", dl->dl_lockres.l_name); + trace_ocfs2_dentry_attach_lock_found(dl->dl_lockres.l_name, + (unsigned long long)parent_blkno, + (unsigned long long)OCFS2_I(inode)->ip_blkno); goto out_attach; } diff --git a/fs/ocfs2/ocfs2_trace.h b/fs/ocfs2/ocfs2_trace.h index a98e52ae06ee9..6ef3a928023b4 100644 --- a/fs/ocfs2/ocfs2_trace.h +++ b/fs/ocfs2/ocfs2_trace.h @@ -2364,6 +2364,105 @@ TRACE_EVENT(ocfs2_orphan_del, ); /* End of trace events for fs/ocfs2/namei.c. */ + +/* Trace events for fs/ocfs2/dcache.c. */ + +TRACE_EVENT(ocfs2_dentry_revalidate, + TP_PROTO(void *dentry, int len, const char *name), + TP_ARGS(dentry, len, name), + TP_STRUCT__entry( + __field(void *, dentry) + __field(int, len) + __string(name, name) + ), + TP_fast_assign( + __entry->dentry = dentry; + __entry->len = len; + __assign_str(name, name); + ), + TP_printk("%p %.*s", __entry->dentry, __entry->len, __get_str(name)) +); + +TRACE_EVENT(ocfs2_dentry_revalidate_negative, + TP_PROTO(int len, const char *name, unsigned long pgen, + unsigned long gen), + TP_ARGS(len, name, pgen, gen), + TP_STRUCT__entry( + __field(int, len) + __string(name, name) + __field(unsigned long, pgen) + __field(unsigned long, gen) + ), + TP_fast_assign( + __entry->len = len; + __assign_str(name, name); + __entry->pgen = pgen; + __entry->gen = gen; + ), + TP_printk("%.*s %lu %lu", __entry->len, __get_str(name), + __entry->pgen, __entry->gen) +); + +DEFINE_OCFS2_ULL_EVENT(ocfs2_dentry_revalidate_delete); + +DEFINE_OCFS2_ULL_INT_EVENT(ocfs2_dentry_revalidate_orphaned); + +DEFINE_OCFS2_ULL_EVENT(ocfs2_dentry_revalidate_nofsdata); + +DEFINE_OCFS2_INT_EVENT(ocfs2_dentry_revalidate_ret); + +TRACE_EVENT(ocfs2_find_local_alias, + TP_PROTO(int len, const char *name), + TP_ARGS(len, name), + TP_STRUCT__entry( + __field(int, len) + __string(name, name) + ), + TP_fast_assign( + __entry->len = len; + __assign_str(name, name); + ), + TP_printk("%.*s", __entry->len, __get_str(name)) +); + +TRACE_EVENT(ocfs2_dentry_attach_lock, + TP_PROTO(int len, const char *name, + unsigned long long parent, void *fsdata), + TP_ARGS(len, name, parent, fsdata), + TP_STRUCT__entry( + __field(int, len) + __string(name, name) + __field(unsigned long long, parent) + __field(void *, fsdata) + ), + TP_fast_assign( + __entry->len = len; + __assign_str(name, name); + __entry->parent = parent; + __entry->fsdata = fsdata; + ), + TP_printk("%.*s %llu %p", __entry->len, __get_str(name), + __entry->parent, __entry->fsdata) +); + +TRACE_EVENT(ocfs2_dentry_attach_lock_found, + TP_PROTO(const char *name, unsigned long long parent, + unsigned long long ino), + TP_ARGS(name, parent, ino), + TP_STRUCT__entry( + __string(name, name) + __field(unsigned long long, parent) + __field(unsigned long long, ino) + ), + TP_fast_assign( + __assign_str(name, name); + __entry->parent = parent; + __entry->ino = ino; + ), + TP_printk("%s %llu %llu", __get_str(name), __entry->parent, __entry->ino) +); + +/* End of trace events for fs/ocfs2/dcache.c. */ #endif /* _TRACE_OCFS2_H */ /* This part must be outside protection */ -- GitLab From 781f200cb7a657339c8760984870c252701aa485 Mon Sep 17 00:00:00 2001 From: Tao Ma Date: Thu, 24 Feb 2011 13:50:19 +0800 Subject: [PATCH 0129/2822] ocfs2: Remove masklog ML_EXPORT. Remove mlog(0) from fs/ocfs2/export.c and the masklog EXPORT. Signed-off-by: Tao Ma --- fs/ocfs2/cluster/masklog.c | 1 - fs/ocfs2/cluster/masklog.h | 1 - fs/ocfs2/export.c | 47 ++++++++++------------ fs/ocfs2/ocfs2_trace.h | 82 +++++++++++++++++++++++++++++++++++++- 4 files changed, 101 insertions(+), 30 deletions(-) diff --git a/fs/ocfs2/cluster/masklog.c b/fs/ocfs2/cluster/masklog.c index 91df3e2571a0c..491923b1e0a66 100644 --- a/fs/ocfs2/cluster/masklog.c +++ b/fs/ocfs2/cluster/masklog.c @@ -99,7 +99,6 @@ static struct mlog_attribute mlog_attrs[MLOG_MAX_BITS] = { define_mask(VOTE), define_mask(CONN), define_mask(QUORUM), - define_mask(EXPORT), define_mask(BASTS), define_mask(CLUSTER), define_mask(ERROR), diff --git a/fs/ocfs2/cluster/masklog.h b/fs/ocfs2/cluster/masklog.h index c64b0aa59e9d9..c5bde37cd8b27 100644 --- a/fs/ocfs2/cluster/masklog.h +++ b/fs/ocfs2/cluster/masklog.h @@ -101,7 +101,6 @@ #define ML_VOTE 0x0000000001000000ULL /* ocfs2 node messaging */ #define ML_CONN 0x0000000004000000ULL /* net connection management */ #define ML_QUORUM 0x0000000008000000ULL /* net connection quorum */ -#define ML_EXPORT 0x0000000010000000ULL /* ocfs2 export operations */ #define ML_BASTS 0x0000000100000000ULL /* dlmglue asts and basts */ #define ML_CLUSTER 0x0000000400000000ULL /* cluster stack */ diff --git a/fs/ocfs2/export.c b/fs/ocfs2/export.c index 96d7ed7f83057..745db42528d5f 100644 --- a/fs/ocfs2/export.c +++ b/fs/ocfs2/export.c @@ -26,7 +26,6 @@ #include #include -#define MLOG_MASK_PREFIX ML_EXPORT #include #include "ocfs2.h" @@ -40,6 +39,7 @@ #include "buffer_head_io.h" #include "suballoc.h" +#include "ocfs2_trace.h" struct ocfs2_inode_handle { @@ -56,10 +56,9 @@ static struct dentry *ocfs2_get_dentry(struct super_block *sb, int status, set; struct dentry *result; - mlog(0, "(0x%p, 0x%p)\n", sb, handle); + trace_ocfs2_get_dentry_begin(sb, handle, (unsigned long long)blkno); if (blkno == 0) { - mlog(0, "nfs wants inode with blkno: 0\n"); result = ERR_PTR(-ESTALE); goto bail; } @@ -83,6 +82,7 @@ static struct dentry *ocfs2_get_dentry(struct super_block *sb, } status = ocfs2_test_inode_bit(osb, blkno, &set); + trace_ocfs2_get_dentry_test_bit(status, set); if (status < 0) { if (status == -EINVAL) { /* @@ -90,18 +90,14 @@ static struct dentry *ocfs2_get_dentry(struct super_block *sb, * as an inode, we return -ESTALE to be * nice */ - mlog(0, "test inode bit failed %d\n", status); status = -ESTALE; - } else { + } else mlog(ML_ERROR, "test inode bit failed %d\n", status); - } goto unlock_nfs_sync; } /* If the inode allocator bit is clear, this inode must be stale */ if (!set) { - mlog(0, "inode %llu suballoc bit is clear\n", - (unsigned long long)blkno); status = -ESTALE; goto unlock_nfs_sync; } @@ -114,8 +110,8 @@ unlock_nfs_sync: check_err: if (status < 0) { if (status == -ESTALE) { - mlog(0, "stale inode ino: %llu generation: %u\n", - (unsigned long long)blkno, handle->ih_generation); + trace_ocfs2_get_dentry_stale((unsigned long long)blkno, + handle->ih_generation); } result = ERR_PTR(status); goto bail; @@ -130,8 +126,9 @@ check_err: check_gen: if (handle->ih_generation != inode->i_generation) { iput(inode); - mlog(0, "stale inode ino: %llu generation: %u\n", - (unsigned long long)blkno, handle->ih_generation); + trace_ocfs2_get_dentry_generation((unsigned long long)blkno, + handle->ih_generation, + inode->i_generation); result = ERR_PTR(-ESTALE); goto bail; } @@ -141,7 +138,7 @@ check_gen: mlog_errno(PTR_ERR(result)); bail: - mlog(0, "result = %p\n", result); + trace_ocfs2_get_dentry_end(result); return result; } @@ -152,11 +149,8 @@ static struct dentry *ocfs2_get_parent(struct dentry *child) struct dentry *parent; struct inode *dir = child->d_inode; - mlog(0, "(0x%p, '%.*s')\n", child, - child->d_name.len, child->d_name.name); - - mlog(0, "find parent of directory %llu\n", - (unsigned long long)OCFS2_I(dir)->ip_blkno); + trace_ocfs2_get_parent(child, child->d_name.len, child->d_name.name, + (unsigned long long)OCFS2_I(dir)->ip_blkno); status = ocfs2_inode_lock(dir, NULL, 0); if (status < 0) { @@ -178,7 +172,7 @@ bail_unlock: ocfs2_inode_unlock(dir, 0); bail: - mlog(0, "parent %p\n", parent); + trace_ocfs2_get_parent_end(parent); return parent; } @@ -193,9 +187,9 @@ static int ocfs2_encode_fh(struct dentry *dentry, u32 *fh_in, int *max_len, u32 generation; __le32 *fh = (__force __le32 *) fh_in; - mlog(0, "(0x%p, '%.*s', 0x%p, %d, %d)\n", dentry, - dentry->d_name.len, dentry->d_name.name, - fh, len, connectable); + trace_ocfs2_encode_fh_begin(dentry, dentry->d_name.len, + dentry->d_name.name, + fh, len, connectable); if (connectable && (len < 6)) { *max_len = 6; @@ -210,8 +204,7 @@ static int ocfs2_encode_fh(struct dentry *dentry, u32 *fh_in, int *max_len, blkno = OCFS2_I(inode)->ip_blkno; generation = inode->i_generation; - mlog(0, "Encoding fh: blkno: %llu, generation: %u\n", - (unsigned long long)blkno, generation); + trace_ocfs2_encode_fh_self((unsigned long long)blkno, generation); len = 3; fh[0] = cpu_to_le32((u32)(blkno >> 32)); @@ -236,14 +229,14 @@ static int ocfs2_encode_fh(struct dentry *dentry, u32 *fh_in, int *max_len, len = 6; type = 2; - mlog(0, "Encoding parent: blkno: %llu, generation: %u\n", - (unsigned long long)blkno, generation); + trace_ocfs2_encode_fh_parent((unsigned long long)blkno, + generation); } *max_len = len; bail: - mlog(0, "type = %d\n", type); + trace_ocfs2_encode_fh_type(type); return type; } diff --git a/fs/ocfs2/ocfs2_trace.h b/fs/ocfs2/ocfs2_trace.h index 6ef3a928023b4..48839054d5afe 100644 --- a/fs/ocfs2/ocfs2_trace.h +++ b/fs/ocfs2/ocfs2_trace.h @@ -2461,8 +2461,88 @@ TRACE_EVENT(ocfs2_dentry_attach_lock_found, ), TP_printk("%s %llu %llu", __get_str(name), __entry->parent, __entry->ino) ); - /* End of trace events for fs/ocfs2/dcache.c. */ + +/* Trace events for fs/ocfs2/export.c. */ + +TRACE_EVENT(ocfs2_get_dentry_begin, + TP_PROTO(void *sb, void *handle, unsigned long long blkno), + TP_ARGS(sb, handle, blkno), + TP_STRUCT__entry( + __field(void *, sb) + __field(void *, handle) + __field(unsigned long long, blkno) + ), + TP_fast_assign( + __entry->sb = sb; + __entry->handle = handle; + __entry->blkno = blkno; + ), + TP_printk("%p %p %llu", __entry->sb, __entry->handle, __entry->blkno) +); + +DEFINE_OCFS2_INT_INT_EVENT(ocfs2_get_dentry_test_bit); + +DEFINE_OCFS2_ULL_UINT_EVENT(ocfs2_get_dentry_stale); + +DEFINE_OCFS2_ULL_UINT_UINT_EVENT(ocfs2_get_dentry_generation); + +DEFINE_OCFS2_POINTER_EVENT(ocfs2_get_dentry_end); + +TRACE_EVENT(ocfs2_get_parent, + TP_PROTO(void *child, int len, const char *name, + unsigned long long ino), + TP_ARGS(child, len, name, ino), + TP_STRUCT__entry( + __field(void *, child) + __field(int, len) + __string(name, name) + __field(unsigned long long, ino) + ), + TP_fast_assign( + __entry->child = child; + __entry->len = len; + __assign_str(name, name); + __entry->ino = ino; + ), + TP_printk("%p %.*s %llu", __entry->child, __entry->len, + __get_str(name), __entry->ino) +); + +DEFINE_OCFS2_POINTER_EVENT(ocfs2_get_parent_end); + +TRACE_EVENT(ocfs2_encode_fh_begin, + TP_PROTO(void *dentry, int name_len, const char *name, + void *fh, int len, int connectable), + TP_ARGS(dentry, name_len, name, fh, len, connectable), + TP_STRUCT__entry( + __field(void *, dentry) + __field(int, name_len) + __string(name, name) + __field(void *, fh) + __field(int, len) + __field(int, connectable) + ), + TP_fast_assign( + __entry->dentry = dentry; + __entry->name_len = name_len; + __assign_str(name, name); + __entry->fh = fh; + __entry->len = len; + __entry->connectable = connectable; + ), + TP_printk("%p %.*s %p %d %d", __entry->dentry, __entry->name_len, + __get_str(name), __entry->fh, __entry->len, + __entry->connectable) +); + +DEFINE_OCFS2_ULL_UINT_EVENT(ocfs2_encode_fh_self); + +DEFINE_OCFS2_ULL_UINT_EVENT(ocfs2_encode_fh_parent); + +DEFINE_OCFS2_INT_EVENT(ocfs2_encode_fh_type); + +/* End of trace events for fs/ocfs2/export.c. */ #endif /* _TRACE_OCFS2_H */ /* This part must be outside protection */ -- GitLab From b41079504c786eb226e7e1e3dc5cc1f37fbd1c2b Mon Sep 17 00:00:00 2001 From: Tao Ma Date: Thu, 24 Feb 2011 14:15:35 +0800 Subject: [PATCH 0130/2822] ocfs2: Remove masklog ML_JOURNAL. Remove mlog(0) from fs/ocfs2/journal.c and the masklog JOURNAL. Signed-off-by: Tao Ma --- fs/ocfs2/cluster/masklog.c | 1 - fs/ocfs2/cluster/masklog.h | 1 - fs/ocfs2/journal.c | 130 +++++++++++++++---------------------- fs/ocfs2/ocfs2_trace.h | 99 ++++++++++++++++++++++++++++ 4 files changed, 153 insertions(+), 78 deletions(-) diff --git a/fs/ocfs2/cluster/masklog.c b/fs/ocfs2/cluster/masklog.c index 491923b1e0a66..b64fb67c29995 100644 --- a/fs/ocfs2/cluster/masklog.c +++ b/fs/ocfs2/cluster/masklog.c @@ -92,7 +92,6 @@ static struct mlog_attribute mlog_attrs[MLOG_MAX_BITS] = { define_mask(DLM_MASTER), define_mask(DLM_RECOVERY), define_mask(AIO), - define_mask(JOURNAL), define_mask(DLM_GLUE), define_mask(BH_IO), define_mask(UPTODATE), diff --git a/fs/ocfs2/cluster/masklog.h b/fs/ocfs2/cluster/masklog.h index c5bde37cd8b27..1340ef0ae3e1d 100644 --- a/fs/ocfs2/cluster/masklog.h +++ b/fs/ocfs2/cluster/masklog.h @@ -94,7 +94,6 @@ #define ML_DLM_MASTER 0x0000000000000800ULL /* dlm master functions */ #define ML_DLM_RECOVERY 0x0000000000001000ULL /* dlm master functions */ #define ML_AIO 0x0000000000002000ULL /* ocfs2 aio read and write */ -#define ML_JOURNAL 0x0000000000004000ULL /* ocfs2 journalling functions */ #define ML_DLM_GLUE 0x0000000000080000ULL /* ocfs2 dlm glue layer */ #define ML_BH_IO 0x0000000000100000ULL /* ocfs2 buffer I/O */ #define ML_UPTODATE 0x0000000000200000ULL /* ocfs2 caching sequence #'s */ diff --git a/fs/ocfs2/journal.c b/fs/ocfs2/journal.c index 956509167bf57..dcc2d9327150a 100644 --- a/fs/ocfs2/journal.c +++ b/fs/ocfs2/journal.c @@ -31,7 +31,6 @@ #include #include -#define MLOG_MASK_PREFIX ML_JOURNAL #include #include "ocfs2.h" @@ -52,6 +51,7 @@ #include "quota.h" #include "buffer_head_io.h" +#include "ocfs2_trace.h" DEFINE_SPINLOCK(trans_inc_lock); @@ -308,9 +308,10 @@ static int ocfs2_commit_cache(struct ocfs2_super *osb) /* Flush all pending commits and checkpoint the journal. */ down_write(&journal->j_trans_barrier); - if (atomic_read(&journal->j_num_trans) == 0) { + flushed = atomic_read(&journal->j_num_trans); + trace_ocfs2_commit_cache_begin(flushed); + if (flushed == 0) { up_write(&journal->j_trans_barrier); - mlog(0, "No transactions for me to flush!\n"); goto finally; } @@ -329,8 +330,7 @@ static int ocfs2_commit_cache(struct ocfs2_super *osb) atomic_set(&journal->j_num_trans, 0); up_write(&journal->j_trans_barrier); - mlog(0, "commit_thread: flushed transaction %lu (%u handles)\n", - journal->j_trans_id, flushed); + trace_ocfs2_commit_cache_end(journal->j_trans_id, flushed); ocfs2_wake_downconvert_thread(osb); wake_up(&journal->j_checkpointed); @@ -423,7 +423,7 @@ int ocfs2_extend_trans(handle_t *handle, int nblocks) old_nblocks = handle->h_buffer_credits; - mlog(0, "Trying to extend transaction by %d blocks\n", nblocks); + trace_ocfs2_extend_trans(old_nblocks, nblocks); #ifdef CONFIG_OCFS2_DEBUG_FS status = 1; @@ -436,9 +436,7 @@ int ocfs2_extend_trans(handle_t *handle, int nblocks) #endif if (status > 0) { - mlog(0, - "jbd2_journal_extend failed, trying " - "jbd2_journal_restart\n"); + trace_ocfs2_extend_trans_restart(old_nblocks + nblocks); status = jbd2_journal_restart(handle, old_nblocks + nblocks); if (status < 0) { @@ -616,12 +614,9 @@ static int __ocfs2_journal_access(handle_t *handle, BUG_ON(!handle); BUG_ON(!bh); - mlog(0, "bh->b_blocknr=%llu, type=%d (\"%s\"), bh->b_size = %zu\n", - (unsigned long long)bh->b_blocknr, type, - (type == OCFS2_JOURNAL_ACCESS_CREATE) ? - "OCFS2_JOURNAL_ACCESS_CREATE" : - "OCFS2_JOURNAL_ACCESS_WRITE", - bh->b_size); + trace_ocfs2_journal_access( + (unsigned long long)ocfs2_metadata_cache_owner(ci), + (unsigned long long)bh->b_blocknr, type, bh->b_size); /* we can safely remove this assertion after testing. */ if (!buffer_uptodate(bh)) { @@ -730,8 +725,7 @@ void ocfs2_journal_dirty(handle_t *handle, struct buffer_head *bh) { int status; - mlog(0, "(bh->b_blocknr=%llu)\n", - (unsigned long long)bh->b_blocknr); + trace_ocfs2_journal_dirty((unsigned long long)bh->b_blocknr); status = jbd2_journal_dirty_metadata(handle, bh); BUG_ON(status); @@ -809,10 +803,9 @@ int ocfs2_journal_init(struct ocfs2_journal *journal, int *dirty) goto done; } - mlog(0, "inode->i_size = %lld\n", inode->i_size); - mlog(0, "inode->i_blocks = %llu\n", - (unsigned long long)inode->i_blocks); - mlog(0, "inode->ip_clusters = %u\n", OCFS2_I(inode)->ip_clusters); + trace_ocfs2_journal_init(inode->i_size, + (unsigned long long)inode->i_blocks, + OCFS2_I(inode)->ip_clusters); /* call the kernels journal init function now */ j_journal = jbd2_journal_init_inode(inode); @@ -822,8 +815,7 @@ int ocfs2_journal_init(struct ocfs2_journal *journal, int *dirty) goto done; } - mlog(0, "Returned from jbd2_journal_init_inode\n"); - mlog(0, "j_journal->j_maxlen = %u\n", j_journal->j_maxlen); + trace_ocfs2_journal_init_maxlen(j_journal->j_maxlen); *dirty = (le32_to_cpu(di->id1.journal1.ij_flags) & OCFS2_JOURNAL_DIRTY_FL); @@ -922,10 +914,7 @@ void ocfs2_journal_shutdown(struct ocfs2_super *osb) BUG(); num_running_trans = atomic_read(&(osb->journal->j_num_trans)); - if (num_running_trans > 0) - mlog(0, "Shutting down journal: must wait on %d " - "running transactions!\n", - num_running_trans); + trace_ocfs2_journal_shutdown(num_running_trans); /* Do a commit_cache here. It will flush our journal, *and* * release any locks that are still held. @@ -938,7 +927,7 @@ void ocfs2_journal_shutdown(struct ocfs2_super *osb) * completely destroy the journal. */ if (osb->commit_task) { /* Wait for the commit thread */ - mlog(0, "Waiting for ocfs2commit to exit....\n"); + trace_ocfs2_journal_shutdown_wait(osb->commit_task); kthread_stop(osb->commit_task); osb->commit_task = NULL; } @@ -1158,7 +1147,7 @@ struct ocfs2_la_recovery_item { */ void ocfs2_complete_recovery(struct work_struct *work) { - int ret; + int ret = 0; struct ocfs2_journal *journal = container_of(work, struct ocfs2_journal, j_recovery_work); struct ocfs2_super *osb = journal->j_osb; @@ -1167,7 +1156,8 @@ void ocfs2_complete_recovery(struct work_struct *work) struct ocfs2_quota_recovery *qrec; LIST_HEAD(tmp_la_list); - mlog(0, "completing recovery from keventd\n"); + trace_ocfs2_complete_recovery( + (unsigned long long)OCFS2_I(journal->j_inode)->ip_blkno); spin_lock(&journal->j_lock); list_splice_init(&journal->j_la_cleanups, &tmp_la_list); @@ -1176,15 +1166,18 @@ void ocfs2_complete_recovery(struct work_struct *work) list_for_each_entry_safe(item, n, &tmp_la_list, lri_list) { list_del_init(&item->lri_list); - mlog(0, "Complete recovery for slot %d\n", item->lri_slot); - ocfs2_wait_on_quotas(osb); la_dinode = item->lri_la_dinode; - if (la_dinode) { - mlog(0, "Clean up local alloc %llu\n", - (unsigned long long)le64_to_cpu(la_dinode->i_blkno)); + tl_dinode = item->lri_tl_dinode; + qrec = item->lri_qrec; + trace_ocfs2_complete_recovery_slot(item->lri_slot, + la_dinode ? le64_to_cpu(la_dinode->i_blkno) : 0, + tl_dinode ? le64_to_cpu(tl_dinode->i_blkno) : 0, + qrec); + + if (la_dinode) { ret = ocfs2_complete_local_alloc_recovery(osb, la_dinode); if (ret < 0) @@ -1193,11 +1186,7 @@ void ocfs2_complete_recovery(struct work_struct *work) kfree(la_dinode); } - tl_dinode = item->lri_tl_dinode; if (tl_dinode) { - mlog(0, "Clean up truncate log %llu\n", - (unsigned long long)le64_to_cpu(tl_dinode->i_blkno)); - ret = ocfs2_complete_truncate_log_recovery(osb, tl_dinode); if (ret < 0) @@ -1210,9 +1199,7 @@ void ocfs2_complete_recovery(struct work_struct *work) if (ret < 0) mlog_errno(ret); - qrec = item->lri_qrec; if (qrec) { - mlog(0, "Recovering quota files"); ret = ocfs2_finish_quota_recovery(osb, qrec, item->lri_slot); if (ret < 0) @@ -1223,7 +1210,7 @@ void ocfs2_complete_recovery(struct work_struct *work) kfree(item); } - mlog(0, "Recovery completion\n"); + trace_ocfs2_complete_recovery_end(ret); } /* NOTE: This function always eats your references to la_dinode and @@ -1340,15 +1327,12 @@ restart: * clear it until ocfs2_recover_node() has succeeded. */ node_num = rm->rm_entries[0]; spin_unlock(&osb->osb_lock); - mlog(0, "checking node %d\n", node_num); slot_num = ocfs2_node_num_to_slot(osb, node_num); + trace_ocfs2_recovery_thread_node(node_num, slot_num); if (slot_num == -ENOENT) { status = 0; - mlog(0, "no slot for this node, so no recovery" - "required.\n"); goto skip_recovery; } - mlog(0, "node %d was using slot %d\n", node_num, slot_num); /* It is a bit subtle with quota recovery. We cannot do it * immediately because we have to obtain cluster locks from @@ -1375,7 +1359,7 @@ skip_recovery: spin_lock(&osb->osb_lock); } spin_unlock(&osb->osb_lock); - mlog(0, "All nodes recovered\n"); + trace_ocfs2_recovery_thread_end(status); /* Refresh all journal recovery generations from disk */ status = ocfs2_check_journals_nolocks(osb); @@ -1428,19 +1412,15 @@ bail: void ocfs2_recovery_thread(struct ocfs2_super *osb, int node_num) { - mlog(0, "(node_num=%d, osb->node_num = %d)\n", - node_num, osb->node_num); - mutex_lock(&osb->recovery_lock); - if (osb->disable_recovery) - goto out; - /* People waiting on recovery will wait on - * the recovery map to empty. */ - if (ocfs2_recovery_map_set(osb, node_num)) - mlog(0, "node %d already in recovery map.\n", node_num); + trace_ocfs2_recovery_thread(node_num, osb->node_num, + osb->disable_recovery, osb->recovery_thread_task, + osb->disable_recovery ? + -1 : ocfs2_recovery_map_set(osb, node_num)); - mlog(0, "starting recovery thread...\n"); + if (osb->disable_recovery) + goto out; if (osb->recovery_thread_task) goto out; @@ -1528,7 +1508,7 @@ static int ocfs2_replay_journal(struct ocfs2_super *osb, * If not, it needs recovery. */ if (osb->slot_recovery_generations[slot_num] != slot_reco_gen) { - mlog(0, "Slot %u already recovered (old/new=%u/%u)\n", slot_num, + trace_ocfs2_replay_journal_recovered(slot_num, osb->slot_recovery_generations[slot_num], slot_reco_gen); osb->slot_recovery_generations[slot_num] = slot_reco_gen; status = -EBUSY; @@ -1539,7 +1519,7 @@ static int ocfs2_replay_journal(struct ocfs2_super *osb, status = ocfs2_inode_lock_full(inode, &bh, 1, OCFS2_META_LOCK_RECOVERY); if (status < 0) { - mlog(0, "status returned from ocfs2_inode_lock=%d\n", status); + trace_ocfs2_replay_journal_lock_err(status); if (status != -ERESTARTSYS) mlog(ML_ERROR, "Could not lock journal!\n"); goto done; @@ -1552,7 +1532,7 @@ static int ocfs2_replay_journal(struct ocfs2_super *osb, slot_reco_gen = ocfs2_get_recovery_generation(fe); if (!(flags & OCFS2_JOURNAL_DIRTY_FL)) { - mlog(0, "No recovery required for node %d\n", node_num); + trace_ocfs2_replay_journal_skip(node_num); /* Refresh recovery generation for the slot */ osb->slot_recovery_generations[slot_num] = slot_reco_gen; goto done; @@ -1573,7 +1553,6 @@ static int ocfs2_replay_journal(struct ocfs2_super *osb, goto done; } - mlog(0, "calling journal_init_inode\n"); journal = jbd2_journal_init_inode(inode); if (journal == NULL) { mlog(ML_ERROR, "Linux journal layer error\n"); @@ -1593,7 +1572,6 @@ static int ocfs2_replay_journal(struct ocfs2_super *osb, ocfs2_clear_journal_error(osb->sb, journal, slot_num); /* wipe the journal */ - mlog(0, "flushing the journal.\n"); jbd2_journal_lock_updates(journal); status = jbd2_journal_flush(journal); jbd2_journal_unlock_updates(journal); @@ -1652,8 +1630,7 @@ static int ocfs2_recover_node(struct ocfs2_super *osb, struct ocfs2_dinode *la_copy = NULL; struct ocfs2_dinode *tl_copy = NULL; - mlog(0, "(node_num=%d, slot_num=%d, osb->node_num = %d)\n", - node_num, slot_num, osb->node_num); + trace_ocfs2_recover_node(node_num, slot_num, osb->node_num); /* Should not ever be called to recover ourselves -- in that * case we should've called ocfs2_journal_load instead. */ @@ -1662,9 +1639,7 @@ static int ocfs2_recover_node(struct ocfs2_super *osb, status = ocfs2_replay_journal(osb, node_num, slot_num); if (status < 0) { if (status == -EBUSY) { - mlog(0, "Skipping recovery for slot %u (node %u) " - "as another node has recovered it\n", slot_num, - node_num); + trace_ocfs2_recover_node_skip(slot_num, node_num); status = 0; goto done; } @@ -1771,8 +1746,8 @@ int ocfs2_mark_dead_nodes(struct ocfs2_super *osb) spin_lock(&osb->osb_lock); osb->slot_recovery_generations[i] = gen; - mlog(0, "Slot %u recovery generation is %u\n", i, - osb->slot_recovery_generations[i]); + trace_ocfs2_mark_dead_nodes(i, + osb->slot_recovery_generations[i]); if (i == osb->slot_num) { spin_unlock(&osb->osb_lock); @@ -1846,11 +1821,12 @@ void ocfs2_queue_orphan_scan(struct ocfs2_super *osb) os = &osb->osb_orphan_scan; - mlog(0, "Begin orphan scan\n"); - if (atomic_read(&os->os_state) == ORPHAN_SCAN_INACTIVE) goto out; + trace_ocfs2_queue_orphan_scan_begin(os->os_count, os->os_seqno, + atomic_read(&os->os_state)); + status = ocfs2_orphan_scan_lock(osb, &seqno); if (status < 0) { if (status != -EAGAIN) @@ -1880,7 +1856,8 @@ void ocfs2_queue_orphan_scan(struct ocfs2_super *osb) unlock: ocfs2_orphan_scan_unlock(osb, seqno); out: - mlog(0, "Orphan scan completed\n"); + trace_ocfs2_queue_orphan_scan_end(os->os_count, os->os_seqno, + atomic_read(&os->os_state)); return; } @@ -1964,8 +1941,7 @@ static int ocfs2_orphan_filldir(void *priv, const char *name, int name_len, if (IS_ERR(iter)) return 0; - mlog(0, "queue orphan %llu\n", - (unsigned long long)OCFS2_I(iter)->ip_blkno); + trace_ocfs2_orphan_filldir((unsigned long long)OCFS2_I(iter)->ip_blkno); /* No locking is required for the next_orphan queue as there * is only ever a single process doing orphan recovery. */ OCFS2_I(iter)->ip_next_orphan = p->head; @@ -2081,7 +2057,7 @@ static int ocfs2_recover_orphans(struct ocfs2_super *osb, struct inode *iter; struct ocfs2_inode_info *oi; - mlog(0, "Recover inodes from orphan dir in slot %d\n", slot); + trace_ocfs2_recover_orphans(slot); ocfs2_mark_recovering_orphan_dir(osb, slot); ret = ocfs2_queue_orphans(osb, slot, &inode); @@ -2094,7 +2070,8 @@ static int ocfs2_recover_orphans(struct ocfs2_super *osb, while (inode) { oi = OCFS2_I(inode); - mlog(0, "iput orphan %llu\n", (unsigned long long)oi->ip_blkno); + trace_ocfs2_recover_orphans_iput( + (unsigned long long)oi->ip_blkno); iter = oi->ip_next_orphan; @@ -2132,6 +2109,7 @@ static int __ocfs2_wait_on_mount(struct ocfs2_super *osb, int quota) * MOUNTED flag, but this is set right before * dismount_volume() so we can trust it. */ if (atomic_read(&osb->vol_state) == VOLUME_DISABLED) { + trace_ocfs2_wait_on_mount(VOLUME_DISABLED); mlog(0, "mount error, exiting!\n"); return -EBUSY; } diff --git a/fs/ocfs2/ocfs2_trace.h b/fs/ocfs2/ocfs2_trace.h index 48839054d5afe..9d1ca49aa98b4 100644 --- a/fs/ocfs2/ocfs2_trace.h +++ b/fs/ocfs2/ocfs2_trace.h @@ -2543,6 +2543,105 @@ DEFINE_OCFS2_ULL_UINT_EVENT(ocfs2_encode_fh_parent); DEFINE_OCFS2_INT_EVENT(ocfs2_encode_fh_type); /* End of trace events for fs/ocfs2/export.c. */ + +/* Trace events for fs/ocfs2/journal.c. */ + +DEFINE_OCFS2_UINT_EVENT(ocfs2_commit_cache_begin); + +DEFINE_OCFS2_ULL_UINT_EVENT(ocfs2_commit_cache_end); + +DEFINE_OCFS2_INT_INT_EVENT(ocfs2_extend_trans); + +DEFINE_OCFS2_INT_EVENT(ocfs2_extend_trans_restart); + +DEFINE_OCFS2_ULL_ULL_UINT_UINT_EVENT(ocfs2_journal_access); + +DEFINE_OCFS2_ULL_EVENT(ocfs2_journal_dirty); + +DEFINE_OCFS2_ULL_ULL_UINT_EVENT(ocfs2_journal_init); + +DEFINE_OCFS2_UINT_EVENT(ocfs2_journal_init_maxlen); + +DEFINE_OCFS2_INT_EVENT(ocfs2_journal_shutdown); + +DEFINE_OCFS2_POINTER_EVENT(ocfs2_journal_shutdown_wait); + +DEFINE_OCFS2_ULL_EVENT(ocfs2_complete_recovery); + +DEFINE_OCFS2_INT_EVENT(ocfs2_complete_recovery_end); + +TRACE_EVENT(ocfs2_complete_recovery_slot, + TP_PROTO(int slot, unsigned long long la_ino, + unsigned long long tl_ino, void *qrec), + TP_ARGS(slot, la_ino, tl_ino, qrec), + TP_STRUCT__entry( + __field(int, slot) + __field(unsigned long long, la_ino) + __field(unsigned long long, tl_ino) + __field(void *, qrec) + ), + TP_fast_assign( + __entry->slot = slot; + __entry->la_ino = la_ino; + __entry->tl_ino = tl_ino; + __entry->qrec = qrec; + ), + TP_printk("%d %llu %llu %p", __entry->slot, __entry->la_ino, + __entry->tl_ino, __entry->qrec) +); + +DEFINE_OCFS2_INT_INT_EVENT(ocfs2_recovery_thread_node); + +DEFINE_OCFS2_INT_EVENT(ocfs2_recovery_thread_end); + +TRACE_EVENT(ocfs2_recovery_thread, + TP_PROTO(int node_num, int osb_node_num, int disable, + void *recovery_thread, int map_set), + TP_ARGS(node_num, osb_node_num, disable, recovery_thread, map_set), + TP_STRUCT__entry( + __field(int, node_num) + __field(int, osb_node_num) + __field(int,disable) + __field(void *, recovery_thread) + __field(int,map_set) + ), + TP_fast_assign( + __entry->node_num = node_num; + __entry->osb_node_num = osb_node_num; + __entry->disable = disable; + __entry->recovery_thread = recovery_thread; + __entry->map_set = map_set; + ), + TP_printk("%d %d %d %p %d", __entry->node_num, + __entry->osb_node_num, __entry->disable, + __entry->recovery_thread, __entry->map_set) +); + +DEFINE_OCFS2_UINT_UINT_UINT_EVENT(ocfs2_replay_journal_recovered); + +DEFINE_OCFS2_INT_EVENT(ocfs2_replay_journal_lock_err); + +DEFINE_OCFS2_INT_EVENT(ocfs2_replay_journal_skip); + +DEFINE_OCFS2_UINT_UINT_UINT_EVENT(ocfs2_recover_node); + +DEFINE_OCFS2_UINT_UINT_EVENT(ocfs2_recover_node_skip); + +DEFINE_OCFS2_UINT_UINT_EVENT(ocfs2_mark_dead_nodes); + +DEFINE_OCFS2_UINT_UINT_UINT_EVENT(ocfs2_queue_orphan_scan_begin); + +DEFINE_OCFS2_UINT_UINT_UINT_EVENT(ocfs2_queue_orphan_scan_end); + +DEFINE_OCFS2_ULL_EVENT(ocfs2_orphan_filldir); + +DEFINE_OCFS2_INT_EVENT(ocfs2_recover_orphans); + +DEFINE_OCFS2_ULL_EVENT(ocfs2_recover_orphans_iput); + +DEFINE_OCFS2_INT_EVENT(ocfs2_wait_on_mount); + +/* End of trace events for fs/ocfs2/journal.c. */ #endif /* _TRACE_OCFS2_H */ /* This part must be outside protection */ -- GitLab From 15057e981abb3436c16835af1001447056a809b5 Mon Sep 17 00:00:00 2001 From: Tao Ma Date: Thu, 24 Feb 2011 16:09:38 +0800 Subject: [PATCH 0131/2822] ocfs2: Remove masklog ML_BH_IO. Remove mlog(0,...) and mlog(ML_BH_IO,...) from fs/ocfs2/buffer_head_io.c. The masklog BH_IO is removed finally. Signed-off-by: Tao Ma --- fs/ocfs2/buffer_head_io.c | 37 +++++++++++------------------- fs/ocfs2/cluster/masklog.c | 1 - fs/ocfs2/cluster/masklog.h | 1 - fs/ocfs2/ocfs2_trace.h | 46 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 59 insertions(+), 26 deletions(-) diff --git a/fs/ocfs2/buffer_head_io.c b/fs/ocfs2/buffer_head_io.c index c23846dbfc8f8..d1cf9abcd8271 100644 --- a/fs/ocfs2/buffer_head_io.c +++ b/fs/ocfs2/buffer_head_io.c @@ -35,8 +35,8 @@ #include "inode.h" #include "journal.h" #include "uptodate.h" - #include "buffer_head_io.h" +#include "ocfs2_trace.h" /* * Bits on bh->b_state used by ocfs2. @@ -55,8 +55,7 @@ int ocfs2_write_block(struct ocfs2_super *osb, struct buffer_head *bh, { int ret = 0; - mlog(0, "(bh->b_blocknr = %llu, ci=%p)\n", - (unsigned long long)bh->b_blocknr, ci); + trace_ocfs2_write_block((unsigned long long)bh->b_blocknr, ci); BUG_ON(bh->b_blocknr < OCFS2_SUPER_BLOCK_BLKNO); BUG_ON(buffer_jbd(bh)); @@ -107,10 +106,10 @@ int ocfs2_read_blocks_sync(struct ocfs2_super *osb, u64 block, unsigned int i; struct buffer_head *bh; - if (!nr) { - mlog(ML_BH_IO, "No buffers will be read!\n"); + trace_ocfs2_read_blocks_sync((unsigned long long)block, nr); + + if (!nr) goto bail; - } for (i = 0 ; i < nr ; i++) { if (bhs[i] == NULL) { @@ -124,10 +123,8 @@ int ocfs2_read_blocks_sync(struct ocfs2_super *osb, u64 block, bh = bhs[i]; if (buffer_jbd(bh)) { - mlog(ML_BH_IO, - "trying to sync read a jbd " - "managed bh (blocknr = %llu), skipping\n", - (unsigned long long)bh->b_blocknr); + trace_ocfs2_read_blocks_sync_jbd( + (unsigned long long)bh->b_blocknr); continue; } @@ -187,8 +184,7 @@ int ocfs2_read_blocks(struct ocfs2_caching_info *ci, u64 block, int nr, struct buffer_head *bh; struct super_block *sb = ocfs2_metadata_cache_get_super(ci); - mlog(0, "(ci=%p, block=(%llu), nr=(%d), flags=%d)\n", - ci, (unsigned long long)block, nr, flags); + trace_ocfs2_read_blocks_begin(ci, (unsigned long long)block, nr, flags); BUG_ON(!ci); BUG_ON((flags & OCFS2_BH_READAHEAD) && @@ -208,7 +204,6 @@ int ocfs2_read_blocks(struct ocfs2_caching_info *ci, u64 block, int nr, } if (nr == 0) { - mlog(ML_BH_IO, "No buffers will be read!\n"); status = 0; goto bail; } @@ -261,11 +256,10 @@ int ocfs2_read_blocks(struct ocfs2_caching_info *ci, u64 block, int nr, ignore_cache = 1; } + trace_ocfs2_read_blocks_bh((unsigned long long)bh->b_blocknr, + ignore_cache, buffer_jbd(bh), buffer_dirty(bh)); + if (buffer_jbd(bh)) { - if (ignore_cache) - mlog(ML_BH_IO, "trying to sync read a jbd " - "managed bh (blocknr = %llu)\n", - (unsigned long long)bh->b_blocknr); continue; } @@ -273,9 +267,6 @@ int ocfs2_read_blocks(struct ocfs2_caching_info *ci, u64 block, int nr, if (buffer_dirty(bh)) { /* This should probably be a BUG, or * at least return an error. */ - mlog(ML_BH_IO, "asking me to sync read a dirty " - "buffer! (blocknr = %llu)\n", - (unsigned long long)bh->b_blocknr); continue; } @@ -368,10 +359,8 @@ int ocfs2_read_blocks(struct ocfs2_caching_info *ci, u64 block, int nr, } ocfs2_metadata_cache_io_unlock(ci); - mlog(ML_BH_IO, "block=(%llu), nr=(%d), cached=%s, flags=0x%x\n", - (unsigned long long)block, nr, - ((flags & OCFS2_BH_IGNORE_CACHE) || ignore_cache) ? "no" : "yes", - flags); + trace_ocfs2_read_blocks_end((unsigned long long)block, nr, + flags, ignore_cache); bail: diff --git a/fs/ocfs2/cluster/masklog.c b/fs/ocfs2/cluster/masklog.c index b64fb67c29995..d845ccef2408b 100644 --- a/fs/ocfs2/cluster/masklog.c +++ b/fs/ocfs2/cluster/masklog.c @@ -93,7 +93,6 @@ static struct mlog_attribute mlog_attrs[MLOG_MAX_BITS] = { define_mask(DLM_RECOVERY), define_mask(AIO), define_mask(DLM_GLUE), - define_mask(BH_IO), define_mask(UPTODATE), define_mask(VOTE), define_mask(CONN), diff --git a/fs/ocfs2/cluster/masklog.h b/fs/ocfs2/cluster/masklog.h index 1340ef0ae3e1d..ad267f6145286 100644 --- a/fs/ocfs2/cluster/masklog.h +++ b/fs/ocfs2/cluster/masklog.h @@ -95,7 +95,6 @@ #define ML_DLM_RECOVERY 0x0000000000001000ULL /* dlm master functions */ #define ML_AIO 0x0000000000002000ULL /* ocfs2 aio read and write */ #define ML_DLM_GLUE 0x0000000000080000ULL /* ocfs2 dlm glue layer */ -#define ML_BH_IO 0x0000000000100000ULL /* ocfs2 buffer I/O */ #define ML_UPTODATE 0x0000000000200000ULL /* ocfs2 caching sequence #'s */ #define ML_VOTE 0x0000000001000000ULL /* ocfs2 node messaging */ #define ML_CONN 0x0000000004000000ULL /* net connection management */ diff --git a/fs/ocfs2/ocfs2_trace.h b/fs/ocfs2/ocfs2_trace.h index 9d1ca49aa98b4..90dc79a22a597 100644 --- a/fs/ocfs2/ocfs2_trace.h +++ b/fs/ocfs2/ocfs2_trace.h @@ -2642,6 +2642,52 @@ DEFINE_OCFS2_ULL_EVENT(ocfs2_recover_orphans_iput); DEFINE_OCFS2_INT_EVENT(ocfs2_wait_on_mount); /* End of trace events for fs/ocfs2/journal.c. */ + +/* Trace events for fs/ocfs2/buffer_head_io.c. */ + +DEFINE_OCFS2_ULL_UINT_EVENT(ocfs2_read_blocks_sync); + +DEFINE_OCFS2_ULL_EVENT(ocfs2_read_blocks_sync_jbd); + +DEFINE_OCFS2_ULL_INT_INT_INT_EVENT(ocfs2_read_blocks_bh); + +DEFINE_OCFS2_ULL_INT_INT_INT_EVENT(ocfs2_read_blocks_end); + +TRACE_EVENT(ocfs2_write_block, + TP_PROTO(unsigned long long block, void *ci), + TP_ARGS(block, ci), + TP_STRUCT__entry( + __field(unsigned long long, block) + __field(void *, ci) + ), + TP_fast_assign( + __entry->block = block; + __entry->ci = ci; + ), + TP_printk("%llu %p", __entry->block, __entry->ci) +); + +TRACE_EVENT(ocfs2_read_blocks_begin, + TP_PROTO(void *ci, unsigned long long block, + unsigned int nr, int flags), + TP_ARGS(ci, block, nr, flags), + TP_STRUCT__entry( + __field(void *, ci) + __field(unsigned long long, block) + __field(unsigned int, nr) + __field(int, flags) + ), + TP_fast_assign( + __entry->ci = ci; + __entry->block = block; + __entry->nr = nr; + __entry->flags = flags; + ), + TP_printk("%p %llu %u %d", __entry->ci, __entry->block, + __entry->nr, __entry->flags) +); + +/* End of trace events for fs/ocfs2/buffer_head_io.c. */ #endif /* _TRACE_OCFS2_H */ /* This part must be outside protection */ -- GitLab From d701485a6246486fda0ee58457b82a81562a7bc4 Mon Sep 17 00:00:00 2001 From: Tao Ma Date: Thu, 24 Feb 2011 16:22:20 +0800 Subject: [PATCH 0132/2822] ocfs2: Remove masklog ML_UPTODATE. Remove mlog(0,...) and mlog(ML_UPTODATE,...) from fs/ocfs2/uptodate.c and fs/ocfs2/buffer_head_io.c. The masklog UPTODATE is removed finally. Signed-off-by: Tao Ma --- fs/ocfs2/buffer_head_io.c | 3 +- fs/ocfs2/cluster/masklog.c | 1 - fs/ocfs2/cluster/masklog.h | 1 - fs/ocfs2/ocfs2_trace.h | 42 ++++++++++++++++++++++ fs/ocfs2/uptodate.c | 73 +++++++++++++++++++------------------- 5 files changed, 79 insertions(+), 41 deletions(-) diff --git a/fs/ocfs2/buffer_head_io.c b/fs/ocfs2/buffer_head_io.c index d1cf9abcd8271..5d18ad10c27fc 100644 --- a/fs/ocfs2/buffer_head_io.c +++ b/fs/ocfs2/buffer_head_io.c @@ -247,8 +247,7 @@ int ocfs2_read_blocks(struct ocfs2_caching_info *ci, u64 block, int nr, */ if (!ignore_cache && !ocfs2_buffer_uptodate(ci, bh)) { - mlog(ML_UPTODATE, - "bh (%llu), owner %llu not uptodate\n", + trace_ocfs2_read_blocks_from_disk( (unsigned long long)bh->b_blocknr, (unsigned long long)ocfs2_metadata_cache_owner(ci)); /* We're using ignore_cache here to say diff --git a/fs/ocfs2/cluster/masklog.c b/fs/ocfs2/cluster/masklog.c index d845ccef2408b..bbea7b6cb4d31 100644 --- a/fs/ocfs2/cluster/masklog.c +++ b/fs/ocfs2/cluster/masklog.c @@ -93,7 +93,6 @@ static struct mlog_attribute mlog_attrs[MLOG_MAX_BITS] = { define_mask(DLM_RECOVERY), define_mask(AIO), define_mask(DLM_GLUE), - define_mask(UPTODATE), define_mask(VOTE), define_mask(CONN), define_mask(QUORUM), diff --git a/fs/ocfs2/cluster/masklog.h b/fs/ocfs2/cluster/masklog.h index ad267f6145286..7a86add27f694 100644 --- a/fs/ocfs2/cluster/masklog.h +++ b/fs/ocfs2/cluster/masklog.h @@ -95,7 +95,6 @@ #define ML_DLM_RECOVERY 0x0000000000001000ULL /* dlm master functions */ #define ML_AIO 0x0000000000002000ULL /* ocfs2 aio read and write */ #define ML_DLM_GLUE 0x0000000000080000ULL /* ocfs2 dlm glue layer */ -#define ML_UPTODATE 0x0000000000200000ULL /* ocfs2 caching sequence #'s */ #define ML_VOTE 0x0000000001000000ULL /* ocfs2 node messaging */ #define ML_CONN 0x0000000004000000ULL /* net connection management */ #define ML_QUORUM 0x0000000008000000ULL /* net connection quorum */ diff --git a/fs/ocfs2/ocfs2_trace.h b/fs/ocfs2/ocfs2_trace.h index 90dc79a22a597..a1dae5bb54acd 100644 --- a/fs/ocfs2/ocfs2_trace.h +++ b/fs/ocfs2/ocfs2_trace.h @@ -2649,6 +2649,8 @@ DEFINE_OCFS2_ULL_UINT_EVENT(ocfs2_read_blocks_sync); DEFINE_OCFS2_ULL_EVENT(ocfs2_read_blocks_sync_jbd); +DEFINE_OCFS2_ULL_ULL_EVENT(ocfs2_read_blocks_from_disk); + DEFINE_OCFS2_ULL_INT_INT_INT_EVENT(ocfs2_read_blocks_bh); DEFINE_OCFS2_ULL_INT_INT_INT_EVENT(ocfs2_read_blocks_end); @@ -2688,6 +2690,46 @@ TRACE_EVENT(ocfs2_read_blocks_begin, ); /* End of trace events for fs/ocfs2/buffer_head_io.c. */ + +/* Trace events for fs/ocfs2/uptodate.c. */ + +DEFINE_OCFS2_ULL_EVENT(ocfs2_purge_copied_metadata_tree); + +DEFINE_OCFS2_ULL_UINT_UINT_EVENT(ocfs2_metadata_cache_purge); + +DEFINE_OCFS2_ULL_ULL_UINT_EVENT(ocfs2_buffer_cached_begin); + +TRACE_EVENT(ocfs2_buffer_cached_end, + TP_PROTO(int index, void *item), + TP_ARGS(index, item), + TP_STRUCT__entry( + __field(int, index) + __field(void *, item) + ), + TP_fast_assign( + __entry->index = index; + __entry->item = item; + ), + TP_printk("%d %p", __entry->index, __entry->item) +); + +DEFINE_OCFS2_ULL_ULL_UINT_EVENT(ocfs2_append_cache_array); + +DEFINE_OCFS2_ULL_ULL_UINT_EVENT(ocfs2_insert_cache_tree); + +DEFINE_OCFS2_ULL_UINT_UINT_EVENT(ocfs2_expand_cache); + +DEFINE_OCFS2_ULL_UINT_UINT_EVENT(ocfs2_set_buffer_uptodate); + +DEFINE_OCFS2_ULL_ULL_EVENT(ocfs2_set_buffer_uptodate_begin); + +DEFINE_OCFS2_ULL_UINT_UINT_EVENT(ocfs2_remove_metadata_array); + +DEFINE_OCFS2_ULL_ULL_EVENT(ocfs2_remove_metadata_tree); + +DEFINE_OCFS2_ULL_ULL_UINT_UINT_EVENT(ocfs2_remove_block_from_cache); + +/* End of trace events for fs/ocfs2/uptodate.c. */ #endif /* _TRACE_OCFS2_H */ /* This part must be outside protection */ diff --git a/fs/ocfs2/uptodate.c b/fs/ocfs2/uptodate.c index a0a120e82b971..52eaf33d346fd 100644 --- a/fs/ocfs2/uptodate.c +++ b/fs/ocfs2/uptodate.c @@ -54,14 +54,13 @@ #include #include -#define MLOG_MASK_PREFIX ML_UPTODATE - #include #include "ocfs2.h" #include "inode.h" #include "uptodate.h" +#include "ocfs2_trace.h" struct ocfs2_meta_cache_item { struct rb_node c_node; @@ -152,8 +151,8 @@ static unsigned int ocfs2_purge_copied_metadata_tree(struct rb_root *root) while ((node = rb_last(root)) != NULL) { item = rb_entry(node, struct ocfs2_meta_cache_item, c_node); - mlog(0, "Purge item %llu\n", - (unsigned long long) item->c_block); + trace_ocfs2_purge_copied_metadata_tree( + (unsigned long long) item->c_block); rb_erase(&item->c_node, root); kmem_cache_free(ocfs2_uptodate_cachep, item); @@ -180,9 +179,9 @@ void ocfs2_metadata_cache_purge(struct ocfs2_caching_info *ci) tree = !(ci->ci_flags & OCFS2_CACHE_FL_INLINE); to_purge = ci->ci_num_cached; - mlog(0, "Purge %u %s items from Owner %llu\n", to_purge, - tree ? "array" : "tree", - (unsigned long long)ocfs2_metadata_cache_owner(ci)); + trace_ocfs2_metadata_cache_purge( + (unsigned long long)ocfs2_metadata_cache_owner(ci), + to_purge, tree); /* If we're a tree, save off the root so that we can safely * initialize the cache. We do the work to free tree members @@ -249,10 +248,10 @@ static int ocfs2_buffer_cached(struct ocfs2_caching_info *ci, ocfs2_metadata_cache_lock(ci); - mlog(0, "Owner %llu, query block %llu (inline = %u)\n", - (unsigned long long)ocfs2_metadata_cache_owner(ci), - (unsigned long long) bh->b_blocknr, - !!(ci->ci_flags & OCFS2_CACHE_FL_INLINE)); + trace_ocfs2_buffer_cached_begin( + (unsigned long long)ocfs2_metadata_cache_owner(ci), + (unsigned long long) bh->b_blocknr, + !!(ci->ci_flags & OCFS2_CACHE_FL_INLINE)); if (ci->ci_flags & OCFS2_CACHE_FL_INLINE) index = ocfs2_search_cache_array(ci, bh->b_blocknr); @@ -261,7 +260,7 @@ static int ocfs2_buffer_cached(struct ocfs2_caching_info *ci, ocfs2_metadata_cache_unlock(ci); - mlog(0, "index = %d, item = %p\n", index, item); + trace_ocfs2_buffer_cached_end(index, item); return (index != -1) || (item != NULL); } @@ -306,8 +305,9 @@ static void ocfs2_append_cache_array(struct ocfs2_caching_info *ci, { BUG_ON(ci->ci_num_cached >= OCFS2_CACHE_INFO_MAX_ARRAY); - mlog(0, "block %llu takes position %u\n", (unsigned long long) block, - ci->ci_num_cached); + trace_ocfs2_append_cache_array( + (unsigned long long)ocfs2_metadata_cache_owner(ci), + (unsigned long long)block, ci->ci_num_cached); ci->ci_cache.ci_array[ci->ci_num_cached] = block; ci->ci_num_cached++; @@ -324,8 +324,9 @@ static void __ocfs2_insert_cache_tree(struct ocfs2_caching_info *ci, struct rb_node **p = &ci->ci_cache.ci_tree.rb_node; struct ocfs2_meta_cache_item *tmp; - mlog(0, "Insert block %llu num = %u\n", (unsigned long long) block, - ci->ci_num_cached); + trace_ocfs2_insert_cache_tree( + (unsigned long long)ocfs2_metadata_cache_owner(ci), + (unsigned long long)block, ci->ci_num_cached); while(*p) { parent = *p; @@ -389,9 +390,9 @@ static void ocfs2_expand_cache(struct ocfs2_caching_info *ci, tree[i] = NULL; } - mlog(0, "Expanded %llu to a tree cache: flags 0x%x, num = %u\n", - (unsigned long long)ocfs2_metadata_cache_owner(ci), - ci->ci_flags, ci->ci_num_cached); + trace_ocfs2_expand_cache( + (unsigned long long)ocfs2_metadata_cache_owner(ci), + ci->ci_flags, ci->ci_num_cached); } /* Slow path function - memory allocation is necessary. See the @@ -405,9 +406,9 @@ static void __ocfs2_set_buffer_uptodate(struct ocfs2_caching_info *ci, struct ocfs2_meta_cache_item *tree[OCFS2_CACHE_INFO_MAX_ARRAY] = { NULL, }; - mlog(0, "Owner %llu, block %llu, expand = %d\n", - (unsigned long long)ocfs2_metadata_cache_owner(ci), - (unsigned long long)block, expand_tree); + trace_ocfs2_set_buffer_uptodate( + (unsigned long long)ocfs2_metadata_cache_owner(ci), + (unsigned long long)block, expand_tree); new = kmem_cache_alloc(ocfs2_uptodate_cachep, GFP_NOFS); if (!new) { @@ -433,7 +434,6 @@ static void __ocfs2_set_buffer_uptodate(struct ocfs2_caching_info *ci, ocfs2_metadata_cache_lock(ci); if (ocfs2_insert_can_use_array(ci)) { - mlog(0, "Someone cleared the tree underneath us\n"); /* Ok, items were removed from the cache in between * locks. Detect this and revert back to the fast path */ ocfs2_append_cache_array(ci, block); @@ -490,9 +490,9 @@ void ocfs2_set_buffer_uptodate(struct ocfs2_caching_info *ci, if (ocfs2_buffer_cached(ci, bh)) return; - mlog(0, "Owner %llu, inserting block %llu\n", - (unsigned long long)ocfs2_metadata_cache_owner(ci), - (unsigned long long)bh->b_blocknr); + trace_ocfs2_set_buffer_uptodate_begin( + (unsigned long long)ocfs2_metadata_cache_owner(ci), + (unsigned long long)bh->b_blocknr); /* No need to recheck under spinlock - insertion is guarded by * co_io_lock() */ @@ -542,8 +542,9 @@ static void ocfs2_remove_metadata_array(struct ocfs2_caching_info *ci, BUG_ON(index >= ci->ci_num_cached); BUG_ON(!ci->ci_num_cached); - mlog(0, "remove index %d (num_cached = %u\n", index, - ci->ci_num_cached); + trace_ocfs2_remove_metadata_array( + (unsigned long long)ocfs2_metadata_cache_owner(ci), + index, ci->ci_num_cached); ci->ci_num_cached--; @@ -559,8 +560,9 @@ static void ocfs2_remove_metadata_array(struct ocfs2_caching_info *ci, static void ocfs2_remove_metadata_tree(struct ocfs2_caching_info *ci, struct ocfs2_meta_cache_item *item) { - mlog(0, "remove block %llu from tree\n", - (unsigned long long) item->c_block); + trace_ocfs2_remove_metadata_tree( + (unsigned long long)ocfs2_metadata_cache_owner(ci), + (unsigned long long)item->c_block); rb_erase(&item->c_node, &ci->ci_cache.ci_tree); ci->ci_num_cached--; @@ -573,10 +575,10 @@ static void ocfs2_remove_block_from_cache(struct ocfs2_caching_info *ci, struct ocfs2_meta_cache_item *item = NULL; ocfs2_metadata_cache_lock(ci); - mlog(0, "Owner %llu, remove %llu, items = %u, array = %u\n", - (unsigned long long)ocfs2_metadata_cache_owner(ci), - (unsigned long long) block, ci->ci_num_cached, - ci->ci_flags & OCFS2_CACHE_FL_INLINE); + trace_ocfs2_remove_block_from_cache( + (unsigned long long)ocfs2_metadata_cache_owner(ci), + (unsigned long long) block, ci->ci_num_cached, + ci->ci_flags); if (ci->ci_flags & OCFS2_CACHE_FL_INLINE) { index = ocfs2_search_cache_array(ci, block); @@ -626,9 +628,6 @@ int __init init_ocfs2_uptodate_cache(void) if (!ocfs2_uptodate_cachep) return -ENOMEM; - mlog(0, "%u inlined cache items per inode.\n", - OCFS2_CACHE_INFO_MAX_ARRAY); - return 0; } -- GitLab From 75ba49ae0637c15880fe8f1c8a89333afa052bd8 Mon Sep 17 00:00:00 2001 From: Tao Ma Date: Mon, 21 Feb 2011 11:19:27 +0800 Subject: [PATCH 0133/2822] ocfs2: Remove masklog ML_AIO. There is no user for masklog AIO, so remove it. Signed-off-by: Tao Ma --- fs/ocfs2/cluster/masklog.c | 1 - fs/ocfs2/cluster/masklog.h | 1 - 2 files changed, 2 deletions(-) diff --git a/fs/ocfs2/cluster/masklog.c b/fs/ocfs2/cluster/masklog.c index bbea7b6cb4d31..07ac24fd92520 100644 --- a/fs/ocfs2/cluster/masklog.c +++ b/fs/ocfs2/cluster/masklog.c @@ -91,7 +91,6 @@ static struct mlog_attribute mlog_attrs[MLOG_MAX_BITS] = { define_mask(DLM_THREAD), define_mask(DLM_MASTER), define_mask(DLM_RECOVERY), - define_mask(AIO), define_mask(DLM_GLUE), define_mask(VOTE), define_mask(CONN), diff --git a/fs/ocfs2/cluster/masklog.h b/fs/ocfs2/cluster/masklog.h index 7a86add27f694..0fe96c2830c2a 100644 --- a/fs/ocfs2/cluster/masklog.h +++ b/fs/ocfs2/cluster/masklog.h @@ -93,7 +93,6 @@ #define ML_DLM_THREAD 0x0000000000000400ULL /* dlm domain thread */ #define ML_DLM_MASTER 0x0000000000000800ULL /* dlm master functions */ #define ML_DLM_RECOVERY 0x0000000000001000ULL /* dlm master functions */ -#define ML_AIO 0x0000000000002000ULL /* ocfs2 aio read and write */ #define ML_DLM_GLUE 0x0000000000080000ULL /* ocfs2 dlm glue layer */ #define ML_VOTE 0x0000000001000000ULL /* ocfs2 node messaging */ #define ML_CONN 0x0000000004000000ULL /* net connection management */ -- GitLab From b4e1b7e88b2c87c358c2a88bec0c76d25accc604 Mon Sep 17 00:00:00 2001 From: Tao Ma Date: Mon, 21 Feb 2011 11:19:43 +0800 Subject: [PATCH 0134/2822] ocfs2: Make the left masklogs compat. Since we have removed almost all of the masklogs in fs/ocfs2/*, make the left masklogs compat. Signed-off-by: Tao Ma --- fs/ocfs2/cluster/masklog.h | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/fs/ocfs2/cluster/masklog.h b/fs/ocfs2/cluster/masklog.h index 0fe96c2830c2a..baa2b9ef7eef9 100644 --- a/fs/ocfs2/cluster/masklog.h +++ b/fs/ocfs2/cluster/masklog.h @@ -82,23 +82,23 @@ /* bits that are frequently given and infrequently matched in the low word */ /* NOTE: If you add a flag, you need to also update masklog.c! */ -#define ML_TCP 0x0000000000000004ULL /* net cluster/tcp.c */ -#define ML_MSG 0x0000000000000008ULL /* net network messages */ -#define ML_SOCKET 0x0000000000000010ULL /* net socket lifetime */ -#define ML_HEARTBEAT 0x0000000000000020ULL /* hb all heartbeat tracking */ -#define ML_HB_BIO 0x0000000000000040ULL /* hb io tracing */ -#define ML_DLMFS 0x0000000000000080ULL /* dlm user dlmfs */ -#define ML_DLM 0x0000000000000100ULL /* dlm general debugging */ -#define ML_DLM_DOMAIN 0x0000000000000200ULL /* dlm domain debugging */ -#define ML_DLM_THREAD 0x0000000000000400ULL /* dlm domain thread */ -#define ML_DLM_MASTER 0x0000000000000800ULL /* dlm master functions */ -#define ML_DLM_RECOVERY 0x0000000000001000ULL /* dlm master functions */ -#define ML_DLM_GLUE 0x0000000000080000ULL /* ocfs2 dlm glue layer */ -#define ML_VOTE 0x0000000001000000ULL /* ocfs2 node messaging */ -#define ML_CONN 0x0000000004000000ULL /* net connection management */ -#define ML_QUORUM 0x0000000008000000ULL /* net connection quorum */ -#define ML_BASTS 0x0000000100000000ULL /* dlmglue asts and basts */ -#define ML_CLUSTER 0x0000000400000000ULL /* cluster stack */ +#define ML_TCP 0x0000000000000001ULL /* net cluster/tcp.c */ +#define ML_MSG 0x0000000000000002ULL /* net network messages */ +#define ML_SOCKET 0x0000000000000004ULL /* net socket lifetime */ +#define ML_HEARTBEAT 0x0000000000000008ULL /* hb all heartbeat tracking */ +#define ML_HB_BIO 0x0000000000000010ULL /* hb io tracing */ +#define ML_DLMFS 0x0000000000000020ULL /* dlm user dlmfs */ +#define ML_DLM 0x0000000000000040ULL /* dlm general debugging */ +#define ML_DLM_DOMAIN 0x0000000000000080ULL /* dlm domain debugging */ +#define ML_DLM_THREAD 0x0000000000000100ULL /* dlm domain thread */ +#define ML_DLM_MASTER 0x0000000000000200ULL /* dlm master functions */ +#define ML_DLM_RECOVERY 0x0000000000000400ULL /* dlm master functions */ +#define ML_DLM_GLUE 0x0000000000000800ULL /* ocfs2 dlm glue layer */ +#define ML_VOTE 0x0000000000001000ULL /* ocfs2 node messaging */ +#define ML_CONN 0x0000000000002000ULL /* net connection management */ +#define ML_QUORUM 0x0000000000004000ULL /* net connection quorum */ +#define ML_BASTS 0x0000000000008000ULL /* dlmglue asts and basts */ +#define ML_CLUSTER 0x0000000000010000ULL /* cluster stack */ /* bits that are infrequently given and frequently matched in the high word */ #define ML_ERROR 0x1000000000000000ULL /* sent to KERN_ERR */ -- GitLab From 964de52147c2842092642512e6f654fc2ab51408 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Wed, 2 Feb 2011 23:21:58 -0800 Subject: [PATCH 0135/2822] Input: qt602240_ts - rename to atmel_mxt_ts Since the driver will be supporting whole range of Atmels mXT touchscreen controllers we better rename it to atmel_mxt_ts. Acked-by: Iiro Valkonen Signed-off-by: Dmitry Torokhov --- arch/arm/mach-s5pv210/mach-goni.c | 2 +- drivers/input/touchscreen/Kconfig | 24 +++++++++---------- drivers/input/touchscreen/Makefile | 2 +- .../{qt602240_ts.c => atmel_mxt_ts.c} | 2 +- .../i2c/{qt602240_ts.h => atmel_mxt_ts.h} | 0 5 files changed, 15 insertions(+), 15 deletions(-) rename drivers/input/touchscreen/{qt602240_ts.c => atmel_mxt_ts.c} (99%) rename include/linux/i2c/{qt602240_ts.h => atmel_mxt_ts.h} (100%) diff --git a/arch/arm/mach-s5pv210/mach-goni.c b/arch/arm/mach-s5pv210/mach-goni.c index e22d5112fd44a..fd2747fd8905a 100644 --- a/arch/arm/mach-s5pv210/mach-goni.c +++ b/arch/arm/mach-s5pv210/mach-goni.c @@ -15,7 +15,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig index 258e43e98ec34..2fbd3d39b7eb1 100644 --- a/drivers/input/touchscreen/Kconfig +++ b/drivers/input/touchscreen/Kconfig @@ -86,6 +86,18 @@ config TOUCHSCREEN_AD7879_SPI To compile this driver as a module, choose M here: the module will be called ad7879-spi. +config TOUCHSCREEN_ATMEL_MXT + tristate "Atmel mXT I2C Touchscreen" + depends on I2C + help + Say Y here if you have Atmel mXT series I2C touchscreen, + such as AT42QT602240/ATMXT224, connected to your system. + + If unsure, say N. + + To compile this driver as a module, choose M here: the + module will be called atmel_mxt_ts. + config TOUCHSCREEN_BITSY tristate "Compaq iPAQ H3600 (Bitsy) touchscreen" depends on SA1100_BITSY @@ -339,18 +351,6 @@ config TOUCHSCREEN_PENMOUNT To compile this driver as a module, choose M here: the module will be called penmount. -config TOUCHSCREEN_QT602240 - tristate "QT602240 I2C Touchscreen" - depends on I2C - help - Say Y here if you have the AT42QT602240/ATMXT224 I2C touchscreen - connected to your system. - - If unsure, say N. - - To compile this driver as a module, choose M here: the - module will be called qt602240_ts. - config TOUCHSCREEN_MIGOR tristate "Renesas MIGO-R touchscreen" depends on SH_MIGOR && I2C diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile index e8dcfab7c2dc0..756156409b833 100644 --- a/drivers/input/touchscreen/Makefile +++ b/drivers/input/touchscreen/Makefile @@ -12,6 +12,7 @@ obj-$(CONFIG_TOUCHSCREEN_AD7879) += ad7879.o obj-$(CONFIG_TOUCHSCREEN_AD7879_I2C) += ad7879-i2c.o obj-$(CONFIG_TOUCHSCREEN_AD7879_SPI) += ad7879-spi.o obj-$(CONFIG_TOUCHSCREEN_ADS7846) += ads7846.o +obj-$(CONFIG_TOUCHSCREEN_ATMEL_MXT) += atmel_mxt_ts.o obj-$(CONFIG_TOUCHSCREEN_ATMEL_TSADCC) += atmel_tsadcc.o obj-$(CONFIG_TOUCHSCREEN_BITSY) += h3600_ts_input.o obj-$(CONFIG_TOUCHSCREEN_BU21013) += bu21013_ts.o @@ -37,7 +38,6 @@ obj-$(CONFIG_TOUCHSCREEN_HTCPEN) += htcpen.o obj-$(CONFIG_TOUCHSCREEN_USB_COMPOSITE) += usbtouchscreen.o obj-$(CONFIG_TOUCHSCREEN_PCAP) += pcap_ts.o obj-$(CONFIG_TOUCHSCREEN_PENMOUNT) += penmount.o -obj-$(CONFIG_TOUCHSCREEN_QT602240) += qt602240_ts.o obj-$(CONFIG_TOUCHSCREEN_S3C2410) += s3c2410_ts.o obj-$(CONFIG_TOUCHSCREEN_ST1232) += st1232.o obj-$(CONFIG_TOUCHSCREEN_STMPE) += stmpe-ts.o diff --git a/drivers/input/touchscreen/qt602240_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c similarity index 99% rename from drivers/input/touchscreen/qt602240_ts.c rename to drivers/input/touchscreen/atmel_mxt_ts.c index 4dcb0e872f6a8..47067789b7475 100644 --- a/drivers/input/touchscreen/qt602240_ts.c +++ b/drivers/input/touchscreen/atmel_mxt_ts.c @@ -16,7 +16,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/include/linux/i2c/qt602240_ts.h b/include/linux/i2c/atmel_mxt_ts.h similarity index 100% rename from include/linux/i2c/qt602240_ts.h rename to include/linux/i2c/atmel_mxt_ts.h -- GitLab From 7686b108d8ef5c32f429d5228798636f3a1caf5a Mon Sep 17 00:00:00 2001 From: Iiro Valkonen Date: Wed, 2 Feb 2011 23:21:58 -0800 Subject: [PATCH 0136/2822] Input: atmel_mxt_ts - get rid of qt602240 prefixes in names Change prefixes from qt602240 to mxt to reflect that the driver supports whole line of mXT touchscreens. Signed-off-by: Iiro Valkonen Signed-off-by: Dmitry Torokhov --- arch/arm/mach-s5pv210/mach-goni.c | 4 +- drivers/input/touchscreen/atmel_mxt_ts.c | 929 ++++++++++++----------- include/linux/i2c/atmel_mxt_ts.h | 28 +- 3 files changed, 481 insertions(+), 480 deletions(-) diff --git a/arch/arm/mach-s5pv210/mach-goni.c b/arch/arm/mach-s5pv210/mach-goni.c index fd2747fd8905a..e9a7d340f4e1f 100644 --- a/arch/arm/mach-s5pv210/mach-goni.c +++ b/arch/arm/mach-s5pv210/mach-goni.c @@ -222,7 +222,7 @@ static void __init goni_radio_init(void) } /* TSP */ -static struct qt602240_platform_data qt602240_platform_data = { +static struct mxt_platform_data qt602240_platform_data = { .x_line = 17, .y_line = 11, .x_size = 800, @@ -230,7 +230,7 @@ static struct qt602240_platform_data qt602240_platform_data = { .blen = 0x21, .threshold = 0x28, .voltage = 2800000, /* 2.8V */ - .orient = QT602240_DIAGONAL, + .orient = MXT_DIAGONAL, }; static struct s3c2410_platform_i2c i2c2_data __initdata = { diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c index 47067789b7475..5dca78a00c946 100644 --- a/drivers/input/touchscreen/atmel_mxt_ts.c +++ b/drivers/input/touchscreen/atmel_mxt_ts.c @@ -1,5 +1,5 @@ /* - * AT42QT602240/ATMXT224 Touchscreen driver + * Atmel maXTouch Touchscreen driver * * Copyright (C) 2010 Samsung Electronics Co.Ltd * Author: Joonyoung Shim @@ -22,300 +22,300 @@ #include /* Version */ -#define QT602240_VER_20 20 -#define QT602240_VER_21 21 -#define QT602240_VER_22 22 +#define MXT_VER_20 20 +#define MXT_VER_21 21 +#define MXT_VER_22 22 /* Slave addresses */ -#define QT602240_APP_LOW 0x4a -#define QT602240_APP_HIGH 0x4b -#define QT602240_BOOT_LOW 0x24 -#define QT602240_BOOT_HIGH 0x25 +#define MXT_APP_LOW 0x4a +#define MXT_APP_HIGH 0x4b +#define MXT_BOOT_LOW 0x24 +#define MXT_BOOT_HIGH 0x25 /* Firmware */ -#define QT602240_FW_NAME "qt602240.fw" +#define MXT_FW_NAME "maxtouch.fw" /* Registers */ -#define QT602240_FAMILY_ID 0x00 -#define QT602240_VARIANT_ID 0x01 -#define QT602240_VERSION 0x02 -#define QT602240_BUILD 0x03 -#define QT602240_MATRIX_X_SIZE 0x04 -#define QT602240_MATRIX_Y_SIZE 0x05 -#define QT602240_OBJECT_NUM 0x06 -#define QT602240_OBJECT_START 0x07 +#define MXT_FAMILY_ID 0x00 +#define MXT_VARIANT_ID 0x01 +#define MXT_VERSION 0x02 +#define MXT_BUILD 0x03 +#define MXT_MATRIX_X_SIZE 0x04 +#define MXT_MATRIX_Y_SIZE 0x05 +#define MXT_OBJECT_NUM 0x06 +#define MXT_OBJECT_START 0x07 -#define QT602240_OBJECT_SIZE 6 +#define MXT_OBJECT_SIZE 6 /* Object types */ -#define QT602240_DEBUG_DIAGNOSTIC 37 -#define QT602240_GEN_MESSAGE 5 -#define QT602240_GEN_COMMAND 6 -#define QT602240_GEN_POWER 7 -#define QT602240_GEN_ACQUIRE 8 -#define QT602240_TOUCH_MULTI 9 -#define QT602240_TOUCH_KEYARRAY 15 -#define QT602240_TOUCH_PROXIMITY 23 -#define QT602240_PROCI_GRIPFACE 20 -#define QT602240_PROCG_NOISE 22 -#define QT602240_PROCI_ONETOUCH 24 -#define QT602240_PROCI_TWOTOUCH 27 -#define QT602240_SPT_COMMSCONFIG 18 /* firmware ver 21 over */ -#define QT602240_SPT_GPIOPWM 19 -#define QT602240_SPT_SELFTEST 25 -#define QT602240_SPT_CTECONFIG 28 -#define QT602240_SPT_USERDATA 38 /* firmware ver 21 over */ - -/* QT602240_GEN_COMMAND field */ -#define QT602240_COMMAND_RESET 0 -#define QT602240_COMMAND_BACKUPNV 1 -#define QT602240_COMMAND_CALIBRATE 2 -#define QT602240_COMMAND_REPORTALL 3 -#define QT602240_COMMAND_DIAGNOSTIC 5 - -/* QT602240_GEN_POWER field */ -#define QT602240_POWER_IDLEACQINT 0 -#define QT602240_POWER_ACTVACQINT 1 -#define QT602240_POWER_ACTV2IDLETO 2 - -/* QT602240_GEN_ACQUIRE field */ -#define QT602240_ACQUIRE_CHRGTIME 0 -#define QT602240_ACQUIRE_TCHDRIFT 2 -#define QT602240_ACQUIRE_DRIFTST 3 -#define QT602240_ACQUIRE_TCHAUTOCAL 4 -#define QT602240_ACQUIRE_SYNC 5 -#define QT602240_ACQUIRE_ATCHCALST 6 -#define QT602240_ACQUIRE_ATCHCALSTHR 7 - -/* QT602240_TOUCH_MULTI field */ -#define QT602240_TOUCH_CTRL 0 -#define QT602240_TOUCH_XORIGIN 1 -#define QT602240_TOUCH_YORIGIN 2 -#define QT602240_TOUCH_XSIZE 3 -#define QT602240_TOUCH_YSIZE 4 -#define QT602240_TOUCH_BLEN 6 -#define QT602240_TOUCH_TCHTHR 7 -#define QT602240_TOUCH_TCHDI 8 -#define QT602240_TOUCH_ORIENT 9 -#define QT602240_TOUCH_MOVHYSTI 11 -#define QT602240_TOUCH_MOVHYSTN 12 -#define QT602240_TOUCH_NUMTOUCH 14 -#define QT602240_TOUCH_MRGHYST 15 -#define QT602240_TOUCH_MRGTHR 16 -#define QT602240_TOUCH_AMPHYST 17 -#define QT602240_TOUCH_XRANGE_LSB 18 -#define QT602240_TOUCH_XRANGE_MSB 19 -#define QT602240_TOUCH_YRANGE_LSB 20 -#define QT602240_TOUCH_YRANGE_MSB 21 -#define QT602240_TOUCH_XLOCLIP 22 -#define QT602240_TOUCH_XHICLIP 23 -#define QT602240_TOUCH_YLOCLIP 24 -#define QT602240_TOUCH_YHICLIP 25 -#define QT602240_TOUCH_XEDGECTRL 26 -#define QT602240_TOUCH_XEDGEDIST 27 -#define QT602240_TOUCH_YEDGECTRL 28 -#define QT602240_TOUCH_YEDGEDIST 29 -#define QT602240_TOUCH_JUMPLIMIT 30 /* firmware ver 22 over */ - -/* QT602240_PROCI_GRIPFACE field */ -#define QT602240_GRIPFACE_CTRL 0 -#define QT602240_GRIPFACE_XLOGRIP 1 -#define QT602240_GRIPFACE_XHIGRIP 2 -#define QT602240_GRIPFACE_YLOGRIP 3 -#define QT602240_GRIPFACE_YHIGRIP 4 -#define QT602240_GRIPFACE_MAXTCHS 5 -#define QT602240_GRIPFACE_SZTHR1 7 -#define QT602240_GRIPFACE_SZTHR2 8 -#define QT602240_GRIPFACE_SHPTHR1 9 -#define QT602240_GRIPFACE_SHPTHR2 10 -#define QT602240_GRIPFACE_SUPEXTTO 11 - -/* QT602240_PROCI_NOISE field */ -#define QT602240_NOISE_CTRL 0 -#define QT602240_NOISE_OUTFLEN 1 -#define QT602240_NOISE_GCAFUL_LSB 3 -#define QT602240_NOISE_GCAFUL_MSB 4 -#define QT602240_NOISE_GCAFLL_LSB 5 -#define QT602240_NOISE_GCAFLL_MSB 6 -#define QT602240_NOISE_ACTVGCAFVALID 7 -#define QT602240_NOISE_NOISETHR 8 -#define QT602240_NOISE_FREQHOPSCALE 10 -#define QT602240_NOISE_FREQ0 11 -#define QT602240_NOISE_FREQ1 12 -#define QT602240_NOISE_FREQ2 13 -#define QT602240_NOISE_FREQ3 14 -#define QT602240_NOISE_FREQ4 15 -#define QT602240_NOISE_IDLEGCAFVALID 16 - -/* QT602240_SPT_COMMSCONFIG */ -#define QT602240_COMMS_CTRL 0 -#define QT602240_COMMS_CMD 1 - -/* QT602240_SPT_CTECONFIG field */ -#define QT602240_CTE_CTRL 0 -#define QT602240_CTE_CMD 1 -#define QT602240_CTE_MODE 2 -#define QT602240_CTE_IDLEGCAFDEPTH 3 -#define QT602240_CTE_ACTVGCAFDEPTH 4 -#define QT602240_CTE_VOLTAGE 5 /* firmware ver 21 over */ - -#define QT602240_VOLTAGE_DEFAULT 2700000 -#define QT602240_VOLTAGE_STEP 10000 - -/* Define for QT602240_GEN_COMMAND */ -#define QT602240_BOOT_VALUE 0xa5 -#define QT602240_BACKUP_VALUE 0x55 -#define QT602240_BACKUP_TIME 25 /* msec */ -#define QT602240_RESET_TIME 65 /* msec */ - -#define QT602240_FWRESET_TIME 175 /* msec */ +#define MXT_DEBUG_DIAGNOSTIC 37 +#define MXT_GEN_MESSAGE 5 +#define MXT_GEN_COMMAND 6 +#define MXT_GEN_POWER 7 +#define MXT_GEN_ACQUIRE 8 +#define MXT_TOUCH_MULTI 9 +#define MXT_TOUCH_KEYARRAY 15 +#define MXT_TOUCH_PROXIMITY 23 +#define MXT_PROCI_GRIPFACE 20 +#define MXT_PROCG_NOISE 22 +#define MXT_PROCI_ONETOUCH 24 +#define MXT_PROCI_TWOTOUCH 27 +#define MXT_SPT_COMMSCONFIG 18 /* firmware ver 21 over */ +#define MXT_SPT_GPIOPWM 19 +#define MXT_SPT_SELFTEST 25 +#define MXT_SPT_CTECONFIG 28 +#define MXT_SPT_USERDATA 38 /* firmware ver 21 over */ + +/* MXT_GEN_COMMAND field */ +#define MXT_COMMAND_RESET 0 +#define MXT_COMMAND_BACKUPNV 1 +#define MXT_COMMAND_CALIBRATE 2 +#define MXT_COMMAND_REPORTALL 3 +#define MXT_COMMAND_DIAGNOSTIC 5 + +/* MXT_GEN_POWER field */ +#define MXT_POWER_IDLEACQINT 0 +#define MXT_POWER_ACTVACQINT 1 +#define MXT_POWER_ACTV2IDLETO 2 + +/* MXT_GEN_ACQUIRE field */ +#define MXT_ACQUIRE_CHRGTIME 0 +#define MXT_ACQUIRE_TCHDRIFT 2 +#define MXT_ACQUIRE_DRIFTST 3 +#define MXT_ACQUIRE_TCHAUTOCAL 4 +#define MXT_ACQUIRE_SYNC 5 +#define MXT_ACQUIRE_ATCHCALST 6 +#define MXT_ACQUIRE_ATCHCALSTHR 7 + +/* MXT_TOUCH_MULTI field */ +#define MXT_TOUCH_CTRL 0 +#define MXT_TOUCH_XORIGIN 1 +#define MXT_TOUCH_YORIGIN 2 +#define MXT_TOUCH_XSIZE 3 +#define MXT_TOUCH_YSIZE 4 +#define MXT_TOUCH_BLEN 6 +#define MXT_TOUCH_TCHTHR 7 +#define MXT_TOUCH_TCHDI 8 +#define MXT_TOUCH_ORIENT 9 +#define MXT_TOUCH_MOVHYSTI 11 +#define MXT_TOUCH_MOVHYSTN 12 +#define MXT_TOUCH_NUMTOUCH 14 +#define MXT_TOUCH_MRGHYST 15 +#define MXT_TOUCH_MRGTHR 16 +#define MXT_TOUCH_AMPHYST 17 +#define MXT_TOUCH_XRANGE_LSB 18 +#define MXT_TOUCH_XRANGE_MSB 19 +#define MXT_TOUCH_YRANGE_LSB 20 +#define MXT_TOUCH_YRANGE_MSB 21 +#define MXT_TOUCH_XLOCLIP 22 +#define MXT_TOUCH_XHICLIP 23 +#define MXT_TOUCH_YLOCLIP 24 +#define MXT_TOUCH_YHICLIP 25 +#define MXT_TOUCH_XEDGECTRL 26 +#define MXT_TOUCH_XEDGEDIST 27 +#define MXT_TOUCH_YEDGECTRL 28 +#define MXT_TOUCH_YEDGEDIST 29 +#define MXT_TOUCH_JUMPLIMIT 30 /* firmware ver 22 over */ + +/* MXT_PROCI_GRIPFACE field */ +#define MXT_GRIPFACE_CTRL 0 +#define MXT_GRIPFACE_XLOGRIP 1 +#define MXT_GRIPFACE_XHIGRIP 2 +#define MXT_GRIPFACE_YLOGRIP 3 +#define MXT_GRIPFACE_YHIGRIP 4 +#define MXT_GRIPFACE_MAXTCHS 5 +#define MXT_GRIPFACE_SZTHR1 7 +#define MXT_GRIPFACE_SZTHR2 8 +#define MXT_GRIPFACE_SHPTHR1 9 +#define MXT_GRIPFACE_SHPTHR2 10 +#define MXT_GRIPFACE_SUPEXTTO 11 + +/* MXT_PROCI_NOISE field */ +#define MXT_NOISE_CTRL 0 +#define MXT_NOISE_OUTFLEN 1 +#define MXT_NOISE_GCAFUL_LSB 3 +#define MXT_NOISE_GCAFUL_MSB 4 +#define MXT_NOISE_GCAFLL_LSB 5 +#define MXT_NOISE_GCAFLL_MSB 6 +#define MXT_NOISE_ACTVGCAFVALID 7 +#define MXT_NOISE_NOISETHR 8 +#define MXT_NOISE_FREQHOPSCALE 10 +#define MXT_NOISE_FREQ0 11 +#define MXT_NOISE_FREQ1 12 +#define MXT_NOISE_FREQ2 13 +#define MXT_NOISE_FREQ3 14 +#define MXT_NOISE_FREQ4 15 +#define MXT_NOISE_IDLEGCAFVALID 16 + +/* MXT_SPT_COMMSCONFIG */ +#define MXT_COMMS_CTRL 0 +#define MXT_COMMS_CMD 1 + +/* MXT_SPT_CTECONFIG field */ +#define MXT_CTE_CTRL 0 +#define MXT_CTE_CMD 1 +#define MXT_CTE_MODE 2 +#define MXT_CTE_IDLEGCAFDEPTH 3 +#define MXT_CTE_ACTVGCAFDEPTH 4 +#define MXT_CTE_VOLTAGE 5 /* firmware ver 21 over */ + +#define MXT_VOLTAGE_DEFAULT 2700000 +#define MXT_VOLTAGE_STEP 10000 + +/* Define for MXT_GEN_COMMAND */ +#define MXT_BOOT_VALUE 0xa5 +#define MXT_BACKUP_VALUE 0x55 +#define MXT_BACKUP_TIME 25 /* msec */ +#define MXT_RESET_TIME 65 /* msec */ + +#define MXT_FWRESET_TIME 175 /* msec */ /* Command to unlock bootloader */ -#define QT602240_UNLOCK_CMD_MSB 0xaa -#define QT602240_UNLOCK_CMD_LSB 0xdc +#define MXT_UNLOCK_CMD_MSB 0xaa +#define MXT_UNLOCK_CMD_LSB 0xdc /* Bootloader mode status */ -#define QT602240_WAITING_BOOTLOAD_CMD 0xc0 /* valid 7 6 bit only */ -#define QT602240_WAITING_FRAME_DATA 0x80 /* valid 7 6 bit only */ -#define QT602240_FRAME_CRC_CHECK 0x02 -#define QT602240_FRAME_CRC_FAIL 0x03 -#define QT602240_FRAME_CRC_PASS 0x04 -#define QT602240_APP_CRC_FAIL 0x40 /* valid 7 8 bit only */ -#define QT602240_BOOT_STATUS_MASK 0x3f +#define MXT_WAITING_BOOTLOAD_CMD 0xc0 /* valid 7 6 bit only */ +#define MXT_WAITING_FRAME_DATA 0x80 /* valid 7 6 bit only */ +#define MXT_FRAME_CRC_CHECK 0x02 +#define MXT_FRAME_CRC_FAIL 0x03 +#define MXT_FRAME_CRC_PASS 0x04 +#define MXT_APP_CRC_FAIL 0x40 /* valid 7 8 bit only */ +#define MXT_BOOT_STATUS_MASK 0x3f /* Touch status */ -#define QT602240_SUPPRESS (1 << 1) -#define QT602240_AMP (1 << 2) -#define QT602240_VECTOR (1 << 3) -#define QT602240_MOVE (1 << 4) -#define QT602240_RELEASE (1 << 5) -#define QT602240_PRESS (1 << 6) -#define QT602240_DETECT (1 << 7) +#define MXT_SUPPRESS (1 << 1) +#define MXT_AMP (1 << 2) +#define MXT_VECTOR (1 << 3) +#define MXT_MOVE (1 << 4) +#define MXT_RELEASE (1 << 5) +#define MXT_PRESS (1 << 6) +#define MXT_DETECT (1 << 7) /* Touchscreen absolute values */ -#define QT602240_MAX_XC 0x3ff -#define QT602240_MAX_YC 0x3ff -#define QT602240_MAX_AREA 0xff +#define MXT_MAX_XC 0x3ff +#define MXT_MAX_YC 0x3ff +#define MXT_MAX_AREA 0xff -#define QT602240_MAX_FINGER 10 +#define MXT_MAX_FINGER 10 /* Initial register values recommended from chip vendor */ static const u8 init_vals_ver_20[] = { - /* QT602240_GEN_COMMAND(6) */ + /* MXT_GEN_COMMAND(6) */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - /* QT602240_GEN_POWER(7) */ + /* MXT_GEN_POWER(7) */ 0x20, 0xff, 0x32, - /* QT602240_GEN_ACQUIRE(8) */ + /* MXT_GEN_ACQUIRE(8) */ 0x08, 0x05, 0x05, 0x00, 0x00, 0x00, 0x05, 0x14, - /* QT602240_TOUCH_MULTI(9) */ + /* MXT_TOUCH_MULTI(9) */ 0x00, 0x00, 0x00, 0x11, 0x0a, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x01, 0x01, 0x0e, 0x0a, 0x0a, 0x0a, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x64, - /* QT602240_TOUCH_KEYARRAY(15) */ + /* MXT_TOUCH_KEYARRAY(15) */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - /* QT602240_SPT_GPIOPWM(19) */ + /* MXT_SPT_GPIOPWM(19) */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - /* QT602240_PROCI_GRIPFACE(20) */ + /* MXT_PROCI_GRIPFACE(20) */ 0x00, 0x64, 0x64, 0x64, 0x64, 0x00, 0x00, 0x1e, 0x14, 0x04, 0x1e, 0x00, - /* QT602240_PROCG_NOISE(22) */ + /* MXT_PROCG_NOISE(22) */ 0x05, 0x00, 0x00, 0x19, 0x00, 0xe7, 0xff, 0x04, 0x32, 0x00, 0x01, 0x0a, 0x0f, 0x14, 0x00, 0x00, 0xe8, - /* QT602240_TOUCH_PROXIMITY(23) */ + /* MXT_TOUCH_PROXIMITY(23) */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - /* QT602240_PROCI_ONETOUCH(24) */ + /* MXT_PROCI_ONETOUCH(24) */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - /* QT602240_SPT_SELFTEST(25) */ + /* MXT_SPT_SELFTEST(25) */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - /* QT602240_PROCI_TWOTOUCH(27) */ + /* MXT_PROCI_TWOTOUCH(27) */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - /* QT602240_SPT_CTECONFIG(28) */ + /* MXT_SPT_CTECONFIG(28) */ 0x00, 0x00, 0x00, 0x04, 0x08, }; static const u8 init_vals_ver_21[] = { - /* QT602240_GEN_COMMAND(6) */ + /* MXT_GEN_COMMAND(6) */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - /* QT602240_GEN_POWER(7) */ + /* MXT_GEN_POWER(7) */ 0x20, 0xff, 0x32, - /* QT602240_GEN_ACQUIRE(8) */ + /* MXT_GEN_ACQUIRE(8) */ 0x0a, 0x00, 0x05, 0x00, 0x00, 0x00, 0x09, 0x23, - /* QT602240_TOUCH_MULTI(9) */ + /* MXT_TOUCH_MULTI(9) */ 0x00, 0x00, 0x00, 0x13, 0x0b, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x01, 0x01, 0x0e, 0x0a, 0x0a, 0x0a, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - /* QT602240_TOUCH_KEYARRAY(15) */ + /* MXT_TOUCH_KEYARRAY(15) */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - /* QT602240_SPT_GPIOPWM(19) */ + /* MXT_SPT_GPIOPWM(19) */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - /* QT602240_PROCI_GRIPFACE(20) */ + /* MXT_PROCI_GRIPFACE(20) */ 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x28, 0x04, 0x0f, 0x0a, - /* QT602240_PROCG_NOISE(22) */ + /* MXT_PROCG_NOISE(22) */ 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x23, 0x00, 0x00, 0x05, 0x0f, 0x19, 0x23, 0x2d, 0x03, - /* QT602240_TOUCH_PROXIMITY(23) */ + /* MXT_TOUCH_PROXIMITY(23) */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - /* QT602240_PROCI_ONETOUCH(24) */ + /* MXT_PROCI_ONETOUCH(24) */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - /* QT602240_SPT_SELFTEST(25) */ + /* MXT_SPT_SELFTEST(25) */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - /* QT602240_PROCI_TWOTOUCH(27) */ + /* MXT_PROCI_TWOTOUCH(27) */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - /* QT602240_SPT_CTECONFIG(28) */ + /* MXT_SPT_CTECONFIG(28) */ 0x00, 0x00, 0x00, 0x08, 0x10, 0x00, }; static const u8 init_vals_ver_22[] = { - /* QT602240_GEN_COMMAND(6) */ + /* MXT_GEN_COMMAND(6) */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - /* QT602240_GEN_POWER(7) */ + /* MXT_GEN_POWER(7) */ 0x20, 0xff, 0x32, - /* QT602240_GEN_ACQUIRE(8) */ + /* MXT_GEN_ACQUIRE(8) */ 0x0a, 0x00, 0x05, 0x00, 0x00, 0x00, 0x09, 0x23, - /* QT602240_TOUCH_MULTI(9) */ + /* MXT_TOUCH_MULTI(9) */ 0x00, 0x00, 0x00, 0x13, 0x0b, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x01, 0x01, 0x0e, 0x0a, 0x0a, 0x0a, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - /* QT602240_TOUCH_KEYARRAY(15) */ + /* MXT_TOUCH_KEYARRAY(15) */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - /* QT602240_SPT_GPIOPWM(19) */ + /* MXT_SPT_GPIOPWM(19) */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - /* QT602240_PROCI_GRIPFACE(20) */ + /* MXT_PROCI_GRIPFACE(20) */ 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x28, 0x04, 0x0f, 0x0a, - /* QT602240_PROCG_NOISE(22) */ + /* MXT_PROCG_NOISE(22) */ 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x23, 0x00, 0x00, 0x05, 0x0f, 0x19, 0x23, 0x2d, 0x03, - /* QT602240_TOUCH_PROXIMITY(23) */ + /* MXT_TOUCH_PROXIMITY(23) */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - /* QT602240_PROCI_ONETOUCH(24) */ + /* MXT_PROCI_ONETOUCH(24) */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - /* QT602240_SPT_SELFTEST(25) */ + /* MXT_SPT_SELFTEST(25) */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - /* QT602240_PROCI_TWOTOUCH(27) */ + /* MXT_PROCI_TWOTOUCH(27) */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - /* QT602240_SPT_CTECONFIG(28) */ + /* MXT_SPT_CTECONFIG(28) */ 0x00, 0x00, 0x00, 0x08, 0x10, 0x00, }; -struct qt602240_info { +struct mxt_info { u8 family_id; u8 variant_id; u8 version; @@ -325,7 +325,7 @@ struct qt602240_info { u8 object_num; }; -struct qt602240_object { +struct mxt_object { u8 type; u16 start_address; u8 size; @@ -336,13 +336,13 @@ struct qt602240_object { u8 max_reportid; }; -struct qt602240_message { +struct mxt_message { u8 reportid; u8 message[7]; u8 checksum; }; -struct qt602240_finger { +struct mxt_finger { int status; int x; int y; @@ -350,65 +350,65 @@ struct qt602240_finger { }; /* Each client has this additional data */ -struct qt602240_data { +struct mxt_data { struct i2c_client *client; struct input_dev *input_dev; - const struct qt602240_platform_data *pdata; - struct qt602240_object *object_table; - struct qt602240_info info; - struct qt602240_finger finger[QT602240_MAX_FINGER]; + const struct mxt_platform_data *pdata; + struct mxt_object *object_table; + struct mxt_info info; + struct mxt_finger finger[MXT_MAX_FINGER]; unsigned int irq; }; -static bool qt602240_object_readable(unsigned int type) +static bool mxt_object_readable(unsigned int type) { switch (type) { - case QT602240_GEN_MESSAGE: - case QT602240_GEN_COMMAND: - case QT602240_GEN_POWER: - case QT602240_GEN_ACQUIRE: - case QT602240_TOUCH_MULTI: - case QT602240_TOUCH_KEYARRAY: - case QT602240_TOUCH_PROXIMITY: - case QT602240_PROCI_GRIPFACE: - case QT602240_PROCG_NOISE: - case QT602240_PROCI_ONETOUCH: - case QT602240_PROCI_TWOTOUCH: - case QT602240_SPT_COMMSCONFIG: - case QT602240_SPT_GPIOPWM: - case QT602240_SPT_SELFTEST: - case QT602240_SPT_CTECONFIG: - case QT602240_SPT_USERDATA: + case MXT_GEN_MESSAGE: + case MXT_GEN_COMMAND: + case MXT_GEN_POWER: + case MXT_GEN_ACQUIRE: + case MXT_TOUCH_MULTI: + case MXT_TOUCH_KEYARRAY: + case MXT_TOUCH_PROXIMITY: + case MXT_PROCI_GRIPFACE: + case MXT_PROCG_NOISE: + case MXT_PROCI_ONETOUCH: + case MXT_PROCI_TWOTOUCH: + case MXT_SPT_COMMSCONFIG: + case MXT_SPT_GPIOPWM: + case MXT_SPT_SELFTEST: + case MXT_SPT_CTECONFIG: + case MXT_SPT_USERDATA: return true; default: return false; } } -static bool qt602240_object_writable(unsigned int type) +static bool mxt_object_writable(unsigned int type) { switch (type) { - case QT602240_GEN_COMMAND: - case QT602240_GEN_POWER: - case QT602240_GEN_ACQUIRE: - case QT602240_TOUCH_MULTI: - case QT602240_TOUCH_KEYARRAY: - case QT602240_TOUCH_PROXIMITY: - case QT602240_PROCI_GRIPFACE: - case QT602240_PROCG_NOISE: - case QT602240_PROCI_ONETOUCH: - case QT602240_PROCI_TWOTOUCH: - case QT602240_SPT_GPIOPWM: - case QT602240_SPT_SELFTEST: - case QT602240_SPT_CTECONFIG: + case MXT_GEN_COMMAND: + case MXT_GEN_POWER: + case MXT_GEN_ACQUIRE: + case MXT_TOUCH_MULTI: + case MXT_TOUCH_KEYARRAY: + case MXT_TOUCH_PROXIMITY: + case MXT_PROCI_GRIPFACE: + case MXT_PROCG_NOISE: + case MXT_PROCI_ONETOUCH: + case MXT_PROCI_TWOTOUCH: + case MXT_SPT_GPIOPWM: + case MXT_SPT_SELFTEST: + case MXT_SPT_CTECONFIG: return true; default: return false; } } -static void qt602240_dump_message(struct device *dev, - struct qt602240_message *message) +static void mxt_dump_message(struct device *dev, + struct mxt_message *message) { dev_dbg(dev, "reportid:\t0x%x\n", message->reportid); dev_dbg(dev, "message1:\t0x%x\n", message->message[0]); @@ -421,7 +421,7 @@ static void qt602240_dump_message(struct device *dev, dev_dbg(dev, "checksum:\t0x%x\n", message->checksum); } -static int qt602240_check_bootloader(struct i2c_client *client, +static int mxt_check_bootloader(struct i2c_client *client, unsigned int state) { u8 val; @@ -433,12 +433,12 @@ recheck: } switch (state) { - case QT602240_WAITING_BOOTLOAD_CMD: - case QT602240_WAITING_FRAME_DATA: - val &= ~QT602240_BOOT_STATUS_MASK; + case MXT_WAITING_BOOTLOAD_CMD: + case MXT_WAITING_FRAME_DATA: + val &= ~MXT_BOOT_STATUS_MASK; break; - case QT602240_FRAME_CRC_PASS: - if (val == QT602240_FRAME_CRC_CHECK) + case MXT_FRAME_CRC_PASS: + if (val == MXT_FRAME_CRC_CHECK) goto recheck; break; default: @@ -453,12 +453,12 @@ recheck: return 0; } -static int qt602240_unlock_bootloader(struct i2c_client *client) +static int mxt_unlock_bootloader(struct i2c_client *client) { u8 buf[2]; - buf[0] = QT602240_UNLOCK_CMD_LSB; - buf[1] = QT602240_UNLOCK_CMD_MSB; + buf[0] = MXT_UNLOCK_CMD_LSB; + buf[1] = MXT_UNLOCK_CMD_MSB; if (i2c_master_send(client, buf, 2) != 2) { dev_err(&client->dev, "%s: i2c send failed\n", __func__); @@ -468,7 +468,7 @@ static int qt602240_unlock_bootloader(struct i2c_client *client) return 0; } -static int qt602240_fw_write(struct i2c_client *client, +static int mxt_fw_write(struct i2c_client *client, const u8 *data, unsigned int frame_size) { if (i2c_master_send(client, data, frame_size) != frame_size) { @@ -479,7 +479,7 @@ static int qt602240_fw_write(struct i2c_client *client, return 0; } -static int __qt602240_read_reg(struct i2c_client *client, +static int __mxt_read_reg(struct i2c_client *client, u16 reg, u16 len, void *val) { struct i2c_msg xfer[2]; @@ -508,12 +508,12 @@ static int __qt602240_read_reg(struct i2c_client *client, return 0; } -static int qt602240_read_reg(struct i2c_client *client, u16 reg, u8 *val) +static int mxt_read_reg(struct i2c_client *client, u16 reg, u8 *val) { - return __qt602240_read_reg(client, reg, 1, val); + return __mxt_read_reg(client, reg, 1, val); } -static int qt602240_write_reg(struct i2c_client *client, u16 reg, u8 val) +static int mxt_write_reg(struct i2c_client *client, u16 reg, u8 val) { u8 buf[3]; @@ -529,17 +529,17 @@ static int qt602240_write_reg(struct i2c_client *client, u16 reg, u8 val) return 0; } -static int qt602240_read_object_table(struct i2c_client *client, +static int mxt_read_object_table(struct i2c_client *client, u16 reg, u8 *object_buf) { - return __qt602240_read_reg(client, reg, QT602240_OBJECT_SIZE, + return __mxt_read_reg(client, reg, MXT_OBJECT_SIZE, object_buf); } -static struct qt602240_object * -qt602240_get_object(struct qt602240_data *data, u8 type) +static struct mxt_object * +mxt_get_object(struct mxt_data *data, u8 type) { - struct qt602240_object *object; + struct mxt_object *object; int i; for (i = 0; i < data->info.object_num; i++) { @@ -552,63 +552,63 @@ qt602240_get_object(struct qt602240_data *data, u8 type) return NULL; } -static int qt602240_read_message(struct qt602240_data *data, - struct qt602240_message *message) +static int mxt_read_message(struct mxt_data *data, + struct mxt_message *message) { - struct qt602240_object *object; + struct mxt_object *object; u16 reg; - object = qt602240_get_object(data, QT602240_GEN_MESSAGE); + object = mxt_get_object(data, MXT_GEN_MESSAGE); if (!object) return -EINVAL; reg = object->start_address; - return __qt602240_read_reg(data->client, reg, - sizeof(struct qt602240_message), message); + return __mxt_read_reg(data->client, reg, + sizeof(struct mxt_message), message); } -static int qt602240_read_object(struct qt602240_data *data, +static int mxt_read_object(struct mxt_data *data, u8 type, u8 offset, u8 *val) { - struct qt602240_object *object; + struct mxt_object *object; u16 reg; - object = qt602240_get_object(data, type); + object = mxt_get_object(data, type); if (!object) return -EINVAL; reg = object->start_address; - return __qt602240_read_reg(data->client, reg + offset, 1, val); + return __mxt_read_reg(data->client, reg + offset, 1, val); } -static int qt602240_write_object(struct qt602240_data *data, +static int mxt_write_object(struct mxt_data *data, u8 type, u8 offset, u8 val) { - struct qt602240_object *object; + struct mxt_object *object; u16 reg; - object = qt602240_get_object(data, type); + object = mxt_get_object(data, type); if (!object) return -EINVAL; reg = object->start_address; - return qt602240_write_reg(data->client, reg + offset, val); + return mxt_write_reg(data->client, reg + offset, val); } -static void qt602240_input_report(struct qt602240_data *data, int single_id) +static void mxt_input_report(struct mxt_data *data, int single_id) { - struct qt602240_finger *finger = data->finger; + struct mxt_finger *finger = data->finger; struct input_dev *input_dev = data->input_dev; int status = finger[single_id].status; int finger_num = 0; int id; - for (id = 0; id < QT602240_MAX_FINGER; id++) { + for (id = 0; id < MXT_MAX_FINGER; id++) { if (!finger[id].status) continue; input_report_abs(input_dev, ABS_MT_TOUCH_MAJOR, - finger[id].status != QT602240_RELEASE ? + finger[id].status != MXT_RELEASE ? finger[id].area : 0); input_report_abs(input_dev, ABS_MT_POSITION_X, finger[id].x); @@ -616,7 +616,7 @@ static void qt602240_input_report(struct qt602240_data *data, int single_id) finger[id].y); input_mt_sync(input_dev); - if (finger[id].status == QT602240_RELEASE) + if (finger[id].status == MXT_RELEASE) finger[id].status = 0; else finger_num++; @@ -624,7 +624,7 @@ static void qt602240_input_report(struct qt602240_data *data, int single_id) input_report_key(input_dev, BTN_TOUCH, finger_num > 0); - if (status != QT602240_RELEASE) { + if (status != MXT_RELEASE) { input_report_abs(input_dev, ABS_X, finger[single_id].x); input_report_abs(input_dev, ABS_Y, finger[single_id].y); } @@ -632,10 +632,10 @@ static void qt602240_input_report(struct qt602240_data *data, int single_id) input_sync(input_dev); } -static void qt602240_input_touchevent(struct qt602240_data *data, - struct qt602240_message *message, int id) +static void mxt_input_touchevent(struct mxt_data *data, + struct mxt_message *message, int id) { - struct qt602240_finger *finger = data->finger; + struct mxt_finger *finger = data->finger; struct device *dev = &data->client->dev; u8 status = message->message[0]; int x; @@ -643,18 +643,18 @@ static void qt602240_input_touchevent(struct qt602240_data *data, int area; /* Check the touch is present on the screen */ - if (!(status & QT602240_DETECT)) { - if (status & QT602240_RELEASE) { + if (!(status & MXT_DETECT)) { + if (status & MXT_RELEASE) { dev_dbg(dev, "[%d] released\n", id); - finger[id].status = QT602240_RELEASE; - qt602240_input_report(data, id); + finger[id].status = MXT_RELEASE; + mxt_input_report(data, id); } return; } /* Check only AMP detection */ - if (!(status & (QT602240_PRESS | QT602240_MOVE))) + if (!(status & (MXT_PRESS | MXT_MOVE))) return; x = (message->message[1] << 2) | ((message->message[3] & ~0x3f) >> 6); @@ -662,23 +662,23 @@ static void qt602240_input_touchevent(struct qt602240_data *data, area = message->message[4]; dev_dbg(dev, "[%d] %s x: %d, y: %d, area: %d\n", id, - status & QT602240_MOVE ? "moved" : "pressed", + status & MXT_MOVE ? "moved" : "pressed", x, y, area); - finger[id].status = status & QT602240_MOVE ? - QT602240_MOVE : QT602240_PRESS; + finger[id].status = status & MXT_MOVE ? + MXT_MOVE : MXT_PRESS; finger[id].x = x; finger[id].y = y; finger[id].area = area; - qt602240_input_report(data, id); + mxt_input_report(data, id); } -static irqreturn_t qt602240_interrupt(int irq, void *dev_id) +static irqreturn_t mxt_interrupt(int irq, void *dev_id) { - struct qt602240_data *data = dev_id; - struct qt602240_message message; - struct qt602240_object *object; + struct mxt_data *data = dev_id; + struct mxt_message message; + struct mxt_object *object; struct device *dev = &data->client->dev; int id; u8 reportid; @@ -686,15 +686,15 @@ static irqreturn_t qt602240_interrupt(int irq, void *dev_id) u8 min_reportid; do { - if (qt602240_read_message(data, &message)) { + if (mxt_read_message(data, &message)) { dev_err(dev, "Failed to read message\n"); goto end; } reportid = message.reportid; - /* whether reportid is thing of QT602240_TOUCH_MULTI */ - object = qt602240_get_object(data, QT602240_TOUCH_MULTI); + /* whether reportid is thing of MXT_TOUCH_MULTI */ + object = mxt_get_object(data, MXT_TOUCH_MULTI); if (!object) goto end; @@ -703,18 +703,18 @@ static irqreturn_t qt602240_interrupt(int irq, void *dev_id) id = reportid - min_reportid; if (reportid >= min_reportid && reportid <= max_reportid) - qt602240_input_touchevent(data, &message, id); + mxt_input_touchevent(data, &message, id); else - qt602240_dump_message(dev, &message); + mxt_dump_message(dev, &message); } while (reportid != 0xff); end: return IRQ_HANDLED; } -static int qt602240_check_reg_init(struct qt602240_data *data) +static int mxt_check_reg_init(struct mxt_data *data) { - struct qt602240_object *object; + struct mxt_object *object; struct device *dev = &data->client->dev; int index = 0; int i, j; @@ -722,13 +722,13 @@ static int qt602240_check_reg_init(struct qt602240_data *data) u8 *init_vals; switch (version) { - case QT602240_VER_20: + case MXT_VER_20: init_vals = (u8 *)init_vals_ver_20; break; - case QT602240_VER_21: + case MXT_VER_21: init_vals = (u8 *)init_vals_ver_21; break; - case QT602240_VER_22: + case MXT_VER_22: init_vals = (u8 *)init_vals_ver_22; break; default: @@ -739,11 +739,11 @@ static int qt602240_check_reg_init(struct qt602240_data *data) for (i = 0; i < data->info.object_num; i++) { object = data->object_table + i; - if (!qt602240_object_writable(object->type)) + if (!mxt_object_writable(object->type)) continue; for (j = 0; j < object->size + 1; j++) - qt602240_write_object(data, object->type, j, + mxt_write_object(data, object->type, j, init_vals[index + j]); index += object->size + 1; @@ -752,9 +752,9 @@ static int qt602240_check_reg_init(struct qt602240_data *data) return 0; } -static int qt602240_check_matrix_size(struct qt602240_data *data) +static int mxt_check_matrix_size(struct mxt_data *data) { - const struct qt602240_platform_data *pdata = data->pdata; + const struct mxt_platform_data *pdata = data->pdata; struct device *dev = &data->client->dev; int mode = -1; int error; @@ -801,8 +801,8 @@ static int qt602240_check_matrix_size(struct qt602240_data *data) return -EINVAL; } - error = qt602240_read_object(data, QT602240_SPT_CTECONFIG, - QT602240_CTE_MODE, &val); + error = mxt_read_object(data, MXT_SPT_CTECONFIG, + MXT_CTE_MODE, &val); if (error) return error; @@ -810,17 +810,17 @@ static int qt602240_check_matrix_size(struct qt602240_data *data) return 0; /* Change the CTE configuration */ - qt602240_write_object(data, QT602240_SPT_CTECONFIG, - QT602240_CTE_CTRL, 1); - qt602240_write_object(data, QT602240_SPT_CTECONFIG, - QT602240_CTE_MODE, mode); - qt602240_write_object(data, QT602240_SPT_CTECONFIG, - QT602240_CTE_CTRL, 0); + mxt_write_object(data, MXT_SPT_CTECONFIG, + MXT_CTE_CTRL, 1); + mxt_write_object(data, MXT_SPT_CTECONFIG, + MXT_CTE_MODE, mode); + mxt_write_object(data, MXT_SPT_CTECONFIG, + MXT_CTE_CTRL, 0); return 0; } -static int qt602240_make_highchg(struct qt602240_data *data) +static int mxt_make_highchg(struct mxt_data *data) { struct device *dev = &data->client->dev; int count = 10; @@ -829,7 +829,7 @@ static int qt602240_make_highchg(struct qt602240_data *data) /* Read dummy message to make high CHG pin */ do { - error = qt602240_read_object(data, QT602240_GEN_MESSAGE, 0, &val); + error = mxt_read_object(data, MXT_GEN_MESSAGE, 0, &val); if (error) return error; } while ((val != 0xff) && --count); @@ -842,82 +842,82 @@ static int qt602240_make_highchg(struct qt602240_data *data) return 0; } -static void qt602240_handle_pdata(struct qt602240_data *data) +static void mxt_handle_pdata(struct mxt_data *data) { - const struct qt602240_platform_data *pdata = data->pdata; + const struct mxt_platform_data *pdata = data->pdata; u8 voltage; /* Set touchscreen lines */ - qt602240_write_object(data, QT602240_TOUCH_MULTI, QT602240_TOUCH_XSIZE, + mxt_write_object(data, MXT_TOUCH_MULTI, MXT_TOUCH_XSIZE, pdata->x_line); - qt602240_write_object(data, QT602240_TOUCH_MULTI, QT602240_TOUCH_YSIZE, + mxt_write_object(data, MXT_TOUCH_MULTI, MXT_TOUCH_YSIZE, pdata->y_line); /* Set touchscreen orient */ - qt602240_write_object(data, QT602240_TOUCH_MULTI, QT602240_TOUCH_ORIENT, + mxt_write_object(data, MXT_TOUCH_MULTI, MXT_TOUCH_ORIENT, pdata->orient); /* Set touchscreen burst length */ - qt602240_write_object(data, QT602240_TOUCH_MULTI, - QT602240_TOUCH_BLEN, pdata->blen); + mxt_write_object(data, MXT_TOUCH_MULTI, + MXT_TOUCH_BLEN, pdata->blen); /* Set touchscreen threshold */ - qt602240_write_object(data, QT602240_TOUCH_MULTI, - QT602240_TOUCH_TCHTHR, pdata->threshold); + mxt_write_object(data, MXT_TOUCH_MULTI, + MXT_TOUCH_TCHTHR, pdata->threshold); /* Set touchscreen resolution */ - qt602240_write_object(data, QT602240_TOUCH_MULTI, - QT602240_TOUCH_XRANGE_LSB, (pdata->x_size - 1) & 0xff); - qt602240_write_object(data, QT602240_TOUCH_MULTI, - QT602240_TOUCH_XRANGE_MSB, (pdata->x_size - 1) >> 8); - qt602240_write_object(data, QT602240_TOUCH_MULTI, - QT602240_TOUCH_YRANGE_LSB, (pdata->y_size - 1) & 0xff); - qt602240_write_object(data, QT602240_TOUCH_MULTI, - QT602240_TOUCH_YRANGE_MSB, (pdata->y_size - 1) >> 8); + mxt_write_object(data, MXT_TOUCH_MULTI, + MXT_TOUCH_XRANGE_LSB, (pdata->x_size - 1) & 0xff); + mxt_write_object(data, MXT_TOUCH_MULTI, + MXT_TOUCH_XRANGE_MSB, (pdata->x_size - 1) >> 8); + mxt_write_object(data, MXT_TOUCH_MULTI, + MXT_TOUCH_YRANGE_LSB, (pdata->y_size - 1) & 0xff); + mxt_write_object(data, MXT_TOUCH_MULTI, + MXT_TOUCH_YRANGE_MSB, (pdata->y_size - 1) >> 8); /* Set touchscreen voltage */ - if (data->info.version >= QT602240_VER_21 && pdata->voltage) { - if (pdata->voltage < QT602240_VOLTAGE_DEFAULT) { - voltage = (QT602240_VOLTAGE_DEFAULT - pdata->voltage) / - QT602240_VOLTAGE_STEP; + if (data->info.version >= MXT_VER_21 && pdata->voltage) { + if (pdata->voltage < MXT_VOLTAGE_DEFAULT) { + voltage = (MXT_VOLTAGE_DEFAULT - pdata->voltage) / + MXT_VOLTAGE_STEP; voltage = 0xff - voltage + 1; } else - voltage = (pdata->voltage - QT602240_VOLTAGE_DEFAULT) / - QT602240_VOLTAGE_STEP; + voltage = (pdata->voltage - MXT_VOLTAGE_DEFAULT) / + MXT_VOLTAGE_STEP; - qt602240_write_object(data, QT602240_SPT_CTECONFIG, - QT602240_CTE_VOLTAGE, voltage); + mxt_write_object(data, MXT_SPT_CTECONFIG, + MXT_CTE_VOLTAGE, voltage); } } -static int qt602240_get_info(struct qt602240_data *data) +static int mxt_get_info(struct mxt_data *data) { struct i2c_client *client = data->client; - struct qt602240_info *info = &data->info; + struct mxt_info *info = &data->info; int error; u8 val; - error = qt602240_read_reg(client, QT602240_FAMILY_ID, &val); + error = mxt_read_reg(client, MXT_FAMILY_ID, &val); if (error) return error; info->family_id = val; - error = qt602240_read_reg(client, QT602240_VARIANT_ID, &val); + error = mxt_read_reg(client, MXT_VARIANT_ID, &val); if (error) return error; info->variant_id = val; - error = qt602240_read_reg(client, QT602240_VERSION, &val); + error = mxt_read_reg(client, MXT_VERSION, &val); if (error) return error; info->version = val; - error = qt602240_read_reg(client, QT602240_BUILD, &val); + error = mxt_read_reg(client, MXT_BUILD, &val); if (error) return error; info->build = val; - error = qt602240_read_reg(client, QT602240_OBJECT_NUM, &val); + error = mxt_read_reg(client, MXT_OBJECT_NUM, &val); if (error) return error; info->object_num = val; @@ -925,19 +925,19 @@ static int qt602240_get_info(struct qt602240_data *data) return 0; } -static int qt602240_get_object_table(struct qt602240_data *data) +static int mxt_get_object_table(struct mxt_data *data) { int error; int i; u16 reg; u8 reportid = 0; - u8 buf[QT602240_OBJECT_SIZE]; + u8 buf[MXT_OBJECT_SIZE]; for (i = 0; i < data->info.object_num; i++) { - struct qt602240_object *object = data->object_table + i; + struct mxt_object *object = data->object_table + i; - reg = QT602240_OBJECT_START + QT602240_OBJECT_SIZE * i; - error = qt602240_read_object_table(data->client, reg, buf); + reg = MXT_OBJECT_START + MXT_OBJECT_SIZE * i; + error = mxt_read_object_table(data->client, reg, buf); if (error) return error; @@ -957,19 +957,19 @@ static int qt602240_get_object_table(struct qt602240_data *data) return 0; } -static int qt602240_initialize(struct qt602240_data *data) +static int mxt_initialize(struct mxt_data *data) { struct i2c_client *client = data->client; - struct qt602240_info *info = &data->info; + struct mxt_info *info = &data->info; int error; u8 val; - error = qt602240_get_info(data); + error = mxt_get_info(data); if (error) return error; data->object_table = kcalloc(info->object_num, - sizeof(struct qt602240_object), + sizeof(struct mxt_object), GFP_KERNEL); if (!data->object_table) { dev_err(&client->dev, "Failed to allocate memory\n"); @@ -977,44 +977,44 @@ static int qt602240_initialize(struct qt602240_data *data) } /* Get object table information */ - error = qt602240_get_object_table(data); + error = mxt_get_object_table(data); if (error) return error; /* Check register init values */ - error = qt602240_check_reg_init(data); + error = mxt_check_reg_init(data); if (error) return error; /* Check X/Y matrix size */ - error = qt602240_check_matrix_size(data); + error = mxt_check_matrix_size(data); if (error) return error; - error = qt602240_make_highchg(data); + error = mxt_make_highchg(data); if (error) return error; - qt602240_handle_pdata(data); + mxt_handle_pdata(data); /* Backup to memory */ - qt602240_write_object(data, QT602240_GEN_COMMAND, - QT602240_COMMAND_BACKUPNV, - QT602240_BACKUP_VALUE); - msleep(QT602240_BACKUP_TIME); + mxt_write_object(data, MXT_GEN_COMMAND, + MXT_COMMAND_BACKUPNV, + MXT_BACKUP_VALUE); + msleep(MXT_BACKUP_TIME); /* Soft reset */ - qt602240_write_object(data, QT602240_GEN_COMMAND, - QT602240_COMMAND_RESET, 1); - msleep(QT602240_RESET_TIME); + mxt_write_object(data, MXT_GEN_COMMAND, + MXT_COMMAND_RESET, 1); + msleep(MXT_RESET_TIME); /* Update matrix size at info struct */ - error = qt602240_read_reg(client, QT602240_MATRIX_X_SIZE, &val); + error = mxt_read_reg(client, MXT_MATRIX_X_SIZE, &val); if (error) return error; info->matrix_xsize = val; - error = qt602240_read_reg(client, QT602240_MATRIX_Y_SIZE, &val); + error = mxt_read_reg(client, MXT_MATRIX_Y_SIZE, &val); if (error) return error; info->matrix_ysize = val; @@ -1032,11 +1032,11 @@ static int qt602240_initialize(struct qt602240_data *data) return 0; } -static ssize_t qt602240_object_show(struct device *dev, +static ssize_t mxt_object_show(struct device *dev, struct device_attribute *attr, char *buf) { - struct qt602240_data *data = dev_get_drvdata(dev); - struct qt602240_object *object; + struct mxt_data *data = dev_get_drvdata(dev); + struct mxt_object *object; int count = 0; int i, j; int error; @@ -1049,13 +1049,13 @@ static ssize_t qt602240_object_show(struct device *dev, "Object Table Element %d(Type %d)\n", i + 1, object->type); - if (!qt602240_object_readable(object->type)) { + if (!mxt_object_readable(object->type)) { count += sprintf(buf + count, "\n"); continue; } for (j = 0; j < object->size + 1; j++) { - error = qt602240_read_object(data, + error = mxt_read_object(data, object->type, j, &val); if (error) return error; @@ -1070,9 +1070,9 @@ static ssize_t qt602240_object_show(struct device *dev, return count; } -static int qt602240_load_fw(struct device *dev, const char *fn) +static int mxt_load_fw(struct device *dev, const char *fn) { - struct qt602240_data *data = dev_get_drvdata(dev); + struct mxt_data *data = dev_get_drvdata(dev); struct i2c_client *client = data->client; const struct firmware *fw = NULL; unsigned int frame_size; @@ -1086,26 +1086,26 @@ static int qt602240_load_fw(struct device *dev, const char *fn) } /* Change to the bootloader mode */ - qt602240_write_object(data, QT602240_GEN_COMMAND, - QT602240_COMMAND_RESET, QT602240_BOOT_VALUE); - msleep(QT602240_RESET_TIME); + mxt_write_object(data, MXT_GEN_COMMAND, + MXT_COMMAND_RESET, MXT_BOOT_VALUE); + msleep(MXT_RESET_TIME); /* Change to slave address of bootloader */ - if (client->addr == QT602240_APP_LOW) - client->addr = QT602240_BOOT_LOW; + if (client->addr == MXT_APP_LOW) + client->addr = MXT_BOOT_LOW; else - client->addr = QT602240_BOOT_HIGH; + client->addr = MXT_BOOT_HIGH; - ret = qt602240_check_bootloader(client, QT602240_WAITING_BOOTLOAD_CMD); + ret = mxt_check_bootloader(client, MXT_WAITING_BOOTLOAD_CMD); if (ret) goto out; /* Unlock bootloader */ - qt602240_unlock_bootloader(client); + mxt_unlock_bootloader(client); while (pos < fw->size) { - ret = qt602240_check_bootloader(client, - QT602240_WAITING_FRAME_DATA); + ret = mxt_check_bootloader(client, + MXT_WAITING_FRAME_DATA); if (ret) goto out; @@ -1117,10 +1117,10 @@ static int qt602240_load_fw(struct device *dev, const char *fn) frame_size += 2; /* Write one frame to device */ - qt602240_fw_write(client, fw->data + pos, frame_size); + mxt_fw_write(client, fw->data + pos, frame_size); - ret = qt602240_check_bootloader(client, - QT602240_FRAME_CRC_PASS); + ret = mxt_check_bootloader(client, + MXT_FRAME_CRC_PASS); if (ret) goto out; @@ -1133,19 +1133,19 @@ out: release_firmware(fw); /* Change to slave address of application */ - if (client->addr == QT602240_BOOT_LOW) - client->addr = QT602240_APP_LOW; + if (client->addr == MXT_BOOT_LOW) + client->addr = MXT_APP_LOW; else - client->addr = QT602240_APP_HIGH; + client->addr = MXT_APP_HIGH; return ret; } -static ssize_t qt602240_update_fw_store(struct device *dev, +static ssize_t mxt_update_fw_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - struct qt602240_data *data = dev_get_drvdata(dev); + struct mxt_data *data = dev_get_drvdata(dev); unsigned int version; int error; @@ -1154,14 +1154,14 @@ static ssize_t qt602240_update_fw_store(struct device *dev, return -EINVAL; } - if (data->info.version < QT602240_VER_21 || version < QT602240_VER_21) { + if (data->info.version < MXT_VER_21 || version < MXT_VER_21) { dev_err(dev, "FW update supported starting with version 21\n"); return -EINVAL; } disable_irq(data->irq); - error = qt602240_load_fw(dev, QT602240_FW_NAME); + error = mxt_load_fw(dev, MXT_FW_NAME); if (error) { dev_err(dev, "The firmware update failed(%d)\n", error); count = error; @@ -1169,12 +1169,12 @@ static ssize_t qt602240_update_fw_store(struct device *dev, dev_dbg(dev, "The firmware update succeeded\n"); /* Wait for reset */ - msleep(QT602240_FWRESET_TIME); + msleep(MXT_FWRESET_TIME); kfree(data->object_table); data->object_table = NULL; - qt602240_initialize(data); + mxt_initialize(data); } enable_irq(data->irq); @@ -1182,60 +1182,60 @@ static ssize_t qt602240_update_fw_store(struct device *dev, return count; } -static DEVICE_ATTR(object, 0444, qt602240_object_show, NULL); -static DEVICE_ATTR(update_fw, 0664, NULL, qt602240_update_fw_store); +static DEVICE_ATTR(object, 0444, mxt_object_show, NULL); +static DEVICE_ATTR(update_fw, 0664, NULL, mxt_update_fw_store); -static struct attribute *qt602240_attrs[] = { +static struct attribute *mxt_attrs[] = { &dev_attr_object.attr, &dev_attr_update_fw.attr, NULL }; -static const struct attribute_group qt602240_attr_group = { - .attrs = qt602240_attrs, +static const struct attribute_group mxt_attr_group = { + .attrs = mxt_attrs, }; -static void qt602240_start(struct qt602240_data *data) +static void mxt_start(struct mxt_data *data) { /* Touch enable */ - qt602240_write_object(data, - QT602240_TOUCH_MULTI, QT602240_TOUCH_CTRL, 0x83); + mxt_write_object(data, + MXT_TOUCH_MULTI, MXT_TOUCH_CTRL, 0x83); } -static void qt602240_stop(struct qt602240_data *data) +static void mxt_stop(struct mxt_data *data) { /* Touch disable */ - qt602240_write_object(data, - QT602240_TOUCH_MULTI, QT602240_TOUCH_CTRL, 0); + mxt_write_object(data, + MXT_TOUCH_MULTI, MXT_TOUCH_CTRL, 0); } -static int qt602240_input_open(struct input_dev *dev) +static int mxt_input_open(struct input_dev *dev) { - struct qt602240_data *data = input_get_drvdata(dev); + struct mxt_data *data = input_get_drvdata(dev); - qt602240_start(data); + mxt_start(data); return 0; } -static void qt602240_input_close(struct input_dev *dev) +static void mxt_input_close(struct input_dev *dev) { - struct qt602240_data *data = input_get_drvdata(dev); + struct mxt_data *data = input_get_drvdata(dev); - qt602240_stop(data); + mxt_stop(data); } -static int __devinit qt602240_probe(struct i2c_client *client, +static int __devinit mxt_probe(struct i2c_client *client, const struct i2c_device_id *id) { - struct qt602240_data *data; + struct mxt_data *data; struct input_dev *input_dev; int error; if (!client->dev.platform_data) return -EINVAL; - data = kzalloc(sizeof(struct qt602240_data), GFP_KERNEL); + data = kzalloc(sizeof(struct mxt_data), GFP_KERNEL); input_dev = input_allocate_device(); if (!data || !input_dev) { dev_err(&client->dev, "Failed to allocate memory\n"); @@ -1243,11 +1243,11 @@ static int __devinit qt602240_probe(struct i2c_client *client, goto err_free_mem; } - input_dev->name = "AT42QT602240/ATMXT224 Touchscreen"; + input_dev->name = "Atmel maXTouch Touchscreen"; input_dev->id.bustype = BUS_I2C; input_dev->dev.parent = &client->dev; - input_dev->open = qt602240_input_open; - input_dev->close = qt602240_input_close; + input_dev->open = mxt_input_open; + input_dev->close = mxt_input_close; __set_bit(EV_ABS, input_dev->evbit); __set_bit(EV_KEY, input_dev->evbit); @@ -1255,17 +1255,17 @@ static int __devinit qt602240_probe(struct i2c_client *client, /* For single touch */ input_set_abs_params(input_dev, ABS_X, - 0, QT602240_MAX_XC, 0, 0); + 0, MXT_MAX_XC, 0, 0); input_set_abs_params(input_dev, ABS_Y, - 0, QT602240_MAX_YC, 0, 0); + 0, MXT_MAX_YC, 0, 0); /* For multi touch */ input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR, - 0, QT602240_MAX_AREA, 0, 0); + 0, MXT_MAX_AREA, 0, 0); input_set_abs_params(input_dev, ABS_MT_POSITION_X, - 0, QT602240_MAX_XC, 0, 0); + 0, MXT_MAX_XC, 0, 0); input_set_abs_params(input_dev, ABS_MT_POSITION_Y, - 0, QT602240_MAX_YC, 0, 0); + 0, MXT_MAX_YC, 0, 0); input_set_drvdata(input_dev, data); @@ -1276,11 +1276,11 @@ static int __devinit qt602240_probe(struct i2c_client *client, i2c_set_clientdata(client, data); - error = qt602240_initialize(data); + error = mxt_initialize(data); if (error) goto err_free_object; - error = request_threaded_irq(client->irq, NULL, qt602240_interrupt, + error = request_threaded_irq(client->irq, NULL, mxt_interrupt, IRQF_TRIGGER_FALLING, client->dev.driver->name, data); if (error) { dev_err(&client->dev, "Failed to register interrupt\n"); @@ -1291,7 +1291,7 @@ static int __devinit qt602240_probe(struct i2c_client *client, if (error) goto err_free_irq; - error = sysfs_create_group(&client->dev.kobj, &qt602240_attr_group); + error = sysfs_create_group(&client->dev.kobj, &mxt_attr_group); if (error) goto err_unregister_device; @@ -1310,11 +1310,11 @@ err_free_mem: return error; } -static int __devexit qt602240_remove(struct i2c_client *client) +static int __devexit mxt_remove(struct i2c_client *client) { - struct qt602240_data *data = i2c_get_clientdata(client); + struct mxt_data *data = i2c_get_clientdata(client); - sysfs_remove_group(&client->dev.kobj, &qt602240_attr_group); + sysfs_remove_group(&client->dev.kobj, &mxt_attr_group); free_irq(data->irq, data); input_unregister_device(data->input_dev); kfree(data->object_table); @@ -1324,83 +1324,84 @@ static int __devexit qt602240_remove(struct i2c_client *client) } #ifdef CONFIG_PM -static int qt602240_suspend(struct device *dev) +static int mxt_suspend(struct device *dev) { struct i2c_client *client = to_i2c_client(dev); - struct qt602240_data *data = i2c_get_clientdata(client); + struct mxt_data *data = i2c_get_clientdata(client); struct input_dev *input_dev = data->input_dev; mutex_lock(&input_dev->mutex); if (input_dev->users) - qt602240_stop(data); + mxt_stop(data); mutex_unlock(&input_dev->mutex); return 0; } -static int qt602240_resume(struct device *dev) +static int mxt_resume(struct device *dev) { struct i2c_client *client = to_i2c_client(dev); - struct qt602240_data *data = i2c_get_clientdata(client); + struct mxt_data *data = i2c_get_clientdata(client); struct input_dev *input_dev = data->input_dev; /* Soft reset */ - qt602240_write_object(data, QT602240_GEN_COMMAND, - QT602240_COMMAND_RESET, 1); + mxt_write_object(data, MXT_GEN_COMMAND, + MXT_COMMAND_RESET, 1); - msleep(QT602240_RESET_TIME); + msleep(MXT_RESET_TIME); mutex_lock(&input_dev->mutex); if (input_dev->users) - qt602240_start(data); + mxt_start(data); mutex_unlock(&input_dev->mutex); return 0; } -static const struct dev_pm_ops qt602240_pm_ops = { - .suspend = qt602240_suspend, - .resume = qt602240_resume, +static const struct dev_pm_ops mxt_pm_ops = { + .suspend = mxt_suspend, + .resume = mxt_resume, }; #endif -static const struct i2c_device_id qt602240_id[] = { +static const struct i2c_device_id mxt_id[] = { { "qt602240_ts", 0 }, + { "atmel_mxt_ts", 0 }, { } }; -MODULE_DEVICE_TABLE(i2c, qt602240_id); +MODULE_DEVICE_TABLE(i2c, mxt_id); -static struct i2c_driver qt602240_driver = { +static struct i2c_driver mxt_driver = { .driver = { - .name = "qt602240_ts", + .name = "atmel_mxt_ts", .owner = THIS_MODULE, #ifdef CONFIG_PM - .pm = &qt602240_pm_ops, + .pm = &mxt_pm_ops, #endif }, - .probe = qt602240_probe, - .remove = __devexit_p(qt602240_remove), - .id_table = qt602240_id, + .probe = mxt_probe, + .remove = __devexit_p(mxt_remove), + .id_table = mxt_id, }; -static int __init qt602240_init(void) +static int __init mxt_init(void) { - return i2c_add_driver(&qt602240_driver); + return i2c_add_driver(&mxt_driver); } -static void __exit qt602240_exit(void) +static void __exit mxt_exit(void) { - i2c_del_driver(&qt602240_driver); + i2c_del_driver(&mxt_driver); } -module_init(qt602240_init); -module_exit(qt602240_exit); +module_init(mxt_init); +module_exit(mxt_exit); /* Module information */ MODULE_AUTHOR("Joonyoung Shim "); -MODULE_DESCRIPTION("AT42QT602240/ATMXT224 Touchscreen driver"); +MODULE_DESCRIPTION("Atmel maXTouch Touchscreen driver"); MODULE_LICENSE("GPL"); diff --git a/include/linux/i2c/atmel_mxt_ts.h b/include/linux/i2c/atmel_mxt_ts.h index c5033e1010946..671967cf4d1a0 100644 --- a/include/linux/i2c/atmel_mxt_ts.h +++ b/include/linux/i2c/atmel_mxt_ts.h @@ -1,5 +1,5 @@ /* - * AT42QT602240/ATMXT224 Touchscreen driver + * Atmel maXTouch Touchscreen driver * * Copyright (C) 2010 Samsung Electronics Co.Ltd * Author: Joonyoung Shim @@ -10,21 +10,21 @@ * option) any later version. */ -#ifndef __LINUX_QT602240_TS_H -#define __LINUX_QT602240_TS_H +#ifndef __LINUX_ATMEL_MXT_TS_H +#define __LINUX_ATMEL_MXT_TS_H /* Orient */ -#define QT602240_NORMAL 0x0 -#define QT602240_DIAGONAL 0x1 -#define QT602240_HORIZONTAL_FLIP 0x2 -#define QT602240_ROTATED_90_COUNTER 0x3 -#define QT602240_VERTICAL_FLIP 0x4 -#define QT602240_ROTATED_90 0x5 -#define QT602240_ROTATED_180 0x6 -#define QT602240_DIAGONAL_COUNTER 0x7 +#define MXT_NORMAL 0x0 +#define MXT_DIAGONAL 0x1 +#define MXT_HORIZONTAL_FLIP 0x2 +#define MXT_ROTATED_90_COUNTER 0x3 +#define MXT_VERTICAL_FLIP 0x4 +#define MXT_ROTATED_90 0x5 +#define MXT_ROTATED_180 0x6 +#define MXT_DIAGONAL_COUNTER 0x7 -/* The platform data for the AT42QT602240/ATMXT224 touchscreen driver */ -struct qt602240_platform_data { +/* The platform data for the Atmel maXTouch touchscreen driver */ +struct mxt_platform_data { unsigned int x_line; unsigned int y_line; unsigned int x_size; @@ -35,4 +35,4 @@ struct qt602240_platform_data { unsigned char orient; }; -#endif /* __LINUX_QT602240_TS_H */ +#endif /* __LINUX_ATMEL_MXT_TS_H */ -- GitLab From 26cdb1ae76f842e895ef4d09796a9101a7f8746b Mon Sep 17 00:00:00 2001 From: Iiro Valkonen Date: Fri, 4 Feb 2011 00:51:05 -0800 Subject: [PATCH 0137/2822] Input: atmel_mxt_ts - read whole message to make CHG low Read the whole message, as reading just the first byte isn't always guaranteed to clear the message. Signed-off-by: Iiro Valkonen Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/atmel_mxt_ts.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c index 5dca78a00c946..162a3bf019e42 100644 --- a/drivers/input/touchscreen/atmel_mxt_ts.c +++ b/drivers/input/touchscreen/atmel_mxt_ts.c @@ -823,16 +823,16 @@ static int mxt_check_matrix_size(struct mxt_data *data) static int mxt_make_highchg(struct mxt_data *data) { struct device *dev = &data->client->dev; + struct mxt_message message; int count = 10; int error; - u8 val; /* Read dummy message to make high CHG pin */ do { - error = mxt_read_object(data, MXT_GEN_MESSAGE, 0, &val); + error = mxt_read_message(data, &message); if (error) return error; - } while ((val != 0xff) && --count); + } while (message.reportid != 0xff && --count); if (!count) { dev_err(dev, "CHG pin isn't cleared\n"); -- GitLab From 5d9d6e91b835796c21fbd7ce479880e5181be112 Mon Sep 17 00:00:00 2001 From: David Herrmann Date: Fri, 11 Feb 2011 01:10:44 -0800 Subject: [PATCH 0138/2822] Input: uinput - fix setting up device name The check for non-empty device name was botched since we tried to account for extra space for the terminating zero at the same time. Convert to kstrndup() to avoid this problem. Signed-off-by: David Herrmann Acked-by: Aristeu Rozanski Signed-off-by: Dmitry Torokhov --- drivers/input/misc/uinput.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/drivers/input/misc/uinput.c b/drivers/input/misc/uinput.c index 82542a1c1098f..c0888e3d2fb40 100644 --- a/drivers/input/misc/uinput.c +++ b/drivers/input/misc/uinput.c @@ -347,8 +347,7 @@ static int uinput_setup_device(struct uinput_device *udev, const char __user *bu { struct uinput_user_dev *user_dev; struct input_dev *dev; - char *name; - int i, size; + int i; int retval; if (count != sizeof(struct uinput_user_dev)) @@ -373,19 +372,19 @@ static int uinput_setup_device(struct uinput_device *udev, const char __user *bu udev->ff_effects_max = user_dev->ff_effects_max; - size = strnlen(user_dev->name, UINPUT_MAX_NAME_SIZE) + 1; - if (!size) { + /* Ensure name is filled in */ + if (!user_dev->name[0]) { retval = -EINVAL; goto exit; } kfree(dev->name); - dev->name = name = kmalloc(size, GFP_KERNEL); - if (!name) { + dev->name = kstrndup(user_dev->name, UINPUT_MAX_NAME_SIZE, + GFP_KERNEL); + if (!dev->name) { retval = -ENOMEM; goto exit; } - strlcpy(name, user_dev->name, size); dev->id.bustype = user_dev->id.bustype; dev->id.vendor = user_dev->id.vendor; -- GitLab From 4dfcc271d587465f0d181c7636453ba4d0ec8acc Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Fri, 11 Feb 2011 01:10:45 -0800 Subject: [PATCH 0139/2822] Input: uinput - use memdup_user() and friends Instead of open-coding copying of data structures from userspace use memdup_user() and strndup_user(). Note that this introduces change in behavior because driver used to truncate 'phys' longer than 1024 bytes, but now it will refuse to set 'phys' that long. Arguably trying to set such 'phys' is suspect anyways. Signed-off-by: Dmitry Torokhov --- drivers/input/misc/uinput.c | 35 ++++++++++------------------------- 1 file changed, 10 insertions(+), 25 deletions(-) diff --git a/drivers/input/misc/uinput.c b/drivers/input/misc/uinput.c index c0888e3d2fb40..7f8331f45bad4 100644 --- a/drivers/input/misc/uinput.c +++ b/drivers/input/misc/uinput.c @@ -361,14 +361,9 @@ static int uinput_setup_device(struct uinput_device *udev, const char __user *bu dev = udev->dev; - user_dev = kmalloc(sizeof(struct uinput_user_dev), GFP_KERNEL); - if (!user_dev) - return -ENOMEM; - - if (copy_from_user(user_dev, buffer, sizeof(struct uinput_user_dev))) { - retval = -EFAULT; - goto exit; - } + user_dev = memdup_user(buffer, sizeof(struct uinput_user_dev)); + if (!IS_ERR(user_dev)) + return PTR_ERR(user_dev); udev->ff_effects_max = user_dev->ff_effects_max; @@ -621,7 +616,6 @@ static long uinput_ioctl_handler(struct file *file, unsigned int cmd, struct uinput_ff_upload ff_up; struct uinput_ff_erase ff_erase; struct uinput_request *req; - int length; char *phys; retval = mutex_lock_interruptible(&udev->mutex); @@ -688,24 +682,15 @@ static long uinput_ioctl_handler(struct file *file, unsigned int cmd, retval = -EINVAL; goto out; } - length = strnlen_user(p, 1024); - if (length <= 0) { - retval = -EFAULT; - break; + + phys = strndup_user(p, 1024); + if (IS_ERR(phys)) { + retval = PTR_ERR(phys); + goto out; } + kfree(udev->dev->phys); - udev->dev->phys = phys = kmalloc(length, GFP_KERNEL); - if (!phys) { - retval = -ENOMEM; - break; - } - if (copy_from_user(phys, p, length)) { - udev->dev->phys = NULL; - kfree(phys); - retval = -EFAULT; - break; - } - phys[length - 1] = '\0'; + udev->dev->phys = phys; break; case UI_BEGIN_FF_UPLOAD: -- GitLab From 6b7cfd193a00ba72efb19a05c486f96ae9297d0b Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 11 Feb 2011 08:49:05 -0800 Subject: [PATCH 0140/2822] Input: ad714x-i2c - convert to dev_pm_ops There is a general move to convert drivers to use dev_pm_ops rather than bus specific PM operations in order to facilitate core work. Do this conversion for ad714x-i2c. Signed-off-by: Mark Brown Acked-by: Michael Hennerich Signed-off-by: Dmitry Torokhov --- drivers/input/misc/ad714x-i2c.c | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/drivers/input/misc/ad714x-i2c.c b/drivers/input/misc/ad714x-i2c.c index 2bef8fa56c948..e21deb1baa8ab 100644 --- a/drivers/input/misc/ad714x-i2c.c +++ b/drivers/input/misc/ad714x-i2c.c @@ -10,23 +10,23 @@ #include #include #include +#include #include "ad714x.h" #ifdef CONFIG_PM -static int ad714x_i2c_suspend(struct i2c_client *client, pm_message_t message) +static int ad714x_i2c_suspend(struct device *dev) { - return ad714x_disable(i2c_get_clientdata(client)); + return ad714x_disable(i2c_get_clientdata(to_i2c_client(dev))); } -static int ad714x_i2c_resume(struct i2c_client *client) +static int ad714x_i2c_resume(struct device *dev) { - return ad714x_enable(i2c_get_clientdata(client)); + return ad714x_enable(i2c_get_clientdata(to_i2c_client(dev))); } -#else -# define ad714x_i2c_suspend NULL -# define ad714x_i2c_resume NULL #endif +static SIMPLE_DEV_PM_OPS(ad714x_i2c_pm, ad714x_i2c_suspend, ad714x_i2c_resume); + static int ad714x_i2c_write(struct device *dev, unsigned short reg, unsigned short data) { @@ -114,11 +114,10 @@ MODULE_DEVICE_TABLE(i2c, ad714x_id); static struct i2c_driver ad714x_i2c_driver = { .driver = { .name = "ad714x_captouch", + .pm = &ad714x_i2c_pm, }, .probe = ad714x_i2c_probe, .remove = __devexit_p(ad714x_i2c_remove), - .suspend = ad714x_i2c_suspend, - .resume = ad714x_i2c_resume, .id_table = ad714x_id, }; -- GitLab From a257090cd4e26b96667a15262f322e51f6582507 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 11 Feb 2011 08:49:37 -0800 Subject: [PATCH 0141/2822] Input: ad714x-spi - convert to dev_pm_ops There is a general move to convert drivers to use dev_pm_ops rather than bus specific PM operations in order to facilitate core work. Do this conversion for ad714x-spi. Signed-off-by: Mark Brown Acked-by: Michael Hennerich Signed-off-by: Dmitry Torokhov --- drivers/input/misc/ad714x-spi.c | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/drivers/input/misc/ad714x-spi.c b/drivers/input/misc/ad714x-spi.c index 7f8dedfd1bfee..4120dd5493059 100644 --- a/drivers/input/misc/ad714x-spi.c +++ b/drivers/input/misc/ad714x-spi.c @@ -9,6 +9,7 @@ #include /* BUS_I2C */ #include #include +#include #include #include "ad714x.h" @@ -16,20 +17,19 @@ #define AD714x_SPI_READ BIT(10) #ifdef CONFIG_PM -static int ad714x_spi_suspend(struct spi_device *spi, pm_message_t message) +static int ad714x_spi_suspend(struct device *dev) { - return ad714x_disable(spi_get_drvdata(spi)); + return ad714x_disable(spi_get_drvdata(to_spi_device(dev))); } -static int ad714x_spi_resume(struct spi_device *spi) +static int ad714x_spi_resume(struct device *dev) { - return ad714x_enable(spi_get_drvdata(spi)); + return ad714x_enable(spi_get_drvdata(to_spi_device(dev))); } -#else -# define ad714x_spi_suspend NULL -# define ad714x_spi_resume NULL #endif +static SIMPLE_DEV_PM_OPS(ad714x_spi_pm, ad714x_spi_suspend, ad714x_spi_resume); + static int ad714x_spi_read(struct device *dev, unsigned short reg, unsigned short *data) { @@ -79,11 +79,10 @@ static struct spi_driver ad714x_spi_driver = { .driver = { .name = "ad714x_captouch", .owner = THIS_MODULE, + .pm = &ad714x_spi_pm, }, .probe = ad714x_spi_probe, .remove = __devexit_p(ad714x_spi_remove), - .suspend = ad714x_spi_suspend, - .resume = ad714x_spi_resume, }; static __init int ad714x_spi_init(void) -- GitLab From 65b0c03852d75e4d7d0bc282344b1500fe471725 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 11 Feb 2011 08:50:37 -0800 Subject: [PATCH 0142/2822] Input: lm8323 - convert to dev_pm_ops There is a general move away from bus specific PM operations to using dev_pm_ops in order to facilicate core improvements. Update lm8323 to the new model. Signed-off-by: Mark Brown Signed-off-by: Dmitry Torokhov --- drivers/input/keyboard/lm8323.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/drivers/input/keyboard/lm8323.c b/drivers/input/keyboard/lm8323.c index f7c2a166576b8..b732870ecc897 100644 --- a/drivers/input/keyboard/lm8323.c +++ b/drivers/input/keyboard/lm8323.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #include @@ -802,8 +803,9 @@ static int __devexit lm8323_remove(struct i2c_client *client) * We don't need to explicitly suspend the chip, as it already switches off * when there's no activity. */ -static int lm8323_suspend(struct i2c_client *client, pm_message_t mesg) +static int lm8323_suspend(struct device *dev) { + struct i2c_client *client = to_i2c_client(dev); struct lm8323_chip *lm = i2c_get_clientdata(client); int i; @@ -821,8 +823,9 @@ static int lm8323_suspend(struct i2c_client *client, pm_message_t mesg) return 0; } -static int lm8323_resume(struct i2c_client *client) +static int lm8323_resume(struct device *dev) { + struct i2c_client *client = to_i2c_client(dev); struct lm8323_chip *lm = i2c_get_clientdata(client); int i; @@ -839,11 +842,10 @@ static int lm8323_resume(struct i2c_client *client) return 0; } -#else -#define lm8323_suspend NULL -#define lm8323_resume NULL #endif +static SIMPLE_DEV_PM_OPS(lm8323_pm_ops, lm8323_suspend, lm8323_resume); + static const struct i2c_device_id lm8323_id[] = { { "lm8323", 0 }, { } @@ -852,11 +854,10 @@ static const struct i2c_device_id lm8323_id[] = { static struct i2c_driver lm8323_i2c_driver = { .driver = { .name = "lm8323", + .pm = &lm8323_pm_ops, }, .probe = lm8323_probe, .remove = __devexit_p(lm8323_remove), - .suspend = lm8323_suspend, - .resume = lm8323_resume, .id_table = lm8323_id, }; MODULE_DEVICE_TABLE(i2c, lm8323_id); -- GitLab From 76e2c68f3214c3a641b9e489cdaea035bfbc8060 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 11 Feb 2011 08:51:13 -0800 Subject: [PATCH 0143/2822] Input: max7359 - convert to dev_pm_ops There is a general move to convert drivers to use dev_pm_ops rather than bus specific ops to facilitate core work. Do this conversion for max7359. Signed-off-by: Mark Brown Signed-off-by: Dmitry Torokhov --- drivers/input/keyboard/max7359_keypad.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/drivers/input/keyboard/max7359_keypad.c b/drivers/input/keyboard/max7359_keypad.c index 9091ff5ea808b..5afe35ad24d37 100644 --- a/drivers/input/keyboard/max7359_keypad.c +++ b/drivers/input/keyboard/max7359_keypad.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include @@ -271,8 +272,10 @@ static int __devexit max7359_remove(struct i2c_client *client) } #ifdef CONFIG_PM -static int max7359_suspend(struct i2c_client *client, pm_message_t mesg) +static int max7359_suspend(struct device *dev) { + struct i2c_client *client = to_i2c_client(dev); + max7359_fall_deepsleep(client); if (device_may_wakeup(&client->dev)) @@ -281,8 +284,10 @@ static int max7359_suspend(struct i2c_client *client, pm_message_t mesg) return 0; } -static int max7359_resume(struct i2c_client *client) +static int max7359_resume(struct device *dev) { + struct i2c_client *client = to_i2c_client(dev); + if (device_may_wakeup(&client->dev)) disable_irq_wake(client->irq); @@ -291,11 +296,10 @@ static int max7359_resume(struct i2c_client *client) return 0; } -#else -#define max7359_suspend NULL -#define max7359_resume NULL #endif +static SIMPLE_DEV_PM_OPS(max7359_pm, max7359_suspend, max7359_resume); + static const struct i2c_device_id max7359_ids[] = { { "max7359", 0 }, { } @@ -305,11 +309,10 @@ MODULE_DEVICE_TABLE(i2c, max7359_ids); static struct i2c_driver max7359_i2c_driver = { .driver = { .name = "max7359", + .pm = &max7359_pm, }, .probe = max7359_probe, .remove = __devexit_p(max7359_remove), - .suspend = max7359_suspend, - .resume = max7359_resume, .id_table = max7359_ids, }; -- GitLab From fbb899356d4a6b6080ab3d9656914938db49449e Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 11 Feb 2011 08:51:52 -0800 Subject: [PATCH 0144/2822] Input: adxl34x-i2c - convert to dev_pm_ops There is a general move to convert drivers to use dev_pm_ops rather than bus specific ones in order to facilitate core development. Do this conversion for adxl34x-i2c. Signed-off-by: Mark Brown Acked-by: Michael Hennerich Signed-off-by: Dmitry Torokhov --- drivers/input/misc/adxl34x-i2c.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/drivers/input/misc/adxl34x-i2c.c b/drivers/input/misc/adxl34x-i2c.c index 0779724af7e79..ccacf2bb06a4e 100644 --- a/drivers/input/misc/adxl34x-i2c.c +++ b/drivers/input/misc/adxl34x-i2c.c @@ -11,6 +11,7 @@ #include #include #include +#include #include "adxl34x.h" static int adxl34x_smbus_read(struct device *dev, unsigned char reg) @@ -105,8 +106,9 @@ static int __devexit adxl34x_i2c_remove(struct i2c_client *client) } #ifdef CONFIG_PM -static int adxl34x_i2c_suspend(struct i2c_client *client, pm_message_t message) +static int adxl34x_i2c_suspend(struct device *dev) { + struct i2c_client *client = to_i2c_client(dev); struct adxl34x *ac = i2c_get_clientdata(client); adxl34x_suspend(ac); @@ -114,19 +116,20 @@ static int adxl34x_i2c_suspend(struct i2c_client *client, pm_message_t message) return 0; } -static int adxl34x_i2c_resume(struct i2c_client *client) +static int adxl34x_i2c_resume(struct device *dev) { + struct i2c_client *client = to_i2c_client(dev); struct adxl34x *ac = i2c_get_clientdata(client); adxl34x_resume(ac); return 0; } -#else -# define adxl34x_i2c_suspend NULL -# define adxl34x_i2c_resume NULL #endif +static SIMPLE_DEV_PM_OPS(adxl34x_i2c_pm, adxl34x_i2c_suspend, + adxl34x_i2c_resume); + static const struct i2c_device_id adxl34x_id[] = { { "adxl34x", 0 }, { } @@ -138,11 +141,10 @@ static struct i2c_driver adxl34x_driver = { .driver = { .name = "adxl34x", .owner = THIS_MODULE, + .pm = &adxl34x_i2c_pm, }, .probe = adxl34x_i2c_probe, .remove = __devexit_p(adxl34x_i2c_remove), - .suspend = adxl34x_i2c_suspend, - .resume = adxl34x_i2c_resume, .id_table = adxl34x_id, }; -- GitLab From 4d1ac94e2e3cd15f06ffc74efa42d6572fdf7689 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 11 Feb 2011 09:22:40 -0800 Subject: [PATCH 0145/2822] Input: adxl34x-spi - convert to dev_pm_ops There is a general move to convert drivers to use dev_pm_ops rather than bus specific ones in order to facilitate core development. Do this conversion for adxl34x-spi. Signed-off-by: Mark Brown Acked-by: Michael Hennerich Signed-off-by: Dmitry Torokhov --- drivers/input/misc/adxl34x-spi.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/drivers/input/misc/adxl34x-spi.c b/drivers/input/misc/adxl34x-spi.c index 782de9e898287..5231add66a65d 100644 --- a/drivers/input/misc/adxl34x-spi.c +++ b/drivers/input/misc/adxl34x-spi.c @@ -10,6 +10,7 @@ #include /* BUS_SPI */ #include #include +#include #include #include "adxl34x.h" @@ -94,8 +95,9 @@ static int __devexit adxl34x_spi_remove(struct spi_device *spi) } #ifdef CONFIG_PM -static int adxl34x_spi_suspend(struct spi_device *spi, pm_message_t message) +static int adxl34x_spi_suspend(struct device *dev) { + struct spi_device *spi = to_spi_device(dev); struct adxl34x *ac = dev_get_drvdata(&spi->dev); adxl34x_suspend(ac); @@ -103,29 +105,29 @@ static int adxl34x_spi_suspend(struct spi_device *spi, pm_message_t message) return 0; } -static int adxl34x_spi_resume(struct spi_device *spi) +static int adxl34x_spi_resume(struct device *dev) { + struct spi_device *spi = to_spi_device(dev); struct adxl34x *ac = dev_get_drvdata(&spi->dev); adxl34x_resume(ac); return 0; } -#else -# define adxl34x_spi_suspend NULL -# define adxl34x_spi_resume NULL #endif +static SIMPLE_DEV_PM_OPS(adxl34x_spi_pm, adxl34x_spi_suspend, + adxl34x_spi_resume); + static struct spi_driver adxl34x_driver = { .driver = { .name = "adxl34x", .bus = &spi_bus_type, .owner = THIS_MODULE, + .pm = &adxl34x_spi_pm, }, .probe = adxl34x_spi_probe, .remove = __devexit_p(adxl34x_spi_remove), - .suspend = adxl34x_spi_suspend, - .resume = adxl34x_spi_resume, }; static int __init adxl34x_spi_init(void) -- GitLab From 3dcab3bdd9cbf45433fc4e1514f3144638652e2b Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 11 Feb 2011 08:53:04 -0800 Subject: [PATCH 0146/2822] Input: adxl34x - fix references to adx134x The adxl34x SPI driver has what appears to be a typo referring to the device as adx134x with the numeral 1 rather than letter l. This appears to be an error so convert. Signed-off-by: Mark Brown Acked-by: Michael Hennerich Signed-off-by: Dmitry Torokhov --- drivers/input/misc/adxl34x-spi.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/input/misc/adxl34x-spi.c b/drivers/input/misc/adxl34x-spi.c index 5231add66a65d..f29de22fdda05 100644 --- a/drivers/input/misc/adxl34x-spi.c +++ b/drivers/input/misc/adxl34x-spi.c @@ -58,7 +58,7 @@ static int adxl34x_spi_read_block(struct device *dev, return (status < 0) ? status : 0; } -static const struct adxl34x_bus_ops adx134x_spi_bops = { +static const struct adxl34x_bus_ops adxl34x_spi_bops = { .bustype = BUS_SPI, .write = adxl34x_spi_write, .read = adxl34x_spi_read, @@ -77,7 +77,7 @@ static int __devinit adxl34x_spi_probe(struct spi_device *spi) ac = adxl34x_probe(&spi->dev, spi->irq, spi->max_speed_hz > MAX_FREQ_NO_FIFODELAY, - &adx134x_spi_bops); + &adxl34x_spi_bops); if (IS_ERR(ac)) return PTR_ERR(ac); -- GitLab From 87b2c7df329e547c1905e0b7e13bfce09cfa5cfe Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 11 Feb 2011 08:53:33 -0800 Subject: [PATCH 0147/2822] Input: synaptics_i2c - convert to dev_pm_ops There is a general move to convert drivers to dev_pm_ops rather than bus specific PM ops in order to facilitate core development. Do this converison for synaptics-i2c. Signed-off-by: Mark Brown Signed-off-by: Dmitry Torokhov --- drivers/input/mouse/synaptics_i2c.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/drivers/input/mouse/synaptics_i2c.c b/drivers/input/mouse/synaptics_i2c.c index 0ae62f0bcb321..f6aa26d305edd 100644 --- a/drivers/input/mouse/synaptics_i2c.c +++ b/drivers/input/mouse/synaptics_i2c.c @@ -18,6 +18,7 @@ #include #include #include +#include #define DRIVER_NAME "synaptics_i2c" /* maximum product id is 15 characters */ @@ -619,8 +620,9 @@ static int __devexit synaptics_i2c_remove(struct i2c_client *client) } #ifdef CONFIG_PM -static int synaptics_i2c_suspend(struct i2c_client *client, pm_message_t mesg) +static int synaptics_i2c_suspend(struct device *dev) { + struct i2c_client *client = to_i2c_client(dev); struct synaptics_i2c *touch = i2c_get_clientdata(client); cancel_delayed_work_sync(&touch->dwork); @@ -631,9 +633,10 @@ static int synaptics_i2c_suspend(struct i2c_client *client, pm_message_t mesg) return 0; } -static int synaptics_i2c_resume(struct i2c_client *client) +static int synaptics_i2c_resume(struct device *dev) { int ret; + struct i2c_client *client = to_i2c_client(dev); struct synaptics_i2c *touch = i2c_get_clientdata(client); ret = synaptics_i2c_reset_config(client); @@ -645,11 +648,11 @@ static int synaptics_i2c_resume(struct i2c_client *client) return 0; } -#else -#define synaptics_i2c_suspend NULL -#define synaptics_i2c_resume NULL #endif +static SIMPLE_DEV_PM_OPS(synaptics_i2c_pm, synaptics_i2c_suspend, + synaptics_i2c_resume); + static const struct i2c_device_id synaptics_i2c_id_table[] = { { "synaptics_i2c", 0 }, { }, @@ -660,13 +663,12 @@ static struct i2c_driver synaptics_i2c_driver = { .driver = { .name = DRIVER_NAME, .owner = THIS_MODULE, + .pm = &synaptics_i2c_pm, }, .probe = synaptics_i2c_probe, .remove = __devexit_p(synaptics_i2c_remove), - .suspend = synaptics_i2c_suspend, - .resume = synaptics_i2c_resume, .id_table = synaptics_i2c_id_table, }; -- GitLab From 46ee2a05a466ca7e34d65fe3feba195d62109362 Mon Sep 17 00:00:00 2001 From: Chris Leech Date: Tue, 15 Feb 2011 13:36:52 -0800 Subject: [PATCH 0148/2822] Input: atmel_mxt_ts - add mXT224 identifier to id_table "mXT224" is used in the Intel mid firmware in SFI tables to identify the presence of this I2C device. Signed-off-by: Chris Leech Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/atmel_mxt_ts.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c index 162a3bf019e42..fe8902e1f010e 100644 --- a/drivers/input/touchscreen/atmel_mxt_ts.c +++ b/drivers/input/touchscreen/atmel_mxt_ts.c @@ -1371,6 +1371,7 @@ static const struct dev_pm_ops mxt_pm_ops = { static const struct i2c_device_id mxt_id[] = { { "qt602240_ts", 0 }, { "atmel_mxt_ts", 0 }, + { "mXT224", 0 }, { } }; MODULE_DEVICE_TABLE(i2c, mxt_id); -- GitLab From 71749f5c66e797a39600dae9de58aab3858dc488 Mon Sep 17 00:00:00 2001 From: Iiro Valkonen Date: Tue, 15 Feb 2011 13:36:52 -0800 Subject: [PATCH 0149/2822] Input: atmel_mxt_ts - allow board code to suppliy controller config As there is no common configuration settings that would work in every situation, remove the fixed config data from driver code and add config data to platform data. Signed-off-by: Iiro Valkonen Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/atmel_mxt_ts.c | 148 ++--------------------- include/linux/i2c/atmel_mxt_ts.h | 5 + 2 files changed, 18 insertions(+), 135 deletions(-) diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c index fe8902e1f010e..52032ef3d3ab3 100644 --- a/drivers/input/touchscreen/atmel_mxt_ts.c +++ b/drivers/input/touchscreen/atmel_mxt_ts.c @@ -199,122 +199,6 @@ #define MXT_MAX_FINGER 10 -/* Initial register values recommended from chip vendor */ -static const u8 init_vals_ver_20[] = { - /* MXT_GEN_COMMAND(6) */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - /* MXT_GEN_POWER(7) */ - 0x20, 0xff, 0x32, - /* MXT_GEN_ACQUIRE(8) */ - 0x08, 0x05, 0x05, 0x00, 0x00, 0x00, 0x05, 0x14, - /* MXT_TOUCH_MULTI(9) */ - 0x00, 0x00, 0x00, 0x11, 0x0a, 0x00, 0x00, 0x00, 0x02, 0x00, - 0x00, 0x01, 0x01, 0x0e, 0x0a, 0x0a, 0x0a, 0x0a, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x64, - /* MXT_TOUCH_KEYARRAY(15) */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, - /* MXT_SPT_GPIOPWM(19) */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, - /* MXT_PROCI_GRIPFACE(20) */ - 0x00, 0x64, 0x64, 0x64, 0x64, 0x00, 0x00, 0x1e, 0x14, 0x04, - 0x1e, 0x00, - /* MXT_PROCG_NOISE(22) */ - 0x05, 0x00, 0x00, 0x19, 0x00, 0xe7, 0xff, 0x04, 0x32, 0x00, - 0x01, 0x0a, 0x0f, 0x14, 0x00, 0x00, 0xe8, - /* MXT_TOUCH_PROXIMITY(23) */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, - /* MXT_PROCI_ONETOUCH(24) */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - /* MXT_SPT_SELFTEST(25) */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - /* MXT_PROCI_TWOTOUCH(27) */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - /* MXT_SPT_CTECONFIG(28) */ - 0x00, 0x00, 0x00, 0x04, 0x08, -}; - -static const u8 init_vals_ver_21[] = { - /* MXT_GEN_COMMAND(6) */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - /* MXT_GEN_POWER(7) */ - 0x20, 0xff, 0x32, - /* MXT_GEN_ACQUIRE(8) */ - 0x0a, 0x00, 0x05, 0x00, 0x00, 0x00, 0x09, 0x23, - /* MXT_TOUCH_MULTI(9) */ - 0x00, 0x00, 0x00, 0x13, 0x0b, 0x00, 0x00, 0x00, 0x02, 0x00, - 0x00, 0x01, 0x01, 0x0e, 0x0a, 0x0a, 0x0a, 0x0a, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - /* MXT_TOUCH_KEYARRAY(15) */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, - /* MXT_SPT_GPIOPWM(19) */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - /* MXT_PROCI_GRIPFACE(20) */ - 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x28, 0x04, - 0x0f, 0x0a, - /* MXT_PROCG_NOISE(22) */ - 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x23, 0x00, - 0x00, 0x05, 0x0f, 0x19, 0x23, 0x2d, 0x03, - /* MXT_TOUCH_PROXIMITY(23) */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, - /* MXT_PROCI_ONETOUCH(24) */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - /* MXT_SPT_SELFTEST(25) */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - /* MXT_PROCI_TWOTOUCH(27) */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - /* MXT_SPT_CTECONFIG(28) */ - 0x00, 0x00, 0x00, 0x08, 0x10, 0x00, -}; - -static const u8 init_vals_ver_22[] = { - /* MXT_GEN_COMMAND(6) */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - /* MXT_GEN_POWER(7) */ - 0x20, 0xff, 0x32, - /* MXT_GEN_ACQUIRE(8) */ - 0x0a, 0x00, 0x05, 0x00, 0x00, 0x00, 0x09, 0x23, - /* MXT_TOUCH_MULTI(9) */ - 0x00, 0x00, 0x00, 0x13, 0x0b, 0x00, 0x00, 0x00, 0x02, 0x00, - 0x00, 0x01, 0x01, 0x0e, 0x0a, 0x0a, 0x0a, 0x0a, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, - /* MXT_TOUCH_KEYARRAY(15) */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, - /* MXT_SPT_GPIOPWM(19) */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - /* MXT_PROCI_GRIPFACE(20) */ - 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x28, 0x04, - 0x0f, 0x0a, - /* MXT_PROCG_NOISE(22) */ - 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x23, 0x00, - 0x00, 0x05, 0x0f, 0x19, 0x23, 0x2d, 0x03, - /* MXT_TOUCH_PROXIMITY(23) */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, - /* MXT_PROCI_ONETOUCH(24) */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - /* MXT_SPT_SELFTEST(25) */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - /* MXT_PROCI_TWOTOUCH(27) */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - /* MXT_SPT_CTECONFIG(28) */ - 0x00, 0x00, 0x00, 0x08, 0x10, 0x00, -}; - struct mxt_info { u8 family_id; u8 variant_id; @@ -714,26 +598,15 @@ end: static int mxt_check_reg_init(struct mxt_data *data) { + const struct mxt_platform_data *pdata = data->pdata; struct mxt_object *object; struct device *dev = &data->client->dev; int index = 0; - int i, j; - u8 version = data->info.version; - u8 *init_vals; + int i, j, config_offset; - switch (version) { - case MXT_VER_20: - init_vals = (u8 *)init_vals_ver_20; - break; - case MXT_VER_21: - init_vals = (u8 *)init_vals_ver_21; - break; - case MXT_VER_22: - init_vals = (u8 *)init_vals_ver_22; - break; - default: - dev_err(dev, "Firmware version %d doesn't support\n", version); - return -EINVAL; + if (!pdata->config) { + dev_dbg(dev, "No cfg data defined, skipping reg init\n"); + return 0; } for (i = 0; i < data->info.object_num; i++) { @@ -742,10 +615,15 @@ static int mxt_check_reg_init(struct mxt_data *data) if (!mxt_object_writable(object->type)) continue; - for (j = 0; j < object->size + 1; j++) + for (j = 0; j < object->size + 1; j++) { + config_offset = index + j; + if (config_offset > pdata->config_length) { + dev_err(dev, "Not enough config data!\n"); + return -EINVAL; + } mxt_write_object(data, object->type, j, - init_vals[index + j]); - + pdata->config[config_offset]); + } index += object->size + 1; } diff --git a/include/linux/i2c/atmel_mxt_ts.h b/include/linux/i2c/atmel_mxt_ts.h index 671967cf4d1a0..b8297685f4898 100644 --- a/include/linux/i2c/atmel_mxt_ts.h +++ b/include/linux/i2c/atmel_mxt_ts.h @@ -13,6 +13,8 @@ #ifndef __LINUX_ATMEL_MXT_TS_H #define __LINUX_ATMEL_MXT_TS_H +#include + /* Orient */ #define MXT_NORMAL 0x0 #define MXT_DIAGONAL 0x1 @@ -25,6 +27,9 @@ /* The platform data for the Atmel maXTouch touchscreen driver */ struct mxt_platform_data { + const u8 *config; + size_t config_length; + unsigned int x_line; unsigned int y_line; unsigned int x_size; -- GitLab From 919ed895f0b4227da26ea1b0a1347db5010f105e Mon Sep 17 00:00:00 2001 From: Iiro Valkonen Date: Tue, 15 Feb 2011 13:36:52 -0800 Subject: [PATCH 0150/2822] Input: atmel_mxt_ts - allow board code to specify IRQ flags Different board have different requirements/setups so let's be more flexible. Signed-off-by: Iiro Valkonen Signed-off-by: Dmitry Torokhov --- arch/arm/mach-s5pv210/mach-goni.c | 2 ++ drivers/input/touchscreen/atmel_mxt_ts.c | 7 ++++--- include/linux/i2c/atmel_mxt_ts.h | 1 + 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/arch/arm/mach-s5pv210/mach-goni.c b/arch/arm/mach-s5pv210/mach-goni.c index e9a7d340f4e1f..be0eb7a2e6124 100644 --- a/arch/arm/mach-s5pv210/mach-goni.c +++ b/arch/arm/mach-s5pv210/mach-goni.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include @@ -231,6 +232,7 @@ static struct mxt_platform_data qt602240_platform_data = { .threshold = 0x28, .voltage = 2800000, /* 2.8V */ .orient = MXT_DIAGONAL, + .irqflags = IRQF_TRIGGER_FALLING, }; static struct s3c2410_platform_i2c i2c2_data __initdata = { diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c index 52032ef3d3ab3..d2e5864ca096a 100644 --- a/drivers/input/touchscreen/atmel_mxt_ts.c +++ b/drivers/input/touchscreen/atmel_mxt_ts.c @@ -1106,11 +1106,12 @@ static void mxt_input_close(struct input_dev *dev) static int __devinit mxt_probe(struct i2c_client *client, const struct i2c_device_id *id) { + const struct mxt_platform_data *pdata = client->dev.platform_data; struct mxt_data *data; struct input_dev *input_dev; int error; - if (!client->dev.platform_data) + if (!pdata) return -EINVAL; data = kzalloc(sizeof(struct mxt_data), GFP_KERNEL); @@ -1149,7 +1150,7 @@ static int __devinit mxt_probe(struct i2c_client *client, data->client = client; data->input_dev = input_dev; - data->pdata = client->dev.platform_data; + data->pdata = pdata; data->irq = client->irq; i2c_set_clientdata(client, data); @@ -1159,7 +1160,7 @@ static int __devinit mxt_probe(struct i2c_client *client, goto err_free_object; error = request_threaded_irq(client->irq, NULL, mxt_interrupt, - IRQF_TRIGGER_FALLING, client->dev.driver->name, data); + pdata->irqflags, client->dev.driver->name, data); if (error) { dev_err(&client->dev, "Failed to register interrupt\n"); goto err_free_object; diff --git a/include/linux/i2c/atmel_mxt_ts.h b/include/linux/i2c/atmel_mxt_ts.h index b8297685f4898..f027f7a63511b 100644 --- a/include/linux/i2c/atmel_mxt_ts.h +++ b/include/linux/i2c/atmel_mxt_ts.h @@ -38,6 +38,7 @@ struct mxt_platform_data { unsigned int threshold; unsigned int voltage; unsigned char orient; + unsigned long irqflags; }; #endif /* __LINUX_ATMEL_MXT_TS_H */ -- GitLab From 163d27706bb91a648cc292151fc072e1e8cd4b4d Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Fri, 18 Feb 2011 08:30:52 -0800 Subject: [PATCH 0151/2822] Input: uinput - reversed test in uinput_setup_device() The test here is reversed. It should be if (IS_ERR()) instead of if (!IS_ERR()). Signed-off-by: Dan Carpenter Signed-off-by: Dmitry Torokhov --- drivers/input/misc/uinput.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/input/misc/uinput.c b/drivers/input/misc/uinput.c index 7f8331f45bad4..364bdf43a381d 100644 --- a/drivers/input/misc/uinput.c +++ b/drivers/input/misc/uinput.c @@ -362,7 +362,7 @@ static int uinput_setup_device(struct uinput_device *udev, const char __user *bu dev = udev->dev; user_dev = memdup_user(buffer, sizeof(struct uinput_user_dev)); - if (!IS_ERR(user_dev)) + if (IS_ERR(user_dev)) return PTR_ERR(user_dev); udev->ff_effects_max = user_dev->ff_effects_max; -- GitLab From e33b9d0878ff6b8a543b3423c3019a5dbbf5689a Mon Sep 17 00:00:00 2001 From: Russell King Date: Sun, 20 Feb 2011 11:47:41 +0000 Subject: [PATCH 0152/2822] ARM: Use long long format when printing meminfo physical addresses Acked-by: Will Deacon Signed-off-by: Russell King --- arch/arm/mm/mmu.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c index e09744e82d50f..176749010935e 100644 --- a/arch/arm/mm/mmu.c +++ b/arch/arm/mm/mmu.c @@ -794,9 +794,10 @@ static void __init sanity_check_meminfo(void) */ if (__va(bank->start) >= vmalloc_min || __va(bank->start) < (void *)PAGE_OFFSET) { - printk(KERN_NOTICE "Ignoring RAM at %.8lx-%.8lx " + printk(KERN_NOTICE "Ignoring RAM at %.8llx-%.8llx " "(vmalloc region overlap).\n", - bank->start, bank->start + bank->size - 1); + (unsigned long long)bank->start, + (unsigned long long)bank->start + bank->size - 1); continue; } @@ -807,10 +808,11 @@ static void __init sanity_check_meminfo(void) if (__va(bank->start + bank->size) > vmalloc_min || __va(bank->start + bank->size) < __va(bank->start)) { unsigned long newsize = vmalloc_min - __va(bank->start); - printk(KERN_NOTICE "Truncating RAM at %.8lx-%.8lx " - "to -%.8lx (vmalloc region overlap).\n", - bank->start, bank->start + bank->size - 1, - bank->start + newsize - 1); + printk(KERN_NOTICE "Truncating RAM at %.8llx-%.8llx " + "to -%.8llx (vmalloc region overlap).\n", + (unsigned long long)bank->start, + (unsigned long long)bank->start + bank->size - 1, + (unsigned long long)bank->start + newsize - 1); bank->size = newsize; } #endif -- GitLab From f60892d3e36dcdd0d9f30db05beae7a446a93f28 Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Tue, 15 Feb 2011 12:44:10 +0100 Subject: [PATCH 0153/2822] ARM: 6673/1: LPAE: use phys_addr_t instead of unsigned long for start of membanks The unsigned long datatype is not sufficient for mapping physical addresses >= 4GB. This patch ensures that the phys_addr_t datatype is used to represent the start address of a membank, which may reside above the 4GB boundary. Acked-by: Catalin Marinas Signed-off-by: Will Deacon Signed-off-by: Russell King --- arch/arm/include/asm/setup.h | 2 +- arch/arm/kernel/setup.c | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/arch/arm/include/asm/setup.h b/arch/arm/include/asm/setup.h index f1e5a9bca2491..50921182b7c38 100644 --- a/arch/arm/include/asm/setup.h +++ b/arch/arm/include/asm/setup.h @@ -199,7 +199,7 @@ static struct tagtable __tagtable_##fn __tag = { tag, fn } #endif struct membank { - unsigned long start; + phys_addr_t start; unsigned long size; unsigned int highmem; }; diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c index 77af580953e62..9d4a84402ae9d 100644 --- a/arch/arm/kernel/setup.c +++ b/arch/arm/kernel/setup.c @@ -442,7 +442,7 @@ static struct machine_desc * __init setup_machine(unsigned int nr) return list; } -static int __init arm_add_memory(unsigned long start, unsigned long size) +static int __init arm_add_memory(phys_addr_t start, unsigned long size) { struct membank *bank = &meminfo.bank[meminfo.nr_banks]; @@ -478,7 +478,8 @@ static int __init arm_add_memory(unsigned long start, unsigned long size) static int __init early_mem(char *p) { static int usermem __initdata = 0; - unsigned long size, start; + unsigned long size; + phys_addr_t start; char *endp; /* -- GitLab From 516295e5ab4bf986865cfff856d484ec678e3b0b Mon Sep 17 00:00:00 2001 From: Russell King Date: Sun, 21 Nov 2010 16:27:49 +0000 Subject: [PATCH 0154/2822] ARM: pgtable: add pud-level code Add pud_offset() et.al. between the pgd and pmd code in preparation of using pgtable-nopud.h rather than 4level-fixup.h. This incorporates a fix from Jamie Iles for uaccess_with_memcpy.c. Signed-off-by: Russell King --- arch/arm/include/asm/pgtable.h | 1 + arch/arm/lib/uaccess_with_memcpy.c | 7 +++++- arch/arm/mm/dma-mapping.c | 11 +++++++++- arch/arm/mm/fault-armv.c | 7 +++++- arch/arm/mm/fault.c | 29 +++++++++++++++++++++---- arch/arm/mm/idmap.c | 35 +++++++++++++++++++++++++----- arch/arm/mm/mm.h | 2 +- arch/arm/mm/mmu.c | 22 +++++++++++++++---- arch/arm/mm/pgd.c | 24 ++++++++++++++++---- 9 files changed, 116 insertions(+), 22 deletions(-) diff --git a/arch/arm/include/asm/pgtable.h b/arch/arm/include/asm/pgtable.h index ca567914d303b..5750704e02718 100644 --- a/arch/arm/include/asm/pgtable.h +++ b/arch/arm/include/asm/pgtable.h @@ -301,6 +301,7 @@ extern pgd_t swapper_pg_dir[PTRS_PER_PGD]; #define pgd_present(pgd) (1) #define pgd_clear(pgdp) do { } while (0) #define set_pgd(pgd,pgdp) do { } while (0) +#define set_pud(pud,pudp) do { } while (0) /* Find an entry in the second-level page table.. */ diff --git a/arch/arm/lib/uaccess_with_memcpy.c b/arch/arm/lib/uaccess_with_memcpy.c index e2d2f2cd0c4f3..8b9b13649f817 100644 --- a/arch/arm/lib/uaccess_with_memcpy.c +++ b/arch/arm/lib/uaccess_with_memcpy.c @@ -27,13 +27,18 @@ pin_page_for_write(const void __user *_addr, pte_t **ptep, spinlock_t **ptlp) pgd_t *pgd; pmd_t *pmd; pte_t *pte; + pud_t *pud; spinlock_t *ptl; pgd = pgd_offset(current->mm, addr); if (unlikely(pgd_none(*pgd) || pgd_bad(*pgd))) return 0; - pmd = pmd_offset(pgd, addr); + pud = pud_offset(pgd, addr); + if (unlikely(pud_none(*pud) || pud_bad(*pud))) + return 0; + + pmd = pmd_offset(pud, addr); if (unlikely(pmd_none(*pmd) || pmd_bad(*pmd))) return 0; diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c index ac6a36142fcd5..a9bdfcda23f49 100644 --- a/arch/arm/mm/dma-mapping.c +++ b/arch/arm/mm/dma-mapping.c @@ -148,6 +148,7 @@ static int __init consistent_init(void) { int ret = 0; pgd_t *pgd; + pud_t *pud; pmd_t *pmd; pte_t *pte; int i = 0; @@ -155,7 +156,15 @@ static int __init consistent_init(void) do { pgd = pgd_offset(&init_mm, base); - pmd = pmd_alloc(&init_mm, pgd, base); + + pud = pud_alloc(&init_mm, pgd, base); + if (!pud) { + printk(KERN_ERR "%s: no pud tables\n", __func__); + ret = -ENOMEM; + break; + } + + pmd = pmd_alloc(&init_mm, pud, base); if (!pmd) { printk(KERN_ERR "%s: no pmd tables\n", __func__); ret = -ENOMEM; diff --git a/arch/arm/mm/fault-armv.c b/arch/arm/mm/fault-armv.c index 01210dba02217..7cab791794218 100644 --- a/arch/arm/mm/fault-armv.c +++ b/arch/arm/mm/fault-armv.c @@ -95,6 +95,7 @@ static int adjust_pte(struct vm_area_struct *vma, unsigned long address, { spinlock_t *ptl; pgd_t *pgd; + pud_t *pud; pmd_t *pmd; pte_t *pte; int ret; @@ -103,7 +104,11 @@ static int adjust_pte(struct vm_area_struct *vma, unsigned long address, if (pgd_none_or_clear_bad(pgd)) return 0; - pmd = pmd_offset(pgd, address); + pud = pud_offset(pgd, address); + if (pud_none_or_clear_bad(pud)) + return 0; + + pmd = pmd_offset(pud, address); if (pmd_none_or_clear_bad(pmd)) return 0; diff --git a/arch/arm/mm/fault.c b/arch/arm/mm/fault.c index ef0e24f578ef2..bc0e1d88fd3ba 100644 --- a/arch/arm/mm/fault.c +++ b/arch/arm/mm/fault.c @@ -80,6 +80,7 @@ void show_pte(struct mm_struct *mm, unsigned long addr) addr, (long long)pgd_val(*pgd)); do { + pud_t *pud; pmd_t *pmd; pte_t *pte; @@ -91,7 +92,19 @@ void show_pte(struct mm_struct *mm, unsigned long addr) break; } - pmd = pmd_offset(pgd, addr); + pud = pud_offset(pgd, addr); + if (PTRS_PER_PUD != 1) + printk(", *pud=%08lx", pud_val(*pud)); + + if (pud_none(*pud)) + break; + + if (pud_bad(*pud)) { + printk("(bad)"); + break; + } + + pmd = pmd_offset(pud, addr); if (PTRS_PER_PMD != 1) printk(", *pmd=%08llx", (long long)pmd_val(*pmd)); @@ -390,6 +403,7 @@ do_translation_fault(unsigned long addr, unsigned int fsr, { unsigned int index; pgd_t *pgd, *pgd_k; + pud_t *pud, *pud_k; pmd_t *pmd, *pmd_k; if (addr < TASK_SIZE) @@ -408,12 +422,19 @@ do_translation_fault(unsigned long addr, unsigned int fsr, if (pgd_none(*pgd_k)) goto bad_area; - if (!pgd_present(*pgd)) set_pgd(pgd, *pgd_k); - pmd_k = pmd_offset(pgd_k, addr); - pmd = pmd_offset(pgd, addr); + pud = pud_offset(pgd, addr); + pud_k = pud_offset(pgd_k, addr); + + if (pud_none(*pud_k)) + goto bad_area; + if (!pud_present(*pud)) + set_pud(pud, *pud_k); + + pmd = pmd_offset(pud, addr); + pmd_k = pmd_offset(pud_k, addr); /* * On ARM one Linux PGD entry contains two hardware entries (see page diff --git a/arch/arm/mm/idmap.c b/arch/arm/mm/idmap.c index 57299446f7871..2be9139a4ef3c 100644 --- a/arch/arm/mm/idmap.c +++ b/arch/arm/mm/idmap.c @@ -4,10 +4,10 @@ #include #include -static void idmap_add_pmd(pgd_t *pgd, unsigned long addr, unsigned long end, +static void idmap_add_pmd(pud_t *pud, unsigned long addr, unsigned long end, unsigned long prot) { - pmd_t *pmd = pmd_offset(pgd, addr); + pmd_t *pmd = pmd_offset(pud, addr); addr = (addr & PMD_MASK) | prot; pmd[0] = __pmd(addr); @@ -16,6 +16,18 @@ static void idmap_add_pmd(pgd_t *pgd, unsigned long addr, unsigned long end, flush_pmd_entry(pmd); } +static void idmap_add_pud(pgd_t *pgd, unsigned long addr, unsigned long end, + unsigned long prot) +{ + pud_t *pud = pud_offset(pgd, addr); + unsigned long next; + + do { + next = pud_addr_end(addr, end); + idmap_add_pmd(pud, addr, next, prot); + } while (pud++, addr = next, addr != end); +} + void identity_mapping_add(pgd_t *pgd, unsigned long addr, unsigned long end) { unsigned long prot, next; @@ -27,17 +39,28 @@ void identity_mapping_add(pgd_t *pgd, unsigned long addr, unsigned long end) pgd += pgd_index(addr); do { next = pgd_addr_end(addr, end); - idmap_add_pmd(pgd, addr, next, prot); + idmap_add_pud(pgd, addr, next, prot); } while (pgd++, addr = next, addr != end); } #ifdef CONFIG_SMP -static void idmap_del_pmd(pgd_t *pgd, unsigned long addr, unsigned long end) +static void idmap_del_pmd(pud_t *pud, unsigned long addr, unsigned long end) { - pmd_t *pmd = pmd_offset(pgd, addr); + pmd_t *pmd = pmd_offset(pud, addr); pmd_clear(pmd); } +static void idmap_del_pud(pgd_t *pgd, unsigned long addr, unsigned long end) +{ + pud_t *pud = pud_offset(pgd, addr); + unsigned long next; + + do { + next = pud_addr_end(addr, end); + idmap_del_pmd(pud, addr, next); + } while (pud++, addr = next, addr != end); +} + void identity_mapping_del(pgd_t *pgd, unsigned long addr, unsigned long end) { unsigned long next; @@ -45,7 +68,7 @@ void identity_mapping_del(pgd_t *pgd, unsigned long addr, unsigned long end) pgd += pgd_index(addr); do { next = pgd_addr_end(addr, end); - idmap_del_pmd(pgd, addr, next); + idmap_del_pud(pgd, addr, next); } while (pgd++, addr = next, addr != end); } #endif diff --git a/arch/arm/mm/mm.h b/arch/arm/mm/mm.h index 36960df5fb762..d2384106af9cb 100644 --- a/arch/arm/mm/mm.h +++ b/arch/arm/mm/mm.h @@ -7,7 +7,7 @@ extern pmd_t *top_pmd; static inline pmd_t *pmd_off(pgd_t *pgd, unsigned long virt) { - return pmd_offset(pgd, virt); + return pmd_offset(pud_offset(pgd, virt), virt); } static inline pmd_t *pmd_off_k(unsigned long virt) diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c index 176749010935e..82ef6966ae098 100644 --- a/arch/arm/mm/mmu.c +++ b/arch/arm/mm/mmu.c @@ -550,11 +550,11 @@ static void __init alloc_init_pte(pmd_t *pmd, unsigned long addr, } while (pte++, addr += PAGE_SIZE, addr != end); } -static void __init alloc_init_section(pgd_t *pgd, unsigned long addr, +static void __init alloc_init_section(pud_t *pud, unsigned long addr, unsigned long end, phys_addr_t phys, const struct mem_type *type) { - pmd_t *pmd = pmd_offset(pgd, addr); + pmd_t *pmd = pmd_offset(pud, addr); /* * Try a section mapping - end, addr and phys must all be aligned @@ -583,6 +583,19 @@ static void __init alloc_init_section(pgd_t *pgd, unsigned long addr, } } +static void alloc_init_pud(pgd_t *pgd, unsigned long addr, unsigned long end, + unsigned long phys, const struct mem_type *type) +{ + pud_t *pud = pud_offset(pgd, addr); + unsigned long next; + + do { + next = pud_addr_end(addr, end); + alloc_init_section(pud, addr, next, phys, type); + phys += next - addr; + } while (pud++, addr = next, addr != end); +} + static void __init create_36bit_mapping(struct map_desc *md, const struct mem_type *type) { @@ -630,7 +643,8 @@ static void __init create_36bit_mapping(struct map_desc *md, pgd = pgd_offset_k(addr); end = addr + length; do { - pmd_t *pmd = pmd_offset(pgd, addr); + pud_t *pud = pud_offset(pgd, addr); + pmd_t *pmd = pmd_offset(pud, addr); int i; for (i = 0; i < 16; i++) @@ -696,7 +710,7 @@ static void __init create_mapping(struct map_desc *md) do { unsigned long next = pgd_addr_end(addr, end); - alloc_init_section(pgd, addr, next, phys, type); + alloc_init_pud(pgd, addr, next, phys, type); phys += next - addr; addr = next; diff --git a/arch/arm/mm/pgd.c b/arch/arm/mm/pgd.c index 93292a18cf77f..f7fafb1741f4c 100644 --- a/arch/arm/mm/pgd.c +++ b/arch/arm/mm/pgd.c @@ -23,6 +23,7 @@ pgd_t *pgd_alloc(struct mm_struct *mm) { pgd_t *new_pgd, *init_pgd; + pud_t *new_pud, *init_pud; pmd_t *new_pmd, *init_pmd; pte_t *new_pte, *init_pte; @@ -46,7 +47,11 @@ pgd_t *pgd_alloc(struct mm_struct *mm) * On ARM, first page must always be allocated since it * contains the machine vectors. */ - new_pmd = pmd_alloc(mm, new_pgd, 0); + new_pud = pud_alloc(mm, new_pgd, 0); + if (!new_pud) + goto no_pud; + + new_pmd = pmd_alloc(mm, new_pud, 0); if (!new_pmd) goto no_pmd; @@ -54,7 +59,8 @@ pgd_t *pgd_alloc(struct mm_struct *mm) if (!new_pte) goto no_pte; - init_pmd = pmd_offset(init_pgd, 0); + init_pud = pud_offset(init_pgd, 0); + init_pmd = pmd_offset(init_pud, 0); init_pte = pte_offset_map(init_pmd, 0); set_pte_ext(new_pte, *init_pte, 0); pte_unmap(init_pte); @@ -66,6 +72,8 @@ pgd_t *pgd_alloc(struct mm_struct *mm) no_pte: pmd_free(mm, new_pmd); no_pmd: + pud_free(mm, new_pud); +no_pud: free_pages((unsigned long)new_pgd, 2); no_pgd: return NULL; @@ -74,6 +82,7 @@ no_pgd: void pgd_free(struct mm_struct *mm, pgd_t *pgd_base) { pgd_t *pgd; + pud_t *pud; pmd_t *pmd; pgtable_t pte; @@ -84,7 +93,11 @@ void pgd_free(struct mm_struct *mm, pgd_t *pgd_base) if (pgd_none_or_clear_bad(pgd)) goto no_pgd; - pmd = pmd_offset(pgd, 0); + pud = pud_offset(pgd, 0); + if (pud_none_or_clear_bad(pud)) + goto no_pud; + + pmd = pmd_offset(pud, 0); if (pmd_none_or_clear_bad(pmd)) goto no_pmd; @@ -92,8 +105,11 @@ void pgd_free(struct mm_struct *mm, pgd_t *pgd_base) pmd_clear(pmd); pte_free(mm, pte); no_pmd: - pgd_clear(pgd); + pud_clear(pud); pmd_free(mm, pmd); +no_pud: + pgd_clear(pgd); + pud_free(mm, pud); no_pgd: free_pages((unsigned long) pgd_base, 2); } -- GitLab From 6f9524e9e118929f1de02840dffe858f99685aea Mon Sep 17 00:00:00 2001 From: Lukas Czerner Date: Mon, 21 Feb 2011 20:16:21 -0500 Subject: [PATCH 0155/2822] ext4: update ext4 documentation Add documentation for mount options and ioctls to Documentation/filesystem/ext4.txt, which has not been udpated for some time. Also add for ext4 sysfs tunables to the Documentation/ABI/testing/sysfs-fs-ext4 file, and fix a few typographical errors in that file. https://bugzilla.kernel.org/show_bug.cgi?id=9423 Signed-off-by: Lukas Czerner Signed-off-by: "Theodore Ts'o" --- Documentation/ABI/testing/sysfs-fs-ext4 | 13 +- Documentation/filesystems/ext4.txt | 207 +++++++++++++++++++++++- 2 files changed, 216 insertions(+), 4 deletions(-) diff --git a/Documentation/ABI/testing/sysfs-fs-ext4 b/Documentation/ABI/testing/sysfs-fs-ext4 index 5fb709997d963..f22ac0872ae8d 100644 --- a/Documentation/ABI/testing/sysfs-fs-ext4 +++ b/Documentation/ABI/testing/sysfs-fs-ext4 @@ -48,7 +48,7 @@ Description: will have its blocks allocated out of its own unique preallocation pool. -What: /sys/fs/ext4//inode_readahead +What: /sys/fs/ext4//inode_readahead_blks Date: March 2008 Contact: "Theodore Ts'o" Description: @@ -85,7 +85,14 @@ Date: June 2008 Contact: "Theodore Ts'o" Description: Tuning parameter which (if non-zero) controls the goal - inode used by the inode allocator in p0reference to - all other allocation hueristics. This is intended for + inode used by the inode allocator in preference to + all other allocation heuristics. This is intended for debugging use only, and should be 0 on production systems. + +What: /sys/fs/ext4//max_writeback_mb_bump +Date: September 2009 +Contact: "Theodore Ts'o" +Description: + The maximum number of megabytes the writeback code will + try to write out before move on to another inode. diff --git a/Documentation/filesystems/ext4.txt b/Documentation/filesystems/ext4.txt index 6ab9442d7eeb6..6b050464a90de 100644 --- a/Documentation/filesystems/ext4.txt +++ b/Documentation/filesystems/ext4.txt @@ -367,12 +367,47 @@ init_itable=n The lazy itable init code will wait n times the minimizes the impact on the systme performance while file system's inode table is being initialized. -discard Controls whether ext4 should issue discard/TRIM +discard Controls whether ext4 should issue discard/TRIM nodiscard(*) commands to the underlying block device when blocks are freed. This is useful for SSD devices and sparse/thinly-provisioned LUNs, but it is off by default until sufficient testing has been done. +nouid32 Disables 32-bit UIDs and GIDs. This is for + interoperability with older kernels which only + store and expect 16-bit values. + +resize Allows to resize filesystem to the end of the last + existing block group, further resize has to be done + with resize2fs either online, or offline. It can be + used only with conjunction with remount. + +block_validity This options allows to enables/disables the in-kernel +noblock_validity facility for tracking filesystem metadata blocks + within internal data structures. This allows multi- + block allocator and other routines to quickly locate + extents which might overlap with filesystem metadata + blocks. This option is intended for debugging + purposes and since it negatively affects the + performance, it is off by default. + +dioread_lock Controls whether or not ext4 should use the DIO read +dioread_nolock locking. If the dioread_nolock option is specified + ext4 will allocate uninitialized extent before buffer + write and convert the extent to initialized after IO + completes. This approach allows ext4 code to avoid + using inode mutex, which improves scalability on high + speed storages. However this does not work with nobh + option and the mount will fail. Nor does it work with + data journaling and dioread_nolock option will be + ignored with kernel warning. Note that dioread_nolock + code path is only used for extent-based files. + Because of the restrictions this options comprises + it is off by default (e.g. dioread_lock). + +i_version Enable 64-bit inode version support. This option is + off by default. + Data Mode ========= There are 3 different data modes: @@ -400,6 +435,176 @@ needs to be read from and written to disk at the same time where it outperforms all others modes. Currently ext4 does not have delayed allocation support if this data journalling mode is selected. +/proc entries +============= + +Information about mounted ext4 file systems can be found in +/proc/fs/ext4. Each mounted filesystem will have a directory in +/proc/fs/ext4 based on its device name (i.e., /proc/fs/ext4/hdc or +/proc/fs/ext4/dm-0). The files in each per-device directory are shown +in table below. + +Files in /proc/fs/ext4/ +.............................................................................. + File Content + mb_groups details of multiblock allocator buddy cache of free blocks +.............................................................................. + +/sys entries +============ + +Information about mounted ext4 file systems can be found in +/sys/fs/ext4. Each mounted filesystem will have a directory in +/sys/fs/ext4 based on its device name (i.e., /sys/fs/ext4/hdc or +/sys/fs/ext4/dm-0). The files in each per-device directory are shown +in table below. + +Files in /sys/fs/ext4/ +(see also Documentation/ABI/testing/sysfs-fs-ext4) +.............................................................................. + File Content + + delayed_allocation_blocks This file is read-only and shows the number of + blocks that are dirty in the page cache, but + which do not have their location in the + filesystem allocated yet. + + inode_goal Tuning parameter which (if non-zero) controls + the goal inode used by the inode allocator in + preference to all other allocation heuristics. + This is intended for debugging use only, and + should be 0 on production systems. + + inode_readahead_blks Tuning parameter which controls the maximum + number of inode table blocks that ext4's inode + table readahead algorithm will pre-read into + the buffer cache + + lifetime_write_kbytes This file is read-only and shows the number of + kilobytes of data that have been written to this + filesystem since it was created. + + max_writeback_mb_bump The maximum number of megabytes the writeback + code will try to write out before move on to + another inode. + + mb_group_prealloc The multiblock allocator will round up allocation + requests to a multiple of this tuning parameter if + the stripe size is not set in the ext4 superblock + + mb_max_to_scan The maximum number of extents the multiblock + allocator will search to find the best extent + + mb_min_to_scan The minimum number of extents the multiblock + allocator will search to find the best extent + + mb_order2_req Tuning parameter which controls the minimum size + for requests (as a power of 2) where the buddy + cache is used + + mb_stats Controls whether the multiblock allocator should + collect statistics, which are shown during the + unmount. 1 means to collect statistics, 0 means + not to collect statistics + + mb_stream_req Files which have fewer blocks than this tunable + parameter will have their blocks allocated out + of a block group specific preallocation pool, so + that small files are packed closely together. + Each large file will have its blocks allocated + out of its own unique preallocation pool. + + session_write_kbytes This file is read-only and shows the number of + kilobytes of data that have been written to this + filesystem since it was mounted. +.............................................................................. + +Ioctls +====== + +There is some Ext4 specific functionality which can be accessed by applications +through the system call interfaces. The list of all Ext4 specific ioctls are +shown in the table below. + +Table of Ext4 specific ioctls +.............................................................................. + Ioctl Description + EXT4_IOC_GETFLAGS Get additional attributes associated with inode. + The ioctl argument is an integer bitfield, with + bit values described in ext4.h. This ioctl is an + alias for FS_IOC_GETFLAGS. + + EXT4_IOC_SETFLAGS Set additional attributes associated with inode. + The ioctl argument is an integer bitfield, with + bit values described in ext4.h. This ioctl is an + alias for FS_IOC_SETFLAGS. + + EXT4_IOC_GETVERSION + EXT4_IOC_GETVERSION_OLD + Get the inode i_generation number stored for + each inode. The i_generation number is normally + changed only when new inode is created and it is + particularly useful for network filesystems. The + '_OLD' version of this ioctl is an alias for + FS_IOC_GETVERSION. + + EXT4_IOC_SETVERSION + EXT4_IOC_SETVERSION_OLD + Set the inode i_generation number stored for + each inode. The '_OLD' version of this ioctl + is an alias for FS_IOC_SETVERSION. + + EXT4_IOC_GROUP_EXTEND This ioctl has the same purpose as the resize + mount option. It allows to resize filesystem + to the end of the last existing block group, + further resize has to be done with resize2fs, + either online, or offline. The argument points + to the unsigned logn number representing the + filesystem new block count. + + EXT4_IOC_MOVE_EXT Move the block extents from orig_fd (the one + this ioctl is pointing to) to the donor_fd (the + one specified in move_extent structure passed + as an argument to this ioctl). Then, exchange + inode metadata between orig_fd and donor_fd. + This is especially useful for online + defragmentation, because the allocator has the + opportunity to allocate moved blocks better, + ideally into one contiguous extent. + + EXT4_IOC_GROUP_ADD Add a new group descriptor to an existing or + new group descriptor block. The new group + descriptor is described by ext4_new_group_input + structure, which is passed as an argument to + this ioctl. This is especially useful in + conjunction with EXT4_IOC_GROUP_EXTEND, + which allows online resize of the filesystem + to the end of the last existing block group. + Those two ioctls combined is used in userspace + online resize tool (e.g. resize2fs). + + EXT4_IOC_MIGRATE This ioctl operates on the filesystem itself. + It converts (migrates) ext3 indirect block mapped + inode to ext4 extent mapped inode by walking + through indirect block mapping of the original + inode and converting contiguous block ranges + into ext4 extents of the temporary inode. Then, + inodes are swapped. This ioctl might help, when + migrating from ext3 to ext4 filesystem, however + suggestion is to create fresh ext4 filesystem + and copy data from the backup. Note, that + filesystem has to support extents for this ioctl + to work. + + EXT4_IOC_ALLOC_DA_BLKS Force all of the delay allocated blocks to be + allocated to preserve application-expected ext3 + behaviour. Note that this will also start + triggering a write of the data blocks, but this + behaviour may change in the future as it is + not necessary and has been done this way only + for sake of simplicity. +.............................................................................. + References ========== -- GitLab From da488945f4bf4096f4ab6091938469bd8822cfec Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Mon, 21 Feb 2011 20:39:58 -0500 Subject: [PATCH 0156/2822] ext4: fix compile warnings with EXT4FS_DEBUG enabled Compile 2.6.38-rc1 with turning EXT4FS_DEBUG on, we get following compile warnings. This patch fixes them. CC fs/ext4/hash.o CC fs/ext4/resize.o fs/ext4/resize.c: In function 'setup_new_group_blocks': fs/ext4/resize.c:233:2: warning: format '%#04llx' expects type 'long long unsigned int', but argument 3 has type 'long unsigned int' fs/ext4/resize.c:251:2: warning: format '%#04llx' expects type 'long long unsigned int', but argument 3 has type 'long unsigned int' CC fs/ext4/extents.o CC fs/ext4/ext4_jbd2.o CC fs/ext4/migrate.o Reported-by: Akira Fujita Signed-off-by: "Theodore Ts'o" --- fs/ext4/resize.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fs/ext4/resize.c b/fs/ext4/resize.c index 3ecc6e45d2f93..66fec4ee76faa 100644 --- a/fs/ext4/resize.c +++ b/fs/ext4/resize.c @@ -230,7 +230,7 @@ static int setup_new_group_blocks(struct super_block *sb, } /* Zero out all of the reserved backup group descriptor table blocks */ - ext4_debug("clear inode table blocks %#04llx -> %#04llx\n", + ext4_debug("clear inode table blocks %#04llx -> %#04lx\n", block, sbi->s_itb_per_group); err = sb_issue_zeroout(sb, gdblocks + start + 1, reserved_gdb, GFP_NOFS); @@ -248,7 +248,7 @@ static int setup_new_group_blocks(struct super_block *sb, /* Zero out all of the inode table blocks */ block = input->inode_table; - ext4_debug("clear inode table blocks %#04llx -> %#04llx\n", + ext4_debug("clear inode table blocks %#04llx -> %#04lx\n", block, sbi->s_itb_per_group); err = sb_issue_zeroout(sb, block, sbi->s_itb_per_group, GFP_NOFS); if (err) -- GitLab From c4d0c3b097f7584772316ee4d64a09fe0e4ddfca Mon Sep 17 00:00:00 2001 From: Dan Rosenberg Date: Mon, 14 Feb 2011 13:45:28 +0000 Subject: [PATCH 0157/2822] xfs: prevent leaking uninitialized stack memory in FSGEOMETRY_V1 The FSGEOMETRY_V1 ioctl (and its compat equivalent) calls out to xfs_fs_geometry() with a version number of 3. This code path does not fill in the logsunit member of the passed xfs_fsop_geom_t, leading to the leaking of four bytes of uninitialized stack data to potentially unprivileged callers. v2 switches to memset() to avoid future issues if structure members change, on suggestion of Dave Chinner. Signed-off-by: Dan Rosenberg Reviewed-by: Eugene Teo Signed-off-by: Alex Elder --- fs/xfs/xfs_fsops.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/fs/xfs/xfs_fsops.c b/fs/xfs/xfs_fsops.c index cec89dd5d7d28..85668efb3e3e0 100644 --- a/fs/xfs/xfs_fsops.c +++ b/fs/xfs/xfs_fsops.c @@ -53,6 +53,9 @@ xfs_fs_geometry( xfs_fsop_geom_t *geo, int new_version) { + + memset(geo, 0, sizeof(*geo)); + geo->blocksize = mp->m_sb.sb_blocksize; geo->rtextsize = mp->m_sb.sb_rextsize; geo->agblocks = mp->m_sb.sb_agblocks; -- GitLab From 7dc576158d7e5cdff3349f78598fdb4080536342 Mon Sep 17 00:00:00 2001 From: Peter Huewe Date: Mon, 21 Feb 2011 21:01:42 -0500 Subject: [PATCH 0158/2822] ext4: Fix sparse warning: Using plain integer as NULL pointer This patch fixes the warning "Using plain integer as NULL pointer", generated by sparse, by replacing the offending 0s with NULL. Signed-off-by: Peter Huewe Signed-off-by: "Theodore Ts'o" --- fs/ext4/extents.c | 8 ++++---- fs/ext4/ialloc.c | 2 +- fs/ext4/inode.c | 18 +++++++++--------- fs/ext4/migrate.c | 10 +++++----- fs/ext4/page-io.c | 4 ++-- fs/ext4/super.c | 2 +- fs/ext4/xattr.c | 2 +- 7 files changed, 23 insertions(+), 23 deletions(-) diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c index ccce8a7e94edc..d16f6b5a140b7 100644 --- a/fs/ext4/extents.c +++ b/fs/ext4/extents.c @@ -1034,7 +1034,7 @@ cleanup: for (i = 0; i < depth; i++) { if (!ablocks[i]) continue; - ext4_free_blocks(handle, inode, 0, ablocks[i], 1, + ext4_free_blocks(handle, inode, NULL, ablocks[i], 1, EXT4_FREE_BLOCKS_METADATA); } } @@ -2059,7 +2059,7 @@ static int ext4_ext_rm_idx(handle_t *handle, struct inode *inode, if (err) return err; ext_debug("index is empty, remove it, free block %llu\n", leaf); - ext4_free_blocks(handle, inode, 0, leaf, 1, + ext4_free_blocks(handle, inode, NULL, leaf, 1, EXT4_FREE_BLOCKS_METADATA | EXT4_FREE_BLOCKS_FORGET); return err; } @@ -2156,7 +2156,7 @@ static int ext4_remove_blocks(handle_t *handle, struct inode *inode, num = le32_to_cpu(ex->ee_block) + ee_len - from; start = ext4_ext_pblock(ex) + ee_len - num; ext_debug("free last %u blocks starting %llu\n", num, start); - ext4_free_blocks(handle, inode, 0, start, num, flags); + ext4_free_blocks(handle, inode, NULL, start, num, flags); } else if (from == le32_to_cpu(ex->ee_block) && to <= le32_to_cpu(ex->ee_block) + ee_len - 1) { printk(KERN_INFO "strange request: removal %u-%u from %u:%u\n", @@ -3485,7 +3485,7 @@ int ext4_ext_map_blocks(handle_t *handle, struct inode *inode, /* not a good idea to call discard here directly, * but otherwise we'd need to call it every free() */ ext4_discard_preallocations(inode); - ext4_free_blocks(handle, inode, 0, ext4_ext_pblock(&newex), + ext4_free_blocks(handle, inode, NULL, ext4_ext_pblock(&newex), ext4_ext_get_actual_len(&newex), 0); goto out2; } diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c index eb9097aec6f09..2fd3b0e41787a 100644 --- a/fs/ext4/ialloc.c +++ b/fs/ext4/ialloc.c @@ -649,7 +649,7 @@ static int find_group_other(struct super_block *sb, struct inode *parent, *group = parent_group + flex_size; if (*group > ngroups) *group = 0; - return find_group_orlov(sb, parent, group, mode, 0); + return find_group_orlov(sb, parent, group, mode, NULL); } /* diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index 9f7f9e49914fa..c6c6b7fcb455a 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -720,7 +720,7 @@ allocated: return ret; failed_out: for (i = 0; i < index; i++) - ext4_free_blocks(handle, inode, 0, new_blocks[i], 1, 0); + ext4_free_blocks(handle, inode, NULL, new_blocks[i], 1, 0); return ret; } @@ -823,20 +823,20 @@ static int ext4_alloc_branch(handle_t *handle, struct inode *inode, return err; failed: /* Allocation failed, free what we already allocated */ - ext4_free_blocks(handle, inode, 0, new_blocks[0], 1, 0); + ext4_free_blocks(handle, inode, NULL, new_blocks[0], 1, 0); for (i = 1; i <= n ; i++) { /* * branch[i].bh is newly allocated, so there is no * need to revoke the block, which is why we don't * need to set EXT4_FREE_BLOCKS_METADATA. */ - ext4_free_blocks(handle, inode, 0, new_blocks[i], 1, + ext4_free_blocks(handle, inode, NULL, new_blocks[i], 1, EXT4_FREE_BLOCKS_FORGET); } for (i = n+1; i < indirect_blks; i++) - ext4_free_blocks(handle, inode, 0, new_blocks[i], 1, 0); + ext4_free_blocks(handle, inode, NULL, new_blocks[i], 1, 0); - ext4_free_blocks(handle, inode, 0, new_blocks[i], num, 0); + ext4_free_blocks(handle, inode, NULL, new_blocks[i], num, 0); return err; } @@ -924,7 +924,7 @@ err_out: ext4_free_blocks(handle, inode, where[i].bh, 0, 1, EXT4_FREE_BLOCKS_FORGET); } - ext4_free_blocks(handle, inode, 0, le32_to_cpu(where[num].key), + ext4_free_blocks(handle, inode, NULL, le32_to_cpu(where[num].key), blks, 0); return err; @@ -4228,7 +4228,7 @@ static int ext4_clear_blocks(handle_t *handle, struct inode *inode, for (p = first; p < last; p++) *p = 0; - ext4_free_blocks(handle, inode, 0, block_to_free, count, flags); + ext4_free_blocks(handle, inode, NULL, block_to_free, count, flags); return 0; } @@ -4416,7 +4416,7 @@ static void ext4_free_branches(handle_t *handle, struct inode *inode, * transaction where the data blocks are * actually freed. */ - ext4_free_blocks(handle, inode, 0, nr, 1, + ext4_free_blocks(handle, inode, NULL, nr, 1, EXT4_FREE_BLOCKS_METADATA| EXT4_FREE_BLOCKS_FORGET); @@ -4875,7 +4875,7 @@ struct inode *ext4_iget(struct super_block *sb, unsigned long ino) return inode; ei = EXT4_I(inode); - iloc.bh = 0; + iloc.bh = NULL; ret = __ext4_get_inode_loc(inode, &iloc, 0); if (ret < 0) diff --git a/fs/ext4/migrate.c b/fs/ext4/migrate.c index b0a126f23c20c..d1bafa57f4836 100644 --- a/fs/ext4/migrate.c +++ b/fs/ext4/migrate.c @@ -263,7 +263,7 @@ static int free_dind_blocks(handle_t *handle, for (i = 0; i < max_entries; i++) { if (tmp_idata[i]) { extend_credit_for_blkdel(handle, inode); - ext4_free_blocks(handle, inode, 0, + ext4_free_blocks(handle, inode, NULL, le32_to_cpu(tmp_idata[i]), 1, EXT4_FREE_BLOCKS_METADATA | EXT4_FREE_BLOCKS_FORGET); @@ -271,7 +271,7 @@ static int free_dind_blocks(handle_t *handle, } put_bh(bh); extend_credit_for_blkdel(handle, inode); - ext4_free_blocks(handle, inode, 0, le32_to_cpu(i_data), 1, + ext4_free_blocks(handle, inode, NULL, le32_to_cpu(i_data), 1, EXT4_FREE_BLOCKS_METADATA | EXT4_FREE_BLOCKS_FORGET); return 0; @@ -302,7 +302,7 @@ static int free_tind_blocks(handle_t *handle, } put_bh(bh); extend_credit_for_blkdel(handle, inode); - ext4_free_blocks(handle, inode, 0, le32_to_cpu(i_data), 1, + ext4_free_blocks(handle, inode, NULL, le32_to_cpu(i_data), 1, EXT4_FREE_BLOCKS_METADATA | EXT4_FREE_BLOCKS_FORGET); return 0; @@ -315,7 +315,7 @@ static int free_ind_block(handle_t *handle, struct inode *inode, __le32 *i_data) /* ei->i_data[EXT4_IND_BLOCK] */ if (i_data[0]) { extend_credit_for_blkdel(handle, inode); - ext4_free_blocks(handle, inode, 0, + ext4_free_blocks(handle, inode, NULL, le32_to_cpu(i_data[0]), 1, EXT4_FREE_BLOCKS_METADATA | EXT4_FREE_BLOCKS_FORGET); @@ -428,7 +428,7 @@ static int free_ext_idx(handle_t *handle, struct inode *inode, } put_bh(bh); extend_credit_for_blkdel(handle, inode); - ext4_free_blocks(handle, inode, 0, block, 1, + ext4_free_blocks(handle, inode, NULL, block, 1, EXT4_FREE_BLOCKS_METADATA | EXT4_FREE_BLOCKS_FORGET); return retval; } diff --git a/fs/ext4/page-io.c b/fs/ext4/page-io.c index 955cc309142fe..68d92a8f71d73 100644 --- a/fs/ext4/page-io.c +++ b/fs/ext4/page-io.c @@ -279,9 +279,9 @@ void ext4_io_submit(struct ext4_io_submit *io) BUG_ON(bio_flagged(io->io_bio, BIO_EOPNOTSUPP)); bio_put(io->io_bio); } - io->io_bio = 0; + io->io_bio = NULL; io->io_op = 0; - io->io_end = 0; + io->io_end = NULL; } static int io_submit_init(struct ext4_io_submit *io, diff --git a/fs/ext4/super.c b/fs/ext4/super.c index f6a318f836b2c..ef83457fd4ead 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c @@ -1451,7 +1451,7 @@ static int parse_options(char *options, struct super_block *sb, * Initialize args struct so we know whether arg was * found; some options take optional arguments. */ - args[0].to = args[0].from = 0; + args[0].to = args[0].from = NULL; token = match_token(p, tokens, args); switch (token) { case Opt_bsd_df: diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c index fc32176eee39e..f4c03af05d694 100644 --- a/fs/ext4/xattr.c +++ b/fs/ext4/xattr.c @@ -833,7 +833,7 @@ inserted: new_bh = sb_getblk(sb, block); if (!new_bh) { getblk_failed: - ext4_free_blocks(handle, inode, 0, block, 1, + ext4_free_blocks(handle, inode, NULL, block, 1, EXT4_FREE_BLOCKS_METADATA); error = -EIO; goto cleanup; -- GitLab From 5dbd571d875d73e087c1eeb3d840cfc653a97422 Mon Sep 17 00:00:00 2001 From: "Alexander V. Lukyanov" Date: Mon, 21 Feb 2011 21:33:21 -0500 Subject: [PATCH 0159/2822] ext4: allow inode_readahead_blks=0 (linux-2.6.37) I cannot disable inode-read-ahead feature of ext4 (on 2.6.37): # echo 0 > /sys/fs/ext4/sda2/inode_readahead_blks bash: echo: write error: Invalid argument On a server with lots of small files and random access this read-ahead makes performance worse, and I'd like to disable it. I work around this problem by using value of 1, but it still reads an extra block. This patch fixes the problem by checking for zero explicitly. Signed-off-by: Alexander V. Lukyanov Signed-off-by: "Theodore Ts'o" --- fs/ext4/super.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fs/ext4/super.c b/fs/ext4/super.c index ef83457fd4ead..a1ac24b6a758a 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c @@ -1771,7 +1771,7 @@ set_qf_format: return 0; if (option < 0 || option > (1 << 30)) return 0; - if (!is_power_of_2(option)) { + if (option && !is_power_of_2(option)) { ext4_msg(sb, KERN_ERR, "EXT4-fs: inode_readahead_blks" " must be a power of 2"); @@ -2412,7 +2412,7 @@ static ssize_t inode_readahead_blks_store(struct ext4_attr *a, if (parse_strtoul(buf, 0x40000000, &t)) return -EINVAL; - if (!is_power_of_2(t)) + if (t && !is_power_of_2(t)) return -EINVAL; sbi->s_inode_readahead_blks = t; -- GitLab From 5d15765594eeb5d82c5630b3428ea0ac4f7d3c31 Mon Sep 17 00:00:00 2001 From: Lukas Czerner Date: Tue, 15 Feb 2011 17:07:36 +0000 Subject: [PATCH 0160/2822] xfs: check if device support discard in xfs_ioc_trim() Right now we, are relying on the fact that when we attempt to actually do the discard, blkdev_issue_discar() returns -EOPNOTSUPP and the user is informed that the device does not support discard. However, in the case where the we do not hit any suitable free extent to trim in FITRIM code, it will finish without any error. This is very confusing, because it seems that FITRIM was successful even though the device does not actually supports discard. Solution: Check for the discard support before attempt to search for free extents. Signed-off-by: Lukas Czerner Signed-off-by: Alex Elder --- fs/xfs/linux-2.6/xfs_discard.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/fs/xfs/linux-2.6/xfs_discard.c b/fs/xfs/linux-2.6/xfs_discard.c index 05201ae719e5f..d61611c88012c 100644 --- a/fs/xfs/linux-2.6/xfs_discard.c +++ b/fs/xfs/linux-2.6/xfs_discard.c @@ -152,6 +152,8 @@ xfs_ioc_trim( if (!capable(CAP_SYS_ADMIN)) return -XFS_ERROR(EPERM); + if (!blk_queue_discard(q)) + return -XFS_ERROR(EOPNOTSUPP); if (copy_from_user(&range, urange, sizeof(range))) return -XFS_ERROR(EFAULT); -- GitLab From f722e17fdb2c97bbec2563636dd88489cdb1428b Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sat, 8 Jan 2011 19:12:26 +0100 Subject: [PATCH 0161/2822] power_supply: Ignore -ENODATA errors when generating uevents Sometimes a driver can not report a meaningful value for a certain property and returns -ENODATA. Currently when generating a uevent and a property return -ENODATA it is treated as an error an no uevent is generated at all. This is not an desirable behavior. This patch adds a special case for -ENODATA and ignores properties which return this error code when generating the uevent. Signed-off-by: Lars-Peter Clausen Tested-by: Grazvydas Ignotas --- drivers/power/power_supply_sysfs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/power/power_supply_sysfs.c b/drivers/power/power_supply_sysfs.c index cd1f90754a3a3..605514afc29f2 100644 --- a/drivers/power/power_supply_sysfs.c +++ b/drivers/power/power_supply_sysfs.c @@ -270,7 +270,7 @@ int power_supply_uevent(struct device *dev, struct kobj_uevent_env *env) attr = &power_supply_attrs[psy->properties[j]]; ret = power_supply_show_property(dev, attr, prop_buf); - if (ret == -ENODEV) { + if (ret == -ENODEV || ret == -ENODATA) { /* When a battery is absent, we expect -ENODEV. Don't abort; send the uevent with at least the the PRESENT=0 property */ ret = 0; -- GitLab From 770c4d81e0d2ca45516ddc9ae0a69565790b5533 Mon Sep 17 00:00:00 2001 From: Sunil Mushran Date: Mon, 21 Feb 2011 14:25:25 -0800 Subject: [PATCH 0162/2822] ocfs2/dlm: Move kmalloc() outside the spinlock In dlm_query_region_handler(), move the kmalloc outside the spinlock. This allows us to use GFP_KERNEL instead of GFP_ATOMIC. Signed-off-by: Sunil Mushran Signed-off-by: Joel Becker --- fs/ocfs2/dlm/dlmdomain.c | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/fs/ocfs2/dlm/dlmdomain.c b/fs/ocfs2/dlm/dlmdomain.c index 7e38a072d7202..99805d578ab55 100644 --- a/fs/ocfs2/dlm/dlmdomain.c +++ b/fs/ocfs2/dlm/dlmdomain.c @@ -926,9 +926,10 @@ static int dlm_assert_joined_handler(struct o2net_msg *msg, u32 len, void *data, } static int dlm_match_regions(struct dlm_ctxt *dlm, - struct dlm_query_region *qr) + struct dlm_query_region *qr, + char *local, int locallen) { - char *local = NULL, *remote = qr->qr_regions; + char *remote = qr->qr_regions; char *l, *r; int localnr, i, j, foundit; int status = 0; @@ -957,13 +958,8 @@ static int dlm_match_regions(struct dlm_ctxt *dlm, r += O2HB_MAX_REGION_NAME_LEN; } - local = kmalloc(sizeof(qr->qr_regions), GFP_ATOMIC); - if (!local) { - status = -ENOMEM; - goto bail; - } - - localnr = o2hb_get_all_regions(local, O2NM_MAX_REGIONS); + localnr = min(O2NM_MAX_REGIONS, locallen/O2HB_MAX_REGION_NAME_LEN); + localnr = o2hb_get_all_regions(local, (u8)localnr); /* compare local regions with remote */ l = local; @@ -1012,8 +1008,6 @@ static int dlm_match_regions(struct dlm_ctxt *dlm, } bail: - kfree(local); - return status; } @@ -1075,6 +1069,7 @@ static int dlm_query_region_handler(struct o2net_msg *msg, u32 len, { struct dlm_query_region *qr; struct dlm_ctxt *dlm = NULL; + char *local = NULL; int status = 0; int locked = 0; @@ -1083,6 +1078,13 @@ static int dlm_query_region_handler(struct o2net_msg *msg, u32 len, mlog(0, "Node %u queries hb regions on domain %s\n", qr->qr_node, qr->qr_domain); + /* buffer used in dlm_mast_regions() */ + local = kmalloc(sizeof(qr->qr_regions), GFP_KERNEL); + if (!local) { + status = -ENOMEM; + goto bail; + } + status = -EINVAL; spin_lock(&dlm_domain_lock); @@ -1112,13 +1114,15 @@ static int dlm_query_region_handler(struct o2net_msg *msg, u32 len, goto bail; } - status = dlm_match_regions(dlm, qr); + status = dlm_match_regions(dlm, qr, local, sizeof(qr->qr_regions)); bail: if (locked) spin_unlock(&dlm->spinlock); spin_unlock(&dlm_domain_lock); + kfree(local); + return status; } -- GitLab From 97774672573ac4355bd12cf84b202555c1131b69 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 21 Feb 2011 15:34:19 +0100 Subject: [PATCH 0163/2822] power_supply: Initialize changed_work before calling device_add Calling device_add causes an inital uevent for that device to be generated. The power_supply uevent function calls the drivers get_property function, which might causes the driver to update its state, which again might causes the driver to call power_supply_changed(). Since the power_supplys changed_work has not been initialized at this point the behavior is undefined and can result in an OOPS. This patch fixes the issue by initializing the power_supplys changed_work prior to adding the power_supplys device to the device tree. Reported-by: Grazvydas Ignotas Signed-off-by: Lars-Peter Clausen Tested-by: Grazvydas Ignotas --- drivers/power/power_supply_core.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/power/power_supply_core.c b/drivers/power/power_supply_core.c index 970f7335d3a7f..329b46b2327d4 100644 --- a/drivers/power/power_supply_core.c +++ b/drivers/power/power_supply_core.c @@ -171,6 +171,8 @@ int power_supply_register(struct device *parent, struct power_supply *psy) dev_set_drvdata(dev, psy); psy->dev = dev; + INIT_WORK(&psy->changed_work, power_supply_changed_work); + rc = kobject_set_name(&dev->kobj, "%s", psy->name); if (rc) goto kobject_set_name_failed; @@ -179,8 +181,6 @@ int power_supply_register(struct device *parent, struct power_supply *psy) if (rc) goto device_add_failed; - INIT_WORK(&psy->changed_work, power_supply_changed_work); - rc = power_supply_create_triggers(psy); if (rc) goto create_triggers_failed; -- GitLab From 5661f334e8a53848552c8763f3bd63d0672b2e7b Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 24 May 2010 20:36:52 +0200 Subject: [PATCH 0164/2822] bq27x00: Add type property This patch adds the type property to the bq27x00 battery driver. All bq27x00 are lithium ion batteries. Signed-off-by: Lars-Peter Clausen Acked-by: Rodolfo Giometti Tested-by: Grazvydas Ignotas --- drivers/power/bq27x00_battery.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/power/bq27x00_battery.c b/drivers/power/bq27x00_battery.c index eff0273d4030d..bb043f93cead8 100644 --- a/drivers/power/bq27x00_battery.c +++ b/drivers/power/bq27x00_battery.c @@ -78,6 +78,7 @@ static enum power_supply_property bq27x00_battery_props[] = { POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW, POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG, POWER_SUPPLY_PROP_TIME_TO_FULL_NOW, + POWER_SUPPLY_PROP_TECHNOLOGY, }; /* @@ -277,6 +278,9 @@ static int bq27x00_battery_get_property(struct power_supply *psy, case POWER_SUPPLY_PROP_TIME_TO_FULL_NOW: ret = bq27x00_battery_time(di, BQ27x00_REG_TTF, val); break; + case POWER_SUPPLY_PROP_TECHNOLOGY: + val->intval = POWER_SUPPLY_TECHNOLOGY_LION; + break; default: return -EINVAL; } -- GitLab From 0e9f30497e88600ba52013665270f543bb94f0d8 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 24 May 2010 20:20:57 +0200 Subject: [PATCH 0165/2822] bq27x00: Improve temperature property precession This patch improves the precession of the temperature property of the bq27x00 driver. By dividing before multiplying the current code effectively cuts of the last decimal digit. This patch fixes it by multiplying before dividing. Signed-off-by: Lars-Peter Clausen Acked-by: Rodolfo Giometti Tested-by: Grazvydas Ignotas --- drivers/power/bq27x00_battery.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/power/bq27x00_battery.c b/drivers/power/bq27x00_battery.c index bb043f93cead8..4f7465999c865 100644 --- a/drivers/power/bq27x00_battery.c +++ b/drivers/power/bq27x00_battery.c @@ -109,7 +109,7 @@ static int bq27x00_battery_temperature(struct bq27x00_device_info *di) if (di->chip == BQ27500) return temp - 2731; else - return ((temp >> 2) - 273) * 10; + return ((temp * 5) - 5463) / 2; } /* -- GitLab From a2e5118c370e78c3841606e7edc7677c986325fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pali=20Roh=C3=A1r?= Date: Mon, 24 May 2010 20:52:13 +0200 Subject: [PATCH 0166/2822] bq27x00: Fix CURRENT_NOW property MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit According to the bq27000 datasheet the current should be calculated by the following formula: current = AI * 3570 / 20 This patch adjust the drivers code accordingly. Signed-off-by: Pali Rohár Signed-off-by: Lars-Peter Clausen Acked-by: Rodolfo Giometti Tested-by: Grazvydas Ignotas --- drivers/power/bq27x00_battery.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/power/bq27x00_battery.c b/drivers/power/bq27x00_battery.c index 4f7465999c865..1b06134e0ae88 100644 --- a/drivers/power/bq27x00_battery.c +++ b/drivers/power/bq27x00_battery.c @@ -44,6 +44,8 @@ #define BQ27500_FLAG_DSC BIT(0) #define BQ27500_FLAG_FC BIT(9) +#define BQ27000_RS 20 /* Resistor sense */ + /* If the system has several batteries we need a different name for each * of them... */ @@ -149,7 +151,7 @@ static int bq27x00_battery_current(struct bq27x00_device_info *di) if (di->chip == BQ27500) { /* bq27500 returns signed value */ - curr = (int)(s16)curr; + curr = (int)((s16)curr) * 1000; } else { ret = bq27x00_read(BQ27x00_REG_FLAGS, &flags, 0, di); if (ret < 0) { @@ -160,9 +162,10 @@ static int bq27x00_battery_current(struct bq27x00_device_info *di) dev_dbg(di->dev, "negative current!\n"); curr = -curr; } + curr = curr * 3570 / BQ27000_RS; } - return curr * 1000; + return curr; } /* -- GitLab From 3413b4ea250ff0b4142a154a2764e33979957e8b Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 24 May 2010 21:57:33 +0200 Subject: [PATCH 0167/2822] bq27x00: Return -ENODEV for properties if the battery is not present This patch changes get_property callback of the bq27x00 battery to return -ENODEV for properties other then the PROP_PRESENT if the battery is not present. The power subsystem core expects a driver to behave that way. Signed-off-by: Lars-Peter Clausen Acked-by: Rodolfo Giometti Tested-by: Grazvydas Ignotas --- drivers/power/bq27x00_battery.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/power/bq27x00_battery.c b/drivers/power/bq27x00_battery.c index 1b06134e0ae88..9f16666dc4668 100644 --- a/drivers/power/bq27x00_battery.c +++ b/drivers/power/bq27x00_battery.c @@ -252,16 +252,21 @@ static int bq27x00_battery_get_property(struct power_supply *psy, { int ret = 0; struct bq27x00_device_info *di = to_bq27x00_device_info(psy); + int voltage = bq27x00_battery_voltage(di); + + if (psp != POWER_SUPPLY_PROP_PRESENT && voltage <= 0) + return -ENODEV; switch (psp) { case POWER_SUPPLY_PROP_STATUS: ret = bq27x00_battery_status(di, val); break; case POWER_SUPPLY_PROP_VOLTAGE_NOW: + val->intval = voltage; + break; case POWER_SUPPLY_PROP_PRESENT: - val->intval = bq27x00_battery_voltage(di); if (psp == POWER_SUPPLY_PROP_PRESENT) - val->intval = val->intval <= 0 ? 0 : 1; + val->intval = voltage <= 0 ? 0 : 1; break; case POWER_SUPPLY_PROP_CURRENT_NOW: val->intval = bq27x00_battery_current(di); -- GitLab From a40402ef0bf3b6e53a7dfd396e9487eb2f613e19 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 24 May 2010 19:37:58 +0200 Subject: [PATCH 0168/2822] bq27x00: Prepare code for addition of bq27000 platform driver This patch simplifies the drivers data structure and moves code to be shared by the bq27000 and bq27200/bq27500 init functions into a common function. This patch has no functional changes, it only moves code around. Signed-off-by: Lars-Peter Clausen Acked-by: Rodolfo Giometti Tested-by: Grazvydas Ignotas --- drivers/power/bq27x00_battery.c | 86 +++++++++++++++------------------ 1 file changed, 39 insertions(+), 47 deletions(-) diff --git a/drivers/power/bq27x00_battery.c b/drivers/power/bq27x00_battery.c index 9f16666dc4668..def951d8fc2b5 100644 --- a/drivers/power/bq27x00_battery.c +++ b/drivers/power/bq27x00_battery.c @@ -54,8 +54,8 @@ static DEFINE_MUTEX(battery_mutex); struct bq27x00_device_info; struct bq27x00_access_methods { - int (*read)(u8 reg, int *rt_value, int b_single, - struct bq27x00_device_info *di); + int (*read)(struct bq27x00_device_info *, u8 reg, int *rt_value, + bool single); }; enum bq27x00_chip { BQ27000, BQ27500 }; @@ -63,11 +63,11 @@ enum bq27x00_chip { BQ27000, BQ27500 }; struct bq27x00_device_info { struct device *dev; int id; - struct bq27x00_access_methods *bus; - struct power_supply bat; enum bq27x00_chip chip; - struct i2c_client *client; + struct power_supply bat; + + struct bq27x00_access_methods bus; }; static enum power_supply_property bq27x00_battery_props[] = { @@ -87,10 +87,10 @@ static enum power_supply_property bq27x00_battery_props[] = { * Common code for BQ27x00 devices */ -static int bq27x00_read(u8 reg, int *rt_value, int b_single, - struct bq27x00_device_info *di) +static inline int bq27x00_read(struct bq27x00_device_info *di, u8 reg, + int *rt_value, bool single) { - return di->bus->read(reg, rt_value, b_single, di); + return di->bus.read(di, reg, rt_value, single); } /* @@ -102,7 +102,7 @@ static int bq27x00_battery_temperature(struct bq27x00_device_info *di) int ret; int temp = 0; - ret = bq27x00_read(BQ27x00_REG_TEMP, &temp, 0, di); + ret = bq27x00_read(di, BQ27x00_REG_TEMP, &temp, false); if (ret) { dev_err(di->dev, "error reading temperature\n"); return ret; @@ -123,7 +123,7 @@ static int bq27x00_battery_voltage(struct bq27x00_device_info *di) int ret; int volt = 0; - ret = bq27x00_read(BQ27x00_REG_VOLT, &volt, 0, di); + ret = bq27x00_read(di, BQ27x00_REG_VOLT, &volt, false); if (ret) { dev_err(di->dev, "error reading voltage\n"); return ret; @@ -143,7 +143,7 @@ static int bq27x00_battery_current(struct bq27x00_device_info *di) int curr = 0; int flags = 0; - ret = bq27x00_read(BQ27x00_REG_AI, &curr, 0, di); + ret = bq27x00_read(di, BQ27x00_REG_AI, &curr, false); if (ret) { dev_err(di->dev, "error reading current\n"); return 0; @@ -153,7 +153,7 @@ static int bq27x00_battery_current(struct bq27x00_device_info *di) /* bq27500 returns signed value */ curr = (int)((s16)curr) * 1000; } else { - ret = bq27x00_read(BQ27x00_REG_FLAGS, &flags, 0, di); + ret = bq27x00_read(di, BQ27x00_REG_FLAGS, &flags, false); if (ret < 0) { dev_err(di->dev, "error reading flags\n"); return 0; @@ -178,9 +178,9 @@ static int bq27x00_battery_rsoc(struct bq27x00_device_info *di) int rsoc = 0; if (di->chip == BQ27500) - ret = bq27x00_read(BQ27500_REG_SOC, &rsoc, 0, di); + ret = bq27x00_read(di, BQ27500_REG_SOC, &rsoc, false); else - ret = bq27x00_read(BQ27000_REG_RSOC, &rsoc, 1, di); + ret = bq27x00_read(di, BQ27000_REG_RSOC, &rsoc, true); if (ret) { dev_err(di->dev, "error reading relative State-of-Charge\n"); return ret; @@ -196,7 +196,7 @@ static int bq27x00_battery_status(struct bq27x00_device_info *di, int status; int ret; - ret = bq27x00_read(BQ27x00_REG_FLAGS, &flags, 0, di); + ret = bq27x00_read(di, BQ27x00_REG_FLAGS, &flags, false); if (ret < 0) { dev_err(di->dev, "error reading flags\n"); return ret; @@ -230,7 +230,7 @@ static int bq27x00_battery_time(struct bq27x00_device_info *di, int reg, int tval = 0; int ret; - ret = bq27x00_read(reg, &tval, 0, di); + ret = bq27x00_read(di, reg, &tval, false); if (ret) { dev_err(di->dev, "error reading register %02x\n", reg); return ret; @@ -296,23 +296,35 @@ static int bq27x00_battery_get_property(struct power_supply *psy, return ret; } -static void bq27x00_powersupply_init(struct bq27x00_device_info *di) +static int bq27x00_powersupply_init(struct bq27x00_device_info *di) { + int ret; + di->bat.type = POWER_SUPPLY_TYPE_BATTERY; di->bat.properties = bq27x00_battery_props; di->bat.num_properties = ARRAY_SIZE(bq27x00_battery_props); di->bat.get_property = bq27x00_battery_get_property; di->bat.external_power_changed = NULL; + + ret = power_supply_register(di->dev, &di->bat); + if (ret) { + dev_err(di->dev, "failed to register battery: %d\n", ret); + return ret; + } + + dev_info(di->dev, "support ver. %s enabled\n", DRIVER_VERSION); + + return 0; } /* * i2c specific code */ -static int bq27x00_read_i2c(u8 reg, int *rt_value, int b_single, - struct bq27x00_device_info *di) +static int bq27x00_read_i2c(struct bq27x00_device_info *di, u8 reg, + int *rt_value, bool single) { - struct i2c_client *client = di->client; + struct i2c_client *client = to_i2c_client(di->dev); struct i2c_msg msg[1]; unsigned char data[2]; int err; @@ -329,7 +341,7 @@ static int bq27x00_read_i2c(u8 reg, int *rt_value, int b_single, err = i2c_transfer(client->adapter, msg, 1); if (err >= 0) { - if (!b_single) + if (!single) msg->len = 2; else msg->len = 1; @@ -337,7 +349,7 @@ static int bq27x00_read_i2c(u8 reg, int *rt_value, int b_single, msg->flags = I2C_M_RD; err = i2c_transfer(client->adapter, msg, 1); if (err >= 0) { - if (!b_single) + if (!single) *rt_value = get_unaligned_le16(data); else *rt_value = data[0]; @@ -353,7 +365,6 @@ static int bq27x00_battery_probe(struct i2c_client *client, { char *name; struct bq27x00_device_info *di; - struct bq27x00_access_methods *bus; int num; int retval = 0; @@ -380,38 +391,20 @@ static int bq27x00_battery_probe(struct i2c_client *client, retval = -ENOMEM; goto batt_failed_2; } + di->id = num; + di->dev = &client->dev; di->chip = id->driver_data; + di->bat.name = name; + di->bus.read = &bq27x00_read_i2c; - bus = kzalloc(sizeof(*bus), GFP_KERNEL); - if (!bus) { - dev_err(&client->dev, "failed to allocate access method " - "data\n"); - retval = -ENOMEM; + if (bq27x00_powersupply_init(di)) goto batt_failed_3; - } i2c_set_clientdata(client, di); - di->dev = &client->dev; - di->bat.name = name; - bus->read = &bq27x00_read_i2c; - di->bus = bus; - di->client = client; - - bq27x00_powersupply_init(di); - - retval = power_supply_register(&client->dev, &di->bat); - if (retval) { - dev_err(&client->dev, "failed to register battery\n"); - goto batt_failed_4; - } - - dev_info(&client->dev, "support ver. %s enabled\n", DRIVER_VERSION); return 0; -batt_failed_4: - kfree(bus); batt_failed_3: kfree(di); batt_failed_2: @@ -430,7 +423,6 @@ static int bq27x00_battery_remove(struct i2c_client *client) power_supply_unregister(&di->bat); - kfree(di->bus); kfree(di->bat.name); mutex_lock(&battery_mutex); -- GitLab From 7fb7ba588c0f276609609565b21fcc853284a9a0 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 24 May 2010 19:55:27 +0200 Subject: [PATCH 0169/2822] bq27x00: Add bq27000 support This patch adds support for the bq27000 battery to the bq27x00 driver. The bq27000 is similar to the bq27200 except that it uses the HDQ bus instead of I2C to communicate with the host system. The driver is implemented as a platform driver. The driver expects to be provided with a read callback function through its platform data. The read function is assumed to do the lowlevel HDQ handling and read out the value of a certain register. Signed-off-by: Lars-Peter Clausen Tested-by: Grazvydas Ignotas --- drivers/power/Kconfig | 14 ++ drivers/power/bq27x00_battery.c | 184 +++++++++++++++++++++++--- include/linux/power/bq27x00_battery.h | 19 +++ 3 files changed, 202 insertions(+), 15 deletions(-) create mode 100644 include/linux/power/bq27x00_battery.h diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig index 61bf5d724139c..52a462fc6b844 100644 --- a/drivers/power/Kconfig +++ b/drivers/power/Kconfig @@ -117,10 +117,24 @@ config BATTERY_BQ20Z75 config BATTERY_BQ27x00 tristate "BQ27x00 battery driver" + help + Say Y here to enable support for batteries with BQ27x00 (I2C/HDQ) chips. + +config BATTERY_BQ27X00_I2C + bool "BQ27200/BQ27500 support" + depends on BATTERY_BQ27x00 depends on I2C + default y help Say Y here to enable support for batteries with BQ27x00 (I2C) chips. +config BATTERY_BQ27X00_PLATFORM + bool "BQ27000 support" + depends on BATTERY_BQ27x00 + default y + help + Say Y here to enable support for batteries with BQ27000 (HDQ) chips. + config BATTERY_DA9030 tristate "DA9030 battery driver" depends on PMIC_DA903X diff --git a/drivers/power/bq27x00_battery.c b/drivers/power/bq27x00_battery.c index def951d8fc2b5..44bc76be0780b 100644 --- a/drivers/power/bq27x00_battery.c +++ b/drivers/power/bq27x00_battery.c @@ -3,6 +3,7 @@ * * Copyright (C) 2008 Rodolfo Giometti * Copyright (C) 2008 Eurotech S.p.A. + * Copyright (C) 2010-2011 Lars-Peter Clausen * * Based on a previous work by Copyright (C) 2008 Texas Instruments, Inc. * @@ -27,6 +28,8 @@ #include #include +#include + #define DRIVER_VERSION "1.1.0" #define BQ27x00_REG_TEMP 0x06 @@ -46,12 +49,6 @@ #define BQ27000_RS 20 /* Resistor sense */ -/* If the system has several batteries we need a different name for each - * of them... - */ -static DEFINE_IDR(battery_id); -static DEFINE_MUTEX(battery_mutex); - struct bq27x00_device_info; struct bq27x00_access_methods { int (*read)(struct bq27x00_device_info *, u8 reg, int *rt_value, @@ -317,9 +314,15 @@ static int bq27x00_powersupply_init(struct bq27x00_device_info *di) return 0; } -/* - * i2c specific code + +/* i2c specific code */ +#ifdef CONFIG_BATTERY_BQ27X00_I2C + +/* If the system has several batteries we need a different name for each + * of them... */ +static DEFINE_IDR(battery_id); +static DEFINE_MUTEX(battery_mutex); static int bq27x00_read_i2c(struct bq27x00_device_info *di, u8 reg, int *rt_value, bool single) @@ -434,10 +437,6 @@ static int bq27x00_battery_remove(struct i2c_client *client) return 0; } -/* - * Module stuff - */ - static const struct i2c_device_id bq27x00_id[] = { { "bq27200", BQ27000 }, /* bq27200 is same as bq27000, but with i2c */ { "bq27500", BQ27500 }, @@ -453,13 +452,167 @@ static struct i2c_driver bq27x00_battery_driver = { .id_table = bq27x00_id, }; +static inline int bq27x00_battery_i2c_init(void) +{ + int ret = i2c_add_driver(&bq27x00_battery_driver); + if (ret) + printk(KERN_ERR "Unable to register BQ27x00 i2c driver\n"); + + return ret; +} + +static inline void bq27x00_battery_i2c_exit(void) +{ + i2c_del_driver(&bq27x00_battery_driver); +} + +#else + +static inline int bq27x00_battery_i2c_init(void) { return 0; } +static inline void bq27x00_battery_i2c_exit(void) {}; + +#endif + +/* platform specific code */ +#ifdef CONFIG_BATTERY_BQ27X00_PLATFORM + +static int bq27000_read_platform(struct bq27x00_device_info *di, u8 reg, + int *rt_value, bool single) +{ + struct device *dev = di->dev; + struct bq27000_platform_data *pdata = dev->platform_data; + unsigned int timeout = 3; + int upper, lower; + int temp; + + if (!single) { + /* Make sure the value has not changed in between reading the + * lower and the upper part */ + upper = pdata->read(dev, reg + 1); + do { + temp = upper; + if (upper < 0) + return upper; + + lower = pdata->read(dev, reg); + if (lower < 0) + return lower; + + upper = pdata->read(dev, reg + 1); + } while (temp != upper && --timeout); + + if (timeout == 0) + return -EIO; + + *rt_value = (upper << 8) | lower; + } else { + lower = pdata->read(dev, reg); + if (lower < 0) + return lower; + *rt_value = lower; + } + return 0; +} + +static int __devinit bq27000_battery_probe(struct platform_device *pdev) +{ + struct bq27x00_device_info *di; + struct bq27000_platform_data *pdata = pdev->dev.platform_data; + int ret; + + if (!pdata) { + dev_err(&pdev->dev, "no platform_data supplied\n"); + return -EINVAL; + } + + if (!pdata->read) { + dev_err(&pdev->dev, "no hdq read callback supplied\n"); + return -EINVAL; + } + + di = kzalloc(sizeof(*di), GFP_KERNEL); + if (!di) { + dev_err(&pdev->dev, "failed to allocate device info data\n"); + return -ENOMEM; + } + + platform_set_drvdata(pdev, di); + + di->dev = &pdev->dev; + di->chip = BQ27000; + + di->bat.name = pdata->name ?: dev_name(&pdev->dev); + di->bus.read = &bq27000_read_platform; + + ret = bq27x00_powersupply_init(di); + if (ret) + goto err_free; + + return 0; + +err_free: + platform_set_drvdata(pdev, NULL); + kfree(di); + + return ret; +} + +static int __devexit bq27000_battery_remove(struct platform_device *pdev) +{ + struct bq27x00_device_info *di = platform_get_drvdata(pdev); + + power_supply_unregister(&di->bat); + platform_set_drvdata(pdev, NULL); + kfree(di); + + return 0; +} + +static struct platform_driver bq27000_battery_driver = { + .probe = bq27000_battery_probe, + .remove = __devexit_p(bq27000_battery_remove), + .driver = { + .name = "bq27000-battery", + .owner = THIS_MODULE, + }, +}; + +static inline int bq27x00_battery_platform_init(void) +{ + int ret = platform_driver_register(&bq27000_battery_driver); + if (ret) + printk(KERN_ERR "Unable to register BQ27000 platform driver\n"); + + return ret; +} + +static inline void bq27x00_battery_platform_exit(void) +{ + platform_driver_unregister(&bq27000_battery_driver); +} + +#else + +static inline int bq27x00_battery_platform_init(void) { return 0; } +static inline void bq27x00_battery_platform_exit(void) {}; + +#endif + +/* + * Module stuff + */ + static int __init bq27x00_battery_init(void) { int ret; - ret = i2c_add_driver(&bq27x00_battery_driver); + ret = bq27x00_battery_i2c_init(); + if (ret) + return ret; + + ret = bq27x00_battery_platform_init(); if (ret) - printk(KERN_ERR "Unable to register BQ27x00 driver\n"); + bq27x00_battery_i2c_exit(); return ret; } @@ -467,7 +620,8 @@ module_init(bq27x00_battery_init); static void __exit bq27x00_battery_exit(void) { - i2c_del_driver(&bq27x00_battery_driver); + bq27x00_battery_platform_exit(); + bq27x00_battery_i2c_exit(); } module_exit(bq27x00_battery_exit); diff --git a/include/linux/power/bq27x00_battery.h b/include/linux/power/bq27x00_battery.h new file mode 100644 index 0000000000000..a857f719bf40d --- /dev/null +++ b/include/linux/power/bq27x00_battery.h @@ -0,0 +1,19 @@ +#ifndef __LINUX_BQ27X00_BATTERY_H__ +#define __LINUX_BQ27X00_BATTERY_H__ + +/** + * struct bq27000_plaform_data - Platform data for bq27000 devices + * @name: Name of the battery. If NULL the driver will fallback to "bq27000". + * @read: HDQ read callback. + * This function should provide access to the HDQ bus the battery is + * connected to. + * The first parameter is a pointer to the battery device, the second the + * register to be read. The return value should either be the content of + * the passed register or an error value. + */ +struct bq27000_platform_data { + const char *name; + int (*read)(struct device *dev, unsigned int); +}; + +#endif -- GitLab From 297a533b3e621be520d44d8baf3bb72ce15c4110 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Fri, 7 Jan 2011 20:12:47 +0100 Subject: [PATCH 0170/2822] bq27x00: Cache battery registers This patch adds a register cache to the bq27x00 battery driver. Usually multiple, if not all, power_supply properties are queried at once, for example when an uevent is generated. Since some registers are used by multiple properties caching the registers should reduce the number of reads. The cache is valid for 5 seconds this roughly matches the internal update interval of the current register for the bq27000/bq27200. Fast changing properties(*_NOW) which can be obtained by reading a single register are not cached. It will also be used in the follow up patch to check if the battery status has been changed since the last update to emit power_supply_changed events. Signed-off-by: Lars-Peter Clausen Tested-by: Grazvydas Ignotas --- drivers/power/bq27x00_battery.c | 271 ++++++++++++++++++-------------- 1 file changed, 150 insertions(+), 121 deletions(-) diff --git a/drivers/power/bq27x00_battery.c b/drivers/power/bq27x00_battery.c index 44bc76be0780b..dbe3fcb3b0ba8 100644 --- a/drivers/power/bq27x00_battery.c +++ b/drivers/power/bq27x00_battery.c @@ -51,17 +51,30 @@ struct bq27x00_device_info; struct bq27x00_access_methods { - int (*read)(struct bq27x00_device_info *, u8 reg, int *rt_value, - bool single); + int (*read)(struct bq27x00_device_info *di, u8 reg, bool single); }; enum bq27x00_chip { BQ27000, BQ27500 }; +struct bq27x00_reg_cache { + int temperature; + int time_to_empty; + int time_to_empty_avg; + int time_to_full; + int capacity; + int flags; + + int current_now; +}; + struct bq27x00_device_info { struct device *dev; int id; enum bq27x00_chip chip; + struct bq27x00_reg_cache cache; + unsigned long last_update; + struct power_supply bat; struct bq27x00_access_methods bus; @@ -85,48 +98,93 @@ static enum power_supply_property bq27x00_battery_props[] = { */ static inline int bq27x00_read(struct bq27x00_device_info *di, u8 reg, - int *rt_value, bool single) + bool single) { - return di->bus.read(di, reg, rt_value, single); + return di->bus.read(di, reg, single); } /* - * Return the battery temperature in tenths of degree Celsius + * Return the battery Relative State-of-Charge * Or < 0 if something fails. */ -static int bq27x00_battery_temperature(struct bq27x00_device_info *di) +static int bq27x00_battery_read_rsoc(struct bq27x00_device_info *di) { - int ret; - int temp = 0; - - ret = bq27x00_read(di, BQ27x00_REG_TEMP, &temp, false); - if (ret) { - dev_err(di->dev, "error reading temperature\n"); - return ret; - } + int rsoc; if (di->chip == BQ27500) - return temp - 2731; + rsoc = bq27x00_read(di, BQ27500_REG_SOC, false); else - return ((temp * 5) - 5463) / 2; + rsoc = bq27x00_read(di, BQ27000_REG_RSOC, true); + + if (rsoc < 0) + dev_err(di->dev, "error reading relative State-of-Charge\n"); + + return rsoc; } /* - * Return the battery Voltage in milivolts - * Or < 0 if something fails. + * Read a time register. + * Return < 0 if something fails. */ -static int bq27x00_battery_voltage(struct bq27x00_device_info *di) +static int bq27x00_battery_read_time(struct bq27x00_device_info *di, u8 reg) { - int ret; - int volt = 0; + int tval; - ret = bq27x00_read(di, BQ27x00_REG_VOLT, &volt, false); - if (ret) { - dev_err(di->dev, "error reading voltage\n"); - return ret; + tval = bq27x00_read(di, reg, false); + if (tval < 0) { + dev_err(di->dev, "error reading register %02x: %d\n", reg, tval); + return tval; } - return volt * 1000; + if (tval == 65535) + return -ENODATA; + + return tval * 60; +} + +static void bq27x00_update(struct bq27x00_device_info *di) +{ + struct bq27x00_reg_cache cache = {0, }; + bool is_bq27500 = di->chip == BQ27500; + + cache.flags = bq27x00_read(di, BQ27x00_REG_FLAGS, is_bq27500); + if (cache.flags >= 0) { + cache.capacity = bq27x00_battery_read_rsoc(di); + cache.temperature = bq27x00_read(di, BQ27x00_REG_TEMP, false); + cache.time_to_empty = bq27x00_battery_read_time(di, BQ27x00_REG_TTE); + cache.time_to_empty_avg = bq27x00_battery_read_time(di, BQ27x00_REG_TTECP); + cache.time_to_full = bq27x00_battery_read_time(di, BQ27x00_REG_TTF); + + if (!is_bq27500) + cache.current_now = bq27x00_read(di, BQ27x00_REG_AI, false); + } + + /* Ignore current_now which is a snapshot of the current battery state + * and is likely to be different even between two consecutive reads */ + if (memcmp(&di->cache, &cache, sizeof(cache) - sizeof(int)) != 0) { + di->cache = cache; + power_supply_changed(&di->bat); + } + + di->last_update = jiffies; +} + +/* + * Return the battery temperature in tenths of degree Celsius + * Or < 0 if something fails. + */ +static int bq27x00_battery_temperature(struct bq27x00_device_info *di, + union power_supply_propval *val) +{ + if (di->cache.temperature < 0) + return di->cache.temperature; + + if (di->chip == BQ27500) + val->intval = di->cache.temperature - 2731; + else + val->intval = ((di->cache.temperature * 5) - 5463) / 2; + + return 0; } /* @@ -134,109 +192,84 @@ static int bq27x00_battery_voltage(struct bq27x00_device_info *di) * Note that current can be negative signed as well * Or 0 if something fails. */ -static int bq27x00_battery_current(struct bq27x00_device_info *di) +static int bq27x00_battery_current(struct bq27x00_device_info *di, + union power_supply_propval *val) { - int ret; - int curr = 0; - int flags = 0; + int curr; - ret = bq27x00_read(di, BQ27x00_REG_AI, &curr, false); - if (ret) { - dev_err(di->dev, "error reading current\n"); - return 0; - } + if (di->chip == BQ27500) + curr = bq27x00_read(di, BQ27x00_REG_AI, false); + else + curr = di->cache.current_now; + + if (curr < 0) + return curr; if (di->chip == BQ27500) { /* bq27500 returns signed value */ - curr = (int)((s16)curr) * 1000; + val->intval = (int)((s16)curr) * 1000; } else { - ret = bq27x00_read(di, BQ27x00_REG_FLAGS, &flags, false); - if (ret < 0) { - dev_err(di->dev, "error reading flags\n"); - return 0; - } - if (flags & BQ27000_FLAG_CHGS) { + if (di->cache.flags & BQ27000_FLAG_CHGS) { dev_dbg(di->dev, "negative current!\n"); curr = -curr; } - curr = curr * 3570 / BQ27000_RS; - } - - return curr; -} - -/* - * Return the battery Relative State-of-Charge - * Or < 0 if something fails. - */ -static int bq27x00_battery_rsoc(struct bq27x00_device_info *di) -{ - int ret; - int rsoc = 0; - if (di->chip == BQ27500) - ret = bq27x00_read(di, BQ27500_REG_SOC, &rsoc, false); - else - ret = bq27x00_read(di, BQ27000_REG_RSOC, &rsoc, true); - if (ret) { - dev_err(di->dev, "error reading relative State-of-Charge\n"); - return ret; + val->intval = curr * 3570 / BQ27000_RS; } - return rsoc; + return 0; } static int bq27x00_battery_status(struct bq27x00_device_info *di, - union power_supply_propval *val) + union power_supply_propval *val) { - int flags = 0; int status; - int ret; - - ret = bq27x00_read(di, BQ27x00_REG_FLAGS, &flags, false); - if (ret < 0) { - dev_err(di->dev, "error reading flags\n"); - return ret; - } if (di->chip == BQ27500) { - if (flags & BQ27500_FLAG_FC) + if (di->cache.flags & BQ27500_FLAG_FC) status = POWER_SUPPLY_STATUS_FULL; - else if (flags & BQ27500_FLAG_DSC) + else if (di->cache.flags & BQ27500_FLAG_DSC) status = POWER_SUPPLY_STATUS_DISCHARGING; else status = POWER_SUPPLY_STATUS_CHARGING; } else { - if (flags & BQ27000_FLAG_CHGS) + if (di->cache.flags & BQ27000_FLAG_CHGS) status = POWER_SUPPLY_STATUS_CHARGING; else status = POWER_SUPPLY_STATUS_DISCHARGING; } val->intval = status; + return 0; } /* - * Read a time register. - * Return < 0 if something fails. + * Return the battery Voltage in milivolts + * Or < 0 if something fails. */ -static int bq27x00_battery_time(struct bq27x00_device_info *di, int reg, - union power_supply_propval *val) +static int bq27x00_battery_voltage(struct bq27x00_device_info *di, + union power_supply_propval *val) { - int tval = 0; - int ret; + int volt; - ret = bq27x00_read(di, reg, &tval, false); - if (ret) { - dev_err(di->dev, "error reading register %02x\n", reg); - return ret; - } + volt = bq27x00_read(di, BQ27x00_REG_VOLT, false); + if (volt < 0) + return volt; - if (tval == 65535) - return -ENODATA; + val->intval = volt * 1000; + + return 0; +} + +static int bq27x00_simple_value(int value, + union power_supply_propval *val) +{ + if (value < 0) + return value; + + val->intval = value; - val->intval = tval * 60; return 0; } @@ -249,9 +282,11 @@ static int bq27x00_battery_get_property(struct power_supply *psy, { int ret = 0; struct bq27x00_device_info *di = to_bq27x00_device_info(psy); - int voltage = bq27x00_battery_voltage(di); - if (psp != POWER_SUPPLY_PROP_PRESENT && voltage <= 0) + if (time_is_before_jiffies(di->last_update + 5 * HZ)) + bq27x00_update(di); + + if (psp != POWER_SUPPLY_PROP_PRESENT && di->cache.flags < 0) return -ENODEV; switch (psp) { @@ -259,29 +294,28 @@ static int bq27x00_battery_get_property(struct power_supply *psy, ret = bq27x00_battery_status(di, val); break; case POWER_SUPPLY_PROP_VOLTAGE_NOW: - val->intval = voltage; + ret = bq27x00_battery_voltage(di, val); break; case POWER_SUPPLY_PROP_PRESENT: - if (psp == POWER_SUPPLY_PROP_PRESENT) - val->intval = voltage <= 0 ? 0 : 1; + val->intval = di->cache.flags < 0 ? 0 : 1; break; case POWER_SUPPLY_PROP_CURRENT_NOW: - val->intval = bq27x00_battery_current(di); + ret = bq27x00_battery_current(di, val); break; case POWER_SUPPLY_PROP_CAPACITY: - val->intval = bq27x00_battery_rsoc(di); + ret = bq27x00_simple_value(di->cache.capacity, val); break; case POWER_SUPPLY_PROP_TEMP: - val->intval = bq27x00_battery_temperature(di); + ret = bq27x00_battery_temperature(di, val); break; case POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW: - ret = bq27x00_battery_time(di, BQ27x00_REG_TTE, val); + ret = bq27x00_simple_value(di->cache.time_to_empty, val); break; case POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG: - ret = bq27x00_battery_time(di, BQ27x00_REG_TTECP, val); + ret = bq27x00_simple_value(di->cache.time_to_empty_avg, val); break; case POWER_SUPPLY_PROP_TIME_TO_FULL_NOW: - ret = bq27x00_battery_time(di, BQ27x00_REG_TTF, val); + ret = bq27x00_simple_value(di->cache.time_to_full, val); break; case POWER_SUPPLY_PROP_TECHNOLOGY: val->intval = POWER_SUPPLY_TECHNOLOGY_LION; @@ -311,6 +345,8 @@ static int bq27x00_powersupply_init(struct bq27x00_device_info *di) dev_info(di->dev, "support ver. %s enabled\n", DRIVER_VERSION); + bq27x00_update(di); + return 0; } @@ -324,13 +360,12 @@ static int bq27x00_powersupply_init(struct bq27x00_device_info *di) static DEFINE_IDR(battery_id); static DEFINE_MUTEX(battery_mutex); -static int bq27x00_read_i2c(struct bq27x00_device_info *di, u8 reg, - int *rt_value, bool single) +static int bq27x00_read_i2c(struct bq27x00_device_info *di, u8 reg, bool single) { struct i2c_client *client = to_i2c_client(di->dev); struct i2c_msg msg[1]; unsigned char data[2]; - int err; + int ret; if (!client->adapter) return -ENODEV; @@ -341,26 +376,24 @@ static int bq27x00_read_i2c(struct bq27x00_device_info *di, u8 reg, msg->buf = data; data[0] = reg; - err = i2c_transfer(client->adapter, msg, 1); + ret = i2c_transfer(client->adapter, msg, 1); - if (err >= 0) { + if (ret >= 0) { if (!single) msg->len = 2; else msg->len = 1; msg->flags = I2C_M_RD; - err = i2c_transfer(client->adapter, msg, 1); - if (err >= 0) { + ret = i2c_transfer(client->adapter, msg, 1); + if (ret >= 0) { if (!single) - *rt_value = get_unaligned_le16(data); + ret = get_unaligned_le16(data); else - *rt_value = data[0]; - - return 0; + ret = data[0]; } } - return err; + return ret; } static int bq27x00_battery_probe(struct i2c_client *client, @@ -477,7 +510,7 @@ static inline void bq27x00_battery_i2c_exit(void) {}; #ifdef CONFIG_BATTERY_BQ27X00_PLATFORM static int bq27000_read_platform(struct bq27x00_device_info *di, u8 reg, - int *rt_value, bool single) + bool single) { struct device *dev = di->dev; struct bq27000_platform_data *pdata = dev->platform_data; @@ -504,14 +537,10 @@ static int bq27000_read_platform(struct bq27x00_device_info *di, u8 reg, if (timeout == 0) return -EIO; - *rt_value = (upper << 8) | lower; - } else { - lower = pdata->read(dev, reg); - if (lower < 0) - return lower; - *rt_value = lower; + return (upper << 8) | lower; } - return 0; + + return pdata->read(dev, reg); } static int __devinit bq27000_battery_probe(struct platform_device *pdev) -- GitLab From 740b755a3b3433f5ee5f9ef54de5d1b4c08223cc Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Fri, 7 Jan 2011 20:14:53 +0100 Subject: [PATCH 0171/2822] bq27x00: Poll battery state This patch adds support for polling the battery state and generating a power_supply_changed() event if it has changed. Signed-off-by: Lars-Peter Clausen Tested-by: Grazvydas Ignotas --- drivers/power/bq27x00_battery.c | 58 ++++++++++++++++++++++++++++++--- 1 file changed, 53 insertions(+), 5 deletions(-) diff --git a/drivers/power/bq27x00_battery.c b/drivers/power/bq27x00_battery.c index dbe3fcb3b0ba8..25350fcbadb38 100644 --- a/drivers/power/bq27x00_battery.c +++ b/drivers/power/bq27x00_battery.c @@ -74,10 +74,13 @@ struct bq27x00_device_info { struct bq27x00_reg_cache cache; unsigned long last_update; + struct delayed_work work; struct power_supply bat; struct bq27x00_access_methods bus; + + struct mutex lock; }; static enum power_supply_property bq27x00_battery_props[] = { @@ -93,6 +96,11 @@ static enum power_supply_property bq27x00_battery_props[] = { POWER_SUPPLY_PROP_TECHNOLOGY, }; +static unsigned int poll_interval = 360; +module_param(poll_interval, uint, 0644); +MODULE_PARM_DESC(poll_interval, "battery poll interval in seconds - " \ + "0 disables polling"); + /* * Common code for BQ27x00 devices */ @@ -169,6 +177,21 @@ static void bq27x00_update(struct bq27x00_device_info *di) di->last_update = jiffies; } +static void bq27x00_battery_poll(struct work_struct *work) +{ + struct bq27x00_device_info *di = + container_of(work, struct bq27x00_device_info, work.work); + + bq27x00_update(di); + + if (poll_interval > 0) { + /* The timer does not have to be accurate. */ + set_timer_slack(&di->work.timer, poll_interval * HZ / 4); + schedule_delayed_work(&di->work, poll_interval * HZ); + } +} + + /* * Return the battery temperature in tenths of degree Celsius * Or < 0 if something fails. @@ -283,8 +306,12 @@ static int bq27x00_battery_get_property(struct power_supply *psy, int ret = 0; struct bq27x00_device_info *di = to_bq27x00_device_info(psy); - if (time_is_before_jiffies(di->last_update + 5 * HZ)) - bq27x00_update(di); + mutex_lock(&di->lock); + if (time_is_before_jiffies(di->last_update + 5 * HZ)) { + cancel_delayed_work_sync(&di->work); + bq27x00_battery_poll(&di->work.work); + } + mutex_unlock(&di->lock); if (psp != POWER_SUPPLY_PROP_PRESENT && di->cache.flags < 0) return -ENODEV; @@ -327,6 +354,14 @@ static int bq27x00_battery_get_property(struct power_supply *psy, return ret; } +static void bq27x00_external_power_changed(struct power_supply *psy) +{ + struct bq27x00_device_info *di = to_bq27x00_device_info(psy); + + cancel_delayed_work_sync(&di->work); + schedule_delayed_work(&di->work, 0); +} + static int bq27x00_powersupply_init(struct bq27x00_device_info *di) { int ret; @@ -335,7 +370,10 @@ static int bq27x00_powersupply_init(struct bq27x00_device_info *di) di->bat.properties = bq27x00_battery_props; di->bat.num_properties = ARRAY_SIZE(bq27x00_battery_props); di->bat.get_property = bq27x00_battery_get_property; - di->bat.external_power_changed = NULL; + di->bat.external_power_changed = bq27x00_external_power_changed; + + INIT_DELAYED_WORK(&di->work, bq27x00_battery_poll); + mutex_init(&di->lock); ret = power_supply_register(di->dev, &di->bat); if (ret) { @@ -350,6 +388,15 @@ static int bq27x00_powersupply_init(struct bq27x00_device_info *di) return 0; } +static void bq27x00_powersupply_unregister(struct bq27x00_device_info *di) +{ + cancel_delayed_work_sync(&di->work); + + power_supply_unregister(&di->bat); + + mutex_destroy(&di->lock); +} + /* i2c specific code */ #ifdef CONFIG_BATTERY_BQ27X00_I2C @@ -457,7 +504,7 @@ static int bq27x00_battery_remove(struct i2c_client *client) { struct bq27x00_device_info *di = i2c_get_clientdata(client); - power_supply_unregister(&di->bat); + bq27x00_powersupply_unregister(di); kfree(di->bat.name); @@ -590,7 +637,8 @@ static int __devexit bq27000_battery_remove(struct platform_device *pdev) { struct bq27x00_device_info *di = platform_get_drvdata(pdev); - power_supply_unregister(&di->bat); + bq27x00_powersupply_unregister(di); + platform_set_drvdata(pdev, NULL); kfree(di); -- GitLab From 631c17ee5daf0ca73688cb5e5216fc0e3e340483 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pali=20Roh=C3=A1r?= Date: Tue, 1 Feb 2011 00:08:02 +0100 Subject: [PATCH 0172/2822] bq27x00: Add new properties MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch add support for reporting properties POWER_SUPPLY_PROP_CHARGE_NOW, POWER_SUPPLY_PROP_CHARGE_FULL, POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN, POWER_SUPPLY_PROP_CHARGE_COUNTER, POWER_SUPPLY_PROP_ENERGY_NOW in module bq27x00_battery. Signed-off-by: Pali Rohár Signed-off-by: Lars-Peter Clausen Tested-by: Grazvydas Ignotas --- drivers/power/bq27x00_battery.c | 152 +++++++++++++++++++++++++++++++- 1 file changed, 151 insertions(+), 1 deletion(-) diff --git a/drivers/power/bq27x00_battery.c b/drivers/power/bq27x00_battery.c index 25350fcbadb38..a1bd1ff753b34 100644 --- a/drivers/power/bq27x00_battery.c +++ b/drivers/power/bq27x00_battery.c @@ -16,6 +16,13 @@ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. * */ + +/* + * Datasheets: + * http://focus.ti.com/docs/prod/folders/print/bq27000.html + * http://focus.ti.com/docs/prod/folders/print/bq27500.html + */ + #include #include #include @@ -30,7 +37,7 @@ #include -#define DRIVER_VERSION "1.1.0" +#define DRIVER_VERSION "1.2.0" #define BQ27x00_REG_TEMP 0x06 #define BQ27x00_REG_VOLT 0x08 @@ -39,11 +46,17 @@ #define BQ27x00_REG_TTE 0x16 #define BQ27x00_REG_TTF 0x18 #define BQ27x00_REG_TTECP 0x26 +#define BQ27x00_REG_NAC 0x0C /* Nominal available capaciy */ +#define BQ27x00_REG_LMD 0x12 /* Last measured discharge */ +#define BQ27x00_REG_CYCT 0x2A /* Cycle count total */ +#define BQ27x00_REG_AE 0x22 /* Available enery */ #define BQ27000_REG_RSOC 0x0B /* Relative State-of-Charge */ +#define BQ27000_REG_ILMD 0x76 /* Initial last measured discharge */ #define BQ27000_FLAG_CHGS BIT(7) #define BQ27500_REG_SOC 0x2c +#define BQ27500_REG_DCAP 0x3C /* Design capacity */ #define BQ27500_FLAG_DSC BIT(0) #define BQ27500_FLAG_FC BIT(9) @@ -61,6 +74,8 @@ struct bq27x00_reg_cache { int time_to_empty; int time_to_empty_avg; int time_to_full; + int charge_full; + int charge_counter; int capacity; int flags; @@ -73,6 +88,8 @@ struct bq27x00_device_info { enum bq27x00_chip chip; struct bq27x00_reg_cache cache; + int charge_design_full; + unsigned long last_update; struct delayed_work work; @@ -94,6 +111,11 @@ static enum power_supply_property bq27x00_battery_props[] = { POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG, POWER_SUPPLY_PROP_TIME_TO_FULL_NOW, POWER_SUPPLY_PROP_TECHNOLOGY, + POWER_SUPPLY_PROP_CHARGE_FULL, + POWER_SUPPLY_PROP_CHARGE_NOW, + POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN, + POWER_SUPPLY_PROP_CHARGE_COUNTER, + POWER_SUPPLY_PROP_ENERGY_NOW, }; static unsigned int poll_interval = 360; @@ -130,6 +152,87 @@ static int bq27x00_battery_read_rsoc(struct bq27x00_device_info *di) return rsoc; } +/* + * Return a battery charge value in µAh + * Or < 0 if something fails. + */ +static int bq27x00_battery_read_charge(struct bq27x00_device_info *di, u8 reg) +{ + int charge; + + charge = bq27x00_read(di, reg, false); + if (charge < 0) { + dev_err(di->dev, "error reading nominal available capacity\n"); + return charge; + } + + if (di->chip == BQ27500) + charge *= 1000; + else + charge = charge * 3570 / BQ27000_RS; + + return charge; +} + +/* + * Return the battery Nominal available capaciy in µAh + * Or < 0 if something fails. + */ +static inline int bq27x00_battery_read_nac(struct bq27x00_device_info *di) +{ + return bq27x00_battery_read_charge(di, BQ27x00_REG_NAC); +} + +/* + * Return the battery Last measured discharge in µAh + * Or < 0 if something fails. + */ +static inline int bq27x00_battery_read_lmd(struct bq27x00_device_info *di) +{ + return bq27x00_battery_read_charge(di, BQ27x00_REG_LMD); +} + +/* + * Return the battery Initial last measured discharge in µAh + * Or < 0 if something fails. + */ +static int bq27x00_battery_read_ilmd(struct bq27x00_device_info *di) +{ + int ilmd; + + if (di->chip == BQ27500) + ilmd = bq27x00_read(di, BQ27500_REG_DCAP, false); + else + ilmd = bq27x00_read(di, BQ27000_REG_ILMD, true); + + if (ilmd < 0) { + dev_err(di->dev, "error reading initial last measured discharge\n"); + return ilmd; + } + + if (di->chip == BQ27500) + ilmd *= 1000; + else + ilmd = ilmd * 256 * 3570 / BQ27000_RS; + + return ilmd; +} + +/* + * Return the battery Cycle count total + * Or < 0 if something fails. + */ +static int bq27x00_battery_read_cyct(struct bq27x00_device_info *di) +{ + int cyct; + + cyct = bq27x00_read(di, BQ27x00_REG_CYCT, false); + if (cyct < 0) + dev_err(di->dev, "error reading cycle count total\n"); + + return cyct; +} + /* * Read a time register. * Return < 0 if something fails. @@ -162,9 +265,15 @@ static void bq27x00_update(struct bq27x00_device_info *di) cache.time_to_empty = bq27x00_battery_read_time(di, BQ27x00_REG_TTE); cache.time_to_empty_avg = bq27x00_battery_read_time(di, BQ27x00_REG_TTECP); cache.time_to_full = bq27x00_battery_read_time(di, BQ27x00_REG_TTF); + cache.charge_full = bq27x00_battery_read_lmd(di); + cache.charge_counter = bq27x00_battery_read_cyct(di); if (!is_bq27500) cache.current_now = bq27x00_read(di, BQ27x00_REG_AI, false); + + /* We only have to read charge design full once */ + if (di->charge_design_full <= 0) + di->charge_design_full = bq27x00_battery_read_ilmd(di); } /* Ignore current_now which is a snapshot of the current battery state @@ -285,6 +394,32 @@ static int bq27x00_battery_voltage(struct bq27x00_device_info *di, return 0; } +/* + * Return the battery Available energy in µWh + * Or < 0 if something fails. + */ +static int bq27x00_battery_energy(struct bq27x00_device_info *di, + union power_supply_propval *val) +{ + int ae; + + ae = bq27x00_read(di, BQ27x00_REG_AE, false); + if (ae < 0) { + dev_err(di->dev, "error reading available energy\n"); + return ae; + } + + if (di->chip == BQ27500) + ae *= 1000; + else + ae = ae * 29200 / BQ27000_RS; + + val->intval = ae; + + return 0; +} + + static int bq27x00_simple_value(int value, union power_supply_propval *val) { @@ -347,6 +482,21 @@ static int bq27x00_battery_get_property(struct power_supply *psy, case POWER_SUPPLY_PROP_TECHNOLOGY: val->intval = POWER_SUPPLY_TECHNOLOGY_LION; break; + case POWER_SUPPLY_PROP_CHARGE_NOW: + ret = bq27x00_simple_value(bq27x00_battery_read_nac(di), val); + break; + case POWER_SUPPLY_PROP_CHARGE_FULL: + ret = bq27x00_simple_value(di->cache.charge_full, val); + break; + case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN: + ret = bq27x00_simple_value(di->charge_design_full, val); + break; + case POWER_SUPPLY_PROP_CHARGE_COUNTER: + ret = bq27x00_simple_value(di->cache.charge_counter, val); + break; + case POWER_SUPPLY_PROP_ENERGY_NOW: + ret = bq27x00_battery_energy(di, val); + break; default: return -EINVAL; } -- GitLab From fd9b958c5525024204e7e2c48fe5eae560d171bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pali=20Roh=C3=A1r?= Date: Tue, 1 Feb 2011 00:10:41 +0100 Subject: [PATCH 0173/2822] bq27x00: Add MODULE_DEVICE_TABLE MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch adds MODULE_DEVICE_TABLE for module bq27x00_battery. Signed-off-by: Pali Rohár Tested-by: Pali Rohár Signed-off-by: Lars-Peter Clausen Acked-by: Rodolfo Giometti Tested-by: Grazvydas Ignotas --- drivers/power/bq27x00_battery.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/power/bq27x00_battery.c b/drivers/power/bq27x00_battery.c index a1bd1ff753b34..0e99d02dea335 100644 --- a/drivers/power/bq27x00_battery.c +++ b/drivers/power/bq27x00_battery.c @@ -672,6 +672,7 @@ static const struct i2c_device_id bq27x00_id[] = { { "bq27500", BQ27500 }, {}, }; +MODULE_DEVICE_TABLE(i2c, bq27x00_id); static struct i2c_driver bq27x00_battery_driver = { .driver = { -- GitLab From c1b9ab67e7c7021be9d0db6345d6ccc5d70248f1 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sat, 18 Sep 2010 17:31:16 +0200 Subject: [PATCH 0174/2822] bq27x00: Give more specific reports on battery status The current code only reports whether the battery is charging or discharging. But the battery also reports whether it is fully charged, furthermore by look at if the battery is supplied we can tell whether it is discharging or not charging. Signed-off-by: Lars-Peter Clausen Acked-by: Rodolfo Giometti Tested-by: Grazvydas Ignotas --- drivers/power/bq27x00_battery.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/power/bq27x00_battery.c b/drivers/power/bq27x00_battery.c index 0e99d02dea335..003be5f1c785d 100644 --- a/drivers/power/bq27x00_battery.c +++ b/drivers/power/bq27x00_battery.c @@ -54,6 +54,7 @@ #define BQ27000_REG_RSOC 0x0B /* Relative State-of-Charge */ #define BQ27000_REG_ILMD 0x76 /* Initial last measured discharge */ #define BQ27000_FLAG_CHGS BIT(7) +#define BQ27000_FLAG_FC BIT(5) #define BQ27500_REG_SOC 0x2c #define BQ27500_REG_DCAP 0x3C /* Design capacity */ @@ -365,8 +366,12 @@ static int bq27x00_battery_status(struct bq27x00_device_info *di, else status = POWER_SUPPLY_STATUS_CHARGING; } else { - if (di->cache.flags & BQ27000_FLAG_CHGS) + if (di->cache.flags & BQ27000_FLAG_FC) + status = POWER_SUPPLY_STATUS_FULL; + else if (di->cache.flags & BQ27000_FLAG_CHGS) status = POWER_SUPPLY_STATUS_CHARGING; + else if (power_supply_am_i_supplied(&di->bat)) + status = POWER_SUPPLY_STATUS_NOT_CHARGING; else status = POWER_SUPPLY_STATUS_DISCHARGING; } -- GitLab From bf7d4140450f6dbc019a8831223e08d778f90dd7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pali=20Roh=C3=A1r?= Date: Tue, 1 Feb 2011 00:23:13 +0100 Subject: [PATCH 0175/2822] bq27x00: Minor cleanups MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Consistently use uppercase for hexadecimal values. * Clarify/fix the unit of functions return value in its comment. Signed-off-by: Pali Rohár Signed-off-by: Lars-Peter Clausen Tested-by: Grazvydas Ignotas --- drivers/power/bq27x00_battery.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/power/bq27x00_battery.c b/drivers/power/bq27x00_battery.c index 003be5f1c785d..b44555f1b6336 100644 --- a/drivers/power/bq27x00_battery.c +++ b/drivers/power/bq27x00_battery.c @@ -56,7 +56,7 @@ #define BQ27000_FLAG_CHGS BIT(7) #define BQ27000_FLAG_FC BIT(5) -#define BQ27500_REG_SOC 0x2c +#define BQ27500_REG_SOC 0x2C #define BQ27500_REG_DCAP 0x3C /* Design capacity */ #define BQ27500_FLAG_DSC BIT(0) #define BQ27500_FLAG_FC BIT(9) @@ -321,7 +321,7 @@ static int bq27x00_battery_temperature(struct bq27x00_device_info *di, } /* - * Return the battery average current + * Return the battery average current in µA * Note that current can be negative signed as well * Or 0 if something fails. */ -- GitLab From 2ec523a8238a117b082ca6b0cef3b9ae812364f9 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Wed, 2 Feb 2011 19:35:07 +0100 Subject: [PATCH 0176/2822] bq27x00: Cleanup bq27x00_i2c_read Some minor stylistic cleanups. Signed-off-by: Lars-Peter Clausen Tested-by: Grazvydas Ignotas --- drivers/power/bq27x00_battery.c | 45 ++++++++++++++++++--------------- 1 file changed, 24 insertions(+), 21 deletions(-) diff --git a/drivers/power/bq27x00_battery.c b/drivers/power/bq27x00_battery.c index b44555f1b6336..740a0ac29dd15 100644 --- a/drivers/power/bq27x00_battery.c +++ b/drivers/power/bq27x00_battery.c @@ -565,36 +565,39 @@ static DEFINE_MUTEX(battery_mutex); static int bq27x00_read_i2c(struct bq27x00_device_info *di, u8 reg, bool single) { struct i2c_client *client = to_i2c_client(di->dev); - struct i2c_msg msg[1]; + struct i2c_msg msg; unsigned char data[2]; int ret; if (!client->adapter) return -ENODEV; - msg->addr = client->addr; - msg->flags = 0; - msg->len = 1; - msg->buf = data; + msg.addr = client->addr; + msg.flags = 0; + msg.len = 1; + msg.buf = data; data[0] = reg; - ret = i2c_transfer(client->adapter, msg, 1); + ret = i2c_transfer(client->adapter, &msg, 1); + + if (ret < 0) + return ret; + + if (single) + msg.len = 1; + else + msg.len = 2; + + msg.flags = I2C_M_RD; + ret = i2c_transfer(client->adapter, &msg, 1); + if (ret < 0) + return ret; + + if (!single) + ret = get_unaligned_le16(data); + else + ret = data[0]; - if (ret >= 0) { - if (!single) - msg->len = 2; - else - msg->len = 1; - - msg->flags = I2C_M_RD; - ret = i2c_transfer(client->adapter, msg, 1); - if (ret >= 0) { - if (!single) - ret = get_unaligned_le16(data); - else - ret = data[0]; - } - } return ret; } -- GitLab From 9e912f452931b3da9d13d716a381ba0d5fb74ced Mon Sep 17 00:00:00 2001 From: Grazvydas Ignotas Date: Tue, 15 Feb 2011 23:27:35 +0200 Subject: [PATCH 0177/2822] bq27x00: Use single i2c_transfer call for property read Doing this by using 2 calls sometimes results in unexpected values being returned on OMAP3 i2c controller. Signed-off-by: Grazvydas Ignotas Signed-off-by: Lars-Peter Clausen --- drivers/power/bq27x00_battery.c | 27 +++++++++++---------------- 1 file changed, 11 insertions(+), 16 deletions(-) diff --git a/drivers/power/bq27x00_battery.c b/drivers/power/bq27x00_battery.c index 740a0ac29dd15..59e68dbd028b3 100644 --- a/drivers/power/bq27x00_battery.c +++ b/drivers/power/bq27x00_battery.c @@ -565,31 +565,26 @@ static DEFINE_MUTEX(battery_mutex); static int bq27x00_read_i2c(struct bq27x00_device_info *di, u8 reg, bool single) { struct i2c_client *client = to_i2c_client(di->dev); - struct i2c_msg msg; + struct i2c_msg msg[2]; unsigned char data[2]; int ret; if (!client->adapter) return -ENODEV; - msg.addr = client->addr; - msg.flags = 0; - msg.len = 1; - msg.buf = data; - - data[0] = reg; - ret = i2c_transfer(client->adapter, &msg, 1); - - if (ret < 0) - return ret; - + msg[0].addr = client->addr; + msg[0].flags = 0; + msg[0].buf = ® + msg[0].len = sizeof(reg); + msg[1].addr = client->addr; + msg[1].flags = I2C_M_RD; + msg[1].buf = data; if (single) - msg.len = 1; + msg[1].len = 1; else - msg.len = 2; + msg[1].len = 2; - msg.flags = I2C_M_RD; - ret = i2c_transfer(client->adapter, &msg, 1); + ret = i2c_transfer(client->adapter, msg, ARRAY_SIZE(msg)); if (ret < 0) return ret; -- GitLab From 1050c71e2925ab0cb025e4c89e08b15529a1ee36 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Sun, 13 Feb 2011 13:25:31 +0000 Subject: [PATCH 0178/2822] xfs: stop using xfs_trans_iget in the RT allocator During mount we establish references to the RT inodes, which we keep for the lifetime of the filesystem. Instead of using xfs_trans_iget to grab additional references when adding RT inodes to transactions use the combination of xfs_ilock and xfs_trans_ijoin_ref, which archives the same end result with less overhead. Signed-off-by: Christoph Hellwig Reviewed-by: Dave Chinner Signed-off-by: Alex Elder --- fs/xfs/xfs_bmap.c | 8 ++----- fs/xfs/xfs_rtalloc.c | 54 +++++++++++++++++--------------------------- 2 files changed, 23 insertions(+), 39 deletions(-) diff --git a/fs/xfs/xfs_bmap.c b/fs/xfs/xfs_bmap.c index d8d0906652830..e7b441db0530d 100644 --- a/fs/xfs/xfs_bmap.c +++ b/fs/xfs/xfs_bmap.c @@ -2333,7 +2333,6 @@ xfs_bmap_rtalloc( xfs_extlen_t prod = 0; /* product factor for allocators */ xfs_extlen_t ralen = 0; /* realtime allocation length */ xfs_extlen_t align; /* minimum allocation alignment */ - xfs_inode_t *ip; /* bitmap incore inode */ xfs_rtblock_t rtb; mp = ap->ip->i_mount; @@ -2370,11 +2369,8 @@ xfs_bmap_rtalloc( /* * Lock out other modifications to the RT bitmap inode. */ - error = xfs_trans_iget(mp, ap->tp, mp->m_sb.sb_rbmino, 0, - XFS_ILOCK_EXCL | XFS_ILOCK_RTBITMAP, &ip); - if (error) - return error; - ASSERT(ip == mp->m_rbmip); + xfs_ilock(mp->m_rbmip, XFS_ILOCK_EXCL); + xfs_trans_ijoin_ref(ap->tp, mp->m_rbmip, XFS_ILOCK_EXCL); /* * If it's an allocation to an empty file at offset 0, diff --git a/fs/xfs/xfs_rtalloc.c b/fs/xfs/xfs_rtalloc.c index f592ac978186a..fbff89344badd 100644 --- a/fs/xfs/xfs_rtalloc.c +++ b/fs/xfs/xfs_rtalloc.c @@ -76,7 +76,7 @@ xfs_growfs_rt_alloc( xfs_mount_t *mp, /* file system mount point */ xfs_extlen_t oblocks, /* old count of blocks */ xfs_extlen_t nblocks, /* new count of blocks */ - xfs_ino_t ino) /* inode number (bitmap/summary) */ + xfs_inode_t *ip) /* inode (bitmap/summary) */ { xfs_fileoff_t bno; /* block number in file */ xfs_buf_t *bp; /* temporary buffer for zeroing */ @@ -86,7 +86,6 @@ xfs_growfs_rt_alloc( xfs_fsblock_t firstblock; /* first block allocated in xaction */ xfs_bmap_free_t flist; /* list of freed blocks */ xfs_fsblock_t fsbno; /* filesystem block for bno */ - xfs_inode_t *ip; /* pointer to incore inode */ xfs_bmbt_irec_t map; /* block map output */ int nmap; /* number of block maps */ int resblks; /* space reservation */ @@ -112,9 +111,9 @@ xfs_growfs_rt_alloc( /* * Lock the inode. */ - if ((error = xfs_trans_iget(mp, tp, ino, 0, - XFS_ILOCK_EXCL, &ip))) - goto error_cancel; + xfs_ilock(ip, XFS_ILOCK_EXCL); + xfs_trans_ijoin_ref(tp, ip, XFS_ILOCK_EXCL); + xfs_bmap_init(&flist, &firstblock); /* * Allocate blocks to the bitmap file. @@ -155,9 +154,8 @@ xfs_growfs_rt_alloc( /* * Lock the bitmap inode. */ - if ((error = xfs_trans_iget(mp, tp, ino, 0, - XFS_ILOCK_EXCL, &ip))) - goto error_cancel; + xfs_ilock(ip, XFS_ILOCK_EXCL); + xfs_trans_ijoin_ref(tp, ip, XFS_ILOCK_EXCL); /* * Get a buffer for the block. */ @@ -1854,7 +1852,6 @@ xfs_growfs_rt( xfs_rtblock_t bmbno; /* bitmap block number */ xfs_buf_t *bp; /* temporary buffer */ int error; /* error return value */ - xfs_inode_t *ip; /* bitmap inode, used as lock */ xfs_mount_t *nmp; /* new (fake) mount structure */ xfs_drfsbno_t nrblocks; /* new number of realtime blocks */ xfs_extlen_t nrbmblocks; /* new number of rt bitmap blocks */ @@ -1918,11 +1915,11 @@ xfs_growfs_rt( /* * Allocate space to the bitmap and summary files, as necessary. */ - if ((error = xfs_growfs_rt_alloc(mp, rbmblocks, nrbmblocks, - mp->m_sb.sb_rbmino))) + error = xfs_growfs_rt_alloc(mp, rbmblocks, nrbmblocks, mp->m_rbmip); + if (error) return error; - if ((error = xfs_growfs_rt_alloc(mp, rsumblocks, nrsumblocks, - mp->m_sb.sb_rsumino))) + error = xfs_growfs_rt_alloc(mp, rsumblocks, nrsumblocks, mp->m_rsumip); + if (error) return error; /* * Allocate a new (fake) mount/sb. @@ -1972,12 +1969,8 @@ xfs_growfs_rt( /* * Lock out other callers by grabbing the bitmap inode lock. */ - error = xfs_trans_iget(mp, tp, mp->m_sb.sb_rbmino, 0, - XFS_ILOCK_EXCL | XFS_ILOCK_RTBITMAP, - &ip); - if (error) - goto error_cancel; - ASSERT(ip == mp->m_rbmip); + xfs_ilock(mp->m_rbmip, XFS_ILOCK_EXCL); + xfs_trans_ijoin_ref(tp, mp->m_rbmip, XFS_ILOCK_EXCL); /* * Update the bitmap inode's size. */ @@ -1988,11 +1981,8 @@ xfs_growfs_rt( /* * Get the summary inode into the transaction. */ - error = xfs_trans_iget(mp, tp, mp->m_sb.sb_rsumino, 0, - XFS_ILOCK_EXCL | XFS_ILOCK_RTSUM, &ip); - if (error) - goto error_cancel; - ASSERT(ip == mp->m_rsumip); + xfs_ilock(mp->m_rsumip, XFS_ILOCK_EXCL); + xfs_trans_ijoin_ref(tp, mp->m_rsumip, XFS_ILOCK_EXCL); /* * Update the summary inode's size. */ @@ -2154,7 +2144,6 @@ xfs_rtfree_extent( xfs_extlen_t len) /* length of extent freed */ { int error; /* error value */ - xfs_inode_t *ip; /* bitmap file inode */ xfs_mount_t *mp; /* file system mount structure */ xfs_fsblock_t sb; /* summary file block number */ xfs_buf_t *sumbp; /* summary file block buffer */ @@ -2163,10 +2152,9 @@ xfs_rtfree_extent( /* * Synchronize by locking the bitmap inode. */ - error = xfs_trans_iget(mp, tp, mp->m_sb.sb_rbmino, 0, - XFS_ILOCK_EXCL | XFS_ILOCK_RTBITMAP, &ip); - if (error) - return error; + xfs_ilock(mp->m_rbmip, XFS_ILOCK_EXCL); + xfs_trans_ijoin_ref(tp, mp->m_rbmip, XFS_ILOCK_EXCL); + #if defined(__KERNEL__) && defined(DEBUG) /* * Check to see that this whole range is currently allocated. @@ -2199,10 +2187,10 @@ xfs_rtfree_extent( */ if (tp->t_frextents_delta + mp->m_sb.sb_frextents == mp->m_sb.sb_rextents) { - if (!(ip->i_d.di_flags & XFS_DIFLAG_NEWRTBM)) - ip->i_d.di_flags |= XFS_DIFLAG_NEWRTBM; - *(__uint64_t *)&ip->i_d.di_atime = 0; - xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); + if (!(mp->m_rbmip->i_d.di_flags & XFS_DIFLAG_NEWRTBM)) + mp->m_rbmip->i_d.di_flags |= XFS_DIFLAG_NEWRTBM; + *(__uint64_t *)&mp->m_rbmip->i_d.di_atime = 0; + xfs_trans_log_inode(tp, mp->m_rbmip, XFS_ILOG_CORE); } return 0; } -- GitLab From ec3ba85f4083d10e32fe58b46db02d78ef71f6b8 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Sun, 13 Feb 2011 13:26:42 +0000 Subject: [PATCH 0179/2822] xfs: more sensible inode refcounting for ialloc Currently we return iodes from xfs_ialloc with just a single reference held. But we need two references, as one is dropped during transaction commit and the second needs to be transfered to the VFS. Change xfs_ialloc to use xfs_iget plus xfs_trans_ijoin_ref to grab two references to the inode, and remove the now superflous IHOLD calls from all callers. This also greatly simplifies the error handling in xfs_create and also allow to remove xfs_trans_iget as no other callers are left. Signed-off-by: Christoph Hellwig Reviewed-by: Dave Chinner Signed-off-by: Alex Elder --- fs/xfs/quota/xfs_qm.c | 7 ----- fs/xfs/xfs_inode.c | 5 ++-- fs/xfs/xfs_trans.h | 2 -- fs/xfs/xfs_trans_inode.c | 22 --------------- fs/xfs/xfs_vnodeops.c | 61 +++++++++++----------------------------- 5 files changed, 19 insertions(+), 78 deletions(-) diff --git a/fs/xfs/quota/xfs_qm.c b/fs/xfs/quota/xfs_qm.c index 206a2815ced67..f517963aec071 100644 --- a/fs/xfs/quota/xfs_qm.c +++ b/fs/xfs/quota/xfs_qm.c @@ -1229,13 +1229,6 @@ xfs_qm_qino_alloc( return error; } - /* - * Keep an extra reference to this quota inode. This inode is - * locked exclusively and joined to the transaction already. - */ - ASSERT(xfs_isilocked(*ip, XFS_ILOCK_EXCL)); - IHOLD(*ip); - /* * Make the changes in the superblock, and log those too. * sbfields arg may contain fields other than *QUOTINO; diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c index be7cf625421f1..c39278b6c871e 100644 --- a/fs/xfs/xfs_inode.c +++ b/fs/xfs/xfs_inode.c @@ -1016,8 +1016,8 @@ xfs_ialloc( * This is because we're setting fields here we need * to prevent others from looking at until we're done. */ - error = xfs_trans_iget(tp->t_mountp, tp, ino, - XFS_IGET_CREATE, XFS_ILOCK_EXCL, &ip); + error = xfs_iget(tp->t_mountp, tp, ino, XFS_IGET_CREATE, + XFS_ILOCK_EXCL, &ip); if (error) return error; ASSERT(ip != NULL); @@ -1166,6 +1166,7 @@ xfs_ialloc( /* * Log the new values stuffed into the inode. */ + xfs_trans_ijoin_ref(tp, ip, XFS_ILOCK_EXCL); xfs_trans_log_inode(tp, ip, flags); /* now that we have an i_mode we can setup inode ops and unlock */ diff --git a/fs/xfs/xfs_trans.h b/fs/xfs/xfs_trans.h index c2042b736b811..06a9759b6352a 100644 --- a/fs/xfs/xfs_trans.h +++ b/fs/xfs/xfs_trans.h @@ -469,8 +469,6 @@ void xfs_trans_inode_buf(xfs_trans_t *, struct xfs_buf *); void xfs_trans_stale_inode_buf(xfs_trans_t *, struct xfs_buf *); void xfs_trans_dquot_buf(xfs_trans_t *, struct xfs_buf *, uint); void xfs_trans_inode_alloc_buf(xfs_trans_t *, struct xfs_buf *); -int xfs_trans_iget(struct xfs_mount *, xfs_trans_t *, - xfs_ino_t , uint, uint, struct xfs_inode **); void xfs_trans_ichgtime(struct xfs_trans *, struct xfs_inode *, int); void xfs_trans_ijoin_ref(struct xfs_trans *, struct xfs_inode *, uint); void xfs_trans_ijoin(struct xfs_trans *, struct xfs_inode *); diff --git a/fs/xfs/xfs_trans_inode.c b/fs/xfs/xfs_trans_inode.c index ccb34532768bd..16084d8ea231a 100644 --- a/fs/xfs/xfs_trans_inode.c +++ b/fs/xfs/xfs_trans_inode.c @@ -43,28 +43,6 @@ xfs_trans_inode_broot_debug( #define xfs_trans_inode_broot_debug(ip) #endif -/* - * Get an inode and join it to the transaction. - */ -int -xfs_trans_iget( - xfs_mount_t *mp, - xfs_trans_t *tp, - xfs_ino_t ino, - uint flags, - uint lock_flags, - xfs_inode_t **ipp) -{ - int error; - - error = xfs_iget(mp, tp, ino, flags, lock_flags, ipp); - if (!error && tp) { - xfs_trans_ijoin(tp, *ipp); - (*ipp)->i_itemp->ili_lock_flags = lock_flags; - } - return error; -} - /* * Add a locked inode to the transaction. * diff --git a/fs/xfs/xfs_vnodeops.c b/fs/xfs/xfs_vnodeops.c index d8e6f8cd6f0c8..258d4f98eb9bb 100644 --- a/fs/xfs/xfs_vnodeops.c +++ b/fs/xfs/xfs_vnodeops.c @@ -1310,7 +1310,7 @@ xfs_create( error = xfs_qm_vop_dqalloc(dp, current_fsuid(), current_fsgid(), prid, XFS_QMOPT_QUOTALL | XFS_QMOPT_INHERIT, &udqp, &gdqp); if (error) - goto std_return; + return error; if (is_dir) { rdev = 0; @@ -1389,12 +1389,6 @@ xfs_create( goto out_trans_abort; } - /* - * At this point, we've gotten a newly allocated inode. - * It is locked (and joined to the transaction). - */ - ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL)); - /* * Now we join the directory inode to the transaction. We do not do it * earlier because xfs_dir_ialloc might commit the previous transaction @@ -1440,22 +1434,13 @@ xfs_create( */ xfs_qm_vop_create_dqattach(tp, ip, udqp, gdqp); - /* - * xfs_trans_commit normally decrements the vnode ref count - * when it unlocks the inode. Since we want to return the - * vnode to the caller, we bump the vnode ref count now. - */ - IHOLD(ip); - error = xfs_bmap_finish(&tp, &free_list, &committed); if (error) - goto out_abort_rele; + goto out_bmap_cancel; error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES); - if (error) { - IRELE(ip); - goto out_dqrele; - } + if (error) + goto out_release_inode; xfs_qm_dqrele(udqp); xfs_qm_dqrele(gdqp); @@ -1469,27 +1454,21 @@ xfs_create( cancel_flags |= XFS_TRANS_ABORT; out_trans_cancel: xfs_trans_cancel(tp, cancel_flags); - out_dqrele: + out_release_inode: + /* + * Wait until after the current transaction is aborted to + * release the inode. This prevents recursive transactions + * and deadlocks from xfs_inactive. + */ + if (ip) + IRELE(ip); + xfs_qm_dqrele(udqp); xfs_qm_dqrele(gdqp); if (unlock_dp_on_error) xfs_iunlock(dp, XFS_ILOCK_EXCL); - std_return: return error; - - out_abort_rele: - /* - * Wait until after the current transaction is aborted to - * release the inode. This prevents recursive transactions - * and deadlocks from xfs_inactive. - */ - xfs_bmap_cancel(&free_list); - cancel_flags |= XFS_TRANS_ABORT; - xfs_trans_cancel(tp, cancel_flags); - IRELE(ip); - unlock_dp_on_error = B_FALSE; - goto out_dqrele; } #ifdef DEBUG @@ -2114,9 +2093,8 @@ xfs_symlink( XFS_BMAPI_WRITE | XFS_BMAPI_METADATA, &first_block, resblks, mval, &nmaps, &free_list); - if (error) { - goto error1; - } + if (error) + goto error2; if (resblks) resblks -= fs_blocks; @@ -2148,7 +2126,7 @@ xfs_symlink( error = xfs_dir_createname(tp, dp, link_name, ip->i_ino, &first_block, &free_list, resblks); if (error) - goto error1; + goto error2; xfs_trans_ichgtime(tp, dp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG); xfs_trans_log_inode(tp, dp, XFS_ILOG_CORE); @@ -2161,13 +2139,6 @@ xfs_symlink( xfs_trans_set_sync(tp); } - /* - * xfs_trans_commit normally decrements the vnode ref count - * when it unlocks the inode. Since we want to return the - * vnode to the caller, we bump the vnode ref count now. - */ - IHOLD(ip); - error = xfs_bmap_finish(&tp, &free_list, &committed); if (error) { goto error2; -- GitLab From 20ad9ea9becd34a3c16252ca9d815f2c74f8f30f Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Sun, 13 Feb 2011 12:06:34 +0000 Subject: [PATCH 0180/2822] xfs: enable delaylog by default Signed-off-by: Christoph Hellwig Signed-off-by: Dave Chinner Signed-off-by: Alex Elder --- Documentation/filesystems/xfs-delayed-logging-design.txt | 7 ------- fs/xfs/linux-2.6/xfs_super.c | 1 + 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/Documentation/filesystems/xfs-delayed-logging-design.txt b/Documentation/filesystems/xfs-delayed-logging-design.txt index 7445bf335dae7..5282e3e514131 100644 --- a/Documentation/filesystems/xfs-delayed-logging-design.txt +++ b/Documentation/filesystems/xfs-delayed-logging-design.txt @@ -791,10 +791,3 @@ mount option. Fundamentally, there is no reason why the log manager would not be able to swap methods automatically and transparently depending on load characteristics, but this should not be necessary if delayed logging works as designed. - -Roadmap: - -2.6.39 Switch default mount option to use delayed logging - => should be roughly 12 months after initial merge - => enough time to shake out remaining problems before next round of - enterprise distro kernel rebases diff --git a/fs/xfs/linux-2.6/xfs_super.c b/fs/xfs/linux-2.6/xfs_super.c index 9731898083ae8..7ec1fb8c13164 100644 --- a/fs/xfs/linux-2.6/xfs_super.c +++ b/fs/xfs/linux-2.6/xfs_super.c @@ -189,6 +189,7 @@ xfs_parseargs( mp->m_flags |= XFS_MOUNT_BARRIER; mp->m_flags |= XFS_MOUNT_COMPAT_IOSIZE; mp->m_flags |= XFS_MOUNT_SMALL_INUMS; + mp->m_flags |= XFS_MOUNT_DELAYLOG; /* * These can be overridden by the mount option parsing. -- GitLab From b3d41885d9cd0d9db31c8f49e362bae02c96fa3f Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Mon, 14 Feb 2011 18:35:22 +0100 Subject: [PATCH 0181/2822] slub: fix kmemcheck calls to match ksize() hints Recent use of ksize() in network stack (commit ca44ac38 : net: don't reallocate skb->head unless the current one hasn't the needed extra size or is shared) triggers kmemcheck warnings, because ksize() can return more space than kmemcheck is aware of. Pekka Enberg noticed SLAB+kmemcheck is doing the right thing, while SLUB +kmemcheck doesnt. Bugzilla reference #27212 Reported-by: Christian Casteyde Suggested-by: Pekka Enberg Signed-off-by: Eric Dumazet Acked-by: David S. Miller Acked-by: David Rientjes Acked-by: Christoph Lameter CC: Changli Gao CC: Andrew Morton Signed-off-by: Pekka Enberg --- mm/slub.c | 49 ++++++++++++++++++++++++++----------------------- 1 file changed, 26 insertions(+), 23 deletions(-) diff --git a/mm/slub.c b/mm/slub.c index d2f343a54bad2..217b5b5338a23 100644 --- a/mm/slub.c +++ b/mm/slub.c @@ -797,10 +797,34 @@ static inline int slab_pre_alloc_hook(struct kmem_cache *s, gfp_t flags) return should_failslab(s->objsize, flags, s->flags); } +static inline size_t slab_ksize(const struct kmem_cache *s) +{ +#ifdef CONFIG_SLUB_DEBUG + /* + * Debugging requires use of the padding between object + * and whatever may come after it. + */ + if (s->flags & (SLAB_RED_ZONE | SLAB_POISON)) + return s->objsize; + +#endif + /* + * If we have the need to store the freelist pointer + * back there or track user information then we can + * only use the space before that information. + */ + if (s->flags & (SLAB_DESTROY_BY_RCU | SLAB_STORE_USER)) + return s->inuse; + /* + * Else we can use all the padding etc for the allocation + */ + return s->size; +} + static inline void slab_post_alloc_hook(struct kmem_cache *s, gfp_t flags, void *object) { flags &= gfp_allowed_mask; - kmemcheck_slab_alloc(s, flags, object, s->objsize); + kmemcheck_slab_alloc(s, flags, object, slab_ksize(s)); kmemleak_alloc_recursive(object, s->objsize, 1, s->flags, flags); } @@ -2690,7 +2714,6 @@ EXPORT_SYMBOL(__kmalloc_node); size_t ksize(const void *object) { struct page *page; - struct kmem_cache *s; if (unlikely(object == ZERO_SIZE_PTR)) return 0; @@ -2701,28 +2724,8 @@ size_t ksize(const void *object) WARN_ON(!PageCompound(page)); return PAGE_SIZE << compound_order(page); } - s = page->slab; -#ifdef CONFIG_SLUB_DEBUG - /* - * Debugging requires use of the padding between object - * and whatever may come after it. - */ - if (s->flags & (SLAB_RED_ZONE | SLAB_POISON)) - return s->objsize; - -#endif - /* - * If we have the need to store the freelist pointer - * back there or track user information then we can - * only use the space before that information. - */ - if (s->flags & (SLAB_DESTROY_BY_RCU | SLAB_STORE_USER)) - return s->inuse; - /* - * Else we can use all the padding etc for the allocation - */ - return s->size; + return slab_ksize(page->slab); } EXPORT_SYMBOL(ksize); -- GitLab From 0b75a840120b1e647e32342e9cc46631410088d5 Mon Sep 17 00:00:00 2001 From: Lukas Czerner Date: Wed, 23 Feb 2011 12:22:49 -0500 Subject: [PATCH 0182/2822] ext4: mark file-local functions and variables as static Signed-off-by: Lukas Czerner Signed-off-by: "Theodore Ts'o" --- fs/ext4/mballoc.c | 3 ++- fs/ext4/super.c | 6 +++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c index d1fe09aea73dc..ae4d7f5edbbf1 100644 --- a/fs/ext4/mballoc.c +++ b/fs/ext4/mballoc.c @@ -4753,7 +4753,8 @@ static int ext4_trim_extent(struct super_block *sb, int start, int count, * bitmap. Then issue a TRIM command on this extent and free the extent in * the group buddy bitmap. This is done until whole group is scanned. */ -ext4_grpblk_t ext4_trim_all_free(struct super_block *sb, struct ext4_buddy *e4b, +static ext4_grpblk_t +ext4_trim_all_free(struct super_block *sb, struct ext4_buddy *e4b, ext4_grpblk_t start, ext4_grpblk_t max, ext4_grpblk_t minblocks) { void *bitmap; diff --git a/fs/ext4/super.c b/fs/ext4/super.c index a1ac24b6a758a..1539cf5597847 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c @@ -54,9 +54,9 @@ static struct proc_dir_entry *ext4_proc_root; static struct kset *ext4_kset; -struct ext4_lazy_init *ext4_li_info; -struct mutex ext4_li_mtx; -struct ext4_features *ext4_feat; +static struct ext4_lazy_init *ext4_li_info; +static struct mutex ext4_li_mtx; +static struct ext4_features *ext4_feat; static int ext4_load_journal(struct super_block *, struct ext4_super_block *, unsigned long journal_devnum); -- GitLab From 4143179218960a70d821a425e3c23ce44aa93dee Mon Sep 17 00:00:00 2001 From: Lukas Czerner Date: Wed, 23 Feb 2011 12:42:32 -0500 Subject: [PATCH 0183/2822] ext4: check if device support discard in FITRIM ioctl For a device that does not support discard, the FITRIM ioctl returns -EOPNOTSUPP when blkdev_issue_discard() returns this error code, which is how the user is informed that the device does not support discard. If there are no suitable free extents to be trimmed, then FITRIM will return success even though the device does not support discard, which could confuse the user. So check explicitly if the device supports discard and return an error code at the beginning of the FITRIM ioctl processing. Signed-off-by: Lukas Czerner Signed-off-by: "Theodore Ts'o" --- fs/ext4/ioctl.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/fs/ext4/ioctl.c b/fs/ext4/ioctl.c index eb3bc2fe647e7..25ba7c79d2893 100644 --- a/fs/ext4/ioctl.c +++ b/fs/ext4/ioctl.c @@ -334,12 +334,16 @@ mext_out: case FITRIM: { struct super_block *sb = inode->i_sb; + struct request_queue *q = bdev_get_queue(sb->s_bdev); struct fstrim_range range; int ret = 0; if (!capable(CAP_SYS_ADMIN)) return -EPERM; + if (!blk_queue_discard(q)) + return -EOPNOTSUPP; + if (copy_from_user(&range, (struct fstrim_range *)arg, sizeof(range))) return -EFAULT; -- GitLab From af90f10d3826525306c96d423df240210640cb72 Mon Sep 17 00:00:00 2001 From: Santosh Shilimkar Date: Wed, 23 Feb 2011 18:53:15 +0100 Subject: [PATCH 0184/2822] ARM: 6759/1: smp: Select local timers vs broadcast timer support runtime The current code support of dummy timers in absence of local timer is compile time. This is an attempt to convert it to runtime so that on few SOC version if the local timers aren't supported kernel can switch to dummy timers. OMAP4430 ES1.0 does suffer from this limitation. This patch should not have any functional impact on affected files. Cc: Daniel Walker Cc: Bryan Huntsman Cc: Tony Lindgren Cc: Kukjin Kim Cc: Paul Mundt Cc: Magnus Damm Cc: Colin Cross Cc: Erik Gilling Cc: Srinidhi Kasagar Cc: Linus Walleij Signed-off-by: Santosh Shilimkar Acked-by: David Brown Signed-off-by: Russell King --- arch/arm/include/asm/localtimer.h | 8 +++++++- arch/arm/kernel/smp.c | 7 +++---- arch/arm/mach-msm/timer.c | 3 ++- arch/arm/mach-omap2/timer-mpu.c | 3 ++- arch/arm/mach-s5pv310/localtimer.c | 3 ++- arch/arm/mach-shmobile/localtimer.c | 3 ++- arch/arm/mach-tegra/localtimer.c | 3 ++- arch/arm/mach-ux500/localtimer.c | 3 ++- arch/arm/plat-versatile/localtimer.c | 3 ++- 9 files changed, 24 insertions(+), 12 deletions(-) diff --git a/arch/arm/include/asm/localtimer.h b/arch/arm/include/asm/localtimer.h index 6bc63ab498ce4..080d74f8128d4 100644 --- a/arch/arm/include/asm/localtimer.h +++ b/arch/arm/include/asm/localtimer.h @@ -44,8 +44,14 @@ int local_timer_ack(void); /* * Setup a local timer interrupt for a CPU. */ -void local_timer_setup(struct clock_event_device *); +int local_timer_setup(struct clock_event_device *); +#else + +static inline int local_timer_setup(struct clock_event_device *evt) +{ + return -ENXIO; +} #endif #endif diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c index 4539ebcb089fa..8fe05ad932e4b 100644 --- a/arch/arm/kernel/smp.c +++ b/arch/arm/kernel/smp.c @@ -474,13 +474,12 @@ static void smp_timer_broadcast(const struct cpumask *mask) #define smp_timer_broadcast NULL #endif -#ifndef CONFIG_LOCAL_TIMERS static void broadcast_timer_set_mode(enum clock_event_mode mode, struct clock_event_device *evt) { } -static void local_timer_setup(struct clock_event_device *evt) +static void broadcast_timer_setup(struct clock_event_device *evt) { evt->name = "dummy_timer"; evt->features = CLOCK_EVT_FEAT_ONESHOT | @@ -492,7 +491,6 @@ static void local_timer_setup(struct clock_event_device *evt) clockevents_register_device(evt); } -#endif void __cpuinit percpu_timer_setup(void) { @@ -502,7 +500,8 @@ void __cpuinit percpu_timer_setup(void) evt->cpumask = cpumask_of(cpu); evt->broadcast = smp_timer_broadcast; - local_timer_setup(evt); + if (local_timer_setup(evt)) + broadcast_timer_setup(evt); } #ifdef CONFIG_HOTPLUG_CPU diff --git a/arch/arm/mach-msm/timer.c b/arch/arm/mach-msm/timer.c index c105d28b53e38..ae85aa951806a 100644 --- a/arch/arm/mach-msm/timer.c +++ b/arch/arm/mach-msm/timer.c @@ -255,7 +255,7 @@ static void __init msm_timer_init(void) } #ifdef CONFIG_SMP -void __cpuinit local_timer_setup(struct clock_event_device *evt) +int __cpuinit local_timer_setup(struct clock_event_device *evt) { struct msm_clock *clock = &msm_clocks[MSM_GLOBAL_TIMER]; @@ -287,6 +287,7 @@ void __cpuinit local_timer_setup(struct clock_event_device *evt) gic_enable_ppi(clock->irq.irq); clockevents_register_device(evt); + return 0; } inline int local_timer_ack(void) diff --git a/arch/arm/mach-omap2/timer-mpu.c b/arch/arm/mach-omap2/timer-mpu.c index 954682e643996..09c73dcfc2ac0 100644 --- a/arch/arm/mach-omap2/timer-mpu.c +++ b/arch/arm/mach-omap2/timer-mpu.c @@ -26,9 +26,10 @@ /* * Setup the local clock events for a CPU. */ -void __cpuinit local_timer_setup(struct clock_event_device *evt) +int __cpuinit local_timer_setup(struct clock_event_device *evt) { evt->irq = OMAP44XX_IRQ_LOCALTIMER; twd_timer_setup(evt); + return 0; } diff --git a/arch/arm/mach-s5pv310/localtimer.c b/arch/arm/mach-s5pv310/localtimer.c index 2784036cd8b10..8239c6a684a1c 100644 --- a/arch/arm/mach-s5pv310/localtimer.c +++ b/arch/arm/mach-s5pv310/localtimer.c @@ -18,8 +18,9 @@ /* * Setup the local clock events for a CPU. */ -void __cpuinit local_timer_setup(struct clock_event_device *evt) +int __cpuinit local_timer_setup(struct clock_event_device *evt) { evt->irq = IRQ_LOCALTIMER; twd_timer_setup(evt); + return 0; } diff --git a/arch/arm/mach-shmobile/localtimer.c b/arch/arm/mach-shmobile/localtimer.c index 2111c28b724e2..ad9ccc9900c82 100644 --- a/arch/arm/mach-shmobile/localtimer.c +++ b/arch/arm/mach-shmobile/localtimer.c @@ -18,8 +18,9 @@ /* * Setup the local clock events for a CPU. */ -void __cpuinit local_timer_setup(struct clock_event_device *evt) +int __cpuinit local_timer_setup(struct clock_event_device *evt) { evt->irq = 29; twd_timer_setup(evt); + return 0; } diff --git a/arch/arm/mach-tegra/localtimer.c b/arch/arm/mach-tegra/localtimer.c index f81ca7cbbc1f7..e91d681d45a2d 100644 --- a/arch/arm/mach-tegra/localtimer.c +++ b/arch/arm/mach-tegra/localtimer.c @@ -18,8 +18,9 @@ /* * Setup the local clock events for a CPU. */ -void __cpuinit local_timer_setup(struct clock_event_device *evt) +int __cpuinit local_timer_setup(struct clock_event_device *evt) { evt->irq = IRQ_LOCALTIMER; twd_timer_setup(evt); + return 0; } diff --git a/arch/arm/mach-ux500/localtimer.c b/arch/arm/mach-ux500/localtimer.c index 2288f6a7c5180..5ba113309a0b3 100644 --- a/arch/arm/mach-ux500/localtimer.c +++ b/arch/arm/mach-ux500/localtimer.c @@ -21,8 +21,9 @@ /* * Setup the local clock events for a CPU. */ -void __cpuinit local_timer_setup(struct clock_event_device *evt) +int __cpuinit local_timer_setup(struct clock_event_device *evt) { evt->irq = IRQ_LOCALTIMER; twd_timer_setup(evt); + return 0; } diff --git a/arch/arm/plat-versatile/localtimer.c b/arch/arm/plat-versatile/localtimer.c index 83ebee569333c..0fb3961999b51 100644 --- a/arch/arm/plat-versatile/localtimer.c +++ b/arch/arm/plat-versatile/localtimer.c @@ -19,8 +19,9 @@ /* * Setup the local clock events for a CPU. */ -void __cpuinit local_timer_setup(struct clock_event_device *evt) +int __cpuinit local_timer_setup(struct clock_event_device *evt) { evt->irq = IRQ_LOCALTIMER; twd_timer_setup(evt); + return 0; } -- GitLab From 07787a85c0c664d434b522c8bdf7cdc636a16e75 Mon Sep 17 00:00:00 2001 From: Santosh Shilimkar Date: Tue, 22 Feb 2011 09:57:47 +0100 Subject: [PATCH 0185/2822] ARM: 6753/1: omap4: Enable ARM local timers with OMAP4430 es1.0 exception On OMAP4430 ES1.0 the local timers are gated by security. Enable the CONFIG_LOCAL_TIMERS for omap2plus build and handle the OMAP4430 es1.0 exception case. This patch has dependency on the first patch in this series. ARM: smp: Select local timers vs dummy timer support runtime Signed-off-by: Santosh Shilimkar Acked-by: Tony Lindgren Signed-off-by: Russell King --- arch/arm/mach-omap2/Kconfig | 1 + arch/arm/mach-omap2/timer-mpu.c | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/arch/arm/mach-omap2/Kconfig b/arch/arm/mach-omap2/Kconfig index 1a2cf6226a55f..ec55fd830f621 100644 --- a/arch/arm/mach-omap2/Kconfig +++ b/arch/arm/mach-omap2/Kconfig @@ -44,6 +44,7 @@ config ARCH_OMAP4 depends on ARCH_OMAP2PLUS select CPU_V7 select ARM_GIC + select LOCAL_TIMERS if SMP select PL310_ERRATA_588369 select ARM_ERRATA_720789 select ARCH_HAS_OPP diff --git a/arch/arm/mach-omap2/timer-mpu.c b/arch/arm/mach-omap2/timer-mpu.c index 09c73dcfc2ac0..31c0ac4cd66a4 100644 --- a/arch/arm/mach-omap2/timer-mpu.c +++ b/arch/arm/mach-omap2/timer-mpu.c @@ -28,6 +28,10 @@ */ int __cpuinit local_timer_setup(struct clock_event_device *evt) { + /* Local timers are not supprted on OMAP4430 ES1.0 */ + if (omap_rev() == OMAP4430_REV_ES1_0) + return -ENXIO; + evt->irq = OMAP44XX_IRQ_LOCALTIMER; twd_timer_setup(evt); return 0; -- GitLab From 5c2ed62fd447e2c696e222dcf71d1322bbbc58d4 Mon Sep 17 00:00:00 2001 From: Lukas Czerner Date: Wed, 23 Feb 2011 17:49:51 -0500 Subject: [PATCH 0186/2822] ext4: Adjust minlen with discard_granularity in the FITRIM ioctl Discard granularity tells us the minimum size of extent that can be discarded by the device. If the user supplies a minimum extent that should be discarded (range.minlen) which is smaller than the discard granularity, increase minlen to the discard granularity, since there's no point submitting trim requests that the device will reject anyway. Signed-off-by: Lukas Czerner Signed-off-by: "Theodore Ts'o" --- fs/ext4/ioctl.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/fs/ext4/ioctl.c b/fs/ext4/ioctl.c index 25ba7c79d2893..c052c9f0f3a16 100644 --- a/fs/ext4/ioctl.c +++ b/fs/ext4/ioctl.c @@ -348,6 +348,8 @@ mext_out: sizeof(range))) return -EFAULT; + range.minlen = max((unsigned int)range.minlen, + q->limits.discard_granularity); ret = ext4_trim_fs(sb, &range); if (ret < 0) return ret; -- GitLab From ea6633369458992241599c9d9ebadffaeddec164 Mon Sep 17 00:00:00 2001 From: Eric Sandeen Date: Wed, 23 Feb 2011 17:51:51 -0500 Subject: [PATCH 0187/2822] ext4: enable acls and user_xattr by default There's no good reason to require the extra step of providing a mount option for acl or user_xattr once the feature is configured on; no other filesystem that I know of requires this. Userspace patches have set these options in default mount options, and this patch makes them default in the kernel. At some point we can start to deprecate the options, perhaps. For now I've removed default mount option checks in show_options() to be explicit about what's set, since it's changing the default, but I'm open to alternatives if desired. Signed-off-by: Eric Sandeen Signed-off-by: "Theodore Ts'o" --- fs/ext4/super.c | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/fs/ext4/super.c b/fs/ext4/super.c index 1539cf5597847..a665d2fb70c14 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c @@ -997,13 +997,10 @@ static int ext4_show_options(struct seq_file *seq, struct vfsmount *vfs) if (test_opt(sb, OLDALLOC)) seq_puts(seq, ",oldalloc"); #ifdef CONFIG_EXT4_FS_XATTR - if (test_opt(sb, XATTR_USER) && - !(def_mount_opts & EXT4_DEFM_XATTR_USER)) + if (test_opt(sb, XATTR_USER)) seq_puts(seq, ",user_xattr"); - if (!test_opt(sb, XATTR_USER) && - (def_mount_opts & EXT4_DEFM_XATTR_USER)) { + if (!test_opt(sb, XATTR_USER)) seq_puts(seq, ",nouser_xattr"); - } #endif #ifdef CONFIG_EXT4_FS_POSIX_ACL if (test_opt(sb, POSIX_ACL) && !(def_mount_opts & EXT4_DEFM_ACL)) @@ -3095,13 +3092,12 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) } if (def_mount_opts & EXT4_DEFM_UID16) set_opt(sb, NO_UID32); + /* xattr user namespace & acls are now defaulted on */ #ifdef CONFIG_EXT4_FS_XATTR - if (def_mount_opts & EXT4_DEFM_XATTR_USER) - set_opt(sb, XATTR_USER); + set_opt(sb, XATTR_USER); #endif #ifdef CONFIG_EXT4_FS_POSIX_ACL - if (def_mount_opts & EXT4_DEFM_ACL) - set_opt(sb, POSIX_ACL); + set_opt(sb, POSIX_ACL); #endif if ((def_mount_opts & EXT4_DEFM_JMODE) == EXT4_DEFM_JMODE_DATA) set_opt(sb, JOURNAL_DATA); -- GitLab From 5ad567ffbaf208bd35bff4341906346c1a1d4574 Mon Sep 17 00:00:00 2001 From: Abraham Arce Date: Tue, 22 Feb 2011 22:25:59 -0800 Subject: [PATCH 0188/2822] Input: omap4-keypad - wire up runtime PM handling Enable Runtime PM functionality in OMAP4 driver based on the following assumptions: - keyboard controller in wakeup domain so it is always on and power impact is minimal; - in OMAP4 the device control is at module/device level and ick/fclk level control is difficult so cutting of clocks will prevent interrupts. Signed-off-by: Abraham Arce Signed-off-by: Shubhrajyoti D Signed-off-by: Dmitry Torokhov --- drivers/input/keyboard/omap4-keypad.c | 74 ++++++++++++++++++++------- 1 file changed, 55 insertions(+), 19 deletions(-) diff --git a/drivers/input/keyboard/omap4-keypad.c b/drivers/input/keyboard/omap4-keypad.c index 45bd0977d0066..c51a3c4a7feb5 100644 --- a/drivers/input/keyboard/omap4-keypad.c +++ b/drivers/input/keyboard/omap4-keypad.c @@ -29,6 +29,7 @@ #include #include #include +#include #include @@ -80,20 +81,6 @@ struct omap4_keypad { unsigned short keymap[]; }; -static void __devinit omap4_keypad_config(struct omap4_keypad *keypad_data) -{ - __raw_writel(OMAP4_VAL_FUNCTIONALCFG, - keypad_data->base + OMAP4_KBD_CTRL); - __raw_writel(OMAP4_VAL_DEBOUNCINGTIME, - keypad_data->base + OMAP4_KBD_DEBOUNCINGTIME); - __raw_writel(OMAP4_VAL_IRQDISABLE, - keypad_data->base + OMAP4_KBD_IRQSTATUS); - __raw_writel(OMAP4_DEF_IRQENABLE_EVENTEN | OMAP4_DEF_IRQENABLE_LONGKEY, - keypad_data->base + OMAP4_KBD_IRQENABLE); - __raw_writel(OMAP4_DEF_WUP_EVENT_ENA | OMAP4_DEF_WUP_LONG_KEY_ENA, - keypad_data->base + OMAP4_KBD_WAKEUPENABLE); -} - /* Interrupt handler */ static irqreturn_t omap4_keypad_interrupt(int irq, void *dev_id) { @@ -144,6 +131,49 @@ static irqreturn_t omap4_keypad_interrupt(int irq, void *dev_id) return IRQ_HANDLED; } +static int omap4_keypad_open(struct input_dev *input) +{ + struct omap4_keypad *keypad_data = input_get_drvdata(input); + + pm_runtime_get_sync(input->dev.parent); + + disable_irq(keypad_data->irq); + + __raw_writel(OMAP4_VAL_FUNCTIONALCFG, + keypad_data->base + OMAP4_KBD_CTRL); + __raw_writel(OMAP4_VAL_DEBOUNCINGTIME, + keypad_data->base + OMAP4_KBD_DEBOUNCINGTIME); + __raw_writel(OMAP4_VAL_IRQDISABLE, + keypad_data->base + OMAP4_KBD_IRQSTATUS); + __raw_writel(OMAP4_DEF_IRQENABLE_EVENTEN | OMAP4_DEF_IRQENABLE_LONGKEY, + keypad_data->base + OMAP4_KBD_IRQENABLE); + __raw_writel(OMAP4_DEF_WUP_EVENT_ENA | OMAP4_DEF_WUP_LONG_KEY_ENA, + keypad_data->base + OMAP4_KBD_WAKEUPENABLE); + + enable_irq(keypad_data->irq); + + return 0; +} + +static void omap4_keypad_close(struct input_dev *input) +{ + struct omap4_keypad *keypad_data = input_get_drvdata(input); + + disable_irq(keypad_data->irq); + + /* Disable interrupts */ + __raw_writel(OMAP4_VAL_IRQDISABLE, + keypad_data->base + OMAP4_KBD_IRQENABLE); + + /* clear pending interrupts */ + __raw_writel(__raw_readl(keypad_data->base + OMAP4_KBD_IRQSTATUS), + keypad_data->base + OMAP4_KBD_IRQSTATUS); + + enable_irq(keypad_data->irq); + + pm_runtime_put_sync(input->dev.parent); +} + static int __devinit omap4_keypad_probe(struct platform_device *pdev) { const struct omap4_keypad_platform_data *pdata; @@ -225,6 +255,9 @@ static int __devinit omap4_keypad_probe(struct platform_device *pdev) input_dev->id.product = 0x0001; input_dev->id.version = 0x0001; + input_dev->open = omap4_keypad_open; + input_dev->close = omap4_keypad_close; + input_dev->keycode = keypad_data->keymap; input_dev->keycodesize = sizeof(keypad_data->keymap[0]); input_dev->keycodemax = max_keys; @@ -239,8 +272,6 @@ static int __devinit omap4_keypad_probe(struct platform_device *pdev) matrix_keypad_build_keymap(pdata->keymap_data, row_shift, input_dev->keycode, input_dev->keybit); - omap4_keypad_config(keypad_data); - error = request_irq(keypad_data->irq, omap4_keypad_interrupt, IRQF_TRIGGER_RISING, "omap4-keypad", keypad_data); @@ -249,17 +280,19 @@ static int __devinit omap4_keypad_probe(struct platform_device *pdev) goto err_free_input; } + pm_runtime_enable(&pdev->dev); + error = input_register_device(keypad_data->input); if (error < 0) { dev_err(&pdev->dev, "failed to register input device\n"); - goto err_free_irq; + goto err_pm_disable; } - platform_set_drvdata(pdev, keypad_data); return 0; -err_free_irq: +err_pm_disable: + pm_runtime_disable(&pdev->dev); free_irq(keypad_data->irq, keypad_data); err_free_input: input_free_device(input_dev); @@ -278,6 +311,9 @@ static int __devexit omap4_keypad_remove(struct platform_device *pdev) struct resource *res; free_irq(keypad_data->irq, keypad_data); + + pm_runtime_disable(&pdev->dev); + input_unregister_device(keypad_data->input); iounmap(keypad_data->base); -- GitLab From adf779c1ee1d5556ebd83e39a7189022d4ebce3a Mon Sep 17 00:00:00 2001 From: Heungjun Kim Date: Wed, 23 Feb 2011 21:40:11 -0800 Subject: [PATCH 0189/2822] Input: mcs_touchkey - add support for suspend/resume This adds support for system-level suspend/resume to the driver. Signed-off-by: Heungjun Kim Signed-off-by: Kyungmin Park Signed-off-by: Dmitry Torokhov --- drivers/input/keyboard/mcs_touchkey.c | 48 ++++++++++++++++++++++++++- include/linux/i2c/mcs.h | 1 + 2 files changed, 48 insertions(+), 1 deletion(-) diff --git a/drivers/input/keyboard/mcs_touchkey.c b/drivers/input/keyboard/mcs_touchkey.c index 63b849d7e90b0..03fa59a0b2206 100644 --- a/drivers/input/keyboard/mcs_touchkey.c +++ b/drivers/input/keyboard/mcs_touchkey.c @@ -1,5 +1,5 @@ /* - * mcs_touchkey.c - Touchkey driver for MELFAS MCS5000/5080 controller + * Touchkey driver for MELFAS MCS5000/5080 controller * * Copyright (C) 2010 Samsung Electronics Co.Ltd * Author: HeungJun Kim @@ -19,6 +19,7 @@ #include #include #include +#include /* MCS5000 Touchkey */ #define MCS5000_TOUCHKEY_STATUS 0x04 @@ -45,6 +46,8 @@ struct mcs_touchkey_chip { }; struct mcs_touchkey_data { + void (*poweron)(bool); + struct i2c_client *client; struct input_dev *input_dev; struct mcs_touchkey_chip chip; @@ -169,6 +172,11 @@ static int __devinit mcs_touchkey_probe(struct i2c_client *client, if (pdata->cfg_pin) pdata->cfg_pin(); + if (pdata->poweron) { + data->poweron = pdata->poweron; + data->poweron(true); + } + error = request_threaded_irq(client->irq, NULL, mcs_touchkey_interrupt, IRQF_TRIGGER_FALLING, client->dev.driver->name, data); if (error) { @@ -196,12 +204,49 @@ static int __devexit mcs_touchkey_remove(struct i2c_client *client) struct mcs_touchkey_data *data = i2c_get_clientdata(client); free_irq(client->irq, data); + if (data->poweron) + data->poweron(false); input_unregister_device(data->input_dev); kfree(data); return 0; } +#ifdef CONFIG_PM_SLEEP +static int mcs_touchkey_suspend(struct device *dev) +{ + struct mcs_touchkey_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; + + /* Disable the work */ + disable_irq(client->irq); + + /* Finally turn off the power */ + if (data->poweron) + data->poweron(false); + + return 0; +} + +static int mcs_touchkey_resume(struct device *dev) +{ + struct mcs_touchkey_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; + + /* Enable the device first */ + if (data->poweron) + data->poweron(true); + + /* Enable irq again */ + enable_irq(client->irq); + + return 0; +} +#endif + +static SIMPLE_DEV_PM_OPS(mcs_touchkey_pm_ops, + mcs_touchkey_suspend, mcs_touchkey_resume); + static const struct i2c_device_id mcs_touchkey_id[] = { { "mcs5000_touchkey", MCS5000_TOUCHKEY }, { "mcs5080_touchkey", MCS5080_TOUCHKEY }, @@ -213,6 +258,7 @@ static struct i2c_driver mcs_touchkey_driver = { .driver = { .name = "mcs_touchkey", .owner = THIS_MODULE, + .pm = &mcs_touchkey_pm_ops, }, .probe = mcs_touchkey_probe, .remove = __devexit_p(mcs_touchkey_remove), diff --git a/include/linux/i2c/mcs.h b/include/linux/i2c/mcs.h index 725ae7c313ff3..61bb18a4fd3c9 100644 --- a/include/linux/i2c/mcs.h +++ b/include/linux/i2c/mcs.h @@ -18,6 +18,7 @@ #define MCS_KEY_CODE(v) ((v) & 0xffff) struct mcs_platform_data { + void (*poweron)(bool); void (*cfg_pin)(void); /* touchscreen */ -- GitLab From 5f62615ef5e50b0ad6c125fe1e38f2ac675012e2 Mon Sep 17 00:00:00 2001 From: HeungJun Kim Date: Wed, 23 Feb 2011 21:42:49 -0800 Subject: [PATCH 0190/2822] Input: mcs_touchkey - add shutdown handler The MCS50XX series has a HW bug that requires explicit chip power down. If chip is not powered down before shutting the system down the control pins (powerup, interrupt) are pulled up and residue current continues flowing into the chips making them continue consuming power. Signed-off-by: Heungjun Kim Signed-off-by: Kyungmin Park Signed-off-by: Dmitry Torokhov --- drivers/input/keyboard/mcs_touchkey.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/input/keyboard/mcs_touchkey.c b/drivers/input/keyboard/mcs_touchkey.c index 03fa59a0b2206..af1aab324a4c5 100644 --- a/drivers/input/keyboard/mcs_touchkey.c +++ b/drivers/input/keyboard/mcs_touchkey.c @@ -212,6 +212,14 @@ static int __devexit mcs_touchkey_remove(struct i2c_client *client) return 0; } +static void mcs_touchkey_shutdown(struct i2c_client *client) +{ + struct mcs_touchkey_data *data = i2c_get_clientdata(client); + + if (data->poweron) + data->poweron(false); +} + #ifdef CONFIG_PM_SLEEP static int mcs_touchkey_suspend(struct device *dev) { @@ -262,6 +270,7 @@ static struct i2c_driver mcs_touchkey_driver = { }, .probe = mcs_touchkey_probe, .remove = __devexit_p(mcs_touchkey_remove), + .shutdown = mcs_touchkey_shutdown, .id_table = mcs_touchkey_id, }; -- GitLab From de933bd833be1a53bd361c9a327afd3c65413351 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Fri, 18 Feb 2011 21:47:20 +0100 Subject: [PATCH 0191/2822] kbuild: reenable section mismatch analysis MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This was disabled in commit e5f95c8 (kbuild: print only total number of section mismatces found) because there were too many warnings. Now we're down to a reasonable number again, so we start scaring people with the details. Signed-off-by: Uwe Kleine-König Acked-by: Randy Dunlap Acked-by: Mike Frysinger Signed-off-by: Michal Marek --- lib/Kconfig.debug | 4 ---- 1 file changed, 4 deletions(-) diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug index 2d05adb984018..8b6a4f13946f4 100644 --- a/lib/Kconfig.debug +++ b/lib/Kconfig.debug @@ -102,11 +102,7 @@ config HEADERS_CHECK config DEBUG_SECTION_MISMATCH bool "Enable full Section mismatch analysis" - depends on UNDEFINED || (BLACKFIN) default y - # This option is on purpose disabled for now. - # It will be enabled when we are down to a reasonable number - # of section mismatch warnings (< 10 for an allyesconfig build) help The section mismatch analysis checks if there are illegal references from one section to another section. -- GitLab From 84b775a354f640736176b5d966408fc5d5da6665 Mon Sep 17 00:00:00 2001 From: Coly Li Date: Thu, 24 Feb 2011 12:51:59 -0500 Subject: [PATCH 0192/2822] ext4: code cleanup in mb_find_buddy() Current code calculate max no matter whether order is zero, it's unnecessary. This cleanup patch sets max to "1 << (e4b->bd_blkbits + 3)" only when order == 0. Signed-off-by: Coly Li Cc: Alex Tomas Cc: Theodore Tso --- fs/ext4/mballoc.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c index ae4d7f5edbbf1..1791dd4207d5f 100644 --- a/fs/ext4/mballoc.c +++ b/fs/ext4/mballoc.c @@ -432,9 +432,10 @@ static void *mb_find_buddy(struct ext4_buddy *e4b, int order, int *max) } /* at order 0 we see each particular block */ - *max = 1 << (e4b->bd_blkbits + 3); - if (order == 0) + if (order == 0) { + *max = 1 << (e4b->bd_blkbits + 3); return EXT4_MB_BITMAP(e4b); + } bb = EXT4_MB_BUDDY(e4b) + EXT4_SB(e4b->bd_sb)->s_mb_offsets[order]; *max = EXT4_SB(e4b->bd_sb)->s_mb_maxs[order]; -- GitLab From 235772da3e2adb1f4d71f27ec5475093dd38b2ac Mon Sep 17 00:00:00 2001 From: Coly Li Date: Thu, 24 Feb 2011 13:24:18 -0500 Subject: [PATCH 0193/2822] ext4: remove unncessary call mb_find_buddy() in debugging code In __mb_check_buddy(), look at the code below: 591 fstart = -1; 592 buddy = mb_find_buddy(e4b, 0, &max); 593 for (i = 0; i < max; i++) { 594 if (!mb_test_bit(i, buddy)) { 595 MB_CHECK_ASSERT(i >= e4b->bd_info->bb_first_free); 596 if (fstart == -1) { 597 fragments++; 598 fstart = i; 599 } 600 continue; 601 } 602 fstart = -1; 603 /* check used bits only */ 604 for (j = 0; j < e4b->bd_blkbits + 1; j++) { 605 buddy2 = mb_find_buddy(e4b, j, &max2); 606 k = i >> j; 607 MB_CHECK_ASSERT(k < max2); 608 MB_CHECK_ASSERT(mb_test_bit(k, buddy2)); 609 } 610 } 611 MB_CHECK_ASSERT(!EXT4_MB_GRP_NEED_INIT(e4b->bd_info)); 612 MB_CHECK_ASSERT(e4b->bd_info->bb_fragments == fragments); 613 614 grp = ext4_get_group_info(sb, e4b->bd_group); 615 buddy = mb_find_buddy(e4b, 0, &max); On line 592, buddy is fetched by mb_find_buddy() with order 0, between line 593 to line 615, buddy is not changed, therefore there is no need to fetch buddy again from mb_find_buddy() with order 0 again. We can safely remove the second mb_find_buddy() on line 615. Signed-off-by: Coly Li Cc: Alex Tomas Cc: Theodore Tso --- fs/ext4/mballoc.c | 1 - 1 file changed, 1 deletion(-) diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c index 1791dd4207d5f..7de0e2824436e 100644 --- a/fs/ext4/mballoc.c +++ b/fs/ext4/mballoc.c @@ -617,7 +617,6 @@ static int __mb_check_buddy(struct ext4_buddy *e4b, char *file, MB_CHECK_ASSERT(e4b->bd_info->bb_fragments == fragments); grp = ext4_get_group_info(sb, e4b->bd_group); - buddy = mb_find_buddy(e4b, 0, &max); list_for_each(cur, &grp->bb_prealloc_list) { ext4_group_t groupnr; struct ext4_prealloc_space *pa; -- GitLab From 7c786059293335412f99732c6f4c2a886eab25c2 Mon Sep 17 00:00:00 2001 From: Coly Li Date: Thu, 24 Feb 2011 13:24:25 -0500 Subject: [PATCH 0194/2822] mballoc: add comments to ext4_mb_mark_free_simple() This patch adds comments to ext4_mb_mark_free_simple to make it more understandable. Signed-off-by: Coly Li Cc: Alex Tomas Cc: Theodore Tso --- fs/ext4/mballoc.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c index 7de0e2824436e..b5235c8a2e78c 100644 --- a/fs/ext4/mballoc.c +++ b/fs/ext4/mballoc.c @@ -635,7 +635,12 @@ static int __mb_check_buddy(struct ext4_buddy *e4b, char *file, #define mb_check_buddy(e4b) #endif -/* FIXME!! need more doc */ +/* + * Divide blocks started from @first with length @len into + * smaller chunks with power of 2 blocks. + * Clear the bits in bitmap which the blocks of the chunk(s) covered, + * then increase bb_counters[] for corresponded chunk size. + */ static void ext4_mb_mark_free_simple(struct super_block *sb, void *buddy, ext4_grpblk_t first, ext4_grpblk_t len, struct ext4_group_info *grp) -- GitLab From 073b4964b3b75fd9e19bf3933b26d9c23591c9db Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Tue, 8 Feb 2011 23:37:31 +0100 Subject: [PATCH 0195/2822] ACPI: Do not export functions that are only used in osl.c The functions acpi_os_map_generic_address() and acpi_os_unmap_generic_address() are only used in drivers/acpi/osl.c, so make them static and remove the extern definitions of them from include/linux/acpi_io.h. Signed-off-by: Rafael J. Wysocki --- drivers/acpi/osl.c | 6 ++---- include/linux/acpi_io.h | 3 --- 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index c90c76aa7f8b7..ff2189d3fa064 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c @@ -397,7 +397,7 @@ void __init early_acpi_os_unmap_memory(void __iomem *virt, acpi_size size) __acpi_unmap_table(virt, size); } -int acpi_os_map_generic_address(struct acpi_generic_address *addr) +static int acpi_os_map_generic_address(struct acpi_generic_address *addr) { void __iomem *virt; @@ -413,9 +413,8 @@ int acpi_os_map_generic_address(struct acpi_generic_address *addr) return 0; } -EXPORT_SYMBOL_GPL(acpi_os_map_generic_address); -void acpi_os_unmap_generic_address(struct acpi_generic_address *addr) +static void acpi_os_unmap_generic_address(struct acpi_generic_address *addr) { void __iomem *virt; unsigned long flags; @@ -433,7 +432,6 @@ void acpi_os_unmap_generic_address(struct acpi_generic_address *addr) acpi_os_unmap_memory(virt, size); } -EXPORT_SYMBOL_GPL(acpi_os_unmap_generic_address); #ifdef ACPI_FUTURE_USAGE acpi_status diff --git a/include/linux/acpi_io.h b/include/linux/acpi_io.h index 7180013a4a3ae..28a3ae279d7ab 100644 --- a/include/linux/acpi_io.h +++ b/include/linux/acpi_io.h @@ -10,7 +10,4 @@ static inline void __iomem *acpi_os_ioremap(acpi_physical_address phys, return ioremap_cache(phys, size); } -int acpi_os_map_generic_address(struct acpi_generic_address *addr); -void acpi_os_unmap_generic_address(struct acpi_generic_address *addr); - #endif -- GitLab From 7bbb890358b96cb6f77adc6815f2072bdf813d5d Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Tue, 8 Feb 2011 23:37:42 +0100 Subject: [PATCH 0196/2822] ACPI: Change acpi_ioremap_lock into a mutex There's no reason why acpi_ioremap_lock has to be a spinlock, because all of the functions it is used in may sleep anyway and there's no reason why it should be locked with interrupts off. Use a mutex instead (that's going to allow us to put some more operations under the lock later). Signed-off-by: Rafael J. Wysocki --- drivers/acpi/osl.c | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index ff2189d3fa064..97061928249a5 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c @@ -109,7 +109,7 @@ struct acpi_ioremap { }; static LIST_HEAD(acpi_ioremaps); -static DEFINE_SPINLOCK(acpi_ioremap_lock); +static DEFINE_MUTEX(acpi_ioremap_lock); static void __init acpi_osi_setup_late(void); @@ -303,7 +303,6 @@ void __iomem *__init_refok acpi_os_map_memory(acpi_physical_address phys, acpi_size size) { struct acpi_ioremap *map, *tmp_map; - unsigned long flags; void __iomem *virt; acpi_physical_address pg_off; acpi_size pg_sz; @@ -334,18 +333,18 @@ acpi_os_map_memory(acpi_physical_address phys, acpi_size size) map->size = pg_sz; kref_init(&map->ref); - spin_lock_irqsave(&acpi_ioremap_lock, flags); + mutex_lock(&acpi_ioremap_lock); /* Check if page has already been mapped. */ tmp_map = acpi_map_lookup(phys, size); if (tmp_map) { kref_get(&tmp_map->ref); - spin_unlock_irqrestore(&acpi_ioremap_lock, flags); + mutex_unlock(&acpi_ioremap_lock); iounmap(map->virt); kfree(map); return tmp_map->virt + (phys - tmp_map->phys); } list_add_tail_rcu(&map->list, &acpi_ioremaps); - spin_unlock_irqrestore(&acpi_ioremap_lock, flags); + mutex_unlock(&acpi_ioremap_lock); return map->virt + (phys - map->phys); } @@ -362,7 +361,6 @@ static void acpi_kref_del_iomap(struct kref *ref) void __ref acpi_os_unmap_memory(void __iomem *virt, acpi_size size) { struct acpi_ioremap *map; - unsigned long flags; int del; if (!acpi_gbl_permanent_mmap) { @@ -370,17 +368,17 @@ void __ref acpi_os_unmap_memory(void __iomem *virt, acpi_size size) return; } - spin_lock_irqsave(&acpi_ioremap_lock, flags); + mutex_lock(&acpi_ioremap_lock); map = acpi_map_lookup_virt(virt, size); if (!map) { - spin_unlock_irqrestore(&acpi_ioremap_lock, flags); + mutex_unlock(&acpi_ioremap_lock); printk(KERN_ERR PREFIX "%s: bad address %p\n", __func__, virt); dump_stack(); return; } del = kref_put(&map->ref, acpi_kref_del_iomap); - spin_unlock_irqrestore(&acpi_ioremap_lock, flags); + mutex_unlock(&acpi_ioremap_lock); if (!del) return; @@ -417,7 +415,6 @@ static int acpi_os_map_generic_address(struct acpi_generic_address *addr) static void acpi_os_unmap_generic_address(struct acpi_generic_address *addr) { void __iomem *virt; - unsigned long flags; acpi_size size = addr->bit_width / 8; if (addr->space_id != ACPI_ADR_SPACE_SYSTEM_MEMORY) @@ -426,9 +423,9 @@ static void acpi_os_unmap_generic_address(struct acpi_generic_address *addr) if (!addr->address || !addr->bit_width) return; - spin_lock_irqsave(&acpi_ioremap_lock, flags); + mutex_lock(&acpi_ioremap_lock); virt = acpi_map_vaddr_lookup(addr->address, size); - spin_unlock_irqrestore(&acpi_ioremap_lock, flags); + mutex_unlock(&acpi_ioremap_lock); acpi_os_unmap_memory(virt, size); } -- GitLab From 7fe135dc058faea0ce319a03e3b6f98c5049955c Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Tue, 8 Feb 2011 23:37:53 +0100 Subject: [PATCH 0197/2822] ACPI: Avoid walking the list of memory mappings in osl.c twice in a row Make acpi_os_unmap_generic_address() use acpi_map_lookup() to find the desired iomap and drop the reference to it directly (and eventually remove it if necessary) instead of calling acpi_os_unmap_memory(), which requires us to walk the list of ACPI iomaps twice in a row (first, to get the virtual address associated with the iomap and second, to get the iomap itself). Signed-off-by: Rafael J. Wysocki --- drivers/acpi/osl.c | 33 ++++++++++++++++++++------------- 1 file changed, 20 insertions(+), 13 deletions(-) diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index 97061928249a5..f6785bced215b 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c @@ -358,6 +358,13 @@ static void acpi_kref_del_iomap(struct kref *ref) list_del_rcu(&map->list); } +static void acpi_os_remove_map(struct acpi_ioremap *map) +{ + synchronize_rcu(); + iounmap(map->virt); + kfree(map); +} + void __ref acpi_os_unmap_memory(void __iomem *virt, acpi_size size) { struct acpi_ioremap *map; @@ -372,20 +379,14 @@ void __ref acpi_os_unmap_memory(void __iomem *virt, acpi_size size) map = acpi_map_lookup_virt(virt, size); if (!map) { mutex_unlock(&acpi_ioremap_lock); - printk(KERN_ERR PREFIX "%s: bad address %p\n", __func__, virt); - dump_stack(); + WARN(true, PREFIX "%s: bad address %p\n", __func__, virt); return; } - del = kref_put(&map->ref, acpi_kref_del_iomap); mutex_unlock(&acpi_ioremap_lock); - if (!del) - return; - - synchronize_rcu(); - iounmap(map->virt); - kfree(map); + if (del) + acpi_os_remove_map(map); } EXPORT_SYMBOL_GPL(acpi_os_unmap_memory); @@ -414,8 +415,8 @@ static int acpi_os_map_generic_address(struct acpi_generic_address *addr) static void acpi_os_unmap_generic_address(struct acpi_generic_address *addr) { - void __iomem *virt; - acpi_size size = addr->bit_width / 8; + struct acpi_ioremap *map; + int del; if (addr->space_id != ACPI_ADR_SPACE_SYSTEM_MEMORY) return; @@ -424,10 +425,16 @@ static void acpi_os_unmap_generic_address(struct acpi_generic_address *addr) return; mutex_lock(&acpi_ioremap_lock); - virt = acpi_map_vaddr_lookup(addr->address, size); + map = acpi_map_lookup(addr->address, addr->bit_width / 8); + if (!map) { + mutex_unlock(&acpi_ioremap_lock); + return; + } + del = kref_put(&map->ref, acpi_kref_del_iomap); mutex_unlock(&acpi_ioremap_lock); - acpi_os_unmap_memory(virt, size); + if (del) + acpi_os_remove_map(map); } #ifdef ACPI_FUTURE_USAGE -- GitLab From 7ffd0443f2502478545e23e194b7eb8e16376072 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Tue, 8 Feb 2011 23:38:05 +0100 Subject: [PATCH 0198/2822] ACPI: Make acpi_os_map_memory() avoid creating unnecessary mappings Modify acpi_os_map_memory() so that it doesn't call acpi_os_ioremap() unconditionally every time it is executed (except when acpi_gbl_permanent_mmap is unset), which pretty much defeats the purpose of maintaining the list of ACPI iomaps in osl.c. Signed-off-by: Rafael J. Wysocki --- drivers/acpi/osl.c | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index f6785bced215b..445f205752a24 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c @@ -302,7 +302,7 @@ acpi_map_lookup_virt(void __iomem *virt, acpi_size size) void __iomem *__init_refok acpi_os_map_memory(acpi_physical_address phys, acpi_size size) { - struct acpi_ioremap *map, *tmp_map; + struct acpi_ioremap *map; void __iomem *virt; acpi_physical_address pg_off; acpi_size pg_sz; @@ -315,14 +315,25 @@ acpi_os_map_memory(acpi_physical_address phys, acpi_size size) if (!acpi_gbl_permanent_mmap) return __acpi_map_table((unsigned long)phys, size); + mutex_lock(&acpi_ioremap_lock); + /* Check if there's a suitable mapping already. */ + map = acpi_map_lookup(phys, size); + if (map) { + kref_get(&map->ref); + goto out; + } + map = kzalloc(sizeof(*map), GFP_KERNEL); - if (!map) + if (!map) { + mutex_unlock(&acpi_ioremap_lock); return NULL; + } pg_off = round_down(phys, PAGE_SIZE); pg_sz = round_up(phys + size, PAGE_SIZE) - pg_off; virt = acpi_os_ioremap(pg_off, pg_sz); if (!virt) { + mutex_unlock(&acpi_ioremap_lock); kfree(map); return NULL; } @@ -333,19 +344,10 @@ acpi_os_map_memory(acpi_physical_address phys, acpi_size size) map->size = pg_sz; kref_init(&map->ref); - mutex_lock(&acpi_ioremap_lock); - /* Check if page has already been mapped. */ - tmp_map = acpi_map_lookup(phys, size); - if (tmp_map) { - kref_get(&tmp_map->ref); - mutex_unlock(&acpi_ioremap_lock); - iounmap(map->virt); - kfree(map); - return tmp_map->virt + (phys - tmp_map->phys); - } list_add_tail_rcu(&map->list, &acpi_ioremaps); - mutex_unlock(&acpi_ioremap_lock); + out: + mutex_unlock(&acpi_ioremap_lock); return map->virt + (phys - map->phys); } EXPORT_SYMBOL_GPL(acpi_os_map_memory); -- GitLab From b7c1fadd6c2eead56d0664a3a921980120de0c11 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Tue, 8 Feb 2011 23:38:15 +0100 Subject: [PATCH 0199/2822] ACPI: Do not use krefs under a mutex in osl.c The reference counting of ACPI iomaps is carried out entirely under acpi_ioremap_lock, so it is sufficient to use simple counters instead of krefs for this purpose. Signed-off-by: Rafael J. Wysocki --- drivers/acpi/osl.c | 36 ++++++++++++++++-------------------- 1 file changed, 16 insertions(+), 20 deletions(-) diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index 445f205752a24..5389f9f2e2ffd 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c @@ -105,7 +105,7 @@ struct acpi_ioremap { void __iomem *virt; acpi_physical_address phys; acpi_size size; - struct kref ref; + unsigned long refcount; }; static LIST_HEAD(acpi_ioremaps); @@ -319,7 +319,7 @@ acpi_os_map_memory(acpi_physical_address phys, acpi_size size) /* Check if there's a suitable mapping already. */ map = acpi_map_lookup(phys, size); if (map) { - kref_get(&map->ref); + map->refcount++; goto out; } @@ -342,7 +342,7 @@ acpi_os_map_memory(acpi_physical_address phys, acpi_size size) map->virt = virt; map->phys = pg_off; map->size = pg_sz; - kref_init(&map->ref); + map->refcount = 1; list_add_tail_rcu(&map->list, &acpi_ioremaps); @@ -352,25 +352,24 @@ acpi_os_map_memory(acpi_physical_address phys, acpi_size size) } EXPORT_SYMBOL_GPL(acpi_os_map_memory); -static void acpi_kref_del_iomap(struct kref *ref) +static void acpi_os_drop_map_ref(struct acpi_ioremap *map) { - struct acpi_ioremap *map; - - map = container_of(ref, struct acpi_ioremap, ref); - list_del_rcu(&map->list); + if (!--map->refcount) + list_del_rcu(&map->list); } -static void acpi_os_remove_map(struct acpi_ioremap *map) +static void acpi_os_map_cleanup(struct acpi_ioremap *map) { - synchronize_rcu(); - iounmap(map->virt); - kfree(map); + if (!map->refcount) { + synchronize_rcu(); + iounmap(map->virt); + kfree(map); + } } void __ref acpi_os_unmap_memory(void __iomem *virt, acpi_size size) { struct acpi_ioremap *map; - int del; if (!acpi_gbl_permanent_mmap) { __acpi_unmap_table(virt, size); @@ -384,11 +383,10 @@ void __ref acpi_os_unmap_memory(void __iomem *virt, acpi_size size) WARN(true, PREFIX "%s: bad address %p\n", __func__, virt); return; } - del = kref_put(&map->ref, acpi_kref_del_iomap); + acpi_os_drop_map_ref(map); mutex_unlock(&acpi_ioremap_lock); - if (del) - acpi_os_remove_map(map); + acpi_os_map_cleanup(map); } EXPORT_SYMBOL_GPL(acpi_os_unmap_memory); @@ -418,7 +416,6 @@ static int acpi_os_map_generic_address(struct acpi_generic_address *addr) static void acpi_os_unmap_generic_address(struct acpi_generic_address *addr) { struct acpi_ioremap *map; - int del; if (addr->space_id != ACPI_ADR_SPACE_SYSTEM_MEMORY) return; @@ -432,11 +429,10 @@ static void acpi_os_unmap_generic_address(struct acpi_generic_address *addr) mutex_unlock(&acpi_ioremap_lock); return; } - del = kref_put(&map->ref, acpi_kref_del_iomap); + acpi_os_drop_map_ref(map); mutex_unlock(&acpi_ioremap_lock); - if (del) - acpi_os_remove_map(map); + acpi_os_map_cleanup(map); } #ifdef ACPI_FUTURE_USAGE -- GitLab From 13606a2de1996f8d83a9ce296f74022bdbadf712 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Tue, 8 Feb 2011 23:38:25 +0100 Subject: [PATCH 0200/2822] ACPI: Introduce acpi_os_get_iomem() Introduce function acpi_os_get_iomem() that may be used by its callers to get a reference to an ACPI iomap. Signed-off-by: Rafael J. Wysocki --- drivers/acpi/osl.c | 16 ++++++++++++++++ include/linux/acpi_io.h | 2 ++ 2 files changed, 18 insertions(+) diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index 5389f9f2e2ffd..52ca8721bc9c9 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c @@ -285,6 +285,22 @@ acpi_map_vaddr_lookup(acpi_physical_address phys, unsigned int size) return NULL; } +void __iomem *acpi_os_get_iomem(acpi_physical_address phys, unsigned int size) +{ + struct acpi_ioremap *map; + void __iomem *virt = NULL; + + mutex_lock(&acpi_ioremap_lock); + map = acpi_map_lookup(phys, size); + if (map) { + virt = map->virt + (phys - map->phys); + map->refcount++; + } + mutex_unlock(&acpi_ioremap_lock); + return virt; +} +EXPORT_SYMBOL_GPL(acpi_os_get_iomem); + /* Must be called with 'acpi_ioremap_lock' or RCU read lock held. */ static struct acpi_ioremap * acpi_map_lookup_virt(void __iomem *virt, acpi_size size) diff --git a/include/linux/acpi_io.h b/include/linux/acpi_io.h index 28a3ae279d7ab..4afd7102459d7 100644 --- a/include/linux/acpi_io.h +++ b/include/linux/acpi_io.h @@ -10,4 +10,6 @@ static inline void __iomem *acpi_os_ioremap(acpi_physical_address phys, return ioremap_cache(phys, size); } +void __iomem *acpi_os_get_iomem(acpi_physical_address phys, unsigned int size); + #endif -- GitLab From bb45e394e21eb2abc710ad43d98ebac1069bf355 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Tue, 8 Feb 2011 23:38:38 +0100 Subject: [PATCH 0201/2822] ACPI / PM: Use existing ACPI iomaps for NVS save/restore (v2) Modify the NVS save/restore code to use acpi_os_get_iomem() and acpi_os_unmap_memory() to acquire and release references to ACPI iomaps, respectively. If there's no ACPI iomap corresponding to the given NVS page, acpi_os_ioremap() is used to map that page and iounmap() is used to unmap it during resume. [If the page is not present in the ACPI iomaps already, it doesn't make sense to add its mapping to the list of ACPI iomaps, because it's going to be thrown away during the subsequent resume anyway.] Testing on my HP nx6325 shows that approx. 90% of the NVS pages have already been mapped by ACPI before suspend and are present in the ACPI iomaps, so this change appears to be the right thing to do in general. Signed-off-by: Rafael J. Wysocki --- drivers/acpi/nvs.c | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/drivers/acpi/nvs.c b/drivers/acpi/nvs.c index fa5a1df42b79a..096787b43c960 100644 --- a/drivers/acpi/nvs.c +++ b/drivers/acpi/nvs.c @@ -26,6 +26,7 @@ struct nvs_page { unsigned int size; void *kaddr; void *data; + bool unmap; struct list_head node; }; @@ -44,6 +45,9 @@ int suspend_nvs_register(unsigned long start, unsigned long size) { struct nvs_page *entry, *next; + pr_info("PM: Registering ACPI NVS region at %lx (%ld bytes)\n", + start, size); + while (size > 0) { unsigned int nr_bytes; @@ -81,7 +85,13 @@ void suspend_nvs_free(void) free_page((unsigned long)entry->data); entry->data = NULL; if (entry->kaddr) { - iounmap(entry->kaddr); + if (entry->unmap) { + iounmap(entry->kaddr); + entry->unmap = false; + } else { + acpi_os_unmap_memory(entry->kaddr, + entry->size); + } entry->kaddr = NULL; } } @@ -115,8 +125,14 @@ int suspend_nvs_save(void) list_for_each_entry(entry, &nvs_list, node) if (entry->data) { - entry->kaddr = acpi_os_ioremap(entry->phys_start, - entry->size); + unsigned long phys = entry->phys_start; + unsigned int size = entry->size; + + entry->kaddr = acpi_os_get_iomem(phys, size); + if (!entry->kaddr) { + entry->kaddr = acpi_os_ioremap(phys, size); + entry->unmap = !!entry->kaddr; + } if (!entry->kaddr) { suspend_nvs_free(); return -ENOMEM; -- GitLab From 5190726765b40774c069e187a958e10ccd970e65 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Tue, 8 Feb 2011 23:40:37 +0100 Subject: [PATCH 0202/2822] ACPI: Remove the wakeup.run_wake_count device field The wakeup.run_wake_count ACPI device field is only used by the PCI runtime PM code to "protect" devices from being prepared for generating wakeup signals more than once in a row. However, it really doesn't provide any protection, because (1) all of the functions it is supposed to protect use their own reference counters effectively ensuring that the device will be set up for generating wakeup signals just once and (2) the PCI runtime PM code uses wakeup.run_wake_count in a racy way, since nothing prevents acpi_dev_run_wake() from being called concurrently from two different threads for the same device. Remove the wakeup.run_wake_count ACPI device field which is unnecessary, confusing and used in a wrong way. Signed-off-by: Rafael J. Wysocki --- drivers/acpi/button.c | 2 -- drivers/acpi/scan.c | 1 - drivers/pci/pci-acpi.c | 16 ++++------------ include/acpi/acpi_bus.h | 1 - 4 files changed, 4 insertions(+), 16 deletions(-) diff --git a/drivers/acpi/button.c b/drivers/acpi/button.c index 76bbb78a5ad95..e643a0936dc4b 100644 --- a/drivers/acpi/button.c +++ b/drivers/acpi/button.c @@ -430,7 +430,6 @@ static int acpi_button_add(struct acpi_device *device) /* Button's GPE is run-wake GPE */ acpi_enable_gpe(device->wakeup.gpe_device, device->wakeup.gpe_number); - device->wakeup.run_wake_count++; device_set_wakeup_enable(&device->dev, true); } @@ -453,7 +452,6 @@ static int acpi_button_remove(struct acpi_device *device, int type) if (device->wakeup.flags.valid) { acpi_disable_gpe(device->wakeup.gpe_device, device->wakeup.gpe_number); - device->wakeup.run_wake_count--; device_set_wakeup_enable(&device->dev, false); } diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index b99e624946074..b136c9c1e5319 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -797,7 +797,6 @@ static void acpi_bus_set_run_wake_flags(struct acpi_device *device) acpi_status status; acpi_event_status event_status; - device->wakeup.run_wake_count = 0; device->wakeup.flags.notifier_present = 0; /* Power button, Lid switch always enable wakeup */ diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c index 6fe0772e0e7de..7c3b18e78cee1 100644 --- a/drivers/pci/pci-acpi.c +++ b/drivers/pci/pci-acpi.c @@ -293,19 +293,11 @@ static int acpi_dev_run_wake(struct device *phys_dev, bool enable) } if (enable) { - if (!dev->wakeup.run_wake_count++) { - acpi_enable_wakeup_device_power(dev, ACPI_STATE_S0); - acpi_enable_gpe(dev->wakeup.gpe_device, - dev->wakeup.gpe_number); - } - } else if (dev->wakeup.run_wake_count > 0) { - if (!--dev->wakeup.run_wake_count) { - acpi_disable_gpe(dev->wakeup.gpe_device, - dev->wakeup.gpe_number); - acpi_disable_wakeup_device_power(dev); - } + acpi_enable_wakeup_device_power(dev, ACPI_STATE_S0); + acpi_enable_gpe(dev->wakeup.gpe_device, dev->wakeup.gpe_number); } else { - error = -EALREADY; + acpi_disable_gpe(dev->wakeup.gpe_device, dev->wakeup.gpe_number); + acpi_disable_wakeup_device_power(dev); } return error; diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h index 78ca429929f74..f50ebb9bc53b8 100644 --- a/include/acpi/acpi_bus.h +++ b/include/acpi/acpi_bus.h @@ -250,7 +250,6 @@ struct acpi_device_wakeup { struct acpi_handle_list resources; struct acpi_device_wakeup_flags flags; int prepare_count; - int run_wake_count; }; /* Device */ -- GitLab From c19f9a84ec807da57fd75bbd9a3f2b8269611f79 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Tue, 8 Feb 2011 23:41:13 +0100 Subject: [PATCH 0203/2822] ACPI / Button: Avoid disabling wakeup unnecessarily on remove If a button device had already been enabled to wake up the system from sleep states before the button driver saw it, the driver shouldn't disable the device's wakeup capability when being detached from the device. Signed-off-by: Rafael J. Wysocki --- drivers/acpi/button.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/acpi/button.c b/drivers/acpi/button.c index e643a0936dc4b..12c28f4adb671 100644 --- a/drivers/acpi/button.c +++ b/drivers/acpi/button.c @@ -98,6 +98,7 @@ struct acpi_button { struct input_dev *input; char phys[32]; /* for input device */ unsigned long pushed; + bool wakeup_enabled; }; static const struct file_operations acpi_button_info_fops = { @@ -430,7 +431,10 @@ static int acpi_button_add(struct acpi_device *device) /* Button's GPE is run-wake GPE */ acpi_enable_gpe(device->wakeup.gpe_device, device->wakeup.gpe_number); - device_set_wakeup_enable(&device->dev, true); + if (!device_may_wakeup(&device->dev)) { + device_set_wakeup_enable(&device->dev, true); + button->wakeup_enabled = true; + } } printk(KERN_INFO PREFIX "%s [%s]\n", name, acpi_device_bid(device)); @@ -452,7 +456,8 @@ static int acpi_button_remove(struct acpi_device *device, int type) if (device->wakeup.flags.valid) { acpi_disable_gpe(device->wakeup.gpe_device, device->wakeup.gpe_number); - device_set_wakeup_enable(&device->dev, false); + if (button->wakeup_enabled) + device_set_wakeup_enable(&device->dev, false); } acpi_button_remove_fs(device); -- GitLab From c41b93fb8551148a93d3bba870365e8489317f02 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Tue, 8 Feb 2011 23:41:35 +0100 Subject: [PATCH 0204/2822] ACPI / PM: Drop acpi_restore_state_mem() The function acpi_restore_state_mem() has never been and most likely never will be used, so remove it. Signed-off-by: Rafael J. Wysocki --- arch/ia64/include/asm/acpi.h | 4 ++-- arch/ia64/kernel/acpi.c | 5 ----- arch/x86/include/asm/acpi.h | 3 +-- arch/x86/kernel/acpi/sleep.c | 8 -------- drivers/acpi/sleep.c | 4 ---- 5 files changed, 3 insertions(+), 21 deletions(-) diff --git a/arch/ia64/include/asm/acpi.h b/arch/ia64/include/asm/acpi.h index 837dc82a013eb..db3986a71af8c 100644 --- a/arch/ia64/include/asm/acpi.h +++ b/arch/ia64/include/asm/acpi.h @@ -128,9 +128,9 @@ static inline const char *acpi_get_sysname (void) int acpi_request_vector (u32 int_type); int acpi_gsi_to_irq (u32 gsi, unsigned int *irq); -/* routines for saving/restoring kernel state */ +/* Routine for saving kernel state during suspend. */ extern int acpi_save_state_mem(void); -extern void acpi_restore_state_mem(void); + extern unsigned long acpi_wakeup_address; /* diff --git a/arch/ia64/kernel/acpi.c b/arch/ia64/kernel/acpi.c index 90ebceb899a08..7cf2d10c0677a 100644 --- a/arch/ia64/kernel/acpi.c +++ b/arch/ia64/kernel/acpi.c @@ -1040,11 +1040,6 @@ EXPORT_SYMBOL(acpi_unregister_ioapic); */ int acpi_save_state_mem(void) { return 0; } -/* - * acpi_restore_state() - */ -void acpi_restore_state_mem(void) {} - /* * do_suspend_lowlevel() */ diff --git a/arch/x86/include/asm/acpi.h b/arch/x86/include/asm/acpi.h index 211ca3f7fd16f..47981f0d121b5 100644 --- a/arch/x86/include/asm/acpi.h +++ b/arch/x86/include/asm/acpi.h @@ -112,9 +112,8 @@ static inline void acpi_disable_pci(void) acpi_noirq_set(); } -/* routines for saving/restoring kernel state */ +/* Routine for saving kernel state during suspend. */ extern int acpi_save_state_mem(void); -extern void acpi_restore_state_mem(void); extern unsigned long acpi_wakeup_address; diff --git a/arch/x86/kernel/acpi/sleep.c b/arch/x86/kernel/acpi/sleep.c index 68d1537b8c812..c27a483094b1a 100644 --- a/arch/x86/kernel/acpi/sleep.c +++ b/arch/x86/kernel/acpi/sleep.c @@ -110,14 +110,6 @@ int acpi_save_state_mem(void) return 0; } -/* - * acpi_restore_state - undo effects of acpi_save_state_mem - */ -void acpi_restore_state_mem(void) -{ -} - - /** * acpi_reserve_wakeup_memory - do _very_ early ACPI initialisation * diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c index d6a8cd14de2e8..67dcd38865632 100644 --- a/drivers/acpi/sleep.c +++ b/drivers/acpi/sleep.c @@ -293,10 +293,6 @@ static int acpi_suspend_enter(suspend_state_t pm_state) local_irq_restore(flags); printk(KERN_DEBUG "Back to C!\n"); - /* restore processor state */ - if (acpi_state == ACPI_STATE_S3) - acpi_restore_state_mem(); - suspend_nvs_restore(); return ACPI_SUCCESS(status) ? 0 : -EFAULT; -- GitLab From 82911fe1988fadfc9c01673202cbc411aa803244 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Tue, 8 Feb 2011 23:41:47 +0100 Subject: [PATCH 0205/2822] ACPI / PM: acpi_suspend_enter() need not switch interrupts off The function acpi_suspend_enter() is always called with interrupts off, so it doesn't need to switch them off and on. Signed-off-by: Rafael J. Wysocki --- drivers/acpi/sleep.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c index 67dcd38865632..3b549379801a6 100644 --- a/drivers/acpi/sleep.c +++ b/drivers/acpi/sleep.c @@ -243,7 +243,6 @@ static int acpi_suspend_begin(suspend_state_t pm_state) static int acpi_suspend_enter(suspend_state_t pm_state) { acpi_status status = AE_OK; - unsigned long flags = 0; u32 acpi_state = acpi_target_sleep_state; ACPI_FLUSH_CPU_CACHE(); @@ -256,7 +255,6 @@ static int acpi_suspend_enter(suspend_state_t pm_state) return error; } - local_irq_save(flags); switch (acpi_state) { case ACPI_STATE_S1: barrier(); @@ -290,7 +288,6 @@ static int acpi_suspend_enter(suspend_state_t pm_state) /* Allow EC transactions to happen. */ acpi_ec_unblock_transactions_early(); - local_irq_restore(flags); printk(KERN_DEBUG "Back to C!\n"); suspend_nvs_restore(); -- GitLab From 7a63f08b2b904d25e966dd0e15c9af4a13c80b90 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Tue, 8 Feb 2011 23:41:57 +0100 Subject: [PATCH 0206/2822] ACPI / PM: Modify the "low-level resume finished" message Move the low-level resume completion message to the point where control goes back to acpi_suspend_enter() during resume and change it so that it's more informative. Signed-off-by: Rafael J. Wysocki --- drivers/acpi/sleep.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c index 3b549379801a6..6bea2fe8434b3 100644 --- a/drivers/acpi/sleep.c +++ b/drivers/acpi/sleep.c @@ -263,6 +263,7 @@ static int acpi_suspend_enter(suspend_state_t pm_state) case ACPI_STATE_S3: do_suspend_lowlevel(); + pr_info(PREFIX "Low-level resume complete\n"); break; } @@ -288,8 +289,6 @@ static int acpi_suspend_enter(suspend_state_t pm_state) /* Allow EC transactions to happen. */ acpi_ec_unblock_transactions_early(); - printk(KERN_DEBUG "Back to C!\n"); - suspend_nvs_restore(); return ACPI_SUCCESS(status) ? 0 : -EFAULT; -- GitLab From 979f11b060c0b35b03b86ae854d6f21a710305d0 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Tue, 8 Feb 2011 23:42:09 +0100 Subject: [PATCH 0207/2822] ACPI / PM: Call acpi_save_state_mem() right before low-level suspend Since acpi_save_state_mem() is only called by acpi_suspend_enter() if the target sleep state is S3, it's better to call it under the switch (acpi_state), right before do_suspend_lowlevel(). Signed-off-by: Rafael J. Wysocki --- drivers/acpi/sleep.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c index 6bea2fe8434b3..2307604064b3b 100644 --- a/drivers/acpi/sleep.c +++ b/drivers/acpi/sleep.c @@ -244,17 +244,10 @@ static int acpi_suspend_enter(suspend_state_t pm_state) { acpi_status status = AE_OK; u32 acpi_state = acpi_target_sleep_state; + int error; ACPI_FLUSH_CPU_CACHE(); - /* Do arch specific saving of state. */ - if (acpi_state == ACPI_STATE_S3) { - int error = acpi_save_state_mem(); - - if (error) - return error; - } - switch (acpi_state) { case ACPI_STATE_S1: barrier(); @@ -262,6 +255,9 @@ static int acpi_suspend_enter(suspend_state_t pm_state) break; case ACPI_STATE_S3: + error = acpi_save_state_mem(); + if (error) + return error; do_suspend_lowlevel(); pr_info(PREFIX "Low-level resume complete\n"); break; -- GitLab From f1a2003e22f6b50ea21f7f4b38b38c5ebc9c8017 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Tue, 8 Feb 2011 23:42:22 +0100 Subject: [PATCH 0208/2822] ACPI / PM: Merge do_suspend_lowlevel() into acpi_save_state_mem() The function do_suspend_lowlevel() is specific to x86 and defined in assembly code, so it should be called from the x86 low-level suspend code rather than from acpi_suspend_enter(). Merge do_suspend_lowlevel() into the x86's acpi_save_state_mem() and change the name of the latter to acpi_suspend_lowlevel(), so that the function's purpose is better reflected by its name. Signed-off-by: Rafael J. Wysocki --- arch/ia64/include/asm/acpi.h | 4 ++-- arch/ia64/kernel/acpi.c | 9 ++------- arch/x86/include/asm/acpi.h | 4 ++-- arch/x86/kernel/acpi/sleep.c | 5 +++-- arch/x86/kernel/acpi/sleep.h | 2 ++ drivers/acpi/sleep.c | 5 +---- 6 files changed, 12 insertions(+), 17 deletions(-) diff --git a/arch/ia64/include/asm/acpi.h b/arch/ia64/include/asm/acpi.h index db3986a71af8c..a06dfb13d518c 100644 --- a/arch/ia64/include/asm/acpi.h +++ b/arch/ia64/include/asm/acpi.h @@ -128,8 +128,8 @@ static inline const char *acpi_get_sysname (void) int acpi_request_vector (u32 int_type); int acpi_gsi_to_irq (u32 gsi, unsigned int *irq); -/* Routine for saving kernel state during suspend. */ -extern int acpi_save_state_mem(void); +/* Low-level suspend routine. */ +extern int acpi_suspend_lowlevel(void); extern unsigned long acpi_wakeup_address; diff --git a/arch/ia64/kernel/acpi.c b/arch/ia64/kernel/acpi.c index 7cf2d10c0677a..a54d054ed4b0f 100644 --- a/arch/ia64/kernel/acpi.c +++ b/arch/ia64/kernel/acpi.c @@ -1034,13 +1034,8 @@ int acpi_unregister_ioapic(acpi_handle handle, u32 gsi_base) EXPORT_SYMBOL(acpi_unregister_ioapic); /* - * acpi_save_state_mem() - save kernel state + * acpi_suspend_lowlevel() - save kernel state and suspend. * * TBD when when IA64 starts to support suspend... */ -int acpi_save_state_mem(void) { return 0; } - -/* - * do_suspend_lowlevel() - */ -void do_suspend_lowlevel(void) {} +int acpi_suspend_lowlevel(void) { return 0; } diff --git a/arch/x86/include/asm/acpi.h b/arch/x86/include/asm/acpi.h index 47981f0d121b5..aa92684aa6747 100644 --- a/arch/x86/include/asm/acpi.h +++ b/arch/x86/include/asm/acpi.h @@ -112,8 +112,8 @@ static inline void acpi_disable_pci(void) acpi_noirq_set(); } -/* Routine for saving kernel state during suspend. */ -extern int acpi_save_state_mem(void); +/* Low-level suspend routine. */ +extern int acpi_suspend_lowlevel(void); extern unsigned long acpi_wakeup_address; diff --git a/arch/x86/kernel/acpi/sleep.c b/arch/x86/kernel/acpi/sleep.c index c27a483094b1a..5f1b747f6ef1b 100644 --- a/arch/x86/kernel/acpi/sleep.c +++ b/arch/x86/kernel/acpi/sleep.c @@ -29,14 +29,14 @@ static char temp_stack[4096]; #endif /** - * acpi_save_state_mem - save kernel state + * acpi_suspend_lowlevel - save kernel state * * Create an identity mapped page table and copy the wakeup routine to * low memory. * * Note that this is too late to change acpi_wakeup_address. */ -int acpi_save_state_mem(void) +int acpi_suspend_lowlevel(void) { struct wakeup_header *header; @@ -107,6 +107,7 @@ int acpi_save_state_mem(void) saved_magic = 0x123456789abcdef0L; #endif /* CONFIG_64BIT */ + do_suspend_lowlevel(); return 0; } diff --git a/arch/x86/kernel/acpi/sleep.h b/arch/x86/kernel/acpi/sleep.h index adbcbaa6f1df6..31ce13f20297f 100644 --- a/arch/x86/kernel/acpi/sleep.h +++ b/arch/x86/kernel/acpi/sleep.h @@ -14,3 +14,5 @@ extern char swsusp_pg_dir[PAGE_SIZE]; extern unsigned long acpi_copy_wakeup_routine(unsigned long); extern void wakeup_long64(void); + +extern void do_suspend_lowlevel(void); diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c index 2307604064b3b..0a81bf11f4739 100644 --- a/drivers/acpi/sleep.c +++ b/drivers/acpi/sleep.c @@ -199,8 +199,6 @@ static void acpi_pm_end(void) #endif /* CONFIG_ACPI_SLEEP */ #ifdef CONFIG_SUSPEND -extern void do_suspend_lowlevel(void); - static u32 acpi_suspend_states[] = { [PM_SUSPEND_ON] = ACPI_STATE_S0, [PM_SUSPEND_STANDBY] = ACPI_STATE_S1, @@ -255,10 +253,9 @@ static int acpi_suspend_enter(suspend_state_t pm_state) break; case ACPI_STATE_S3: - error = acpi_save_state_mem(); + error = acpi_suspend_lowlevel(); if (error) return error; - do_suspend_lowlevel(); pr_info(PREFIX "Low-level resume complete\n"); break; } -- GitLab From aad83b143008e1d406248803550bfbfc600b6398 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Tue, 8 Feb 2011 23:42:35 +0100 Subject: [PATCH 0209/2822] ACPI / PM: acpi_hibernation_enter() need not switch interrupts off The function acpi_hibernation_enter() is always called with interrupts off, so it doesn't need to switch them off and on. Signed-off-by: Rafael J. Wysocki --- drivers/acpi/sleep.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c index 0a81bf11f4739..84f57143ad7c1 100644 --- a/drivers/acpi/sleep.c +++ b/drivers/acpi/sleep.c @@ -457,16 +457,13 @@ static int acpi_hibernation_begin(void) static int acpi_hibernation_enter(void) { acpi_status status = AE_OK; - unsigned long flags = 0; ACPI_FLUSH_CPU_CACHE(); - local_irq_save(flags); /* This shouldn't return. If it returns, we have a problem */ status = acpi_enter_sleep_state(ACPI_STATE_S4); /* Reprogram control registers and execute _BFS */ acpi_leave_sleep_state_prep(ACPI_STATE_S4); - local_irq_restore(flags); return ACPI_SUCCESS(status) ? 0 : -EFAULT; } -- GitLab From 23fe36306ea489eef7dd88506bdcefdc8da39c91 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Tue, 8 Feb 2011 23:48:16 +0100 Subject: [PATCH 0210/2822] ACPI: Avoid calling request_irq() many times for the same interrupt In principle acpi_os_install_interrupt_handler() may be called multiple times for different interrupts, either from acpi_ev_get_gpe_xrupt_block(), or from acpi_ev_install_sci_handler(). However, it always attempts to request the same interrupt, acpi_gbl_FADT.sci_interrupt and it doesn't check whether or not this interrupt has already been requested. Modify this function so that it refuses to request interrupts other than acpi_gbl_FADT.sci_interrupt and change acpi_os_remove_interrupt_handler() so that it refuses to free such interrupts. Use the observation that the only supported ACPI interrupt must be equal to acpi_gbl_FADT.sci_interrupt and drop an unnecessary variable acpi_irq_irq. This change has been tested on Toshiba Portege R500 and HP nx6325 without introducing any visible problems. Signed-off-by: Rafael J. Wysocki --- drivers/acpi/osl.c | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index c90c76aa7f8b7..187dff96356bd 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c @@ -76,7 +76,6 @@ EXPORT_SYMBOL(acpi_in_debugger); extern char line_buf[80]; #endif /*ENABLE_DEBUGGER */ -static unsigned int acpi_irq_irq; static acpi_osd_handler acpi_irq_handler; static void *acpi_irq_context; static struct workqueue_struct *kacpid_wq; @@ -516,11 +515,15 @@ acpi_os_install_interrupt_handler(u32 gsi, acpi_osd_handler handler, acpi_irq_stats_init(); /* - * Ignore the GSI from the core, and use the value in our copy of the - * FADT. It may not be the same if an interrupt source override exists - * for the SCI. + * ACPI interrupts different from the SCI in our copy of the FADT are + * not supported. */ - gsi = acpi_gbl_FADT.sci_interrupt; + if (gsi != acpi_gbl_FADT.sci_interrupt) + return AE_BAD_PARAMETER; + + if (acpi_irq_handler) + return AE_ALREADY_ACQUIRED; + if (acpi_gsi_to_irq(gsi, &irq) < 0) { printk(KERN_ERR PREFIX "SCI (ACPI GSI %d) not registered\n", gsi); @@ -531,20 +534,20 @@ acpi_os_install_interrupt_handler(u32 gsi, acpi_osd_handler handler, acpi_irq_context = context; if (request_irq(irq, acpi_irq, IRQF_SHARED, "acpi", acpi_irq)) { printk(KERN_ERR PREFIX "SCI (IRQ%d) allocation failed\n", irq); + acpi_irq_handler = NULL; return AE_NOT_ACQUIRED; } - acpi_irq_irq = irq; return AE_OK; } acpi_status acpi_os_remove_interrupt_handler(u32 irq, acpi_osd_handler handler) { - if (irq) { - free_irq(irq, acpi_irq); - acpi_irq_handler = NULL; - acpi_irq_irq = 0; - } + if (irq != acpi_gbl_FADT.sci_interrupt) + return AE_BAD_PARAMETER; + + free_irq(irq, acpi_irq); + acpi_irq_handler = NULL; return AE_OK; } @@ -1603,7 +1606,7 @@ acpi_status __init acpi_os_initialize1(void) acpi_status acpi_os_terminate(void) { if (acpi_irq_handler) { - acpi_os_remove_interrupt_handler(acpi_irq_irq, + acpi_os_remove_interrupt_handler(acpi_gbl_FADT.sci_interrupt, acpi_irq_handler); } -- GitLab From 58696f3ab2b23fd6519189875fafdb5d1281eb54 Mon Sep 17 00:00:00 2001 From: Coly Li Date: Thu, 24 Feb 2011 14:10:00 -0500 Subject: [PATCH 0211/2822] ext4: clarify description of ac_g_ex in struct ext4_allocation_context Signed-off-by: Coly Li Cc: Alex Tomas Cc: Theodore Tso --- fs/ext4/mballoc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/ext4/mballoc.h b/fs/ext4/mballoc.h index b619322c76f0c..22bd4d7f289b8 100644 --- a/fs/ext4/mballoc.h +++ b/fs/ext4/mballoc.h @@ -169,7 +169,7 @@ struct ext4_allocation_context { /* original request */ struct ext4_free_extent ac_o_ex; - /* goal request (after normalization) */ + /* goal request (normalized ac_o_ex) */ struct ext4_free_extent ac_g_ex; /* the best found extent */ -- GitLab From 5a54b2f199fdf19533f96c3e285b70c6729e1e4a Mon Sep 17 00:00:00 2001 From: Coly Li Date: Thu, 24 Feb 2011 14:10:05 -0500 Subject: [PATCH 0212/2822] ext4: mballoc: don't replace the current preallocation group unnecessarily In ext4_mb_check_group_pa(), the current preallocation space is replaced with a new preallocation space when the two have the same distance from the goal block. This doesn't actually gain us anything, so change things so that the function only switches to the new preallocation group if its distance from the goal block is strictly smaller than the current preallocaiton group's distance from the goal block. Signed-off-by: Coly Li Signed-off-by: "Theodore Ts'o" --- fs/ext4/mballoc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c index b5235c8a2e78c..66bee7274d6a8 100644 --- a/fs/ext4/mballoc.c +++ b/fs/ext4/mballoc.c @@ -3213,7 +3213,7 @@ ext4_mb_check_group_pa(ext4_fsblk_t goal_block, cur_distance = abs(goal_block - cpa->pa_pstart); new_distance = abs(goal_block - pa->pa_pstart); - if (cur_distance < new_distance) + if (cur_distance <= new_distance) return cpa; /* drop the previous reference */ -- GitLab From 0d3c07378bb7d423302d7cb0dcd3fa5a26c40220 Mon Sep 17 00:00:00 2001 From: Iiro Valkonen Date: Wed, 23 Feb 2011 21:07:20 -0800 Subject: [PATCH 0213/2822] Input: atmel_mxt_ts - remove matrix size check The mxt_check_matrix_size() is currently setting the CTE mode to match xline/yline information that is in the platform data, but it does not take into account for example the fact that we could have a key array in use too (key array would use some x/y lines as well). It would be better to simply rely on the configuration data, and make sure that the CTE mode set in there matches the touch object (touchscreen, key array, proximity) configuration (which are set in the config data too). Signed-off-by: Iiro Valkonen Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/atmel_mxt_ts.c | 73 ------------------------ 1 file changed, 73 deletions(-) diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c index d2e5864ca096a..6264ba80c38cc 100644 --- a/drivers/input/touchscreen/atmel_mxt_ts.c +++ b/drivers/input/touchscreen/atmel_mxt_ts.c @@ -630,74 +630,6 @@ static int mxt_check_reg_init(struct mxt_data *data) return 0; } -static int mxt_check_matrix_size(struct mxt_data *data) -{ - const struct mxt_platform_data *pdata = data->pdata; - struct device *dev = &data->client->dev; - int mode = -1; - int error; - u8 val; - - dev_dbg(dev, "Number of X lines: %d\n", pdata->x_line); - dev_dbg(dev, "Number of Y lines: %d\n", pdata->y_line); - - switch (pdata->x_line) { - case 0 ... 15: - if (pdata->y_line <= 14) - mode = 0; - break; - case 16: - if (pdata->y_line <= 12) - mode = 1; - if (pdata->y_line == 13 || pdata->y_line == 14) - mode = 0; - break; - case 17: - if (pdata->y_line <= 11) - mode = 2; - if (pdata->y_line == 12 || pdata->y_line == 13) - mode = 1; - break; - case 18: - if (pdata->y_line <= 10) - mode = 3; - if (pdata->y_line == 11 || pdata->y_line == 12) - mode = 2; - break; - case 19: - if (pdata->y_line <= 9) - mode = 4; - if (pdata->y_line == 10 || pdata->y_line == 11) - mode = 3; - break; - case 20: - mode = 4; - } - - if (mode < 0) { - dev_err(dev, "Invalid X/Y lines\n"); - return -EINVAL; - } - - error = mxt_read_object(data, MXT_SPT_CTECONFIG, - MXT_CTE_MODE, &val); - if (error) - return error; - - if (mode == val) - return 0; - - /* Change the CTE configuration */ - mxt_write_object(data, MXT_SPT_CTECONFIG, - MXT_CTE_CTRL, 1); - mxt_write_object(data, MXT_SPT_CTECONFIG, - MXT_CTE_MODE, mode); - mxt_write_object(data, MXT_SPT_CTECONFIG, - MXT_CTE_CTRL, 0); - - return 0; -} - static int mxt_make_highchg(struct mxt_data *data) { struct device *dev = &data->client->dev; @@ -864,11 +796,6 @@ static int mxt_initialize(struct mxt_data *data) if (error) return error; - /* Check X/Y matrix size */ - error = mxt_check_matrix_size(data); - if (error) - return error; - error = mxt_make_highchg(data); if (error) return error; -- GitLab From 8fd2af11d2fe1d50621e958747744f1c93e5b758 Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Sun, 23 Jan 2011 12:26:51 +0100 Subject: [PATCH 0214/2822] firewire: nosy: should work on Power Mac G4 PCI too The first board generation of Power Mac G4 ("Yikes!", those with PCI graphics) still had a PCILynx controller like their G3 predecessors, but not the later AGP models. (Jonathan Woithe recalls to have heard of it, and some web sources reinforce it.) Signed-off-by: Stefan Richter --- drivers/firewire/Kconfig | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/firewire/Kconfig b/drivers/firewire/Kconfig index 68f942cb30f26..49009b489f376 100644 --- a/drivers/firewire/Kconfig +++ b/drivers/firewire/Kconfig @@ -77,7 +77,8 @@ config FIREWIRE_NOSY The following cards are known to be based on PCILynx or PCILynx-2: IOI IOI-1394TT (PCI card), Unibrain Fireboard 400 PCI Lynx-2 (PCI card), Newer Technology FireWire 2 Go (CardBus card), - Apple Power Mac G3 blue & white (onboard controller). + Apple Power Mac G3 blue & white and G4 with PCI graphics + (onboard controller). To compile this driver as a module, say M here: The module will be called nosy. Source code of a userspace interface to nosy, called -- GitLab From 5aaffc65a27dd9db65455c2c9ab3ede57238d2f5 Mon Sep 17 00:00:00 2001 From: Clemens Ladisch Date: Mon, 31 Jan 2011 11:58:58 +0100 Subject: [PATCH 0215/2822] firewire: core: rename some variables In manage_channel(), rename the variables "c" and "i" to the more expressive "bit" and "channel". Signed-off-by: Clemens Ladisch Signed-off-by: Stefan Richter --- drivers/firewire/core-iso.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/drivers/firewire/core-iso.c b/drivers/firewire/core-iso.c index c003fa4e2db1f..95bc01a02a88c 100644 --- a/drivers/firewire/core-iso.c +++ b/drivers/firewire/core-iso.c @@ -235,45 +235,45 @@ static int manage_bandwidth(struct fw_card *card, int irm_id, int generation, static int manage_channel(struct fw_card *card, int irm_id, int generation, u32 channels_mask, u64 offset, bool allocate, __be32 data[2]) { - __be32 c, all, old; - int i, ret = -EIO, retry = 5; + __be32 bit, all, old; + int channel, ret = -EIO, retry = 5; old = all = allocate ? cpu_to_be32(~0) : 0; - for (i = 0; i < 32; i++) { - if (!(channels_mask & 1 << i)) + for (channel = 0; channel < 32; channel++) { + if (!(channels_mask & 1 << channel)) continue; ret = -EBUSY; - c = cpu_to_be32(1 << (31 - i)); - if ((old & c) != (all & c)) + bit = cpu_to_be32(1 << (31 - channel)); + if ((old & bit) != (all & bit)) continue; data[0] = old; - data[1] = old ^ c; + data[1] = old ^ bit; switch (fw_run_transaction(card, TCODE_LOCK_COMPARE_SWAP, irm_id, generation, SCODE_100, offset, data, 8)) { case RCODE_GENERATION: /* A generation change frees all channels. */ - return allocate ? -EAGAIN : i; + return allocate ? -EAGAIN : channel; case RCODE_COMPLETE: if (data[0] == old) - return i; + return channel; old = data[0]; /* Is the IRM 1394a-2000 compliant? */ - if ((data[0] & c) == (data[1] & c)) + if ((data[0] & bit) == (data[1] & bit)) continue; /* 1394-1995 IRM, fall through to retry. */ default: if (retry) { retry--; - i--; + channel--; } else { ret = -EIO; } -- GitLab From e81cbebdfc384f9c2ae91225f16ef994118e5e2c Mon Sep 17 00:00:00 2001 From: Clemens Ladisch Date: Wed, 16 Feb 2011 10:32:11 +0100 Subject: [PATCH 0216/2822] firewire: ohci: prevent iso completion callbacks after context stop To prevent the iso packet callback from being called after fw_iso_context_stop() has returned, make sure that the context's tasklet has finished executing before that. This fixes access-after-free bugs that have so far been observed only in the upcoming snd-firewire-speakers driver, but can theoretically also happen in the firedtv driver. Signed-off-by: Clemens Ladisch Signed-off-by: Stefan Richter --- drivers/firewire/ohci.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/firewire/ohci.c b/drivers/firewire/ohci.c index c7394361afcb1..f1497b1fcf2e7 100644 --- a/drivers/firewire/ohci.c +++ b/drivers/firewire/ohci.c @@ -2764,6 +2764,7 @@ static int ohci_stop_iso(struct fw_iso_context *base) } flush_writes(ohci); context_stop(&ctx->context); + tasklet_kill(&ctx->context.tasklet); return 0; } -- GitLab From 44b74d909dc943fd9384930a141450cb17133511 Mon Sep 17 00:00:00 2001 From: Clemens Ladisch Date: Wed, 23 Feb 2011 09:27:40 +0100 Subject: [PATCH 0217/2822] firewire: ohci: prevent starting of iso contexts with empty queue If a misguided program tried to start an isochronous context before it has queued any packets, the call would appear to succeed, but the context would not actually go into the running state, and the OHCI controller would then raise an unrecoverableError interrupt because the first Z value is zero and thus invalid. The driver logs such errors, but there is no mechanism to report this back to the program. Add an explicit check so that this error can be returned synchronously. Signed-off-by: Clemens Ladisch Signed-off-by: Stefan Richter --- drivers/firewire/ohci.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/firewire/ohci.c b/drivers/firewire/ohci.c index f1497b1fcf2e7..c0572283b93ed 100644 --- a/drivers/firewire/ohci.c +++ b/drivers/firewire/ohci.c @@ -2706,6 +2706,10 @@ static int ohci_start_iso(struct fw_iso_context *base, u32 control = IR_CONTEXT_ISOCH_HEADER, match; int index; + /* the controller cannot start without any queued packets */ + if (ctx->context.last->branch_address == 0) + return -ENODATA; + switch (ctx->base.type) { case FW_ISO_CONTEXT_TRANSMIT: index = ctx - ohci->it_context_list; -- GitLab From c5a9f9d0895b2c16908979244d3d678fd6db0545 Mon Sep 17 00:00:00 2001 From: Tomoya MORINAGA Date: Fri, 18 Feb 2011 10:01:20 +0530 Subject: [PATCH 0218/2822] pch_dma: fix kernel error issue fix the following kernel error ------------[ cut here ]------------ WARNING: at kernel/softirq.c:159 _local_bh_enable_ip.clone.5+0x35/0x71() Hardware name: To be filled by O.E.M. Modules linked in: pch_uart pch_dma fuse mga drm cpufreq_ondemand acpi_cpufreq mperf ip6t_REJECT nf_conntrack_ipv6 nf_defrag_ipv6 ip6table_filter ip6_tables ipv6 uinput snd_hda_codec_realtek snd_hda_intel snd_hda_codec matroxfb_base snd_hwdep 8250_pnp snd_seq snd_seq_device matroxfb_DAC1064 snd_pcm joydev 8250 matroxfb_accel snd_timer matroxfb_Ti3026 ppdev pegasus parport_pc snd parport matroxfb_g450 g450_pll serial_core video output matroxfb_misc soundcore snd_page_alloc serio_raw pcspkr ext4 jbd2 crc16 sdhci_pci sdhci mmc_core floppy [last unloaded: scsi_wait_scan] Pid: 0, comm: swapper Not tainted 2.6.37.upstream_check+ #8 Call Trace: [] warn_slowpath_common+0x65/0x7a [] ? _local_bh_enable_ip.clone.5+0x35/0x71 [] warn_slowpath_null+0xf/0x13 [] _local_bh_enable_ip.clone.5+0x35/0x71 [] local_bh_enable_ip+0x8/0xa [] _raw_spin_unlock_bh+0x10/0x12 [] pd_prep_slave_sg+0xba/0x200 [pch_dma] [] pch_uart_interrupt+0x44d/0x6aa [pch_uart] [] handle_IRQ_event+0x1d/0x9e [] handle_fasteoi_irq+0x90/0xc7 [] ? handle_fasteoi_irq+0x0/0xc7 [] ? do_IRQ+0x3e/0x89 [] ? common_interrupt+0x29/0x30 [] ? sys_getpriority+0x12d/0x1a2 [] ? arch_local_irq_enable+0x5/0xb [] ? acpi_idle_enter_bm+0x22a/0x261 [] ? cpuidle_idle_call+0x70/0xa1 [] ? cpu_idle+0x49/0x6a [] ? rest_init+0x58/0x5a [] ? start_kernel+0x2d0/0x2d5 [] ? i386_start_kernel+0xce/0xd5 Signed-off-by: Tomoya MORINAGA Signed-off-by: Vinod Koul --- drivers/dma/pch_dma.c | 29 ++++++++++++++--------------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/drivers/dma/pch_dma.c b/drivers/dma/pch_dma.c index 1c38418ae61f0..bf2ddd601dc22 100644 --- a/drivers/dma/pch_dma.c +++ b/drivers/dma/pch_dma.c @@ -366,7 +366,7 @@ static dma_cookie_t pd_tx_submit(struct dma_async_tx_descriptor *txd) struct pch_dma_chan *pd_chan = to_pd_chan(txd->chan); dma_cookie_t cookie; - spin_lock_bh(&pd_chan->lock); + spin_lock(&pd_chan->lock); cookie = pdc_assign_cookie(pd_chan, desc); if (list_empty(&pd_chan->active_list)) { @@ -376,7 +376,7 @@ static dma_cookie_t pd_tx_submit(struct dma_async_tx_descriptor *txd) list_add_tail(&desc->desc_node, &pd_chan->queue); } - spin_unlock_bh(&pd_chan->lock); + spin_unlock(&pd_chan->lock); return 0; } @@ -386,7 +386,7 @@ static struct pch_dma_desc *pdc_alloc_desc(struct dma_chan *chan, gfp_t flags) struct pch_dma *pd = to_pd(chan->device); dma_addr_t addr; - desc = pci_pool_alloc(pd->pool, GFP_KERNEL, &addr); + desc = pci_pool_alloc(pd->pool, flags, &addr); if (desc) { memset(desc, 0, sizeof(struct pch_dma_desc)); INIT_LIST_HEAD(&desc->tx_list); @@ -405,7 +405,7 @@ static struct pch_dma_desc *pdc_desc_get(struct pch_dma_chan *pd_chan) struct pch_dma_desc *ret = NULL; int i; - spin_lock_bh(&pd_chan->lock); + spin_lock(&pd_chan->lock); list_for_each_entry_safe(desc, _d, &pd_chan->free_list, desc_node) { i++; if (async_tx_test_ack(&desc->txd)) { @@ -415,15 +415,15 @@ static struct pch_dma_desc *pdc_desc_get(struct pch_dma_chan *pd_chan) } dev_dbg(chan2dev(&pd_chan->chan), "desc %p not ACKed\n", desc); } - spin_unlock_bh(&pd_chan->lock); + spin_unlock(&pd_chan->lock); dev_dbg(chan2dev(&pd_chan->chan), "scanned %d descriptors\n", i); if (!ret) { ret = pdc_alloc_desc(&pd_chan->chan, GFP_NOIO); if (ret) { - spin_lock_bh(&pd_chan->lock); + spin_lock(&pd_chan->lock); pd_chan->descs_allocated++; - spin_unlock_bh(&pd_chan->lock); + spin_unlock(&pd_chan->lock); } else { dev_err(chan2dev(&pd_chan->chan), "failed to alloc desc\n"); @@ -437,10 +437,10 @@ static void pdc_desc_put(struct pch_dma_chan *pd_chan, struct pch_dma_desc *desc) { if (desc) { - spin_lock_bh(&pd_chan->lock); + spin_lock(&pd_chan->lock); list_splice_init(&desc->tx_list, &pd_chan->free_list); list_add(&desc->desc_node, &pd_chan->free_list); - spin_unlock_bh(&pd_chan->lock); + spin_unlock(&pd_chan->lock); } } @@ -530,9 +530,9 @@ static void pd_issue_pending(struct dma_chan *chan) struct pch_dma_chan *pd_chan = to_pd_chan(chan); if (pdc_is_idle(pd_chan)) { - spin_lock_bh(&pd_chan->lock); + spin_lock(&pd_chan->lock); pdc_advance_work(pd_chan); - spin_unlock_bh(&pd_chan->lock); + spin_unlock(&pd_chan->lock); } } @@ -592,7 +592,6 @@ static struct dma_async_tx_descriptor *pd_prep_slave_sg(struct dma_chan *chan, goto err_desc_get; } - if (!first) { first = desc; } else { @@ -641,13 +640,13 @@ static int pd_device_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd, spin_unlock_bh(&pd_chan->lock); - return 0; } static void pdc_tasklet(unsigned long data) { struct pch_dma_chan *pd_chan = (struct pch_dma_chan *)data; + unsigned long flags; if (!pdc_is_idle(pd_chan)) { dev_err(chan2dev(&pd_chan->chan), @@ -655,12 +654,12 @@ static void pdc_tasklet(unsigned long data) return; } - spin_lock_bh(&pd_chan->lock); + spin_lock_irqsave(&pd_chan->lock, flags); if (test_and_clear_bit(0, &pd_chan->err_status)) pdc_handle_error(pd_chan); else pdc_advance_work(pd_chan); - spin_unlock_bh(&pd_chan->lock); + spin_unlock_irqrestore(&pd_chan->lock, flags); } static irqreturn_t pd_irq(int irq, void *devid) -- GitLab From 26d890f0d09fd58f7194aad651e86283cb9e6574 Mon Sep 17 00:00:00 2001 From: Tomoya MORINAGA Date: Fri, 18 Feb 2011 10:01:21 +0530 Subject: [PATCH 0219/2822] pch_dma: set the number of array correctly set the number of array correctly. Signed-off-by: Tomoya MORINAGA Signed-off-by: Vinod Koul --- drivers/dma/pch_dma.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/dma/pch_dma.c b/drivers/dma/pch_dma.c index bf2ddd601dc22..b1dfba7e37b4e 100644 --- a/drivers/dma/pch_dma.c +++ b/drivers/dma/pch_dma.c @@ -82,7 +82,7 @@ struct pch_dma_regs { u32 dma_sts1; u32 reserved2; u32 reserved3; - struct pch_dma_desc_regs desc[0]; + struct pch_dma_desc_regs desc[MAX_CHAN_NR]; }; struct pch_dma_desc { @@ -124,7 +124,7 @@ struct pch_dma { struct pci_pool *pool; struct pch_dma_regs regs; struct pch_dma_desc_regs ch_regs[MAX_CHAN_NR]; - struct pch_dma_chan channels[0]; + struct pch_dma_chan channels[MAX_CHAN_NR]; }; #define PCH_DMA_CTL0 0x00 -- GitLab From e0fd9b90765f604374c42de8ac59d6584afce264 Mon Sep 17 00:00:00 2001 From: Curt Wohlgemuth Date: Sat, 26 Feb 2011 12:25:52 -0500 Subject: [PATCH 0220/2822] ext4: mark multi-page IO complete on mapping failure In mpage_da_map_and_submit(), if we have a delayed block allocation failure from ext4_map_blocks(), we need to mark the IO as complete, by setting mpd->io_done = 1; Otherwise, we could end up submitting the pages in an outer loop; since they are unlocked on mapping failure in ext4_da_block_invalidatepages(), this will cause a bug check in mpage_da_submit_io(). I tested this by injected failures into ext4_map_blocks(). Without this patch, a simple fsstress run will bug check; with the patch, it works fine. Signed-off-by: Curt Wohlgemuth Signed-off-by: "Theodore Ts'o" --- fs/ext4/inode.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index c6c6b7fcb455a..fd369dbce6af2 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -2314,6 +2314,9 @@ static void mpage_da_map_and_submit(struct mpage_da_data *mpd) /* invalidate all the pages */ ext4_da_block_invalidatepages(mpd, next, mpd->b_size >> mpd->inode->i_blkbits); + + /* Mark this page range as having been completed */ + mpd->io_done = 1; return; } BUG_ON(blks == 0); -- GitLab From c7f5938adce6727b9d17785f289c1146bd88d678 Mon Sep 17 00:00:00 2001 From: Curt Wohlgemuth Date: Sat, 26 Feb 2011 12:27:52 -0500 Subject: [PATCH 0221/2822] ext4: fix ext4_da_block_invalidatepages() to handle page range properly If ext4_da_block_invalidatepages() is called because of a failure from ext4_map_blocks() in mpage_da_map_and_submit(), it's supposed to clean up -- including unlock -- all the pages in the mpd structure. But these values may not match up, even on a system in which block size == page size: mpd->b_blocknr != mpd->first_page mpd->b_size != (mpd->next_page - mpd->first_page) ext4_da_block_invalidatepages() has been using b_blocknr and b_size; this patch changes it to use first_page and next_page. Tested: I injected a small number (5%) of failures in ext4_map_blocks() in the case that the flags contain EXT4_GET_BLOCKS_DELALLOC_RESERVE, and ran fsstress on this kernel. Without this patch, I got hung tasks every time. With this patch, I see no hangs in many runs of fsstress. Signed-off-by: Curt Wohlgemuth Signed-off-by: "Theodore Ts'o" --- fs/ext4/inode.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index fd369dbce6af2..e878c3a7aaf03 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -2165,8 +2165,7 @@ static int mpage_da_submit_io(struct mpage_da_data *mpd, return ret; } -static void ext4_da_block_invalidatepages(struct mpage_da_data *mpd, - sector_t logical, long blk_cnt) +static void ext4_da_block_invalidatepages(struct mpage_da_data *mpd) { int nr_pages, i; pgoff_t index, end; @@ -2174,9 +2173,8 @@ static void ext4_da_block_invalidatepages(struct mpage_da_data *mpd, struct inode *inode = mpd->inode; struct address_space *mapping = inode->i_mapping; - index = logical >> (PAGE_CACHE_SHIFT - inode->i_blkbits); - end = (logical + blk_cnt - 1) >> - (PAGE_CACHE_SHIFT - inode->i_blkbits); + index = mpd->first_page; + end = mpd->next_page - 1; while (index <= end) { nr_pages = pagevec_lookup(&pvec, mapping, index, PAGEVEC_SIZE); if (nr_pages == 0) @@ -2312,8 +2310,7 @@ static void mpage_da_map_and_submit(struct mpage_da_data *mpd) ext4_print_free_blocks(mpd->inode); } /* invalidate all the pages */ - ext4_da_block_invalidatepages(mpd, next, - mpd->b_size >> mpd->inode->i_blkbits); + ext4_da_block_invalidatepages(mpd); /* Mark this page range as having been completed */ mpd->io_done = 1; -- GitLab From 6fd7a46781999c32f423025767e43b349b967d57 Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Sat, 26 Feb 2011 13:53:09 -0500 Subject: [PATCH 0222/2822] ext4: enable mblk_io_submit by default Now that we've fixed the file corruption bug in commit d50bdd5aa55, it's time to enable mblk_io_submit by default. Signed-off-by: "Theodore Ts'o" --- fs/ext4/super.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/fs/ext4/super.c b/fs/ext4/super.c index a665d2fb70c14..33c398785e53c 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c @@ -1038,8 +1038,8 @@ static int ext4_show_options(struct seq_file *seq, struct vfsmount *vfs) !(def_mount_opts & EXT4_DEFM_NODELALLOC)) seq_puts(seq, ",nodelalloc"); - if (test_opt(sb, MBLK_IO_SUBMIT)) - seq_puts(seq, ",mblk_io_submit"); + if (!test_opt(sb, MBLK_IO_SUBMIT)) + seq_puts(seq, ",nomblk_io_submit"); if (sbi->s_stripe) seq_printf(seq, ",stripe=%lu", sbi->s_stripe); /* @@ -3099,6 +3099,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) #ifdef CONFIG_EXT4_FS_POSIX_ACL set_opt(sb, POSIX_ACL); #endif + set_opt(sb, MBLK_IO_SUBMIT); if ((def_mount_opts & EXT4_DEFM_JMODE) == EXT4_DEFM_JMODE_DATA) set_opt(sb, JOURNAL_DATA); else if ((def_mount_opts & EXT4_DEFM_JMODE) == EXT4_DEFM_JMODE_ORDERED) -- GitLab From 8eb9e5ce211de1b98bc84e93258b7db0860a103c Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Sat, 26 Feb 2011 14:07:31 -0500 Subject: [PATCH 0223/2822] ext4: fold __mpage_da_writepage() into write_cache_pages_da() Fold the __mpage_da_writepage() function into write_cache_pages_da(). This will give us opportunities to clean up and simplify the resulting code. Signed-off-by: "Theodore Ts'o" --- fs/ext4/inode.c | 206 +++++++++++++++++++++--------------------------- 1 file changed, 91 insertions(+), 115 deletions(-) diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index e878c3a7aaf03..fcd08ca0643b4 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -2437,102 +2437,6 @@ static int ext4_bh_delay_or_unwritten(handle_t *handle, struct buffer_head *bh) return (buffer_delay(bh) || buffer_unwritten(bh)) && buffer_dirty(bh); } -/* - * __mpage_da_writepage - finds extent of pages and blocks - * - * @page: page to consider - * @wbc: not used, we just follow rules - * @data: context - * - * The function finds extents of pages and scan them for all blocks. - */ -static int __mpage_da_writepage(struct page *page, - struct writeback_control *wbc, - struct mpage_da_data *mpd) -{ - struct inode *inode = mpd->inode; - struct buffer_head *bh, *head; - sector_t logical; - - /* - * Can we merge this page to current extent? - */ - if (mpd->next_page != page->index) { - /* - * Nope, we can't. So, we map non-allocated blocks - * and start IO on them - */ - if (mpd->next_page != mpd->first_page) { - mpage_da_map_and_submit(mpd); - /* - * skip rest of the page in the page_vec - */ - redirty_page_for_writepage(wbc, page); - unlock_page(page); - return MPAGE_DA_EXTENT_TAIL; - } - - /* - * Start next extent of pages ... - */ - mpd->first_page = page->index; - - /* - * ... and blocks - */ - mpd->b_size = 0; - mpd->b_state = 0; - mpd->b_blocknr = 0; - } - - mpd->next_page = page->index + 1; - logical = (sector_t) page->index << - (PAGE_CACHE_SHIFT - inode->i_blkbits); - - if (!page_has_buffers(page)) { - mpage_add_bh_to_extent(mpd, logical, PAGE_CACHE_SIZE, - (1 << BH_Dirty) | (1 << BH_Uptodate)); - if (mpd->io_done) - return MPAGE_DA_EXTENT_TAIL; - } else { - /* - * Page with regular buffer heads, just add all dirty ones - */ - head = page_buffers(page); - bh = head; - do { - BUG_ON(buffer_locked(bh)); - /* - * We need to try to allocate - * unmapped blocks in the same page. - * Otherwise we won't make progress - * with the page in ext4_writepage - */ - if (ext4_bh_delay_or_unwritten(NULL, bh)) { - mpage_add_bh_to_extent(mpd, logical, - bh->b_size, - bh->b_state); - if (mpd->io_done) - return MPAGE_DA_EXTENT_TAIL; - } else if (buffer_dirty(bh) && (buffer_mapped(bh))) { - /* - * mapped dirty buffer. We need to update - * the b_state because we look at - * b_state in mpage_da_map_blocks. We don't - * update b_size because if we find an - * unmapped buffer_head later we need to - * use the b_state flag of that buffer_head. - */ - if (mpd->b_size == 0) - mpd->b_state = bh->b_state & BH_FLAGS; - } - logical++; - } while ((bh = bh->b_this_page) != head); - } - - return 0; -} - /* * This is a special get_blocks_t callback which is used by * ext4_da_write_begin(). It will either return mapped block or @@ -2811,18 +2715,17 @@ static int ext4_da_writepages_trans_blocks(struct inode *inode) /* * write_cache_pages_da - walk the list of dirty pages of the given - * address space and call the callback function (which usually writes - * the pages). - * - * This is a forked version of write_cache_pages(). Differences: - * Range cyclic is ignored. - * no_nrwrite_index_update is always presumed true + * address space and accumulate pages that need writing, and call + * mpage_da_map_and_submit to map the pages and then write them. */ static int write_cache_pages_da(struct address_space *mapping, struct writeback_control *wbc, struct mpage_da_data *mpd, pgoff_t *done_index) { + struct inode *inode = mpd->inode; + struct buffer_head *bh, *head; + sector_t logical; int ret = 0; int done = 0; struct pagevec pvec; @@ -2899,17 +2802,90 @@ continue_unlock: if (!clear_page_dirty_for_io(page)) goto continue_unlock; - ret = __mpage_da_writepage(page, wbc, mpd); - if (unlikely(ret)) { - if (ret == AOP_WRITEPAGE_ACTIVATE) { + /* BEGIN __mpage_da_writepage */ + + /* + * Can we merge this page to current extent? + */ + if (mpd->next_page != page->index) { + /* + * Nope, we can't. So, we map + * non-allocated blocks and start IO + * on them + */ + if (mpd->next_page != mpd->first_page) { + mpage_da_map_and_submit(mpd); + /* + * skip rest of the page in the page_vec + */ + redirty_page_for_writepage(wbc, page); unlock_page(page); - ret = 0; - } else { - done = 1; - break; + ret = MPAGE_DA_EXTENT_TAIL; + goto out; } + + /* + * Start next extent of pages and blocks + */ + mpd->first_page = page->index; + mpd->b_size = 0; + mpd->b_state = 0; + mpd->b_blocknr = 0; + } + + mpd->next_page = page->index + 1; + logical = (sector_t) page->index << + (PAGE_CACHE_SHIFT - inode->i_blkbits); + + if (!page_has_buffers(page)) { + mpage_add_bh_to_extent(mpd, logical, PAGE_CACHE_SIZE, + (1 << BH_Dirty) | (1 << BH_Uptodate)); + if (mpd->io_done) { + ret = MPAGE_DA_EXTENT_TAIL; + goto out; + } + } else { + /* + * Page with regular buffer heads, just add all dirty ones + */ + head = page_buffers(page); + bh = head; + do { + BUG_ON(buffer_locked(bh)); + /* + * We need to try to allocate + * unmapped blocks in the same page. + * Otherwise we won't make progress + * with the page in ext4_writepage + */ + if (ext4_bh_delay_or_unwritten(NULL, bh)) { + mpage_add_bh_to_extent(mpd, logical, + bh->b_size, + bh->b_state); + if (mpd->io_done) { + ret = MPAGE_DA_EXTENT_TAIL; + goto out; + } + } else if (buffer_dirty(bh) && (buffer_mapped(bh))) { + /* + * mapped dirty buffer. We need to update + * the b_state because we look at + * b_state in mpage_da_map_blocks. We don't + * update b_size because if we find an + * unmapped buffer_head later we need to + * use the b_state flag of that buffer_head. + */ + if (mpd->b_size == 0) + mpd->b_state = bh->b_state & BH_FLAGS; + } + logical++; + } while ((bh = bh->b_this_page) != head); } + ret = 0; + + /* END __mpage_da_writepage */ + if (nr_to_write > 0) { nr_to_write--; if (nr_to_write == 0 && @@ -2933,6 +2909,10 @@ continue_unlock: cond_resched(); } return ret; +out: + pagevec_release(&pvec); + cond_resched(); + return ret; } @@ -3059,13 +3039,9 @@ retry: } /* - * Now call __mpage_da_writepage to find the next + * Now call write_cache_pages_da() to find the next * contiguous region of logical blocks that need - * blocks to be allocated by ext4. We don't actually - * submit the blocks for I/O here, even though - * write_cache_pages thinks it will, and will set the - * pages as clean for write before calling - * __mpage_da_writepage(). + * blocks to be allocated by ext4 and submit them. */ mpd.b_size = 0; mpd.b_state = 0; -- GitLab From 4f01b02c8c4e4111bd1adbcafb5741e8e991f5fd Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Sat, 26 Feb 2011 14:07:37 -0500 Subject: [PATCH 0224/2822] ext4: simple cleanups to write_cache_pages_da() Eliminate duplicate code, unneeded variables, etc., to make it easier to understand the code. No behavioral changes were made in this patch. Signed-off-by: "Theodore Ts'o" --- fs/ext4/inode.c | 115 ++++++++++++++++++++---------------------------- 1 file changed, 48 insertions(+), 67 deletions(-) diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index fcd08ca0643b4..1e718e87f466a 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -2723,17 +2723,14 @@ static int write_cache_pages_da(struct address_space *mapping, struct mpage_da_data *mpd, pgoff_t *done_index) { - struct inode *inode = mpd->inode; - struct buffer_head *bh, *head; - sector_t logical; - int ret = 0; - int done = 0; - struct pagevec pvec; - unsigned nr_pages; - pgoff_t index; - pgoff_t end; /* Inclusive */ - long nr_to_write = wbc->nr_to_write; - int tag; + struct buffer_head *bh, *head; + struct inode *inode = mpd->inode; + struct pagevec pvec; + unsigned int nr_pages; + sector_t logical; + pgoff_t index, end; + long nr_to_write = wbc->nr_to_write; + int i, tag, ret = 0; pagevec_init(&pvec, 0); index = wbc->range_start >> PAGE_CACHE_SHIFT; @@ -2745,13 +2742,11 @@ static int write_cache_pages_da(struct address_space *mapping, tag = PAGECACHE_TAG_DIRTY; *done_index = index; - while (!done && (index <= end)) { - int i; - + while (index <= end) { nr_pages = pagevec_lookup_tag(&pvec, mapping, &index, tag, min(end - index, (pgoff_t)PAGEVEC_SIZE-1) + 1); if (nr_pages == 0) - break; + return 0; for (i = 0; i < nr_pages; i++) { struct page *page = pvec.pages[i]; @@ -2763,47 +2758,37 @@ static int write_cache_pages_da(struct address_space *mapping, * mapping. However, page->index will not change * because we have a reference on the page. */ - if (page->index > end) { - done = 1; - break; - } + if (page->index > end) + goto out; *done_index = page->index + 1; lock_page(page); /* - * Page truncated or invalidated. We can freely skip it - * then, even for data integrity operations: the page - * has disappeared concurrently, so there could be no - * real expectation of this data interity operation - * even if there is now a new, dirty page at the same - * pagecache address. + * If the page is no longer dirty, or its + * mapping no longer corresponds to inode we + * are writing (which means it has been + * truncated or invalidated), or the page is + * already under writeback and we are not + * doing a data integrity writeback, skip the page */ - if (unlikely(page->mapping != mapping)) { -continue_unlock: + if (!PageDirty(page) || + (PageWriteback(page) && + (wbc->sync_mode == WB_SYNC_NONE)) || + unlikely(page->mapping != mapping)) { + continue_unlock: unlock_page(page); continue; } - if (!PageDirty(page)) { - /* someone wrote it for us */ - goto continue_unlock; - } - - if (PageWriteback(page)) { - if (wbc->sync_mode != WB_SYNC_NONE) - wait_on_page_writeback(page); - else - goto continue_unlock; - } + if (PageWriteback(page)) + wait_on_page_writeback(page); BUG_ON(PageWriteback(page)); if (!clear_page_dirty_for_io(page)) goto continue_unlock; - /* BEGIN __mpage_da_writepage */ - /* * Can we merge this page to current extent? */ @@ -2820,8 +2805,7 @@ continue_unlock: */ redirty_page_for_writepage(wbc, page); unlock_page(page); - ret = MPAGE_DA_EXTENT_TAIL; - goto out; + goto ret_extent_tail; } /* @@ -2838,15 +2822,15 @@ continue_unlock: (PAGE_CACHE_SHIFT - inode->i_blkbits); if (!page_has_buffers(page)) { - mpage_add_bh_to_extent(mpd, logical, PAGE_CACHE_SIZE, + mpage_add_bh_to_extent(mpd, logical, + PAGE_CACHE_SIZE, (1 << BH_Dirty) | (1 << BH_Uptodate)); - if (mpd->io_done) { - ret = MPAGE_DA_EXTENT_TAIL; - goto out; - } + if (mpd->io_done) + goto ret_extent_tail; } else { /* - * Page with regular buffer heads, just add all dirty ones + * Page with regular buffer heads, + * just add all dirty ones */ head = page_buffers(page); bh = head; @@ -2862,18 +2846,19 @@ continue_unlock: mpage_add_bh_to_extent(mpd, logical, bh->b_size, bh->b_state); - if (mpd->io_done) { - ret = MPAGE_DA_EXTENT_TAIL; - goto out; - } + if (mpd->io_done) + goto ret_extent_tail; } else if (buffer_dirty(bh) && (buffer_mapped(bh))) { /* - * mapped dirty buffer. We need to update - * the b_state because we look at - * b_state in mpage_da_map_blocks. We don't - * update b_size because if we find an - * unmapped buffer_head later we need to - * use the b_state flag of that buffer_head. + * mapped dirty buffer. We need + * to update the b_state + * because we look at b_state + * in mpage_da_map_blocks. We + * don't update b_size because + * if we find an unmapped + * buffer_head later we need to + * use the b_state flag of that + * buffer_head. */ if (mpd->b_size == 0) mpd->b_state = bh->b_state & BH_FLAGS; @@ -2882,14 +2867,10 @@ continue_unlock: } while ((bh = bh->b_this_page) != head); } - ret = 0; - - /* END __mpage_da_writepage */ - if (nr_to_write > 0) { nr_to_write--; if (nr_to_write == 0 && - wbc->sync_mode == WB_SYNC_NONE) { + wbc->sync_mode == WB_SYNC_NONE) /* * We stop writing back only if we are * not doing integrity sync. In case of @@ -2900,15 +2881,15 @@ continue_unlock: * pages, but have not synced all of the * old dirty pages. */ - done = 1; - break; - } + goto out; } } pagevec_release(&pvec); cond_resched(); } - return ret; + return 0; +ret_extent_tail: + ret = MPAGE_DA_EXTENT_TAIL; out: pagevec_release(&pvec); cond_resched(); -- GitLab From 9749895644a817cfd28a535bc3ae60e4267bdc50 Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Sat, 26 Feb 2011 14:08:01 -0500 Subject: [PATCH 0225/2822] ext4: clear the dirty bit for a page in writeback at the last minute Move when we call clear_page_dirty_for_io() to just before we actually write the page. This simplifies the code somewhat, and avoids marking pages as clean and then needing to remark them as dirty later. Signed-off-by: "Theodore Ts'o" --- fs/ext4/inode.c | 28 +++++++++++----------------- 1 file changed, 11 insertions(+), 17 deletions(-) diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index 1e718e87f466a..ae6e2f43d8736 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -2060,7 +2060,7 @@ static int mpage_da_submit_io(struct mpage_da_data *mpd, if (nr_pages == 0) break; for (i = 0; i < nr_pages; i++) { - int commit_write = 0, redirty_page = 0; + int commit_write = 0, skip_page = 0; struct page *page = pvec.pages[i]; index = page->index; @@ -2086,14 +2086,12 @@ static int mpage_da_submit_io(struct mpage_da_data *mpd, * If the page does not have buffers (for * whatever reason), try to create them using * __block_write_begin. If this fails, - * redirty the page and move on. + * skip the page and move on. */ if (!page_has_buffers(page)) { if (__block_write_begin(page, 0, len, noalloc_get_block_write)) { - redirty_page: - redirty_page_for_writepage(mpd->wbc, - page); + skip_page: unlock_page(page); continue; } @@ -2104,7 +2102,7 @@ static int mpage_da_submit_io(struct mpage_da_data *mpd, block_start = 0; do { if (!bh) - goto redirty_page; + goto skip_page; if (map && (cur_logical >= map->m_lblk) && (cur_logical <= (map->m_lblk + (map->m_len - 1)))) { @@ -2120,22 +2118,23 @@ static int mpage_da_submit_io(struct mpage_da_data *mpd, clear_buffer_unwritten(bh); } - /* redirty page if block allocation undone */ + /* skip page if block allocation undone */ if (buffer_delay(bh) || buffer_unwritten(bh)) - redirty_page = 1; + skip_page = 1; bh = bh->b_this_page; block_start += bh->b_size; cur_logical++; pblock++; } while (bh != page_bufs); - if (redirty_page) - goto redirty_page; + if (skip_page) + goto skip_page; if (commit_write) /* mark the buffer_heads as dirty & uptodate */ block_commit_write(page, 0, len); + clear_page_dirty_for_io(page); /* * Delalloc doesn't support data journalling, * but eventually maybe we'll lift this @@ -2277,9 +2276,8 @@ static void mpage_da_map_and_submit(struct mpage_da_data *mpd) err = blks; /* * If get block returns EAGAIN or ENOSPC and there - * appears to be free blocks we will call - * ext4_writepage() for all of the pages which will - * just redirty the pages. + * appears to be free blocks we will just let + * mpage_da_submit_io() unlock all of the pages. */ if (err == -EAGAIN) goto submit_io; @@ -2777,7 +2775,6 @@ static int write_cache_pages_da(struct address_space *mapping, (PageWriteback(page) && (wbc->sync_mode == WB_SYNC_NONE)) || unlikely(page->mapping != mapping)) { - continue_unlock: unlock_page(page); continue; } @@ -2786,8 +2783,6 @@ static int write_cache_pages_da(struct address_space *mapping, wait_on_page_writeback(page); BUG_ON(PageWriteback(page)); - if (!clear_page_dirty_for_io(page)) - goto continue_unlock; /* * Can we merge this page to current extent? @@ -2803,7 +2798,6 @@ static int write_cache_pages_da(struct address_space *mapping, /* * skip rest of the page in the page_vec */ - redirty_page_for_writepage(wbc, page); unlock_page(page); goto ret_extent_tail; } -- GitLab From ee6ecbcc5d73672217fdea420d182ecb0cdf310c Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Sat, 26 Feb 2011 14:08:11 -0500 Subject: [PATCH 0226/2822] ext4: remove page_skipped hackery in ext4_da_writepages() Because the ext4 page writeback codepath had been prematurely calling clear_page_dirty_for_io(), if it turned out that a particular page couldn't be written out during a particular pass of write_cache_pages_da(), the page would have to get redirtied by calling redirty_pages_for_writeback(). Not only was this wasted work, but redirty_page_for_writeback() would increment wbc->pages_skipped to signal to writeback_sb_inodes() that buffers were locked, and that it should skip this inode until later. Since this signal was incorrect in ext4's case --- which was caused by ext4's historically incorrect use of write_cache_pages() --- ext4_da_writepages() saved and restored wbc->skipped_pages to avoid confusing writeback_sb_inodes(). Now that we've fixed ext4 to call clear_page_dirty_for_io() right before initiating the page I/O, we can nuke the page_skipped save/restore hackery, and breathe a sigh of relief. Signed-off-by: "Theodore Ts'o" --- fs/ext4/inode.c | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index ae6e2f43d8736..617c9cbba1828 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -2900,7 +2900,6 @@ static int ext4_da_writepages(struct address_space *mapping, struct mpage_da_data mpd; struct inode *inode = mapping->host; int pages_written = 0; - long pages_skipped; unsigned int max_pages; int range_cyclic, cycled = 1, io_done = 0; int needed_blocks, ret = 0; @@ -2986,8 +2985,6 @@ static int ext4_da_writepages(struct address_space *mapping, mpd.wbc = wbc; mpd.inode = mapping->host; - pages_skipped = wbc->pages_skipped; - retry: if (wbc->sync_mode == WB_SYNC_ALL) tag_pages_for_writeback(mapping, index, end); @@ -3047,7 +3044,6 @@ retry: * and try again */ jbd2_journal_force_commit_nested(sbi->s_journal); - wbc->pages_skipped = pages_skipped; ret = 0; } else if (ret == MPAGE_DA_EXTENT_TAIL) { /* @@ -3055,7 +3051,6 @@ retry: * rest of the pages */ pages_written += mpd.pages_written; - wbc->pages_skipped = pages_skipped; ret = 0; io_done = 1; } else if (wbc->nr_to_write) @@ -3073,11 +3068,6 @@ retry: wbc->range_end = mapping->writeback_index - 1; goto retry; } - if (pages_skipped != wbc->pages_skipped) - ext4_msg(inode->i_sb, KERN_CRIT, - "This should not happen leaving %s " - "with nr_to_write = %ld ret = %d", - __func__, wbc->nr_to_write, ret); /* Update index */ wbc->range_cyclic = range_cyclic; -- GitLab From 78aaced3408141bb7c836f2db0ca435790399da5 Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Sat, 26 Feb 2011 14:09:14 -0500 Subject: [PATCH 0227/2822] ext4: don't lock the next page in write_cache_pages if not needed If we have accumulated a contiguous region of memory to be written out, and the next page can added to this region, don't bother locking (and then unlocking the page) before writing out the memory. In the unlikely event that the next page was being written back by some other CPU, we can also skip waiting that page to finish writeback. Signed-off-by: "Theodore Ts'o" --- fs/ext4/inode.c | 27 ++++++++++----------------- 1 file changed, 10 insertions(+), 17 deletions(-) diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index 617c9cbba1828..c2e6af3382341 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -2761,6 +2761,16 @@ static int write_cache_pages_da(struct address_space *mapping, *done_index = page->index + 1; + /* + * If we can't merge this page, and we have + * accumulated an contiguous region, write it + */ + if ((mpd->next_page != page->index) && + (mpd->next_page != mpd->first_page)) { + mpage_da_map_and_submit(mpd); + goto ret_extent_tail; + } + lock_page(page); /* @@ -2784,24 +2794,7 @@ static int write_cache_pages_da(struct address_space *mapping, BUG_ON(PageWriteback(page)); - /* - * Can we merge this page to current extent? - */ if (mpd->next_page != page->index) { - /* - * Nope, we can't. So, we map - * non-allocated blocks and start IO - * on them - */ - if (mpd->next_page != mpd->first_page) { - mpage_da_map_and_submit(mpd); - /* - * skip rest of the page in the page_vec - */ - unlock_page(page); - goto ret_extent_tail; - } - /* * Start next extent of pages and blocks */ -- GitLab From 168fc0223c0e944957b1f31d88c2334fc904baf1 Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Sat, 26 Feb 2011 14:09:20 -0500 Subject: [PATCH 0228/2822] ext4: move setup of the mpd structure to write_cache_pages_da() Move the initialization of all of the fields of the mpd structure to write_cache_pages_da(). This simplifies the code considerably. Signed-off-by: "Theodore Ts'o" --- fs/ext4/inode.c | 29 +++++++---------------------- 1 file changed, 7 insertions(+), 22 deletions(-) diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index c2e6af3382341..dcc2287433b6f 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -2714,7 +2714,8 @@ static int ext4_da_writepages_trans_blocks(struct inode *inode) /* * write_cache_pages_da - walk the list of dirty pages of the given * address space and accumulate pages that need writing, and call - * mpage_da_map_and_submit to map the pages and then write them. + * mpage_da_map_and_submit to map a single contiguous memory region + * and then write them. */ static int write_cache_pages_da(struct address_space *mapping, struct writeback_control *wbc, @@ -2722,7 +2723,7 @@ static int write_cache_pages_da(struct address_space *mapping, pgoff_t *done_index) { struct buffer_head *bh, *head; - struct inode *inode = mpd->inode; + struct inode *inode = mapping->host; struct pagevec pvec; unsigned int nr_pages; sector_t logical; @@ -2730,6 +2731,9 @@ static int write_cache_pages_da(struct address_space *mapping, long nr_to_write = wbc->nr_to_write; int i, tag, ret = 0; + memset(mpd, 0, sizeof(struct mpage_da_data)); + mpd->wbc = wbc; + mpd->inode = inode; pagevec_init(&pvec, 0); index = wbc->range_start >> PAGE_CACHE_SHIFT; end = wbc->range_end >> PAGE_CACHE_SHIFT; @@ -2794,16 +2798,8 @@ static int write_cache_pages_da(struct address_space *mapping, BUG_ON(PageWriteback(page)); - if (mpd->next_page != page->index) { - /* - * Start next extent of pages and blocks - */ + if (mpd->next_page != page->index) mpd->first_page = page->index; - mpd->b_size = 0; - mpd->b_state = 0; - mpd->b_blocknr = 0; - } - mpd->next_page = page->index + 1; logical = (sector_t) page->index << (PAGE_CACHE_SHIFT - inode->i_blkbits); @@ -2975,9 +2971,6 @@ static int ext4_da_writepages(struct address_space *mapping, wbc->nr_to_write = desired_nr_to_write; } - mpd.wbc = wbc; - mpd.inode = mapping->host; - retry: if (wbc->sync_mode == WB_SYNC_ALL) tag_pages_for_writeback(mapping, index, end); @@ -3008,14 +3001,6 @@ retry: * contiguous region of logical blocks that need * blocks to be allocated by ext4 and submit them. */ - mpd.b_size = 0; - mpd.b_state = 0; - mpd.b_blocknr = 0; - mpd.first_page = 0; - mpd.next_page = 0; - mpd.io_done = 0; - mpd.pages_written = 0; - mpd.retval = 0; ret = write_cache_pages_da(mapping, wbc, &mpd, &done_index); /* * If we have a contiguous extent of pages and we -- GitLab From 5063511539bbb436ae8e4f75409561ef547f8516 Mon Sep 17 00:00:00 2001 From: Henrik Rydberg Date: Fri, 25 Feb 2011 09:33:13 -0800 Subject: [PATCH 0229/2822] Input: bcm5974 - Report button also for zero fingers With the current code, pressing the integrated button with an isolating tool does not result in any button report. Fixed with this this patch. Signed-off-by: Henrik Rydberg Signed-off-by: Dmitry Torokhov --- drivers/input/mouse/bcm5974.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/input/mouse/bcm5974.c b/drivers/input/mouse/bcm5974.c index b952317639116..d24837210f04a 100644 --- a/drivers/input/mouse/bcm5974.c +++ b/drivers/input/mouse/bcm5974.c @@ -390,10 +390,6 @@ static int report_tp_state(struct bcm5974 *dev, int size) ptest = int2bound(&c->p, raw_p); origin = raw2int(f->origin); - /* set the integrated button if applicable */ - if (c->tp_type == TYPE2) - ibt = raw2int(dev->tp_data[BUTTON_TYPE2]); - /* while tracking finger still valid, count all fingers */ if (ptest > PRESSURE_LOW && origin) { abs_p = ptest; @@ -412,6 +408,10 @@ static int report_tp_state(struct bcm5974 *dev, int size) } } + /* set the integrated button if applicable */ + if (c->tp_type == TYPE2) + ibt = raw2int(dev->tp_data[BUTTON_TYPE2]); + if (dev->fingers < nmin) dev->fingers = nmin; if (dev->fingers > nmax) -- GitLab From 439581ec07fa9cf3f519dd461a2cf41cfd3adcb4 Mon Sep 17 00:00:00 2001 From: Peter Korsgaard Date: Fri, 25 Feb 2011 09:30:46 -0800 Subject: [PATCH 0230/2822] Input: evdev - fix evdev_write return value on partial writes As was recently brought up on the busybox list (http://lists.busybox.net/pipermail/busybox/2011-January/074565.html), evdev_write doesn't properly check the count argument, which will lead to a return value > count on partial writes if the remaining bytes are accessible - causing userspace confusion. Fix it by only handling each full input_event structure and return -EINVAL if less than 1 struct was written, similar to how it is done in evdev_read. Reported-by: Baruch Siach Signed-off-by: Peter Korsgaard Acked-by: Henrik Rydberg Signed-off-by: Dmitry Torokhov --- drivers/input/evdev.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c index c8471a2552e73..7f42d3a454d2d 100644 --- a/drivers/input/evdev.c +++ b/drivers/input/evdev.c @@ -321,6 +321,9 @@ static ssize_t evdev_write(struct file *file, const char __user *buffer, struct input_event event; int retval; + if (count < input_event_size()) + return -EINVAL; + retval = mutex_lock_interruptible(&evdev->mutex); if (retval) return retval; @@ -330,17 +333,16 @@ static ssize_t evdev_write(struct file *file, const char __user *buffer, goto out; } - while (retval < count) { - + do { if (input_event_from_user(buffer + retval, &event)) { retval = -EFAULT; goto out; } + retval += input_event_size(); input_inject_event(&evdev->handle, event.type, event.code, event.value); - retval += input_event_size(); - } + } while (retval + input_event_size() <= count); out: mutex_unlock(&evdev->mutex); -- GitLab From d71f606f687ef9d0cdddfd3619ca7cb9a0b3fb63 Mon Sep 17 00:00:00 2001 From: Mariusz Kozlowski Date: Sat, 26 Feb 2011 20:10:26 +0100 Subject: [PATCH 0231/2822] slub: fix ksize() build error mm/slub.c: In function 'ksize': mm/slub.c:2728: error: implicit declaration of function 'slab_ksize' slab_ksize() needs to go out of CONFIG_SLUB_DEBUG section. Acked-by: Randy Dunlap Acked-by: David Rientjes Signed-off-by: Mariusz Kozlowski Signed-off-by: Pekka Enberg --- mm/slub.c | 48 ++++++++++++++++++++++++------------------------ 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/mm/slub.c b/mm/slub.c index 217b5b5338a23..ea6f0390996f0 100644 --- a/mm/slub.c +++ b/mm/slub.c @@ -281,6 +281,30 @@ static inline int slab_index(void *p, struct kmem_cache *s, void *addr) return (p - addr) / s->size; } +static inline size_t slab_ksize(const struct kmem_cache *s) +{ +#ifdef CONFIG_SLUB_DEBUG + /* + * Debugging requires use of the padding between object + * and whatever may come after it. + */ + if (s->flags & (SLAB_RED_ZONE | SLAB_POISON)) + return s->objsize; + +#endif + /* + * If we have the need to store the freelist pointer + * back there or track user information then we can + * only use the space before that information. + */ + if (s->flags & (SLAB_DESTROY_BY_RCU | SLAB_STORE_USER)) + return s->inuse; + /* + * Else we can use all the padding etc for the allocation + */ + return s->size; +} + static inline struct kmem_cache_order_objects oo_make(int order, unsigned long size) { @@ -797,30 +821,6 @@ static inline int slab_pre_alloc_hook(struct kmem_cache *s, gfp_t flags) return should_failslab(s->objsize, flags, s->flags); } -static inline size_t slab_ksize(const struct kmem_cache *s) -{ -#ifdef CONFIG_SLUB_DEBUG - /* - * Debugging requires use of the padding between object - * and whatever may come after it. - */ - if (s->flags & (SLAB_RED_ZONE | SLAB_POISON)) - return s->objsize; - -#endif - /* - * If we have the need to store the freelist pointer - * back there or track user information then we can - * only use the space before that information. - */ - if (s->flags & (SLAB_DESTROY_BY_RCU | SLAB_STORE_USER)) - return s->inuse; - /* - * Else we can use all the padding etc for the allocation - */ - return s->size; -} - static inline void slab_post_alloc_hook(struct kmem_cache *s, gfp_t flags, void *object) { flags &= gfp_allowed_mask; -- GitLab From 3de4ade3d696db31d1543dce585ba6296f876612 Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Mon, 21 Feb 2011 19:12:27 +0100 Subject: [PATCH 0232/2822] ARM: 6751/1: vexpress: select applicable errata workarounds in Kconfig The Cortex-A9 tile on the Versatile Express suffers from a number of engineering errata. This patch selects workarounds in the ARCH_VEXPRESS_CA9X4 Kconfig entry so that users don't need to worry about which ones to apply. Reported-by: Ulrich Weigand Signed-off-by: Will Deacon Signed-off-by: Russell King --- arch/arm/mach-vexpress/Kconfig | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/arm/mach-vexpress/Kconfig b/arch/arm/mach-vexpress/Kconfig index 3f19b660a1654..931148487f0bc 100644 --- a/arch/arm/mach-vexpress/Kconfig +++ b/arch/arm/mach-vexpress/Kconfig @@ -5,5 +5,8 @@ config ARCH_VEXPRESS_CA9X4 bool "Versatile Express Cortex-A9x4 tile" select CPU_V7 select ARM_GIC + select ARM_ERRATA_720789 + select ARM_ERRATA_751472 + select ARM_ERRATA_753970 endmenu -- GitLab From a54aa76108619e5d8290b49081c2aaaeff5be9a2 Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Sun, 27 Feb 2011 16:43:24 -0500 Subject: [PATCH 0233/2822] ext4: don't leave PageWriteback set after memory failure In ext4_bio_write_page(), if the memory allocation for the struct ext4_io_page fails, it returns with the page's PageWriteback flag set. This will end up causing the page not to skip writeback in WB_SYNC_NONE mode, and in WB_SYNC_ALL mode (i.e., on a sync, fsync, or umount) the writeback daemon will get stuck forever on the wait_on_page_writeback() function in write_cache_pages_da(). Or, if journalling is enabled and the file gets deleted, it the journal thread can get stuck in journal_finish_inode_data_buffers() call to filemap_fdatawait(). Another place where things can get hung up is in truncate_inode_pages(), called out of ext4_evict_inode(). Fix this by not setting PageWriteback until after we have successfully allocated the struct ext4_io_page. Signed-off-by: "Theodore Ts'o" --- fs/ext4/page-io.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fs/ext4/page-io.c b/fs/ext4/page-io.c index 68d92a8f71d73..d5c391ffad7a3 100644 --- a/fs/ext4/page-io.c +++ b/fs/ext4/page-io.c @@ -381,8 +381,6 @@ int ext4_bio_write_page(struct ext4_io_submit *io, BUG_ON(!PageLocked(page)); BUG_ON(PageWriteback(page)); - set_page_writeback(page); - ClearPageError(page); io_page = kmem_cache_alloc(io_page_cachep, GFP_NOFS); if (!io_page) { @@ -393,6 +391,8 @@ int ext4_bio_write_page(struct ext4_io_submit *io, io_page->p_page = page; atomic_set(&io_page->p_count, 1); get_page(page); + set_page_writeback(page); + ClearPageError(page); for (bh = head = page_buffers(page), block_start = 0; bh != head || !block_start; -- GitLab From 4dd89fc6251a6bda2c18e71e7d266e983806579d Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Sun, 27 Feb 2011 17:23:47 -0500 Subject: [PATCH 0234/2822] ext4: suppress verbose debugging information if malloc-debug is off If CONFIG_EXT4_DEBUG is enabled, then if a block allocation fails due to disk being full, a verbose debugging message is printed, even if the malloc-debug switch has not been enabled. Suppress the debugging message so that nothing is printed unless malloc-debug has been turned on. Signed-off-by: "Theodore Ts'o" --- fs/ext4/mballoc.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c index 66bee7274d6a8..2f6f0dd08fcaf 100644 --- a/fs/ext4/mballoc.c +++ b/fs/ext4/mballoc.c @@ -3912,7 +3912,8 @@ static void ext4_mb_show_ac(struct ext4_allocation_context *ac) struct super_block *sb = ac->ac_sb; ext4_group_t ngroups, i; - if (EXT4_SB(sb)->s_mount_flags & EXT4_MF_FS_ABORTED) + if (!mb_enable_debug || + (EXT4_SB(sb)->s_mount_flags & EXT4_MF_FS_ABORTED)) return; printk(KERN_ERR "EXT4-fs: Can't allocate:" -- GitLab From 6d9c85eb700bd3ac59e63bb9de463dea1aca084c Mon Sep 17 00:00:00 2001 From: Yongqiang Yang Date: Sun, 27 Feb 2011 17:25:47 -0500 Subject: [PATCH 0235/2822] ext4: make FIEMAP and delayed allocation play well together Fix the FIEMAP ioctl so that it returns all of the page ranges which are still subject to delayed allocation. We were missing some cases if the file was sparse. Reported by Chris Mason : >We've had reports on btrfs that cp is giving us files full of zeros >instead of actually copying them. It was tracked down to a bug with >the btrfs fiemap implementation where it was returning holes for >delalloc ranges. > >Newer versions of cp are trusting fiemap to tell it where the holes >are, which does seem like a pretty neat trick. > >I decided to give xfs and ext4 a shot with a few tests cases too, xfs >passed with all the ones btrfs was getting wrong, and ext4 got the basic >delalloc case right. >$ mkfs.ext4 /dev/xxx >$ mount /dev/xxx /mnt >$ dd if=/dev/zero of=/mnt/foo bs=1M count=1 >$ fiemap-test foo >ext: 0 logical: [ 0.. 255] phys: 0.. 255 >flags: 0x007 tot: 256 > >Horray! But once we throw a hole in, things go bad: >$ mkfs.ext4 /dev/xxx >$ mount /dev/xxx /mnt >$ dd if=/dev/zero of=/mnt/foo bs=1M count=1 seek=1 >$ fiemap-test foo >< no output > > >We've got a delalloc extent after the hole and ext4 fiemap didn't find >it. If I run sync to kick the delalloc out: >$sync >$ fiemap-test foo >ext: 0 logical: [ 256.. 511] phys: 34048.. 34303 >flags: 0x001 tot: 256 > >fiemap-test is sitting in my /usr/local/bin, and I have no idea how it >got there. It's full of pretty comments so I know it isn't mine, but >you can grab it here: > >http://oss.oracle.com/~mason/fiemap-test.c > >xfsqa has a fiemap program too. After Fix, test results are as follows: ext: 0 logical: [ 256.. 511] phys: 0.. 255 flags: 0x007 tot: 256 ext: 0 logical: [ 256.. 511] phys: 33280.. 33535 flags: 0x001 tot: 256 $ mkfs.ext4 /dev/xxx $ mount /dev/xxx /mnt $ dd if=/dev/zero of=/mnt/foo bs=1M count=1 seek=1 $ sync $ dd if=/dev/zero of=/mnt/foo bs=1M count=1 seek=3 $ dd if=/dev/zero of=/mnt/foo bs=1M count=1 seek=5 $ fiemap-test foo ext: 0 logical: [ 256.. 511] phys: 33280.. 33535 flags: 0x000 tot: 256 ext: 1 logical: [ 768.. 1023] phys: 0.. 255 flags: 0x006 tot: 256 ext: 2 logical: [ 1280.. 1535] phys: 0.. 255 flags: 0x007 tot: 256 Tested-by: Eric Sandeen Reviewed-by: Andreas Dilger Signed-off-by: Yongqiang Yang Signed-off-by: "Theodore Ts'o" --- fs/ext4/extents.c | 187 ++++++++++++++++++++++++++++++++++++---------- 1 file changed, 148 insertions(+), 39 deletions(-) diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c index d16f6b5a140b7..9ea1bc64ca6df 100644 --- a/fs/ext4/extents.c +++ b/fs/ext4/extents.c @@ -3775,6 +3775,7 @@ int ext4_convert_unwritten_extents(struct inode *inode, loff_t offset, } return ret > 0 ? ret2 : ret; } + /* * Callback function called for each extent to gather FIEMAP information. */ @@ -3782,38 +3783,162 @@ static int ext4_ext_fiemap_cb(struct inode *inode, struct ext4_ext_path *path, struct ext4_ext_cache *newex, struct ext4_extent *ex, void *data) { - struct fiemap_extent_info *fieinfo = data; - unsigned char blksize_bits = inode->i_sb->s_blocksize_bits; __u64 logical; __u64 physical; __u64 length; + loff_t size; __u32 flags = 0; - int error; + int ret = 0; + struct fiemap_extent_info *fieinfo = data; + unsigned char blksize_bits; - logical = (__u64)newex->ec_block << blksize_bits; + blksize_bits = inode->i_sb->s_blocksize_bits; + logical = (__u64)newex->ec_block << blksize_bits; if (newex->ec_start == 0) { - pgoff_t offset; - struct page *page; + /* + * No extent in extent-tree contains block @newex->ec_start, + * then the block may stay in 1)a hole or 2)delayed-extent. + * + * Holes or delayed-extents are processed as follows. + * 1. lookup dirty pages with specified range in pagecache. + * If no page is got, then there is no delayed-extent and + * return with EXT_CONTINUE. + * 2. find the 1st mapped buffer, + * 3. check if the mapped buffer is both in the request range + * and a delayed buffer. If not, there is no delayed-extent, + * then return. + * 4. a delayed-extent is found, the extent will be collected. + */ + ext4_lblk_t end = 0; + pgoff_t last_offset; + pgoff_t offset; + pgoff_t index; + struct page **pages = NULL; struct buffer_head *bh = NULL; + struct buffer_head *head = NULL; + unsigned int nr_pages = PAGE_SIZE / sizeof(struct page *); + + pages = kmalloc(PAGE_SIZE, GFP_KERNEL); + if (pages == NULL) + return -ENOMEM; offset = logical >> PAGE_SHIFT; - page = find_get_page(inode->i_mapping, offset); - if (!page || !page_has_buffers(page)) - return EXT_CONTINUE; +repeat: + last_offset = offset; + head = NULL; + ret = find_get_pages_tag(inode->i_mapping, &offset, + PAGECACHE_TAG_DIRTY, nr_pages, pages); + + if (!(flags & FIEMAP_EXTENT_DELALLOC)) { + /* First time, try to find a mapped buffer. */ + if (ret == 0) { +out: + for (index = 0; index < ret; index++) + page_cache_release(pages[index]); + /* just a hole. */ + kfree(pages); + return EXT_CONTINUE; + } - bh = page_buffers(page); + /* Try to find the 1st mapped buffer. */ + end = ((__u64)pages[0]->index << PAGE_SHIFT) >> + blksize_bits; + if (!page_has_buffers(pages[0])) + goto out; + head = page_buffers(pages[0]); + if (!head) + goto out; - if (!bh) - return EXT_CONTINUE; + bh = head; + do { + if (buffer_mapped(bh)) { + /* get the 1st mapped buffer. */ + if (end > newex->ec_block + + newex->ec_len) + /* The buffer is out of + * the request range. + */ + goto out; + goto found_mapped_buffer; + } + bh = bh->b_this_page; + end++; + } while (bh != head); - if (buffer_delay(bh)) { - flags |= FIEMAP_EXTENT_DELALLOC; - page_cache_release(page); + /* No mapped buffer found. */ + goto out; } else { - page_cache_release(page); - return EXT_CONTINUE; + /*Find contiguous delayed buffers. */ + if (ret > 0 && pages[0]->index == last_offset) + head = page_buffers(pages[0]); + bh = head; + } + +found_mapped_buffer: + if (bh != NULL && buffer_delay(bh)) { + /* 1st or contiguous delayed buffer found. */ + if (!(flags & FIEMAP_EXTENT_DELALLOC)) { + /* + * 1st delayed buffer found, record + * the start of extent. + */ + flags |= FIEMAP_EXTENT_DELALLOC; + newex->ec_block = end; + logical = (__u64)end << blksize_bits; + } + /* Find contiguous delayed buffers. */ + do { + if (!buffer_delay(bh)) + goto found_delayed_extent; + bh = bh->b_this_page; + end++; + } while (bh != head); + + for (index = 1; index < ret; index++) { + if (!page_has_buffers(pages[index])) { + bh = NULL; + break; + } + head = page_buffers(pages[index]); + if (!head) { + bh = NULL; + break; + } + if (pages[index]->index != + pages[0]->index + index) { + /* Blocks are not contiguous. */ + bh = NULL; + break; + } + bh = head; + do { + if (!buffer_delay(bh)) + /* Delayed-extent ends. */ + goto found_delayed_extent; + bh = bh->b_this_page; + end++; + } while (bh != head); + } + } else if (!(flags & FIEMAP_EXTENT_DELALLOC)) + /* a hole found. */ + goto out; + +found_delayed_extent: + newex->ec_len = min(end - newex->ec_block, + (ext4_lblk_t)EXT_INIT_MAX_LEN); + if (ret == nr_pages && bh != NULL && + newex->ec_len < EXT_INIT_MAX_LEN && + buffer_delay(bh)) { + /* Have not collected an extent and continue. */ + for (index = 0; index < ret; index++) + page_cache_release(pages[index]); + goto repeat; } + + for (index = 0; index < ret; index++) + page_cache_release(pages[index]); + kfree(pages); } physical = (__u64)newex->ec_start << blksize_bits; @@ -3822,32 +3947,16 @@ static int ext4_ext_fiemap_cb(struct inode *inode, struct ext4_ext_path *path, if (ex && ext4_ext_is_uninitialized(ex)) flags |= FIEMAP_EXTENT_UNWRITTEN; - /* - * If this extent reaches EXT_MAX_BLOCK, it must be last. - * - * Or if ext4_ext_next_allocated_block is EXT_MAX_BLOCK, - * this also indicates no more allocated blocks. - * - * XXX this might miss a single-block extent at EXT_MAX_BLOCK - */ - if (ext4_ext_next_allocated_block(path) == EXT_MAX_BLOCK || - newex->ec_block + newex->ec_len - 1 == EXT_MAX_BLOCK) { - loff_t size = i_size_read(inode); - loff_t bs = EXT4_BLOCK_SIZE(inode->i_sb); - + size = i_size_read(inode); + if (logical + length >= size) flags |= FIEMAP_EXTENT_LAST; - if ((flags & FIEMAP_EXTENT_DELALLOC) && - logical+length > size) - length = (size - logical + bs - 1) & ~(bs-1); - } - error = fiemap_fill_next_extent(fieinfo, logical, physical, + ret = fiemap_fill_next_extent(fieinfo, logical, physical, length, flags); - if (error < 0) - return error; - if (error == 1) + if (ret < 0) + return ret; + if (ret == 1) return EXT_BREAK; - return EXT_CONTINUE; } -- GitLab From 32a9bb57d7c1fd04ae0f72b8f671501f000a0e9f Mon Sep 17 00:00:00 2001 From: Manish Katiyar Date: Sun, 27 Feb 2011 20:42:06 -0500 Subject: [PATCH 0236/2822] ext4: fix missing iput of root inode for some mount error paths This assures that the root inode is not leaked, and that sb->s_root is NULL, which will prevent generic_shutdown_super() from doing extra work, including call sync_filesystem, which ultimately results in ext4_sync_fs() getting called with an uninitialized struct super, which is the cause of the crash noted in Kernel Bugzilla #26752. https://bugzilla.kernel.org/show_bug.cgi?id=26752 Signed-off-by: Manish Katiyar Signed-off-by: "Theodore Ts'o" --- fs/ext4/super.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/fs/ext4/super.c b/fs/ext4/super.c index 33c398785e53c..bd6e86aa82aa0 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c @@ -3521,17 +3521,16 @@ no_journal: if (IS_ERR(root)) { ext4_msg(sb, KERN_ERR, "get root inode failed"); ret = PTR_ERR(root); + root = NULL; goto failed_mount4; } if (!S_ISDIR(root->i_mode) || !root->i_blocks || !root->i_size) { - iput(root); ext4_msg(sb, KERN_ERR, "corrupt root inode, run e2fsck"); goto failed_mount4; } sb->s_root = d_alloc_root(root); if (!sb->s_root) { ext4_msg(sb, KERN_ERR, "get root dentry failed"); - iput(root); ret = -ENOMEM; goto failed_mount4; } @@ -3647,6 +3646,8 @@ cantfind_ext4: goto failed_mount; failed_mount4: + iput(root); + sb->s_root = NULL; ext4_msg(sb, KERN_ERR, "mount failed"); destroy_workqueue(EXT4_SB(sb)->dio_unwritten_wq); failed_mount_wq: -- GitLab From 8e8eaabefee3ff645b9551ee32c6c54c7d80ad19 Mon Sep 17 00:00:00 2001 From: Amir Goldstein Date: Sun, 27 Feb 2011 23:32:12 -0500 Subject: [PATCH 0237/2822] ext4: use the nblocks arg to ext4_truncate_restart_trans() nblocks is passed into ext4_truncate_restart_trans() from ext4_ext_truncate_extend_restart() with a value different from the default blocks_for_truncate(), but is being ignored. The two other calls to ext4_truncate_restart_trans() already pass the default value, which is then being recalculated inside the function. Fix the problem by using the passed argument. Signed-off-by: Amir Goldstein --- fs/ext4/inode.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index dcc2287433b6f..67e7a3caf9ed7 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -173,7 +173,7 @@ int ext4_truncate_restart_trans(handle_t *handle, struct inode *inode, BUG_ON(EXT4_JOURNAL(inode) == NULL); jbd_debug(2, "restarting handle %p\n", handle); up_write(&EXT4_I(inode)->i_data_sem); - ret = ext4_journal_restart(handle, blocks_for_truncate(inode)); + ret = ext4_journal_restart(handle, nblocks); down_write(&EXT4_I(inode)->i_data_sem); ext4_discard_preallocations(inode); -- GitLab From d39195c33bb1b5fdcb0f416e8a0b34bfdb07a027 Mon Sep 17 00:00:00 2001 From: Amir Goldstein Date: Mon, 28 Feb 2011 00:53:45 -0500 Subject: [PATCH 0238/2822] ext4: skip orphan cleanup if fs has unknown ROCOMPAT features Orphan cleanup is currently executed even if the file system has some number of unknown ROCOMPAT features, which deletes inodes and frees blocks, which could be very bad for some RO_COMPAT features, especially the SNAPSHOT feature. This patch skips the orphan cleanup if it contains readonly compatible features not known by this ext4 implementation, which would prevent the fs from being mounted (or remounted) readwrite. Signed-off-by: Amir Goldstein Signed-off-by: "Theodore Ts'o" --- fs/ext4/super.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/fs/ext4/super.c b/fs/ext4/super.c index bd6e86aa82aa0..9eaec22aa088e 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c @@ -75,6 +75,7 @@ static void ext4_write_super(struct super_block *sb); static int ext4_freeze(struct super_block *sb); static struct dentry *ext4_mount(struct file_system_type *fs_type, int flags, const char *dev_name, void *data); +static int ext4_feature_set_ok(struct super_block *sb, int readonly); static void ext4_destroy_lazyinit_thread(void); static void ext4_unregister_li_request(struct super_block *sb); static void ext4_clear_request_list(void); @@ -2117,6 +2118,13 @@ static void ext4_orphan_cleanup(struct super_block *sb, return; } + /* Check if feature set would not allow a r/w mount */ + if (!ext4_feature_set_ok(sb, 0)) { + ext4_msg(sb, KERN_INFO, "Skipping orphan cleanup due to " + "unknown ROCOMPAT features"); + return; + } + if (EXT4_SB(sb)->s_mount_state & EXT4_ERROR_FS) { if (es->s_last_orphan) jbd_debug(1, "Errors on filesystem, " -- GitLab From d6ccc442b12102414c1343f0adacaa8a1aaa516c Mon Sep 17 00:00:00 2001 From: Heikki Krogerus Date: Fri, 25 Feb 2011 13:56:36 +0200 Subject: [PATCH 0239/2822] twl4030_charger: Make the driver atomic notifier safe This queues work from the otg notification where the i2c operations can be safely made. Needed for atomic otg notifiers. Signed-off-by: Heikki Krogerus Tested-by: Grazvydas Ignotas Signed-off-by: Anton Vorontsov --- drivers/power/twl4030_charger.c | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/drivers/power/twl4030_charger.c b/drivers/power/twl4030_charger.c index ff1f42398a2ed..92c16e1677bd7 100644 --- a/drivers/power/twl4030_charger.c +++ b/drivers/power/twl4030_charger.c @@ -71,8 +71,11 @@ struct twl4030_bci { struct power_supply usb; struct otg_transceiver *transceiver; struct notifier_block otg_nb; + struct work_struct work; int irq_chg; int irq_bci; + + unsigned long event; }; /* @@ -258,14 +261,11 @@ static irqreturn_t twl4030_bci_interrupt(int irq, void *arg) return IRQ_HANDLED; } -static int twl4030_bci_usb_ncb(struct notifier_block *nb, unsigned long val, - void *priv) +static void twl4030_bci_usb_work(struct work_struct *data) { - struct twl4030_bci *bci = container_of(nb, struct twl4030_bci, otg_nb); + struct twl4030_bci *bci = container_of(data, struct twl4030_bci, work); - dev_dbg(bci->dev, "OTG notify %lu\n", val); - - switch (val) { + switch (bci->event) { case USB_EVENT_VBUS: case USB_EVENT_CHARGER: twl4030_charger_enable_usb(bci, true); @@ -274,6 +274,17 @@ static int twl4030_bci_usb_ncb(struct notifier_block *nb, unsigned long val, twl4030_charger_enable_usb(bci, false); break; } +} + +static int twl4030_bci_usb_ncb(struct notifier_block *nb, unsigned long val, + void *priv) +{ + struct twl4030_bci *bci = container_of(nb, struct twl4030_bci, otg_nb); + + dev_dbg(bci->dev, "OTG notify %lu\n", val); + + bci->event = val; + schedule_work(&bci->work); return NOTIFY_OK; } @@ -466,6 +477,8 @@ static int __init twl4030_bci_probe(struct platform_device *pdev) goto fail_bci_irq; } + INIT_WORK(&bci->work, twl4030_bci_usb_work); + bci->transceiver = otg_get_transceiver(); if (bci->transceiver != NULL) { bci->otg_nb.notifier_call = twl4030_bci_usb_ncb; -- GitLab From 15e123e5d7e8ee9ba3717e743d8eb5fd0fe57712 Mon Sep 17 00:00:00 2001 From: Thomas Renninger Date: Sun, 27 Feb 2011 22:36:43 +0100 Subject: [PATCH 0240/2822] intel_idle: Rename cpuidle states Userspace apps might have to cut off parts off the idle state name for display reasons. Switch NHM-C1 to C1-NHM (and others) so that a cut off name is unique and makes sense to the user. Signed-off-by: Thomas Renninger CC: lenb@kernel.org Signed-off-by: Len Brown --- drivers/idle/intel_idle.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/drivers/idle/intel_idle.c b/drivers/idle/intel_idle.c index 4a5c4a44ffb17..a46dddf610788 100644 --- a/drivers/idle/intel_idle.c +++ b/drivers/idle/intel_idle.c @@ -107,7 +107,7 @@ static unsigned long long auto_demotion_disable_flags; static struct cpuidle_state nehalem_cstates[MWAIT_MAX_NUM_CSTATES] = { { /* MWAIT C0 */ }, { /* MWAIT C1 */ - .name = "NHM-C1", + .name = "C1-NHM", .desc = "MWAIT 0x00", .driver_data = (void *) 0x00, .flags = CPUIDLE_FLAG_TIME_VALID, @@ -115,7 +115,7 @@ static struct cpuidle_state nehalem_cstates[MWAIT_MAX_NUM_CSTATES] = { .target_residency = 6, .enter = &intel_idle }, { /* MWAIT C2 */ - .name = "NHM-C3", + .name = "C3-NHM", .desc = "MWAIT 0x10", .driver_data = (void *) 0x10, .flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED, @@ -123,7 +123,7 @@ static struct cpuidle_state nehalem_cstates[MWAIT_MAX_NUM_CSTATES] = { .target_residency = 80, .enter = &intel_idle }, { /* MWAIT C3 */ - .name = "NHM-C6", + .name = "C6-NHM", .desc = "MWAIT 0x20", .driver_data = (void *) 0x20, .flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED, @@ -135,7 +135,7 @@ static struct cpuidle_state nehalem_cstates[MWAIT_MAX_NUM_CSTATES] = { static struct cpuidle_state snb_cstates[MWAIT_MAX_NUM_CSTATES] = { { /* MWAIT C0 */ }, { /* MWAIT C1 */ - .name = "SNB-C1", + .name = "C1-SNB", .desc = "MWAIT 0x00", .driver_data = (void *) 0x00, .flags = CPUIDLE_FLAG_TIME_VALID, @@ -143,7 +143,7 @@ static struct cpuidle_state snb_cstates[MWAIT_MAX_NUM_CSTATES] = { .target_residency = 1, .enter = &intel_idle }, { /* MWAIT C2 */ - .name = "SNB-C3", + .name = "C3-SNB", .desc = "MWAIT 0x10", .driver_data = (void *) 0x10, .flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED, @@ -151,7 +151,7 @@ static struct cpuidle_state snb_cstates[MWAIT_MAX_NUM_CSTATES] = { .target_residency = 211, .enter = &intel_idle }, { /* MWAIT C3 */ - .name = "SNB-C6", + .name = "C6-SNB", .desc = "MWAIT 0x20", .driver_data = (void *) 0x20, .flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED, @@ -159,7 +159,7 @@ static struct cpuidle_state snb_cstates[MWAIT_MAX_NUM_CSTATES] = { .target_residency = 345, .enter = &intel_idle }, { /* MWAIT C4 */ - .name = "SNB-C7", + .name = "C7-SNB", .desc = "MWAIT 0x30", .driver_data = (void *) 0x30, .flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED, @@ -171,7 +171,7 @@ static struct cpuidle_state snb_cstates[MWAIT_MAX_NUM_CSTATES] = { static struct cpuidle_state atom_cstates[MWAIT_MAX_NUM_CSTATES] = { { /* MWAIT C0 */ }, { /* MWAIT C1 */ - .name = "ATM-C1", + .name = "C1-ATM", .desc = "MWAIT 0x00", .driver_data = (void *) 0x00, .flags = CPUIDLE_FLAG_TIME_VALID, @@ -179,7 +179,7 @@ static struct cpuidle_state atom_cstates[MWAIT_MAX_NUM_CSTATES] = { .target_residency = 4, .enter = &intel_idle }, { /* MWAIT C2 */ - .name = "ATM-C2", + .name = "C2-ATM", .desc = "MWAIT 0x10", .driver_data = (void *) 0x10, .flags = CPUIDLE_FLAG_TIME_VALID, @@ -188,7 +188,7 @@ static struct cpuidle_state atom_cstates[MWAIT_MAX_NUM_CSTATES] = { .enter = &intel_idle }, { /* MWAIT C3 */ }, { /* MWAIT C4 */ - .name = "ATM-C4", + .name = "C4-ATM", .desc = "MWAIT 0x30", .driver_data = (void *) 0x30, .flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED, @@ -197,7 +197,7 @@ static struct cpuidle_state atom_cstates[MWAIT_MAX_NUM_CSTATES] = { .enter = &intel_idle }, { /* MWAIT C5 */ }, { /* MWAIT C6 */ - .name = "ATM-C6", + .name = "C6-ATM", .desc = "MWAIT 0x52", .driver_data = (void *) 0x52, .flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED, -- GitLab From b616844310a6c8a4ab405d3436bbb6e53cfd852f Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Mon, 28 Feb 2011 13:12:38 -0500 Subject: [PATCH 0241/2822] ext4: optimize ext4_bio_write_page() when no extent conversion is needed If no extent conversion is required, wake up any processes waiting for the page's writeback to be complete and free the ext4_io_end structure directly in ext4_end_bio() instead of dropping it on the linked list (which requires taking a spinlock to queue and dequeue the io_end structure), and waiting for the workqueue to do this work. This removes an extra scheduling delay before process waiting for an fsync() to complete gets woken up, and it also reduces the CPU overhead for a random write workload. Signed-off-by: "Theodore Ts'o" --- fs/ext4/page-io.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/fs/ext4/page-io.c b/fs/ext4/page-io.c index d5c391ffad7a3..0cfd03e19d7d2 100644 --- a/fs/ext4/page-io.c +++ b/fs/ext4/page-io.c @@ -259,6 +259,11 @@ static void ext4_end_bio(struct bio *bio, int error) bi_sector >> (inode->i_blkbits - 9)); } + if (!(io_end->flag & EXT4_IO_END_UNWRITTEN)) { + ext4_free_io_end(io_end); + return; + } + /* Add the io_end to per-inode completed io list*/ spin_lock_irqsave(&EXT4_I(inode)->i_completed_io_lock, flags); list_add_tail(&io_end->list, &EXT4_I(inode)->i_completed_io_list); -- GitLab From b7fc0ff09d24b372dc04b0c02b80659c0a66fdfe Mon Sep 17 00:00:00 2001 From: Phillip Lougher Date: Mon, 28 Feb 2011 01:45:42 +0000 Subject: [PATCH 0242/2822] Squashfs: extend decompressor framework to handle compression options Extend decompressor framework to handle compression options stored in the filesystem. These options can be used by the relevant decompressor at initialisation time to over-ride defaults. The presence of compression options in the filesystem is indicated by the COMP_OPT filesystem flag. If present the data is read from the filesystem and passed to the decompressor init function. The decompressor init function signature has been extended to take this data. Also update the init function signature in the glib, lzo and xz decompressor wrappers. Signed-off-by: Phillip Lougher --- fs/squashfs/decompressor.c | 34 ++++++++++++++++++++++++++++++++++ fs/squashfs/decompressor.h | 7 +------ fs/squashfs/lzo_wrapper.c | 4 ++-- fs/squashfs/squashfs.h | 1 + fs/squashfs/squashfs_fs.h | 4 ++++ fs/squashfs/super.c | 11 +++++++---- fs/squashfs/xz_wrapper.c | 5 +++-- fs/squashfs/zlib_wrapper.c | 4 ++-- 8 files changed, 54 insertions(+), 16 deletions(-) diff --git a/fs/squashfs/decompressor.c b/fs/squashfs/decompressor.c index a5940e54c4dde..e921bd213738f 100644 --- a/fs/squashfs/decompressor.c +++ b/fs/squashfs/decompressor.c @@ -23,6 +23,7 @@ #include #include +#include #include #include "squashfs_fs.h" @@ -74,3 +75,36 @@ const struct squashfs_decompressor *squashfs_lookup_decompressor(int id) return decompressor[i]; } + + +void *squashfs_decompressor_init(struct super_block *sb, unsigned short flags) +{ + struct squashfs_sb_info *msblk = sb->s_fs_info; + void *strm, *buffer = NULL; + int length = 0; + + /* + * Read decompressor specific options from file system if present + */ + if (SQUASHFS_COMP_OPTS(flags)) { + buffer = kmalloc(PAGE_CACHE_SIZE, GFP_KERNEL); + if (buffer == NULL) + return ERR_PTR(-ENOMEM); + + length = squashfs_read_data(sb, &buffer, + sizeof(struct squashfs_super_block), 0, NULL, + PAGE_CACHE_SIZE, 1); + + if (length < 0) { + strm = ERR_PTR(length); + goto finished; + } + } + + strm = msblk->decompressor->init(msblk, buffer, length); + +finished: + kfree(buffer); + + return strm; +} diff --git a/fs/squashfs/decompressor.h b/fs/squashfs/decompressor.h index 3b305a70f7aa2..099745ad5691e 100644 --- a/fs/squashfs/decompressor.h +++ b/fs/squashfs/decompressor.h @@ -24,7 +24,7 @@ */ struct squashfs_decompressor { - void *(*init)(struct squashfs_sb_info *); + void *(*init)(struct squashfs_sb_info *, void *, int); void (*free)(void *); int (*decompress)(struct squashfs_sb_info *, void **, struct buffer_head **, int, int, int, int, int); @@ -33,11 +33,6 @@ struct squashfs_decompressor { int supported; }; -static inline void *squashfs_decompressor_init(struct squashfs_sb_info *msblk) -{ - return msblk->decompressor->init(msblk); -} - static inline void squashfs_decompressor_free(struct squashfs_sb_info *msblk, void *s) { diff --git a/fs/squashfs/lzo_wrapper.c b/fs/squashfs/lzo_wrapper.c index 7da759e34c525..00f4dfc5f0884 100644 --- a/fs/squashfs/lzo_wrapper.c +++ b/fs/squashfs/lzo_wrapper.c @@ -37,7 +37,7 @@ struct squashfs_lzo { void *output; }; -static void *lzo_init(struct squashfs_sb_info *msblk) +static void *lzo_init(struct squashfs_sb_info *msblk, void *buff, int len) { int block_size = max_t(int, msblk->block_size, SQUASHFS_METADATA_SIZE); @@ -58,7 +58,7 @@ failed2: failed: ERROR("Failed to allocate lzo workspace\n"); kfree(stream); - return NULL; + return ERR_PTR(-ENOMEM); } diff --git a/fs/squashfs/squashfs.h b/fs/squashfs/squashfs.h index ba729d808876d..1f2e608b87858 100644 --- a/fs/squashfs/squashfs.h +++ b/fs/squashfs/squashfs.h @@ -48,6 +48,7 @@ extern int squashfs_read_table(struct super_block *, void *, u64, int); /* decompressor.c */ extern const struct squashfs_decompressor *squashfs_lookup_decompressor(int); +extern void *squashfs_decompressor_init(struct super_block *, unsigned short); /* export.c */ extern __le64 *squashfs_read_inode_lookup_table(struct super_block *, u64, diff --git a/fs/squashfs/squashfs_fs.h b/fs/squashfs/squashfs_fs.h index 39533feffd6d3..4582c568ef4d1 100644 --- a/fs/squashfs/squashfs_fs.h +++ b/fs/squashfs/squashfs_fs.h @@ -57,6 +57,7 @@ #define SQUASHFS_ALWAYS_FRAG 5 #define SQUASHFS_DUPLICATE 6 #define SQUASHFS_EXPORT 7 +#define SQUASHFS_COMP_OPT 10 #define SQUASHFS_BIT(flag, bit) ((flag >> bit) & 1) @@ -81,6 +82,9 @@ #define SQUASHFS_EXPORTABLE(flags) SQUASHFS_BIT(flags, \ SQUASHFS_EXPORT) +#define SQUASHFS_COMP_OPTS(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_COMP_OPT) + /* Max number of types and file types */ #define SQUASHFS_DIR_TYPE 1 #define SQUASHFS_REG_TYPE 2 diff --git a/fs/squashfs/super.c b/fs/squashfs/super.c index 20700b9f2b4cd..95467db71a8e5 100644 --- a/fs/squashfs/super.c +++ b/fs/squashfs/super.c @@ -199,10 +199,6 @@ static int squashfs_fill_super(struct super_block *sb, void *data, int silent) err = -ENOMEM; - msblk->stream = squashfs_decompressor_init(msblk); - if (msblk->stream == NULL) - goto failed_mount; - msblk->block_cache = squashfs_cache_init("metadata", SQUASHFS_CACHED_BLKS, SQUASHFS_METADATA_SIZE); if (msblk->block_cache == NULL) @@ -215,6 +211,13 @@ static int squashfs_fill_super(struct super_block *sb, void *data, int silent) goto failed_mount; } + msblk->stream = squashfs_decompressor_init(sb, flags); + if (IS_ERR(msblk->stream)) { + err = PTR_ERR(msblk->stream); + msblk->stream = NULL; + goto failed_mount; + } + /* Allocate and read id index table */ msblk->id_table = squashfs_read_id_index_table(sb, le64_to_cpu(sblk->id_table_start), le16_to_cpu(sblk->no_ids)); diff --git a/fs/squashfs/xz_wrapper.c b/fs/squashfs/xz_wrapper.c index c4eb400182564..397adea72eb96 100644 --- a/fs/squashfs/xz_wrapper.c +++ b/fs/squashfs/xz_wrapper.c @@ -38,7 +38,8 @@ struct squashfs_xz { struct xz_buf buf; }; -static void *squashfs_xz_init(struct squashfs_sb_info *msblk) +static void *squashfs_xz_init(struct squashfs_sb_info *msblk, void *buff, + int len) { int block_size = max_t(int, msblk->block_size, SQUASHFS_METADATA_SIZE); @@ -55,7 +56,7 @@ static void *squashfs_xz_init(struct squashfs_sb_info *msblk) failed: ERROR("Failed to allocate xz workspace\n"); kfree(stream); - return NULL; + return ERR_PTR(-ENOMEM); } diff --git a/fs/squashfs/zlib_wrapper.c b/fs/squashfs/zlib_wrapper.c index 4661ae2b1cec8..195b0d035e9b4 100644 --- a/fs/squashfs/zlib_wrapper.c +++ b/fs/squashfs/zlib_wrapper.c @@ -32,7 +32,7 @@ #include "squashfs.h" #include "decompressor.h" -static void *zlib_init(struct squashfs_sb_info *dummy) +static void *zlib_init(struct squashfs_sb_info *dummy, void *buff, int len) { z_stream *stream = kmalloc(sizeof(z_stream), GFP_KERNEL); if (stream == NULL) @@ -47,7 +47,7 @@ static void *zlib_init(struct squashfs_sb_info *dummy) failed: ERROR("Failed to allocate zlib workspace\n"); kfree(stream); - return NULL; + return ERR_PTR(-ENOMEM); } -- GitLab From ff750311d30acc9564ef577050794953eee59f01 Mon Sep 17 00:00:00 2001 From: Phillip Lougher Date: Mon, 28 Feb 2011 15:31:46 +0000 Subject: [PATCH 0243/2822] Squashfs: add compression options support to xz decompressor Pass the dictionary size used to compress datablocks. Using a dictionary size less than the block size saves memory overhead, in many cases without adversely affecting compression ratio. Signed-off-by: Phillip Lougher --- fs/squashfs/xz_wrapper.c | 49 +++++++++++++++++++++++++++++++++------- 1 file changed, 41 insertions(+), 8 deletions(-) diff --git a/fs/squashfs/xz_wrapper.c b/fs/squashfs/xz_wrapper.c index 397adea72eb96..06d0d11b482a6 100644 --- a/fs/squashfs/xz_wrapper.c +++ b/fs/squashfs/xz_wrapper.c @@ -26,6 +26,7 @@ #include #include #include +#include #include "squashfs_fs.h" #include "squashfs_fs_sb.h" @@ -38,25 +39,57 @@ struct squashfs_xz { struct xz_buf buf; }; +struct comp_opts { + __le32 dictionary_size; + __le32 flags; +}; + static void *squashfs_xz_init(struct squashfs_sb_info *msblk, void *buff, int len) { - int block_size = max_t(int, msblk->block_size, SQUASHFS_METADATA_SIZE); + struct comp_opts *comp_opts = buff; + struct squashfs_xz *stream; + int dict_size = msblk->block_size; + int err, n; + + if (comp_opts) { + /* check compressor options are the expected length */ + if (len < sizeof(*comp_opts)) { + err = -EIO; + goto failed; + } - struct squashfs_xz *stream = kmalloc(sizeof(*stream), GFP_KERNEL); - if (stream == NULL) + dict_size = le32_to_cpu(comp_opts->dictionary_size); + + /* the dictionary size should be 2^n or 2^n+2^(n+1) */ + n = ffs(dict_size) - 1; + if (dict_size != (1 << n) && dict_size != (1 << n) + + (1 << (n + 1))) { + err = -EIO; + goto failed; + } + } + + dict_size = max_t(int, dict_size, SQUASHFS_METADATA_SIZE); + + stream = kmalloc(sizeof(*stream), GFP_KERNEL); + if (stream == NULL) { + err = -ENOMEM; goto failed; + } - stream->state = xz_dec_init(XZ_PREALLOC, block_size); - if (stream->state == NULL) + stream->state = xz_dec_init(XZ_PREALLOC, dict_size); + if (stream->state == NULL) { + kfree(stream); + err = -ENOMEM; goto failed; + } return stream; failed: - ERROR("Failed to allocate xz workspace\n"); - kfree(stream); - return ERR_PTR(-ENOMEM); + ERROR("Failed to initialise xz decompressor\n"); + return ERR_PTR(err); } -- GitLab From 681ffe2e4316801529fdafe379743d1d41fe2086 Mon Sep 17 00:00:00 2001 From: Phillip Lougher Date: Mon, 28 Feb 2011 16:21:34 +0000 Subject: [PATCH 0244/2822] Squashfs: Update Kconfig help text to include xz compression Signed-off-by: Phillip Lougher --- fs/squashfs/Kconfig | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/fs/squashfs/Kconfig b/fs/squashfs/Kconfig index aa68a8a315180..efc309fa30359 100644 --- a/fs/squashfs/Kconfig +++ b/fs/squashfs/Kconfig @@ -5,12 +5,12 @@ config SQUASHFS help Saying Y here includes support for SquashFS 4.0 (a Compressed Read-Only File System). Squashfs is a highly compressed read-only - filesystem for Linux. It uses zlib/lzo compression to compress both - files, inodes and directories. Inodes in the system are very small - and all blocks are packed to minimise data overhead. Block sizes - greater than 4K are supported up to a maximum of 1 Mbytes (default - block size 128K). SquashFS 4.0 supports 64 bit filesystems and files - (larger than 4GB), full uid/gid information, hard links and + filesystem for Linux. It uses zlib, lzo or xz compression to + compress both files, inodes and directories. Inodes in the system + are very small and all blocks are packed to minimise data overhead. + Block sizes greater than 4K are supported up to a maximum of 1 Mbytes + (default block size 128K). SquashFS 4.0 supports 64 bit filesystems + and files (larger than 4GB), full uid/gid information, hard links and timestamps. Squashfs is intended for general read-only filesystem use, for -- GitLab From 4c1d204cde1470863e78aa0e6f55246c57f15038 Mon Sep 17 00:00:00 2001 From: Phillip Lougher Date: Mon, 28 Feb 2011 16:32:39 +0000 Subject: [PATCH 0245/2822] Squashfs: Update documentation to include compression options Signed-off-by: Phillip Lougher --- Documentation/filesystems/squashfs.txt | 28 +++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/Documentation/filesystems/squashfs.txt b/Documentation/filesystems/squashfs.txt index 66699afd66cad..2d78f19118449 100644 --- a/Documentation/filesystems/squashfs.txt +++ b/Documentation/filesystems/squashfs.txt @@ -59,12 +59,15 @@ obtained from this site also. 3. SQUASHFS FILESYSTEM DESIGN ----------------------------- -A squashfs filesystem consists of a maximum of eight parts, packed together on a byte -alignment: +A squashfs filesystem consists of a maximum of nine parts, packed together on a +byte alignment: --------------- | superblock | |---------------| + | compression | + | options | + |---------------| | datablocks | | & fragments | |---------------| @@ -91,7 +94,14 @@ the source directory, and checked for duplicates. Once all file data has been written the completed inode, directory, fragment, export and uid/gid lookup tables are written. -3.1 Inodes +3.1 Compression options +----------------------- + +Compressors can optionally support compression specific options (e.g. +dictionary size). If non-default compression options have been used, then +these are stored here. + +3.2 Inodes ---------- Metadata (inodes and directories) are compressed in 8Kbyte blocks. Each @@ -114,7 +124,7 @@ directory inode are defined: inodes optimised for frequently occurring regular files and directories, and extended types where extra information has to be stored. -3.2 Directories +3.3 Directories --------------- Like inodes, directories are packed into compressed metadata blocks, stored @@ -144,7 +154,7 @@ decompressed to do a lookup irrespective of the length of the directory. This scheme has the advantage that it doesn't require extra memory overhead and doesn't require much extra storage on disk. -3.3 File data +3.4 File data ------------- Regular files consist of a sequence of contiguous compressed blocks, and/or a @@ -163,7 +173,7 @@ Larger files use multiple slots, with 1.75 TiB files using all 8 slots. The index cache is designed to be memory efficient, and by default uses 16 KiB. -3.4 Fragment lookup table +3.5 Fragment lookup table ------------------------- Regular files can contain a fragment index which is mapped to a fragment @@ -173,7 +183,7 @@ A second index table is used to locate these. This second index table for speed of access (and because it is small) is read at mount time and cached in memory. -3.5 Uid/gid lookup table +3.6 Uid/gid lookup table ------------------------ For space efficiency regular files store uid and gid indexes, which are @@ -182,7 +192,7 @@ stored compressed into metadata blocks. A second index table is used to locate these. This second index table for speed of access (and because it is small) is read at mount time and cached in memory. -3.6 Export table +3.7 Export table ---------------- To enable Squashfs filesystems to be exportable (via NFS etc.) filesystems @@ -196,7 +206,7 @@ This table is stored compressed into metadata blocks. A second index table is used to locate these. This second index table for speed of access (and because it is small) is read at mount time and cached in memory. -3.7 Xattr table +3.8 Xattr table --------------- The xattr table contains extended attributes for each inode. The xattrs -- GitLab From 3ad126641c05f93d2fa153bb8ff762fb4cdbb885 Mon Sep 17 00:00:00 2001 From: Phillip Lougher Date: Mon, 28 Feb 2011 16:42:20 +0000 Subject: [PATCH 0246/2822] Squashfs: xz_wrapper doesn't need to include squashfs_fs_i.h anymore Signed-off-by: Phillip Lougher --- fs/squashfs/xz_wrapper.c | 1 - 1 file changed, 1 deletion(-) diff --git a/fs/squashfs/xz_wrapper.c b/fs/squashfs/xz_wrapper.c index 06d0d11b482a6..aa47a286d1f8e 100644 --- a/fs/squashfs/xz_wrapper.c +++ b/fs/squashfs/xz_wrapper.c @@ -30,7 +30,6 @@ #include "squashfs_fs.h" #include "squashfs_fs_sb.h" -#include "squashfs_fs_i.h" #include "squashfs.h" #include "decompressor.h" -- GitLab From 003a3194d36dc22c29cacda4d0c6fede2753c9d0 Mon Sep 17 00:00:00 2001 From: Phillip Lougher Date: Mon, 28 Feb 2011 18:43:48 +0000 Subject: [PATCH 0247/2822] Squashfs: wrap squashfs_mount() definition Squashfs_get_sb() to squashfs_mount() conversion (commit 152a0836) results in line over 80 characters. Signed-off-by: Phillip Lougher --- fs/squashfs/super.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fs/squashfs/super.c b/fs/squashfs/super.c index 95467db71a8e5..5c8184c061a49 100644 --- a/fs/squashfs/super.c +++ b/fs/squashfs/super.c @@ -373,8 +373,8 @@ static void squashfs_put_super(struct super_block *sb) } -static struct dentry *squashfs_mount(struct file_system_type *fs_type, int flags, - const char *dev_name, void *data) +static struct dentry *squashfs_mount(struct file_system_type *fs_type, + int flags, const char *dev_name, void *data) { return mount_bdev(fs_type, flags, dev_name, data, squashfs_fill_super); } -- GitLab From bb879101606dd7235d8f4ecd0f707b63281d0838 Mon Sep 17 00:00:00 2001 From: Rhyland Klein Date: Mon, 28 Feb 2011 16:55:28 -0800 Subject: [PATCH 0248/2822] bq20z75: Add optional battery detect gpio Adding support for an optional gpio for battery detection. This is passed in through the i2c platform data. It also accepts another field, battery_detect_present to signify the gpio state which means the battery is present, either 0 (low) or 1 (high). Signed-off-by: Rhyland Klein Signed-off-by: Anton Vorontsov --- drivers/power/bq20z75.c | 160 +++++++++++++++++++++++++++------- include/linux/power/bq20z75.h | 37 ++++++++ 2 files changed, 166 insertions(+), 31 deletions(-) create mode 100644 include/linux/power/bq20z75.h diff --git a/drivers/power/bq20z75.c b/drivers/power/bq20z75.c index 4141775e5ff60..a51e98d74d343 100644 --- a/drivers/power/bq20z75.c +++ b/drivers/power/bq20z75.c @@ -25,6 +25,10 @@ #include #include #include +#include +#include + +#include enum { REG_MANUFACTURER_DATA, @@ -141,8 +145,13 @@ static enum power_supply_property bq20z75_properties[] = { }; struct bq20z75_info { - struct i2c_client *client; - struct power_supply power_supply; + struct i2c_client *client; + struct power_supply power_supply; + struct bq20z75_platform_data *pdata; + bool is_present; + bool gpio_detect; + bool enable_detection; + int irq; }; static int bq20z75_read_word_data(struct i2c_client *client, u8 address) @@ -179,6 +188,18 @@ static int bq20z75_get_battery_presence_and_health( union power_supply_propval *val) { s32 ret; + struct bq20z75_info *bq20z75_device = i2c_get_clientdata(client); + + if (psp == POWER_SUPPLY_PROP_PRESENT && + bq20z75_device->gpio_detect) { + ret = gpio_get_value( + bq20z75_device->pdata->battery_detect); + if (ret == bq20z75_device->pdata->battery_detect_present) + val->intval = 1; + else + val->intval = 0; + return ret; + } /* Write to ManufacturerAccess with * ManufacturerAccess command and then @@ -192,8 +213,11 @@ static int bq20z75_get_battery_presence_and_health( ret = bq20z75_read_word_data(client, bq20z75_data[REG_MANUFACTURER_DATA].addr); - if (ret < 0) + if (ret < 0) { + if (psp == POWER_SUPPLY_PROP_PRESENT) + val->intval = 0; /* battery removed */ return ret; + } if (ret < bq20z75_data[REG_MANUFACTURER_DATA].min_value || ret > bq20z75_data[REG_MANUFACTURER_DATA].max_value) { @@ -397,8 +421,7 @@ static int bq20z75_get_property(struct power_supply *psy, enum power_supply_property psp, union power_supply_propval *val) { - int ps_index; - int ret; + int ret = 0; struct bq20z75_info *bq20z75_device = container_of(psy, struct bq20z75_info, power_supply); struct i2c_client *client = bq20z75_device->client; @@ -407,8 +430,6 @@ static int bq20z75_get_property(struct power_supply *psy, case POWER_SUPPLY_PROP_PRESENT: case POWER_SUPPLY_PROP_HEALTH: ret = bq20z75_get_battery_presence_and_health(client, psp, val); - if (ret) - return ret; break; case POWER_SUPPLY_PROP_TECHNOLOGY: @@ -422,20 +443,15 @@ static int bq20z75_get_property(struct power_supply *psy, case POWER_SUPPLY_PROP_CHARGE_FULL: case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN: case POWER_SUPPLY_PROP_CAPACITY: - ps_index = bq20z75_get_property_index(client, psp); - if (ps_index < 0) - return ps_index; - - ret = bq20z75_get_battery_capacity(client, ps_index, psp, val); - if (ret) - return ret; + ret = bq20z75_get_property_index(client, psp); + if (ret < 0) + break; + ret = bq20z75_get_battery_capacity(client, ret, psp, val); break; case POWER_SUPPLY_PROP_SERIAL_NUMBER: ret = bq20z75_get_battery_serial_number(client, val); - if (ret) - return ret; break; case POWER_SUPPLY_PROP_STATUS: @@ -446,14 +462,11 @@ static int bq20z75_get_property(struct power_supply *psy, case POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG: case POWER_SUPPLY_PROP_TIME_TO_FULL_AVG: case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN: - ps_index = bq20z75_get_property_index(client, psp); - if (ps_index < 0) - return ps_index; - - ret = bq20z75_get_battery_property(client, ps_index, psp, val); - if (ret) - return ret; + ret = bq20z75_get_property_index(client, psp); + if (ret < 0) + break; + ret = bq20z75_get_battery_property(client, ret, psp, val); break; default: @@ -462,26 +475,51 @@ static int bq20z75_get_property(struct power_supply *psy, return -EINVAL; } - /* Convert units to match requirements for power supply class */ - bq20z75_unit_adjustment(client, psp, val); + if (!bq20z75_device->enable_detection) + goto done; + + if (!bq20z75_device->gpio_detect && + bq20z75_device->is_present != (ret >= 0)) { + bq20z75_device->is_present = (ret >= 0); + power_supply_changed(&bq20z75_device->power_supply); + } + +done: + if (!ret) { + /* Convert units to match requirements for power supply class */ + bq20z75_unit_adjustment(client, psp, val); + } dev_dbg(&client->dev, "%s: property = %d, value = %d\n", __func__, psp, val->intval); - return 0; + return ret; } -static int bq20z75_probe(struct i2c_client *client, +static irqreturn_t bq20z75_irq(int irq, void *devid) +{ + struct power_supply *battery = devid; + + power_supply_changed(battery); + + return IRQ_HANDLED; +} + +static int __devinit bq20z75_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct bq20z75_info *bq20z75_device; + struct bq20z75_platform_data *pdata = client->dev.platform_data; int rc; + int irq; bq20z75_device = kzalloc(sizeof(struct bq20z75_info), GFP_KERNEL); if (!bq20z75_device) return -ENOMEM; bq20z75_device->client = client; + bq20z75_device->enable_detection = false; + bq20z75_device->gpio_detect = false; bq20z75_device->power_supply.name = "battery"; bq20z75_device->power_supply.type = POWER_SUPPLY_TYPE_BATTERY; bq20z75_device->power_supply.properties = bq20z75_properties; @@ -489,26 +527,86 @@ static int bq20z75_probe(struct i2c_client *client, ARRAY_SIZE(bq20z75_properties); bq20z75_device->power_supply.get_property = bq20z75_get_property; + if (pdata) { + bq20z75_device->gpio_detect = + gpio_is_valid(pdata->battery_detect); + bq20z75_device->pdata = pdata; + } + i2c_set_clientdata(client, bq20z75_device); + if (!bq20z75_device->gpio_detect) + goto skip_gpio; + + rc = gpio_request(pdata->battery_detect, dev_name(&client->dev)); + if (rc) { + dev_warn(&client->dev, "Failed to request gpio: %d\n", rc); + bq20z75_device->gpio_detect = false; + goto skip_gpio; + } + + rc = gpio_direction_input(pdata->battery_detect); + if (rc) { + dev_warn(&client->dev, "Failed to get gpio as input: %d\n", rc); + gpio_free(pdata->battery_detect); + bq20z75_device->gpio_detect = false; + goto skip_gpio; + } + + irq = gpio_to_irq(pdata->battery_detect); + if (irq <= 0) { + dev_warn(&client->dev, "Failed to get gpio as irq: %d\n", irq); + gpio_free(pdata->battery_detect); + bq20z75_device->gpio_detect = false; + goto skip_gpio; + } + + rc = request_irq(irq, bq20z75_irq, + IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, + dev_name(&client->dev), &bq20z75_device->power_supply); + if (rc) { + dev_warn(&client->dev, "Failed to request irq: %d\n", rc); + gpio_free(pdata->battery_detect); + bq20z75_device->gpio_detect = false; + goto skip_gpio; + } + + bq20z75_device->irq = irq; + +skip_gpio: + rc = power_supply_register(&client->dev, &bq20z75_device->power_supply); if (rc) { dev_err(&client->dev, "%s: Failed to register power supply\n", __func__); - kfree(bq20z75_device); - return rc; + goto exit_psupply; } dev_info(&client->dev, "%s: battery gas gauge device registered\n", client->name); return 0; + +exit_psupply: + if (bq20z75_device->irq) + free_irq(bq20z75_device->irq, &bq20z75_device->power_supply); + if (bq20z75_device->gpio_detect) + gpio_free(pdata->battery_detect); + + kfree(bq20z75_device); + + return rc; } -static int bq20z75_remove(struct i2c_client *client) +static int __devexit bq20z75_remove(struct i2c_client *client) { struct bq20z75_info *bq20z75_device = i2c_get_clientdata(client); + if (bq20z75_device->irq) + free_irq(bq20z75_device->irq, &bq20z75_device->power_supply); + if (bq20z75_device->gpio_detect) + gpio_free(bq20z75_device->pdata->battery_detect); + power_supply_unregister(&bq20z75_device->power_supply); kfree(bq20z75_device); bq20z75_device = NULL; @@ -544,7 +642,7 @@ static const struct i2c_device_id bq20z75_id[] = { static struct i2c_driver bq20z75_battery_driver = { .probe = bq20z75_probe, - .remove = bq20z75_remove, + .remove = __devexit_p(bq20z75_remove), .suspend = bq20z75_suspend, .resume = bq20z75_resume, .id_table = bq20z75_id, diff --git a/include/linux/power/bq20z75.h b/include/linux/power/bq20z75.h new file mode 100644 index 0000000000000..0e1b8a26a9b1e --- /dev/null +++ b/include/linux/power/bq20z75.h @@ -0,0 +1,37 @@ +/* + * Gas Gauge driver for TI's BQ20Z75 + * + * Copyright (c) 2010, NVIDIA Corporation. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef __LINUX_POWER_BQ20Z75_H_ +#define __LINUX_POWER_BQ20Z75_H_ + +#include +#include + +/** + * struct bq20z75_platform_data - platform data for bq20z75 devices + * @battery_detect: GPIO which is used to detect battery presence + * @battery_detect_present: gpio state when battery is present (0 / 1) + */ +struct bq20z75_platform_data { + int battery_detect; + int battery_detect_present; +}; + +#endif -- GitLab From ff28fcef1bedcfbdf49500fee1573dc2f3eedb22 Mon Sep 17 00:00:00 2001 From: Rhyland Klein Date: Mon, 28 Feb 2011 16:55:29 -0800 Subject: [PATCH 0249/2822] bq20z75: Add i2c retry mechanism With the support of platform data, now adding support for option i2c retries on read/write failures. Ths is specified through the optional platform data. Signed-off-by: Rhyland Klein Signed-off-by: Anton Vorontsov --- drivers/power/bq20z75.c | 37 +++++++++++++++++++++++++++++------ include/linux/power/bq20z75.h | 2 ++ 2 files changed, 33 insertions(+), 6 deletions(-) diff --git a/drivers/power/bq20z75.c b/drivers/power/bq20z75.c index a51e98d74d343..e82d10e25e8c2 100644 --- a/drivers/power/bq20z75.c +++ b/drivers/power/bq20z75.c @@ -156,30 +156,55 @@ struct bq20z75_info { static int bq20z75_read_word_data(struct i2c_client *client, u8 address) { - s32 ret; + struct bq20z75_info *bq20z75_device = i2c_get_clientdata(client); + s32 ret = 0; + int retries = 1; + + if (bq20z75_device->pdata) + retries = max(bq20z75_device->pdata->i2c_retry_count + 1, 1); + + while (retries > 0) { + ret = i2c_smbus_read_word_data(client, address); + if (ret >= 0) + break; + retries--; + } - ret = i2c_smbus_read_word_data(client, address); if (ret < 0) { - dev_err(&client->dev, + dev_warn(&client->dev, "%s: i2c read at address 0x%x failed\n", __func__, address); return ret; } + return le16_to_cpu(ret); } static int bq20z75_write_word_data(struct i2c_client *client, u8 address, u16 value) { - s32 ret; + struct bq20z75_info *bq20z75_device = i2c_get_clientdata(client); + s32 ret = 0; + int retries = 1; + + if (bq20z75_device->pdata) + retries = max(bq20z75_device->pdata->i2c_retry_count + 1, 1); + + while (retries > 0) { + ret = i2c_smbus_write_word_data(client, address, + le16_to_cpu(value)); + if (ret >= 0) + break; + retries--; + } - ret = i2c_smbus_write_word_data(client, address, le16_to_cpu(value)); if (ret < 0) { - dev_err(&client->dev, + dev_warn(&client->dev, "%s: i2c write to address 0x%x failed\n", __func__, address); return ret; } + return 0; } diff --git a/include/linux/power/bq20z75.h b/include/linux/power/bq20z75.h index 0e1b8a26a9b1e..b0843b68af926 100644 --- a/include/linux/power/bq20z75.h +++ b/include/linux/power/bq20z75.h @@ -28,10 +28,12 @@ * struct bq20z75_platform_data - platform data for bq20z75 devices * @battery_detect: GPIO which is used to detect battery presence * @battery_detect_present: gpio state when battery is present (0 / 1) + * @i2c_retry_count: # of times to retry on i2c IO failure */ struct bq20z75_platform_data { int battery_detect; int battery_detect_present; + int i2c_retry_count; }; #endif -- GitLab From 35c9d267665230cf44445be616d491d3763a5cd3 Mon Sep 17 00:00:00 2001 From: Rhyland Klein Date: Mon, 28 Feb 2011 16:55:31 -0800 Subject: [PATCH 0250/2822] power_supply: Update power_supply_is_watt_property Update the power_supply_is_watt_property function to include POWER_NOW. Signed-off-by: Rhyland Klein Signed-off-by: Anton Vorontsov --- include/linux/power_supply.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/linux/power_supply.h b/include/linux/power_supply.h index 20f23fef63cce..204c18dfdc9e8 100644 --- a/include/linux/power_supply.h +++ b/include/linux/power_supply.h @@ -251,6 +251,7 @@ static inline bool power_supply_is_watt_property(enum power_supply_property psp) case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN: case POWER_SUPPLY_PROP_VOLTAGE_NOW: case POWER_SUPPLY_PROP_VOLTAGE_AVG: + case POWER_SUPPLY_PROP_POWER_NOW: return 1; default: break; -- GitLab From f3da0dee31689130a06f12f06575c7a5b62421ad Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Tue, 1 Mar 2011 17:22:33 +0800 Subject: [PATCH 0251/2822] bq20z75: Add MODULE_DEVICE_TABLE The device table is required to load modules based on modaliases. After adding the MODULE_DEVICE_TABLE, below entry will be added to modules.alias: alias i2c:bq20z75 bq20z75 Signed-off-by: Axel Lin Signed-off-by: Anton Vorontsov --- drivers/power/bq20z75.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/power/bq20z75.c b/drivers/power/bq20z75.c index e82d10e25e8c2..8018e8cc7a743 100644 --- a/drivers/power/bq20z75.c +++ b/drivers/power/bq20z75.c @@ -664,6 +664,7 @@ static const struct i2c_device_id bq20z75_id[] = { { "bq20z75", 0 }, {} }; +MODULE_DEVICE_TABLE(i2c, bq20z75_id); static struct i2c_driver bq20z75_battery_driver = { .probe = bq20z75_probe, -- GitLab From 84ab16f54bbde67c8c2aabc36b034c91044935cb Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Tue, 1 Mar 2011 17:23:34 +0800 Subject: [PATCH 0252/2822] ds2782_battery: Add MODULE_DEVICE_TABLE The device table is required to load modules based on modaliases. After adding the MODULE_DEVICE_TABLE, below entries will be added to modules.alias: alias i2c:ds2786 ds2782_battery alias i2c:ds2782 ds2782_battery Signed-off-by: Axel Lin Signed-off-by: Anton Vorontsov --- drivers/power/ds2782_battery.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/power/ds2782_battery.c b/drivers/power/ds2782_battery.c index 6957e8af64490..4d2dc4fa2888f 100644 --- a/drivers/power/ds2782_battery.c +++ b/drivers/power/ds2782_battery.c @@ -393,6 +393,7 @@ static const struct i2c_device_id ds278x_id[] = { {"ds2786", DS2786}, {}, }; +MODULE_DEVICE_TABLE(i2c, ds278x_id); static struct i2c_driver ds278x_battery_driver = { .driver = { -- GitLab From dcbc9169ed3ce7cd12328fec8b9eb9f7b91ce130 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Tue, 1 Mar 2011 17:24:34 +0800 Subject: [PATCH 0253/2822] z2_battery: Add MODULE_DEVICE_TABLE The device table is required to load modules based on modaliases. After adding the MODULE_DEVICE_TABLE, below entry will be added to modules.alias: alias i2c:aer915 z2_battery Signed-off-by: Axel Lin Signed-off-by: Anton Vorontsov --- drivers/power/z2_battery.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/power/z2_battery.c b/drivers/power/z2_battery.c index e5ed52d719376..81304c0bb9d3b 100644 --- a/drivers/power/z2_battery.c +++ b/drivers/power/z2_battery.c @@ -293,6 +293,7 @@ static const struct i2c_device_id z2_batt_id[] = { { "aer915", 0 }, { } }; +MODULE_DEVICE_TABLE(i2c, z2_batt_id); static struct i2c_driver z2_batt_driver = { .driver = { -- GitLab From 0bbfeb8320421989d3e12bd95fae86b9ac0712aa Mon Sep 17 00:00:00 2001 From: Justin TerAvest Date: Tue, 1 Mar 2011 15:05:08 -0500 Subject: [PATCH 0254/2822] cfq-iosched: Always provide group isolation. Effectively, make group_isolation=1 the default and remove the tunable. The setting group_isolation=0 was because by default we idle on sync-noidle tree and on fast devices, this can be very harmful for throughput. However, this problem can also be addressed by tuning slice_idle and possibly group_idle on faster storage devices. This change simplifies the CFQ code by removing the feature entirely. Signed-off-by: Justin TerAvest Acked-by: Vivek Goyal Signed-off-by: Jens Axboe --- Documentation/cgroups/blkio-controller.txt | 28 ---------------- block/cfq-iosched.c | 37 +--------------------- 2 files changed, 1 insertion(+), 64 deletions(-) diff --git a/Documentation/cgroups/blkio-controller.txt b/Documentation/cgroups/blkio-controller.txt index 4ed7b5ceeed21..d915c16df42c1 100644 --- a/Documentation/cgroups/blkio-controller.txt +++ b/Documentation/cgroups/blkio-controller.txt @@ -343,34 +343,6 @@ Common files among various policies CFQ sysfs tunable ================= -/sys/block//queue/iosched/group_isolation ------------------------------------------------ - -If group_isolation=1, it provides stronger isolation between groups at the -expense of throughput. By default group_isolation is 0. In general that -means that if group_isolation=0, expect fairness for sequential workload -only. Set group_isolation=1 to see fairness for random IO workload also. - -Generally CFQ will put random seeky workload in sync-noidle category. CFQ -will disable idling on these queues and it does a collective idling on group -of such queues. Generally these are slow moving queues and if there is a -sync-noidle service tree in each group, that group gets exclusive access to -disk for certain period. That means it will bring the throughput down if -group does not have enough IO to drive deeper queue depths and utilize disk -capacity to the fullest in the slice allocated to it. But the flip side is -that even a random reader should get better latencies and overall throughput -if there are lots of sequential readers/sync-idle workload running in the -system. - -If group_isolation=0, then CFQ automatically moves all the random seeky queues -in the root group. That means there will be no service differentiation for -that kind of workload. This leads to better throughput as we do collective -idling on root sync-noidle tree. - -By default one should run with group_isolation=0. If that is not sufficient -and one wants stronger isolation between groups, then set group_isolation=1 -but this will come at cost of reduced throughput. - /sys/block//queue/iosched/slice_idle ------------------------------------------ On a faster hardware CFQ can be slow, especially with sequential workload. diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c index f27ff3efe6cd2..3202c7e87fb3d 100644 --- a/block/cfq-iosched.c +++ b/block/cfq-iosched.c @@ -146,7 +146,6 @@ struct cfq_queue { struct cfq_rb_root *service_tree; struct cfq_queue *new_cfqq; struct cfq_group *cfqg; - struct cfq_group *orig_cfqg; /* Number of sectors dispatched from queue in single dispatch round */ unsigned long nr_sectors; }; @@ -285,7 +284,6 @@ struct cfq_data { unsigned int cfq_slice_idle; unsigned int cfq_group_idle; unsigned int cfq_latency; - unsigned int cfq_group_isolation; unsigned int cic_index; struct list_head cic_list; @@ -1187,32 +1185,6 @@ static void cfq_service_tree_add(struct cfq_data *cfqd, struct cfq_queue *cfqq, int new_cfqq = 1; int group_changed = 0; -#ifdef CONFIG_CFQ_GROUP_IOSCHED - if (!cfqd->cfq_group_isolation - && cfqq_type(cfqq) == SYNC_NOIDLE_WORKLOAD - && cfqq->cfqg && cfqq->cfqg != &cfqd->root_group) { - /* Move this cfq to root group */ - cfq_log_cfqq(cfqd, cfqq, "moving to root group"); - if (!RB_EMPTY_NODE(&cfqq->rb_node)) - cfq_group_service_tree_del(cfqd, cfqq->cfqg); - cfqq->orig_cfqg = cfqq->cfqg; - cfqq->cfqg = &cfqd->root_group; - cfqd->root_group.ref++; - group_changed = 1; - } else if (!cfqd->cfq_group_isolation - && cfqq_type(cfqq) == SYNC_WORKLOAD && cfqq->orig_cfqg) { - /* cfqq is sequential now needs to go to its original group */ - BUG_ON(cfqq->cfqg != &cfqd->root_group); - if (!RB_EMPTY_NODE(&cfqq->rb_node)) - cfq_group_service_tree_del(cfqd, cfqq->cfqg); - cfq_put_cfqg(cfqq->cfqg); - cfqq->cfqg = cfqq->orig_cfqg; - cfqq->orig_cfqg = NULL; - group_changed = 1; - cfq_log_cfqq(cfqd, cfqq, "moved to origin group"); - } -#endif - service_tree = service_tree_for(cfqq->cfqg, cfqq_prio(cfqq), cfqq_type(cfqq)); if (cfq_class_idle(cfqq)) { @@ -2542,7 +2514,7 @@ static int cfq_dispatch_requests(struct request_queue *q, int force) static void cfq_put_queue(struct cfq_queue *cfqq) { struct cfq_data *cfqd = cfqq->cfqd; - struct cfq_group *cfqg, *orig_cfqg; + struct cfq_group *cfqg; BUG_ON(cfqq->ref <= 0); @@ -2554,7 +2526,6 @@ static void cfq_put_queue(struct cfq_queue *cfqq) BUG_ON(rb_first(&cfqq->sort_list)); BUG_ON(cfqq->allocated[READ] + cfqq->allocated[WRITE]); cfqg = cfqq->cfqg; - orig_cfqg = cfqq->orig_cfqg; if (unlikely(cfqd->active_queue == cfqq)) { __cfq_slice_expired(cfqd, cfqq, 0); @@ -2564,8 +2535,6 @@ static void cfq_put_queue(struct cfq_queue *cfqq) BUG_ON(cfq_cfqq_on_rr(cfqq)); kmem_cache_free(cfq_pool, cfqq); cfq_put_cfqg(cfqg); - if (orig_cfqg) - cfq_put_cfqg(orig_cfqg); } /* @@ -3953,7 +3922,6 @@ static void *cfq_init_queue(struct request_queue *q) cfqd->cfq_slice_idle = cfq_slice_idle; cfqd->cfq_group_idle = cfq_group_idle; cfqd->cfq_latency = 1; - cfqd->cfq_group_isolation = 0; cfqd->hw_tag = -1; /* * we optimistically start assuming sync ops weren't delayed in last @@ -4029,7 +3997,6 @@ SHOW_FUNCTION(cfq_slice_sync_show, cfqd->cfq_slice[1], 1); SHOW_FUNCTION(cfq_slice_async_show, cfqd->cfq_slice[0], 1); SHOW_FUNCTION(cfq_slice_async_rq_show, cfqd->cfq_slice_async_rq, 0); SHOW_FUNCTION(cfq_low_latency_show, cfqd->cfq_latency, 0); -SHOW_FUNCTION(cfq_group_isolation_show, cfqd->cfq_group_isolation, 0); #undef SHOW_FUNCTION #define STORE_FUNCTION(__FUNC, __PTR, MIN, MAX, __CONV) \ @@ -4063,7 +4030,6 @@ STORE_FUNCTION(cfq_slice_async_store, &cfqd->cfq_slice[0], 1, UINT_MAX, 1); STORE_FUNCTION(cfq_slice_async_rq_store, &cfqd->cfq_slice_async_rq, 1, UINT_MAX, 0); STORE_FUNCTION(cfq_low_latency_store, &cfqd->cfq_latency, 0, 1, 0); -STORE_FUNCTION(cfq_group_isolation_store, &cfqd->cfq_group_isolation, 0, 1, 0); #undef STORE_FUNCTION #define CFQ_ATTR(name) \ @@ -4081,7 +4047,6 @@ static struct elv_fs_entry cfq_attrs[] = { CFQ_ATTR(slice_idle), CFQ_ATTR(group_idle), CFQ_ATTR(low_latency), - CFQ_ATTR(group_isolation), __ATTR_NULL }; -- GitLab From 173442f2787c88e1ed1bb62aaeb6fd9127720559 Mon Sep 17 00:00:00 2001 From: Tomoya MORINAGA Date: Tue, 1 Mar 2011 14:16:23 +0900 Subject: [PATCH 0255/2822] i2c-eg20t: support new device OKI SEMICONDUCTOR ML7213 IOH Support new device OKI SEMICONDUCTOR ML7213 IOH. The ML7213 which is for IVI(In-Vehicle Infotainment) is a companion chip for the Atom E6xx series and compatible with the Intel EG20T PCH. Signed-off-by: Tomoya MORINAGA Signed-off-by: Ben Dooks --- drivers/i2c/busses/Kconfig | 15 +-- drivers/i2c/busses/i2c-eg20t.c | 161 ++++++++++++++++++++------------- 2 files changed, 108 insertions(+), 68 deletions(-) diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig index 113505a6434ed..5b592dfcbd78e 100644 --- a/drivers/i2c/busses/Kconfig +++ b/drivers/i2c/busses/Kconfig @@ -639,12 +639,15 @@ config I2C_XILINX will be called xilinx_i2c. config I2C_EG20T - tristate "PCH I2C of Intel EG20T" - depends on PCI - help - This driver is for PCH(Platform controller Hub) I2C of EG20T which - is an IOH(Input/Output Hub) for x86 embedded processor. - This driver can access PCH I2C bus device. + tristate "Intel EG20T PCH/OKI SEMICONDUCTOR ML7213 IOH" + depends on PCI + help + This driver is for PCH(Platform controller Hub) I2C of EG20T which + is an IOH(Input/Output Hub) for x86 embedded processor. + This driver can access PCH I2C bus device. + + This driver also supports the ML7213, a companion chip for the + Atom E6xx series and compatible with the Intel EG20T PCH. comment "External I2C/SMBus adapter drivers" diff --git a/drivers/i2c/busses/i2c-eg20t.c b/drivers/i2c/busses/i2c-eg20t.c index 2e067dd2ee515..c57c837346922 100644 --- a/drivers/i2c/busses/i2c-eg20t.c +++ b/drivers/i2c/busses/i2c-eg20t.c @@ -131,6 +131,13 @@ #define pch_pci_dbg(pdev, fmt, arg...) \ dev_dbg(&pdev->dev, "%s :" fmt, __func__, ##arg) +/* +Set the number of I2C instance max +Intel EG20T PCH : 1ch +OKI SEMICONDUCTOR ML7213 IOH : 2ch +*/ +#define PCH_I2C_MAX_DEV 2 + /** * struct i2c_algo_pch_data - for I2C driver functionalities * @pch_adapter: stores the reference to i2c_adapter structure @@ -155,12 +162,14 @@ struct i2c_algo_pch_data { * @pch_data: stores a list of i2c_algo_pch_data * @pch_i2c_suspended: specifies whether the system is suspended or not * perhaps with more lines and words. + * @ch_num: specifies the number of i2c instance * * pch_data has as many elements as maximum I2C channels */ struct adapter_info { - struct i2c_algo_pch_data pch_data; + struct i2c_algo_pch_data pch_data[PCH_I2C_MAX_DEV]; bool pch_i2c_suspended; + int ch_num; }; @@ -169,8 +178,13 @@ static int pch_clk = 50000; /* specifies I2C clock speed in KHz */ static wait_queue_head_t pch_event; static DEFINE_MUTEX(pch_mutex); +/* Definition for ML7213 by OKI SEMICONDUCTOR */ +#define PCI_VENDOR_ID_ROHM 0x10DB +#define PCI_DEVICE_ID_ML7213_I2C 0x802D + static struct pci_device_id __devinitdata pch_pcidev_id[] = { - {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_PCH_I2C)}, + { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_PCH_I2C), 1, }, + { PCI_VDEVICE(ROHM, PCI_DEVICE_ID_ML7213_I2C), 2, }, {0,} }; @@ -211,8 +225,7 @@ static void pch_i2c_init(struct i2c_algo_pch_data *adap) /* Initialize I2C registers */ iowrite32(0x21, p + PCH_I2CNF); - pch_setbit(adap->pch_base_address, PCH_I2CCTL, - PCH_I2CCTL_I2CMEN); + pch_setbit(adap->pch_base_address, PCH_I2CCTL, PCH_I2CCTL_I2CMEN); if (pch_i2c_speed != 400) pch_i2c_speed = 100; @@ -254,7 +267,7 @@ static inline bool ktime_lt(const ktime_t cmp1, const ktime_t cmp2) * @timeout: waiting time counter (us). */ static s32 pch_i2c_wait_for_bus_idle(struct i2c_algo_pch_data *adap, - s32 timeout) + s32 timeout) { void __iomem *p = adap->pch_base_address; @@ -474,8 +487,8 @@ static void pch_i2c_sendnack(struct i2c_algo_pch_data *adap) * @last: specifies whether last message or not. * @first: specifies whether first message or not. */ -s32 pch_i2c_readbytes(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs, - u32 last, u32 first) +static s32 pch_i2c_readbytes(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs, + u32 last, u32 first) { struct i2c_algo_pch_data *adap = i2c_adap->algo_data; @@ -568,10 +581,10 @@ s32 pch_i2c_readbytes(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs, } /** - * pch_i2c_cb_ch0() - Interrupt handler Call back function + * pch_i2c_cb() - Interrupt handler Call back function * @adap: Pointer to struct i2c_algo_pch_data. */ -static void pch_i2c_cb_ch0(struct i2c_algo_pch_data *adap) +static void pch_i2c_cb(struct i2c_algo_pch_data *adap) { u32 sts; void __iomem *p = adap->pch_base_address; @@ -599,24 +612,30 @@ static void pch_i2c_cb_ch0(struct i2c_algo_pch_data *adap) */ static irqreturn_t pch_i2c_handler(int irq, void *pData) { - s32 reg_val; - - struct i2c_algo_pch_data *adap_data = (struct i2c_algo_pch_data *)pData; - void __iomem *p = adap_data->pch_base_address; - u32 mode = ioread32(p + PCH_I2CMOD) & (BUFFER_MODE | EEPROM_SR_MODE); - - if (mode != NORMAL_MODE) { - pch_err(adap_data, "I2C mode is not supported\n"); - return IRQ_NONE; + u32 reg_val; + int flag; + int i; + struct adapter_info *adap_info = pData; + void __iomem *p; + u32 mode; + + for (i = 0, flag = 0; i < adap_info->ch_num; i++) { + p = adap_info->pch_data[i].pch_base_address; + mode = ioread32(p + PCH_I2CMOD); + mode &= BUFFER_MODE | EEPROM_SR_MODE; + if (mode != NORMAL_MODE) { + pch_err(adap_info->pch_data, + "I2C-%d mode(%d) is not supported\n", mode, i); + continue; + } + reg_val = ioread32(p + PCH_I2CSR); + if (reg_val & (I2CMAL_BIT | I2CMCF_BIT | I2CMIF_BIT)) { + pch_i2c_cb(&adap_info->pch_data[i]); + flag = 1; + } } - reg_val = ioread32(p + PCH_I2CSR); - if (reg_val & (I2CMAL_BIT | I2CMCF_BIT | I2CMIF_BIT)) - pch_i2c_cb_ch0(adap_data); - else - return IRQ_NONE; - - return IRQ_HANDLED; + return flag ? IRQ_HANDLED : IRQ_NONE; } /** @@ -626,7 +645,7 @@ static irqreturn_t pch_i2c_handler(int irq, void *pData) * @num: number of messages. */ static s32 pch_i2c_xfer(struct i2c_adapter *i2c_adap, - struct i2c_msg *msgs, s32 num) + struct i2c_msg *msgs, s32 num) { struct i2c_msg *pmsg; u32 i = 0; @@ -709,11 +728,13 @@ static void pch_i2c_disbl_int(struct i2c_algo_pch_data *adap) } static int __devinit pch_i2c_probe(struct pci_dev *pdev, - const struct pci_device_id *id) + const struct pci_device_id *id) { void __iomem *base_addr; - s32 ret; + int ret; + int i, j; struct adapter_info *adap_info; + struct i2c_adapter *pch_adap; pch_pci_dbg(pdev, "Entered.\n"); @@ -743,44 +764,48 @@ static int __devinit pch_i2c_probe(struct pci_dev *pdev, goto err_pci_iomap; } - adap_info->pch_i2c_suspended = false; + /* Set the number of I2C channel instance */ + adap_info->ch_num = id->driver_data; - adap_info->pch_data.p_adapter_info = adap_info; + for (i = 0; i < adap_info->ch_num; i++) { + pch_adap = &adap_info->pch_data[i].pch_adapter; + adap_info->pch_i2c_suspended = false; - adap_info->pch_data.pch_adapter.owner = THIS_MODULE; - adap_info->pch_data.pch_adapter.class = I2C_CLASS_HWMON; - strcpy(adap_info->pch_data.pch_adapter.name, KBUILD_MODNAME); - adap_info->pch_data.pch_adapter.algo = &pch_algorithm; - adap_info->pch_data.pch_adapter.algo_data = - &adap_info->pch_data; + adap_info->pch_data[i].p_adapter_info = adap_info; - /* (i * 0x80) + base_addr; */ - adap_info->pch_data.pch_base_address = base_addr; + pch_adap->owner = THIS_MODULE; + pch_adap->class = I2C_CLASS_HWMON; + strcpy(pch_adap->name, KBUILD_MODNAME); + pch_adap->algo = &pch_algorithm; + pch_adap->algo_data = &adap_info->pch_data[i]; - adap_info->pch_data.pch_adapter.dev.parent = &pdev->dev; + /* base_addr + offset; */ + adap_info->pch_data[i].pch_base_address = base_addr + 0x100 * i; - ret = i2c_add_adapter(&(adap_info->pch_data.pch_adapter)); + pch_adap->dev.parent = &pdev->dev; - if (ret) { - pch_pci_err(pdev, "i2c_add_adapter FAILED\n"); - goto err_i2c_add_adapter; - } + ret = i2c_add_adapter(pch_adap); + if (ret) { + pch_pci_err(pdev, "i2c_add_adapter[ch:%d] FAILED\n", i); + goto err_i2c_add_adapter; + } - pch_i2c_init(&adap_info->pch_data); + pch_i2c_init(&adap_info->pch_data[i]); + } ret = request_irq(pdev->irq, pch_i2c_handler, IRQF_SHARED, - KBUILD_MODNAME, &adap_info->pch_data); + KBUILD_MODNAME, adap_info); if (ret) { pch_pci_err(pdev, "request_irq FAILED\n"); - goto err_request_irq; + goto err_i2c_add_adapter; } pci_set_drvdata(pdev, adap_info); pch_pci_dbg(pdev, "returns %d.\n", ret); return 0; -err_request_irq: - i2c_del_adapter(&(adap_info->pch_data.pch_adapter)); err_i2c_add_adapter: + for (j = 0; j < i; j++) + i2c_del_adapter(&adap_info->pch_data[j].pch_adapter); pci_iounmap(pdev, base_addr); err_pci_iomap: pci_release_regions(pdev); @@ -793,17 +818,22 @@ err_pci_enable: static void __devexit pch_i2c_remove(struct pci_dev *pdev) { + int i; struct adapter_info *adap_info = pci_get_drvdata(pdev); - pch_i2c_disbl_int(&adap_info->pch_data); - free_irq(pdev->irq, &adap_info->pch_data); - i2c_del_adapter(&(adap_info->pch_data.pch_adapter)); + free_irq(pdev->irq, adap_info); - if (adap_info->pch_data.pch_base_address) { - pci_iounmap(pdev, adap_info->pch_data.pch_base_address); - adap_info->pch_data.pch_base_address = 0; + for (i = 0; i < adap_info->ch_num; i++) { + pch_i2c_disbl_int(&adap_info->pch_data[i]); + i2c_del_adapter(&adap_info->pch_data[i].pch_adapter); } + if (adap_info->pch_data[0].pch_base_address) + pci_iounmap(pdev, adap_info->pch_data[0].pch_base_address); + + for (i = 0; i < adap_info->ch_num; i++) + adap_info->pch_data[i].pch_base_address = 0; + pci_set_drvdata(pdev, NULL); pci_release_regions(pdev); @@ -816,17 +846,22 @@ static void __devexit pch_i2c_remove(struct pci_dev *pdev) static int pch_i2c_suspend(struct pci_dev *pdev, pm_message_t state) { int ret; + int i; struct adapter_info *adap_info = pci_get_drvdata(pdev); - void __iomem *p = adap_info->pch_data.pch_base_address; + void __iomem *p = adap_info->pch_data[0].pch_base_address; adap_info->pch_i2c_suspended = true; - while ((adap_info->pch_data.pch_i2c_xfer_in_progress)) { - /* Wait until all channel transfers are completed */ - msleep(20); + for (i = 0; i < adap_info->ch_num; i++) { + while ((adap_info->pch_data[i].pch_i2c_xfer_in_progress)) { + /* Wait until all channel transfers are completed */ + msleep(20); + } } + /* Disable the i2c interrupts */ - pch_i2c_disbl_int(&adap_info->pch_data); + for (i = 0; i < adap_info->ch_num; i++) + pch_i2c_disbl_int(&adap_info->pch_data[i]); pch_pci_dbg(pdev, "I2CSR = %x I2CBUFSTA = %x I2CESRSTA = %x " "invoked function pch_i2c_disbl_int successfully\n", @@ -849,6 +884,7 @@ static int pch_i2c_suspend(struct pci_dev *pdev, pm_message_t state) static int pch_i2c_resume(struct pci_dev *pdev) { + int i; struct adapter_info *adap_info = pci_get_drvdata(pdev); pci_set_power_state(pdev, PCI_D0); @@ -861,7 +897,8 @@ static int pch_i2c_resume(struct pci_dev *pdev) pci_enable_wake(pdev, PCI_D3hot, 0); - pch_i2c_init(&adap_info->pch_data); + for (i = 0; i < adap_info->ch_num; i++) + pch_i2c_init(&adap_info->pch_data[i]); adap_info->pch_i2c_suspended = false; @@ -893,7 +930,7 @@ static void __exit pch_pci_exit(void) } module_exit(pch_pci_exit); -MODULE_DESCRIPTION("PCH I2C PCI Driver"); +MODULE_DESCRIPTION("Intel EG20T PCH/OKI SEMICONDUCTOR ML7213 IOH I2C Driver"); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Tomoya MORINAGA. "); module_param(pch_i2c_speed, int, (S_IRUSR | S_IWUSR)); -- GitLab From a580b8c5429a624d120cd603e1498bf676e2b4da Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Sun, 27 Feb 2011 00:47:42 +0800 Subject: [PATCH 0256/2822] dmaengine: mxs-dma: add dma support for i.MX23/28 This patch adds dma support for Freescale MXS-based SoC i.MX23/28, including apbh-dma and apbx-dma. * apbh-dma and apbx-dma are supported in the driver as two mxs-dma instances. * apbh-dma is different between mx23 and mx28, hardware version register is used to differentiate. * mxs-dma supports pio function besides data transfer. The driver uses dma_data_direction DMA_NONE to identify the pio mode, and steals sgl and sg_len to get pio words and numbers from clients. * mxs dmaengine has some very specific features, like sense function and the special NAND support (nand_lock, nand_wait4ready). These are too specific to implemented in generic dmaengine driver. * The driver refers to imx-sdma and only a single descriptor is statically assigned to each channel. Signed-off-by: Shawn Guo Signed-off-by: Vinod Koul --- arch/arm/mach-mxs/include/mach/dma.h | 26 + drivers/dma/Kconfig | 8 + drivers/dma/Makefile | 1 + drivers/dma/mxs-dma.c | 724 +++++++++++++++++++++++++++ 4 files changed, 759 insertions(+) create mode 100644 arch/arm/mach-mxs/include/mach/dma.h create mode 100644 drivers/dma/mxs-dma.c diff --git a/arch/arm/mach-mxs/include/mach/dma.h b/arch/arm/mach-mxs/include/mach/dma.h new file mode 100644 index 0000000000000..7f4aeeaba8df2 --- /dev/null +++ b/arch/arm/mach-mxs/include/mach/dma.h @@ -0,0 +1,26 @@ +/* + * Copyright 2011 Freescale Semiconductor, Inc. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef __MACH_MXS_DMA_H__ +#define __MACH_MXS_DMA_H__ + +struct mxs_dma_data { + int chan_irq; +}; + +static inline int mxs_dma_is_apbh(struct dma_chan *chan) +{ + return !strcmp(dev_name(chan->device->dev), "mxs-dma-apbh"); +} + +static inline int mxs_dma_is_apbx(struct dma_chan *chan) +{ + return !strcmp(dev_name(chan->device->dev), "mxs-dma-apbx"); +} + +#endif /* __MACH_MXS_DMA_H__ */ diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig index 1c28816152fa3..76f6472ba315f 100644 --- a/drivers/dma/Kconfig +++ b/drivers/dma/Kconfig @@ -227,6 +227,14 @@ config IMX_DMA Support the i.MX DMA engine. This engine is integrated into Freescale i.MX1/21/27 chips. +config MXS_DMA + bool "MXS DMA support" + depends on SOC_IMX23 || SOC_IMX28 + select DMA_ENGINE + help + Support the MXS DMA engine. This engine including APBH-DMA + and APBX-DMA is integrated into Freescale i.MX23/28 chips. + config DMA_ENGINE bool diff --git a/drivers/dma/Makefile b/drivers/dma/Makefile index 64b21f5cd740f..802b55795f8b7 100644 --- a/drivers/dma/Makefile +++ b/drivers/dma/Makefile @@ -23,6 +23,7 @@ obj-$(CONFIG_COH901318) += coh901318.o coh901318_lli.o obj-$(CONFIG_AMCC_PPC440SPE_ADMA) += ppc4xx/ obj-$(CONFIG_IMX_SDMA) += imx-sdma.o obj-$(CONFIG_IMX_DMA) += imx-dma.o +obj-$(CONFIG_MXS_DMA) += mxs-dma.o obj-$(CONFIG_TIMB_DMA) += timb_dma.o obj-$(CONFIG_STE_DMA40) += ste_dma40.o ste_dma40_ll.o obj-$(CONFIG_PL330_DMA) += pl330.o diff --git a/drivers/dma/mxs-dma.c b/drivers/dma/mxs-dma.c new file mode 100644 index 0000000000000..88aad4f540026 --- /dev/null +++ b/drivers/dma/mxs-dma.c @@ -0,0 +1,724 @@ +/* + * Copyright 2011 Freescale Semiconductor, Inc. All Rights Reserved. + * + * Refer to drivers/dma/imx-sdma.c + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +/* + * NOTE: The term "PIO" throughout the mxs-dma implementation means + * PIO mode of mxs apbh-dma and apbx-dma. With this working mode, + * dma can program the controller registers of peripheral devices. + */ + +#define MXS_DMA_APBH 0 +#define MXS_DMA_APBX 1 +#define dma_is_apbh() (mxs_dma->dev_id == MXS_DMA_APBH) + +#define APBH_VERSION_LATEST 3 +#define apbh_is_old() (mxs_dma->version < APBH_VERSION_LATEST) + +#define HW_APBHX_CTRL0 0x000 +#define BM_APBH_CTRL0_APB_BURST8_EN (1 << 29) +#define BM_APBH_CTRL0_APB_BURST_EN (1 << 28) +#define BP_APBH_CTRL0_CLKGATE_CHANNEL 8 +#define BP_APBH_CTRL0_RESET_CHANNEL 16 +#define HW_APBHX_CTRL1 0x010 +#define HW_APBHX_CTRL2 0x020 +#define HW_APBHX_CHANNEL_CTRL 0x030 +#define BP_APBHX_CHANNEL_CTRL_RESET_CHANNEL 16 +#define HW_APBH_VERSION (cpu_is_mx23() ? 0x3f0 : 0x800) +#define HW_APBX_VERSION 0x800 +#define BP_APBHX_VERSION_MAJOR 24 +#define HW_APBHX_CHn_NXTCMDAR(n) \ + (((dma_is_apbh() && apbh_is_old()) ? 0x050 : 0x110) + (n) * 0x70) +#define HW_APBHX_CHn_SEMA(n) \ + (((dma_is_apbh() && apbh_is_old()) ? 0x080 : 0x140) + (n) * 0x70) + +/* + * ccw bits definitions + * + * COMMAND: 0..1 (2) + * CHAIN: 2 (1) + * IRQ: 3 (1) + * NAND_LOCK: 4 (1) - not implemented + * NAND_WAIT4READY: 5 (1) - not implemented + * DEC_SEM: 6 (1) + * WAIT4END: 7 (1) + * HALT_ON_TERMINATE: 8 (1) + * TERMINATE_FLUSH: 9 (1) + * RESERVED: 10..11 (2) + * PIO_NUM: 12..15 (4) + */ +#define BP_CCW_COMMAND 0 +#define BM_CCW_COMMAND (3 << 0) +#define CCW_CHAIN (1 << 2) +#define CCW_IRQ (1 << 3) +#define CCW_DEC_SEM (1 << 6) +#define CCW_WAIT4END (1 << 7) +#define CCW_HALT_ON_TERM (1 << 8) +#define CCW_TERM_FLUSH (1 << 9) +#define BP_CCW_PIO_NUM 12 +#define BM_CCW_PIO_NUM (0xf << 12) + +#define BF_CCW(value, field) (((value) << BP_CCW_##field) & BM_CCW_##field) + +#define MXS_DMA_CMD_NO_XFER 0 +#define MXS_DMA_CMD_WRITE 1 +#define MXS_DMA_CMD_READ 2 +#define MXS_DMA_CMD_DMA_SENSE 3 /* not implemented */ + +struct mxs_dma_ccw { + u32 next; + u16 bits; + u16 xfer_bytes; +#define MAX_XFER_BYTES 0xff00 + u32 bufaddr; +#define MXS_PIO_WORDS 16 + u32 pio_words[MXS_PIO_WORDS]; +}; + +#define NUM_CCW (int)(PAGE_SIZE / sizeof(struct mxs_dma_ccw)) + +struct mxs_dma_chan { + struct mxs_dma_engine *mxs_dma; + struct dma_chan chan; + struct dma_async_tx_descriptor desc; + struct tasklet_struct tasklet; + int chan_irq; + struct mxs_dma_ccw *ccw; + dma_addr_t ccw_phys; + dma_cookie_t last_completed; + enum dma_status status; + unsigned int flags; +#define MXS_DMA_SG_LOOP (1 << 0) +}; + +#define MXS_DMA_CHANNELS 16 +#define MXS_DMA_CHANNELS_MASK 0xffff + +struct mxs_dma_engine { + int dev_id; + unsigned int version; + void __iomem *base; + struct clk *clk; + struct dma_device dma_device; + struct device_dma_parameters dma_parms; + struct mxs_dma_chan mxs_chans[MXS_DMA_CHANNELS]; +}; + +static void mxs_dma_reset_chan(struct mxs_dma_chan *mxs_chan) +{ + struct mxs_dma_engine *mxs_dma = mxs_chan->mxs_dma; + int chan_id = mxs_chan->chan.chan_id; + + if (dma_is_apbh() && apbh_is_old()) + writel(1 << (chan_id + BP_APBH_CTRL0_RESET_CHANNEL), + mxs_dma->base + HW_APBHX_CTRL0 + MXS_SET_ADDR); + else + writel(1 << (chan_id + BP_APBHX_CHANNEL_CTRL_RESET_CHANNEL), + mxs_dma->base + HW_APBHX_CHANNEL_CTRL + MXS_SET_ADDR); +} + +static void mxs_dma_enable_chan(struct mxs_dma_chan *mxs_chan) +{ + struct mxs_dma_engine *mxs_dma = mxs_chan->mxs_dma; + int chan_id = mxs_chan->chan.chan_id; + + /* set cmd_addr up */ + writel(mxs_chan->ccw_phys, + mxs_dma->base + HW_APBHX_CHn_NXTCMDAR(chan_id)); + + /* enable apbh channel clock */ + if (dma_is_apbh()) { + if (apbh_is_old()) + writel(1 << (chan_id + BP_APBH_CTRL0_CLKGATE_CHANNEL), + mxs_dma->base + HW_APBHX_CTRL0 + MXS_CLR_ADDR); + else + writel(1 << chan_id, + mxs_dma->base + HW_APBHX_CTRL0 + MXS_CLR_ADDR); + } + + /* write 1 to SEMA to kick off the channel */ + writel(1, mxs_dma->base + HW_APBHX_CHn_SEMA(chan_id)); +} + +static void mxs_dma_disable_chan(struct mxs_dma_chan *mxs_chan) +{ + struct mxs_dma_engine *mxs_dma = mxs_chan->mxs_dma; + int chan_id = mxs_chan->chan.chan_id; + + /* disable apbh channel clock */ + if (dma_is_apbh()) { + if (apbh_is_old()) + writel(1 << (chan_id + BP_APBH_CTRL0_CLKGATE_CHANNEL), + mxs_dma->base + HW_APBHX_CTRL0 + MXS_SET_ADDR); + else + writel(1 << chan_id, + mxs_dma->base + HW_APBHX_CTRL0 + MXS_SET_ADDR); + } + + mxs_chan->status = DMA_SUCCESS; +} + +static void mxs_dma_pause_chan(struct mxs_dma_chan *mxs_chan) +{ + struct mxs_dma_engine *mxs_dma = mxs_chan->mxs_dma; + int chan_id = mxs_chan->chan.chan_id; + + /* freeze the channel */ + if (dma_is_apbh() && apbh_is_old()) + writel(1 << chan_id, + mxs_dma->base + HW_APBHX_CTRL0 + MXS_SET_ADDR); + else + writel(1 << chan_id, + mxs_dma->base + HW_APBHX_CHANNEL_CTRL + MXS_SET_ADDR); + + mxs_chan->status = DMA_PAUSED; +} + +static void mxs_dma_resume_chan(struct mxs_dma_chan *mxs_chan) +{ + struct mxs_dma_engine *mxs_dma = mxs_chan->mxs_dma; + int chan_id = mxs_chan->chan.chan_id; + + /* unfreeze the channel */ + if (dma_is_apbh() && apbh_is_old()) + writel(1 << chan_id, + mxs_dma->base + HW_APBHX_CTRL0 + MXS_CLR_ADDR); + else + writel(1 << chan_id, + mxs_dma->base + HW_APBHX_CHANNEL_CTRL + MXS_CLR_ADDR); + + mxs_chan->status = DMA_IN_PROGRESS; +} + +static dma_cookie_t mxs_dma_assign_cookie(struct mxs_dma_chan *mxs_chan) +{ + dma_cookie_t cookie = mxs_chan->chan.cookie; + + if (++cookie < 0) + cookie = 1; + + mxs_chan->chan.cookie = cookie; + mxs_chan->desc.cookie = cookie; + + return cookie; +} + +static struct mxs_dma_chan *to_mxs_dma_chan(struct dma_chan *chan) +{ + return container_of(chan, struct mxs_dma_chan, chan); +} + +static dma_cookie_t mxs_dma_tx_submit(struct dma_async_tx_descriptor *tx) +{ + struct mxs_dma_chan *mxs_chan = to_mxs_dma_chan(tx->chan); + + mxs_dma_enable_chan(mxs_chan); + + return mxs_dma_assign_cookie(mxs_chan); +} + +static void mxs_dma_tasklet(unsigned long data) +{ + struct mxs_dma_chan *mxs_chan = (struct mxs_dma_chan *) data; + + if (mxs_chan->desc.callback) + mxs_chan->desc.callback(mxs_chan->desc.callback_param); +} + +static irqreturn_t mxs_dma_int_handler(int irq, void *dev_id) +{ + struct mxs_dma_engine *mxs_dma = dev_id; + u32 stat1, stat2; + + /* completion status */ + stat1 = readl(mxs_dma->base + HW_APBHX_CTRL1); + stat1 &= MXS_DMA_CHANNELS_MASK; + writel(stat1, mxs_dma->base + HW_APBHX_CTRL1 + MXS_CLR_ADDR); + + /* error status */ + stat2 = readl(mxs_dma->base + HW_APBHX_CTRL2); + writel(stat2, mxs_dma->base + HW_APBHX_CTRL2 + MXS_CLR_ADDR); + + /* + * When both completion and error of termination bits set at the + * same time, we do not take it as an error. IOW, it only becomes + * an error we need to handler here in case of ether it's (1) an bus + * error or (2) a termination error with no completion. + */ + stat2 = ((stat2 >> MXS_DMA_CHANNELS) & stat2) | /* (1) */ + (~(stat2 >> MXS_DMA_CHANNELS) & stat2 & ~stat1); /* (2) */ + + /* combine error and completion status for checking */ + stat1 = (stat2 << MXS_DMA_CHANNELS) | stat1; + while (stat1) { + int channel = fls(stat1) - 1; + struct mxs_dma_chan *mxs_chan = + &mxs_dma->mxs_chans[channel % MXS_DMA_CHANNELS]; + + if (channel >= MXS_DMA_CHANNELS) { + dev_dbg(mxs_dma->dma_device.dev, + "%s: error in channel %d\n", __func__, + channel - MXS_DMA_CHANNELS); + mxs_chan->status = DMA_ERROR; + mxs_dma_reset_chan(mxs_chan); + } else { + if (mxs_chan->flags & MXS_DMA_SG_LOOP) + mxs_chan->status = DMA_IN_PROGRESS; + else + mxs_chan->status = DMA_SUCCESS; + } + + stat1 &= ~(1 << channel); + + if (mxs_chan->status == DMA_SUCCESS) + mxs_chan->last_completed = mxs_chan->desc.cookie; + + /* schedule tasklet on this channel */ + tasklet_schedule(&mxs_chan->tasklet); + } + + return IRQ_HANDLED; +} + +static int mxs_dma_alloc_chan_resources(struct dma_chan *chan) +{ + struct mxs_dma_chan *mxs_chan = to_mxs_dma_chan(chan); + struct mxs_dma_data *data = chan->private; + struct mxs_dma_engine *mxs_dma = mxs_chan->mxs_dma; + int ret; + + if (!data) + return -EINVAL; + + mxs_chan->chan_irq = data->chan_irq; + + mxs_chan->ccw = dma_alloc_coherent(mxs_dma->dma_device.dev, PAGE_SIZE, + &mxs_chan->ccw_phys, GFP_KERNEL); + if (!mxs_chan->ccw) { + ret = -ENOMEM; + goto err_alloc; + } + + memset(mxs_chan->ccw, 0, PAGE_SIZE); + + ret = request_irq(mxs_chan->chan_irq, mxs_dma_int_handler, + 0, "mxs-dma", mxs_dma); + if (ret) + goto err_irq; + + ret = clk_enable(mxs_dma->clk); + if (ret) + goto err_clk; + + mxs_dma_reset_chan(mxs_chan); + + dma_async_tx_descriptor_init(&mxs_chan->desc, chan); + mxs_chan->desc.tx_submit = mxs_dma_tx_submit; + + /* the descriptor is ready */ + async_tx_ack(&mxs_chan->desc); + + return 0; + +err_clk: + free_irq(mxs_chan->chan_irq, mxs_dma); +err_irq: + dma_free_coherent(mxs_dma->dma_device.dev, PAGE_SIZE, + mxs_chan->ccw, mxs_chan->ccw_phys); +err_alloc: + return ret; +} + +static void mxs_dma_free_chan_resources(struct dma_chan *chan) +{ + struct mxs_dma_chan *mxs_chan = to_mxs_dma_chan(chan); + struct mxs_dma_engine *mxs_dma = mxs_chan->mxs_dma; + + mxs_dma_disable_chan(mxs_chan); + + free_irq(mxs_chan->chan_irq, mxs_dma); + + dma_free_coherent(mxs_dma->dma_device.dev, PAGE_SIZE, + mxs_chan->ccw, mxs_chan->ccw_phys); + + clk_disable(mxs_dma->clk); +} + +static struct dma_async_tx_descriptor *mxs_dma_prep_slave_sg( + struct dma_chan *chan, struct scatterlist *sgl, + unsigned int sg_len, enum dma_data_direction direction, + unsigned long append) +{ + struct mxs_dma_chan *mxs_chan = to_mxs_dma_chan(chan); + struct mxs_dma_engine *mxs_dma = mxs_chan->mxs_dma; + struct mxs_dma_ccw *ccw; + struct scatterlist *sg; + int i, j; + u32 *pio; + static int idx; + + if (mxs_chan->status == DMA_IN_PROGRESS && !append) + return NULL; + + if (sg_len + (append ? idx : 0) > NUM_CCW) { + dev_err(mxs_dma->dma_device.dev, + "maximum number of sg exceeded: %d > %d\n", + sg_len, NUM_CCW); + goto err_out; + } + + mxs_chan->status = DMA_IN_PROGRESS; + mxs_chan->flags = 0; + + /* + * If the sg is prepared with append flag set, the sg + * will be appended to the last prepared sg. + */ + if (append) { + BUG_ON(idx < 1); + ccw = &mxs_chan->ccw[idx - 1]; + ccw->next = mxs_chan->ccw_phys + sizeof(*ccw) * idx; + ccw->bits |= CCW_CHAIN; + ccw->bits &= ~CCW_IRQ; + ccw->bits &= ~CCW_DEC_SEM; + ccw->bits &= ~CCW_WAIT4END; + } else { + idx = 0; + } + + if (direction == DMA_NONE) { + ccw = &mxs_chan->ccw[idx++]; + pio = (u32 *) sgl; + + for (j = 0; j < sg_len;) + ccw->pio_words[j++] = *pio++; + + ccw->bits = 0; + ccw->bits |= CCW_IRQ; + ccw->bits |= CCW_DEC_SEM; + ccw->bits |= CCW_WAIT4END; + ccw->bits |= CCW_HALT_ON_TERM; + ccw->bits |= CCW_TERM_FLUSH; + ccw->bits |= BF_CCW(sg_len, PIO_NUM); + ccw->bits |= BF_CCW(MXS_DMA_CMD_NO_XFER, COMMAND); + } else { + for_each_sg(sgl, sg, sg_len, i) { + if (sg->length > MAX_XFER_BYTES) { + dev_err(mxs_dma->dma_device.dev, "maximum bytes for sg entry exceeded: %d > %d\n", + sg->length, MAX_XFER_BYTES); + goto err_out; + } + + ccw = &mxs_chan->ccw[idx++]; + + ccw->next = mxs_chan->ccw_phys + sizeof(*ccw) * idx; + ccw->bufaddr = sg->dma_address; + ccw->xfer_bytes = sg->length; + + ccw->bits = 0; + ccw->bits |= CCW_CHAIN; + ccw->bits |= CCW_HALT_ON_TERM; + ccw->bits |= CCW_TERM_FLUSH; + ccw->bits |= BF_CCW(direction == DMA_FROM_DEVICE ? + MXS_DMA_CMD_WRITE : MXS_DMA_CMD_READ, + COMMAND); + + if (i + 1 == sg_len) { + ccw->bits &= ~CCW_CHAIN; + ccw->bits |= CCW_IRQ; + ccw->bits |= CCW_DEC_SEM; + ccw->bits |= CCW_WAIT4END; + } + } + } + + return &mxs_chan->desc; + +err_out: + mxs_chan->status = DMA_ERROR; + return NULL; +} + +static struct dma_async_tx_descriptor *mxs_dma_prep_dma_cyclic( + struct dma_chan *chan, dma_addr_t dma_addr, size_t buf_len, + size_t period_len, enum dma_data_direction direction) +{ + struct mxs_dma_chan *mxs_chan = to_mxs_dma_chan(chan); + struct mxs_dma_engine *mxs_dma = mxs_chan->mxs_dma; + int num_periods = buf_len / period_len; + int i = 0, buf = 0; + + if (mxs_chan->status == DMA_IN_PROGRESS) + return NULL; + + mxs_chan->status = DMA_IN_PROGRESS; + mxs_chan->flags |= MXS_DMA_SG_LOOP; + + if (num_periods > NUM_CCW) { + dev_err(mxs_dma->dma_device.dev, + "maximum number of sg exceeded: %d > %d\n", + num_periods, NUM_CCW); + goto err_out; + } + + if (period_len > MAX_XFER_BYTES) { + dev_err(mxs_dma->dma_device.dev, + "maximum period size exceeded: %d > %d\n", + period_len, MAX_XFER_BYTES); + goto err_out; + } + + while (buf < buf_len) { + struct mxs_dma_ccw *ccw = &mxs_chan->ccw[i]; + + if (i + 1 == num_periods) + ccw->next = mxs_chan->ccw_phys; + else + ccw->next = mxs_chan->ccw_phys + sizeof(*ccw) * (i + 1); + + ccw->bufaddr = dma_addr; + ccw->xfer_bytes = period_len; + + ccw->bits = 0; + ccw->bits |= CCW_CHAIN; + ccw->bits |= CCW_IRQ; + ccw->bits |= CCW_HALT_ON_TERM; + ccw->bits |= CCW_TERM_FLUSH; + ccw->bits |= BF_CCW(direction == DMA_FROM_DEVICE ? + MXS_DMA_CMD_WRITE : MXS_DMA_CMD_READ, COMMAND); + + dma_addr += period_len; + buf += period_len; + + i++; + } + + return &mxs_chan->desc; + +err_out: + mxs_chan->status = DMA_ERROR; + return NULL; +} + +static int mxs_dma_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd, + unsigned long arg) +{ + struct mxs_dma_chan *mxs_chan = to_mxs_dma_chan(chan); + int ret = 0; + + switch (cmd) { + case DMA_TERMINATE_ALL: + mxs_dma_disable_chan(mxs_chan); + break; + case DMA_PAUSE: + mxs_dma_pause_chan(mxs_chan); + break; + case DMA_RESUME: + mxs_dma_resume_chan(mxs_chan); + break; + default: + ret = -ENOSYS; + } + + return ret; +} + +static enum dma_status mxs_dma_tx_status(struct dma_chan *chan, + dma_cookie_t cookie, struct dma_tx_state *txstate) +{ + struct mxs_dma_chan *mxs_chan = to_mxs_dma_chan(chan); + dma_cookie_t last_used; + + last_used = chan->cookie; + dma_set_tx_state(txstate, mxs_chan->last_completed, last_used, 0); + + return mxs_chan->status; +} + +static void mxs_dma_issue_pending(struct dma_chan *chan) +{ + /* + * Nothing to do. We only have a single descriptor. + */ +} + +static int __init mxs_dma_init(struct mxs_dma_engine *mxs_dma) +{ + int ret; + + ret = clk_enable(mxs_dma->clk); + if (ret) + goto err_out; + + ret = mxs_reset_block(mxs_dma->base); + if (ret) + goto err_out; + + /* only major version matters */ + mxs_dma->version = readl(mxs_dma->base + + ((mxs_dma->dev_id == MXS_DMA_APBX) ? + HW_APBX_VERSION : HW_APBH_VERSION)) >> + BP_APBHX_VERSION_MAJOR; + + /* enable apbh burst */ + if (dma_is_apbh()) { + writel(BM_APBH_CTRL0_APB_BURST_EN, + mxs_dma->base + HW_APBHX_CTRL0 + MXS_SET_ADDR); + writel(BM_APBH_CTRL0_APB_BURST8_EN, + mxs_dma->base + HW_APBHX_CTRL0 + MXS_SET_ADDR); + } + + /* enable irq for all the channels */ + writel(MXS_DMA_CHANNELS_MASK << MXS_DMA_CHANNELS, + mxs_dma->base + HW_APBHX_CTRL1 + MXS_SET_ADDR); + + clk_disable(mxs_dma->clk); + + return 0; + +err_out: + return ret; +} + +static int __init mxs_dma_probe(struct platform_device *pdev) +{ + const struct platform_device_id *id_entry = + platform_get_device_id(pdev); + struct mxs_dma_engine *mxs_dma; + struct resource *iores; + int ret, i; + + mxs_dma = kzalloc(sizeof(*mxs_dma), GFP_KERNEL); + if (!mxs_dma) + return -ENOMEM; + + mxs_dma->dev_id = id_entry->driver_data; + + iores = platform_get_resource(pdev, IORESOURCE_MEM, 0); + + if (!request_mem_region(iores->start, resource_size(iores), + pdev->name)) { + ret = -EBUSY; + goto err_request_region; + } + + mxs_dma->base = ioremap(iores->start, resource_size(iores)); + if (!mxs_dma->base) { + ret = -ENOMEM; + goto err_ioremap; + } + + mxs_dma->clk = clk_get(&pdev->dev, NULL); + if (IS_ERR(mxs_dma->clk)) { + ret = PTR_ERR(mxs_dma->clk); + goto err_clk; + } + + dma_cap_set(DMA_SLAVE, mxs_dma->dma_device.cap_mask); + dma_cap_set(DMA_CYCLIC, mxs_dma->dma_device.cap_mask); + + INIT_LIST_HEAD(&mxs_dma->dma_device.channels); + + /* Initialize channel parameters */ + for (i = 0; i < MXS_DMA_CHANNELS; i++) { + struct mxs_dma_chan *mxs_chan = &mxs_dma->mxs_chans[i]; + + mxs_chan->mxs_dma = mxs_dma; + mxs_chan->chan.device = &mxs_dma->dma_device; + + tasklet_init(&mxs_chan->tasklet, mxs_dma_tasklet, + (unsigned long) mxs_chan); + + + /* Add the channel to mxs_chan list */ + list_add_tail(&mxs_chan->chan.device_node, + &mxs_dma->dma_device.channels); + } + + ret = mxs_dma_init(mxs_dma); + if (ret) + goto err_init; + + mxs_dma->dma_device.dev = &pdev->dev; + + /* mxs_dma gets 65535 bytes maximum sg size */ + mxs_dma->dma_device.dev->dma_parms = &mxs_dma->dma_parms; + dma_set_max_seg_size(mxs_dma->dma_device.dev, MAX_XFER_BYTES); + + mxs_dma->dma_device.device_alloc_chan_resources = mxs_dma_alloc_chan_resources; + mxs_dma->dma_device.device_free_chan_resources = mxs_dma_free_chan_resources; + mxs_dma->dma_device.device_tx_status = mxs_dma_tx_status; + mxs_dma->dma_device.device_prep_slave_sg = mxs_dma_prep_slave_sg; + mxs_dma->dma_device.device_prep_dma_cyclic = mxs_dma_prep_dma_cyclic; + mxs_dma->dma_device.device_control = mxs_dma_control; + mxs_dma->dma_device.device_issue_pending = mxs_dma_issue_pending; + + ret = dma_async_device_register(&mxs_dma->dma_device); + if (ret) { + dev_err(mxs_dma->dma_device.dev, "unable to register\n"); + goto err_init; + } + + dev_info(mxs_dma->dma_device.dev, "initialized\n"); + + return 0; + +err_init: + clk_put(mxs_dma->clk); +err_clk: + iounmap(mxs_dma->base); +err_ioremap: + release_mem_region(iores->start, resource_size(iores)); +err_request_region: + kfree(mxs_dma); + return ret; +} + +static struct platform_device_id mxs_dma_type[] = { + { + .name = "mxs-dma-apbh", + .driver_data = MXS_DMA_APBH, + }, { + .name = "mxs-dma-apbx", + .driver_data = MXS_DMA_APBX, + } +}; + +static struct platform_driver mxs_dma_driver = { + .driver = { + .name = "mxs-dma", + }, + .id_table = mxs_dma_type, +}; + +static int __init mxs_dma_module_init(void) +{ + return platform_driver_probe(&mxs_dma_driver, mxs_dma_probe); +} +subsys_initcall(mxs_dma_module_init); -- GitLab From eeb2036b8a148629b762ae6d85cff0be8106f081 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Tue, 1 Mar 2011 17:50:00 +0000 Subject: [PATCH 0257/2822] xfs: zero proper structure size for geometry calls Commit 493f3358cb289ccf716c5a14fa5bb52ab75943e5 added this call to xfs_fs_geometry() in order to avoid passing kernel stack data back to user space: + memset(geo, 0, sizeof(*geo)); Unfortunately, one of the callers of that function passes the address of a smaller data type, cast to fit the type that xfs_fs_geometry() requires. As a result, this can happen: Kernel panic - not syncing: stack-protector: Kernel stack is corrupted in: f87aca93 Pid: 262, comm: xfs_fsr Not tainted 2.6.38-rc6-493f3358cb2+ #1 Call Trace: [] ? panic+0x50/0x150 [] ? __stack_chk_fail+0x10/0x18 [] ? xfs_ioc_fsgeometry_v1+0x56/0x5d [xfs] Fix this by fixing that one caller to pass the right type and then copy out the subset it is interested in. Note: This patch is an alternative to one originally proposed by Eric Sandeen. Reported-by: Jeffrey Hundstad Signed-off-by: Alex Elder Reviewed-by: Eric Sandeen Tested-by: Jeffrey Hundstad --- fs/xfs/linux-2.6/xfs_ioctl.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/fs/xfs/linux-2.6/xfs_ioctl.c b/fs/xfs/linux-2.6/xfs_ioctl.c index f5e2a19e0f8eb..0ca0e3c024d7b 100644 --- a/fs/xfs/linux-2.6/xfs_ioctl.c +++ b/fs/xfs/linux-2.6/xfs_ioctl.c @@ -695,14 +695,19 @@ xfs_ioc_fsgeometry_v1( xfs_mount_t *mp, void __user *arg) { - xfs_fsop_geom_v1_t fsgeo; + xfs_fsop_geom_t fsgeo; int error; - error = xfs_fs_geometry(mp, (xfs_fsop_geom_t *)&fsgeo, 3); + error = xfs_fs_geometry(mp, &fsgeo, 3); if (error) return -error; - if (copy_to_user(arg, &fsgeo, sizeof(fsgeo))) + /* + * Caller should have passed an argument of type + * xfs_fsop_geom_v1_t. This is a proper subset of the + * xfs_fsop_geom_t that xfs_fs_geometry() fills in. + */ + if (copy_to_user(arg, &fsgeo, sizeof(xfs_fsop_geom_v1_t))) return -XFS_ERROR(EFAULT); return 0; } -- GitLab From 10e38391c0e242e53e30094f6c00553418ab2f2e Mon Sep 17 00:00:00 2001 From: Dave Chinner Date: Wed, 2 Mar 2011 14:20:59 +1100 Subject: [PATCH 0258/2822] xfs: introduce new logging API. Most of the logging infrastructure in XFS is unneccessary and designed around the infrastructure supplied by Irix rather than Linux. To rationalise the logging interfaces, start by introducing simple printk wrappers similar to the dev_printk() infrastructure. Later patches will convert code to use this new interface. Signed-off-by: Dave Chinner Reviewed-by: Alex Elder Reviewed-by: Christoph Hellwig --- fs/xfs/Makefile | 1 + fs/xfs/linux-2.6/xfs_linux.h | 1 + fs/xfs/linux-2.6/xfs_message.c | 119 +++++++++++++++++++++++++++++++++ fs/xfs/linux-2.6/xfs_message.h | 34 ++++++++++ 4 files changed, 155 insertions(+) create mode 100644 fs/xfs/linux-2.6/xfs_message.c create mode 100644 fs/xfs/linux-2.6/xfs_message.h diff --git a/fs/xfs/Makefile b/fs/xfs/Makefile index faca449970995..077784ed6a7f5 100644 --- a/fs/xfs/Makefile +++ b/fs/xfs/Makefile @@ -105,6 +105,7 @@ xfs-y += $(addprefix $(XFS_LINUX)/, \ xfs_globals.o \ xfs_ioctl.o \ xfs_iops.o \ + xfs_message.o \ xfs_super.o \ xfs_sync.o \ xfs_xattr.o) diff --git a/fs/xfs/linux-2.6/xfs_linux.h b/fs/xfs/linux-2.6/xfs_linux.h index 096494997747d..1189bfcbcd3ef 100644 --- a/fs/xfs/linux-2.6/xfs_linux.h +++ b/fs/xfs/linux-2.6/xfs_linux.h @@ -86,6 +86,7 @@ #include #include #include +#include /* * Feature macros (disable/enable) diff --git a/fs/xfs/linux-2.6/xfs_message.c b/fs/xfs/linux-2.6/xfs_message.c new file mode 100644 index 0000000000000..6f3368eec25db --- /dev/null +++ b/fs/xfs/linux-2.6/xfs_message.c @@ -0,0 +1,119 @@ +/* + * Copyright (c) 2011 Red Hat, Inc. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it would be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "xfs.h" +#include "xfs_fs.h" +#include "xfs_types.h" +#include "xfs_log.h" +#include "xfs_inum.h" +#include "xfs_trans.h" +#include "xfs_sb.h" +#include "xfs_ag.h" +#include "xfs_mount.h" + +/* + * XFS logging functions + */ +static int +__xfs_printk( + const char *level, + const struct xfs_mount *mp, + struct va_format *vaf) +{ + if (mp && mp->m_fsname) + return printk("%sXFS (%s): %pV\n", level, mp->m_fsname, vaf); + return printk("%sXFS: %pV\n", level, vaf); +} + +int xfs_printk( + const char *level, + const struct xfs_mount *mp, + const char *fmt, ...) +{ + struct va_format vaf; + va_list args; + int r; + + va_start(args, fmt); + + vaf.fmt = fmt; + vaf.va = &args; + + r = __xfs_printk(level, mp, &vaf); + va_end(args); + + return r; +} + +#define define_xfs_printk_level(func, kern_level) \ +int func(const struct xfs_mount *mp, const char *fmt, ...) \ +{ \ + struct va_format vaf; \ + va_list args; \ + int r; \ + \ + va_start(args, fmt); \ + \ + vaf.fmt = fmt; \ + vaf.va = &args; \ + \ + r = __xfs_printk(kern_level, mp, &vaf); \ + va_end(args); \ + \ + return r; \ +} \ + +define_xfs_printk_level(xfs_emerg, KERN_EMERG); +define_xfs_printk_level(xfs_alert, KERN_ALERT); +define_xfs_printk_level(xfs_crit, KERN_CRIT); +define_xfs_printk_level(xfs_err, KERN_ERR); +define_xfs_printk_level(xfs_warn, KERN_WARNING); +define_xfs_printk_level(xfs_notice, KERN_NOTICE); +define_xfs_printk_level(xfs_info, KERN_INFO); +#ifdef DEBUG +define_xfs_printk_level(xfs_debug, KERN_DEBUG); +#endif + +int +xfs_alert_tag( + const struct xfs_mount *mp, + int panic_tag, + const char *fmt, ...) +{ + struct va_format vaf; + va_list args; + int panic = 0; + int r; + + if (xfs_panic_mask && (xfs_panic_mask & panic_tag)) { + xfs_printk(KERN_ALERT, mp, + "XFS: Transforming an alert into a BUG."); + panic = 1; + } + + va_start(args, fmt); + + vaf.fmt = fmt; + vaf.va = &args; + + r = __xfs_printk(KERN_ALERT, mp, &vaf); + va_end(args); + + BUG_ON(panic); + + return r; +} diff --git a/fs/xfs/linux-2.6/xfs_message.h b/fs/xfs/linux-2.6/xfs_message.h new file mode 100644 index 0000000000000..8d2df01753040 --- /dev/null +++ b/fs/xfs/linux-2.6/xfs_message.h @@ -0,0 +1,34 @@ +#ifndef __XFS_MESSAGE_H +#define __XFS_MESSAGE_H 1 + +struct xfs_mount; + +extern int xfs_printk(const char *level, const struct xfs_mount *mp, + const char *fmt, ...) + __attribute__ ((format (printf, 3, 4))); +extern int xfs_emerg(const struct xfs_mount *mp, const char *fmt, ...) + __attribute__ ((format (printf, 2, 3))); +extern int xfs_alert(const struct xfs_mount *mp, const char *fmt, ...) + __attribute__ ((format (printf, 2, 3))); +extern int xfs_alert_tag(const struct xfs_mount *mp, int tag, + const char *fmt, ...) + __attribute__ ((format (printf, 3, 4))); +extern int xfs_crit(const struct xfs_mount *mp, const char *fmt, ...) + __attribute__ ((format (printf, 2, 3))); +extern int xfs_err(const struct xfs_mount *mp, const char *fmt, ...) + __attribute__ ((format (printf, 2, 3))); +extern int xfs_warn(const struct xfs_mount *mp, const char *fmt, ...) + __attribute__ ((format (printf, 2, 3))); +extern int xfs_notice(const struct xfs_mount *mp, const char *fmt, ...) + __attribute__ ((format (printf, 2, 3))); +extern int xfs_info(const struct xfs_mount *mp, const char *fmt, ...) + __attribute__ ((format (printf, 2, 3))); + +#ifdef DEBUG +extern int xfs_debug(const struct xfs_mount *mp, const char *fmt, ...) + __attribute__ ((format (printf, 2, 3))); +#else +#define xfs_debug(mp, fmt, ...) (0) +#endif + +#endif /* __XFS_MESSAGE_H */ -- GitLab From 53f22956effe1c9e7961b8c6e4362ecca5e460b7 Mon Sep 17 00:00:00 2001 From: Liu Yuan Date: Wed, 2 Mar 2011 11:00:15 -0500 Subject: [PATCH 0259/2822] block/genhd: Change some numerals into macros Rename the numerals in the diskstats_show() into the macros. Cc: Jens Axboe Signed-off-by: Liu Yuan Signed-off-by: Jens Axboe --- block/genhd.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/block/genhd.c b/block/genhd.c index 6a5b772aa2016..73d85a8e3c852 100644 --- a/block/genhd.c +++ b/block/genhd.c @@ -1158,14 +1158,14 @@ static int diskstats_show(struct seq_file *seqf, void *v) "%u %lu %lu %llu %u %u %u %u\n", MAJOR(part_devt(hd)), MINOR(part_devt(hd)), disk_name(gp, hd->partno, buf), - part_stat_read(hd, ios[0]), - part_stat_read(hd, merges[0]), - (unsigned long long)part_stat_read(hd, sectors[0]), - jiffies_to_msecs(part_stat_read(hd, ticks[0])), - part_stat_read(hd, ios[1]), - part_stat_read(hd, merges[1]), - (unsigned long long)part_stat_read(hd, sectors[1]), - jiffies_to_msecs(part_stat_read(hd, ticks[1])), + part_stat_read(hd, ios[READ]), + part_stat_read(hd, merges[READ]), + (unsigned long long)part_stat_read(hd, sectors[READ]), + jiffies_to_msecs(part_stat_read(hd, ticks[READ])), + part_stat_read(hd, ios[WRITE]), + part_stat_read(hd, merges[WRITE]), + (unsigned long long)part_stat_read(hd, sectors[WRITE]), + jiffies_to_msecs(part_stat_read(hd, ticks[WRITE])), part_in_flight(hd), jiffies_to_msecs(part_stat_read(hd, io_ticks)), jiffies_to_msecs(part_stat_read(hd, time_in_queue)) -- GitLab From c94a96ac93b4f5b8d1ff8430b1afa1a25610cf53 Mon Sep 17 00:00:00 2001 From: Vivek Goyal Date: Wed, 2 Mar 2011 19:04:42 -0500 Subject: [PATCH 0260/2822] block: Initialize ->queue_lock to internal lock at queue allocation time There does not seem to be a clear convention whether q->queue_lock is initialized or not when blk_cleanup_queue() is called. In the past it was not necessary but now blk_throtl_exit() takes up queue lock by default and needs queue lock to be available. In fact elevator_exit() code also has similar requirement just that it is less stringent in the sense that elevator_exit() is called only if elevator is initialized. Two problems have been noticed because of ambiguity about spin lock status. - If a driver calls blk_alloc_queue() and then soon calls blk_cleanup_queue() almost immediately, (because some other driver structure allocation failed or some other error happened) then blk_throtl_exit() will run into issues as queue lock is not initialized. Loop driver ran into this issue recently and I noticed error paths in md driver too. Similar error paths should exist in other drivers too. - If some driver provided external spin lock and zapped the lock before blk_cleanup_queue(), then it can lead to issues. So this patch initializes the default queue lock at queue allocation time. block throttling code is one of the users of queue lock and it is initialized at the queue allocation time, so it makes sense to initialize ->queue_lock also to internal lock. A driver can overide that lock later. This will take care of the issue where a driver does not have to worry about initializing the queue lock to default before calling blk_cleanup_queue() Signed-off-by: Vivek Goyal Signed-off-by: Jens Axboe --- block/blk-core.c | 16 +++++++++++++++- block/blk-settings.c | 7 ------- 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/block/blk-core.c b/block/blk-core.c index 3cc17e6064d68..bc2b7c5004e17 100644 --- a/block/blk-core.c +++ b/block/blk-core.c @@ -446,6 +446,11 @@ void blk_put_queue(struct request_queue *q) kobject_put(&q->kobj); } +/* + * Note: If a driver supplied the queue lock, it should not zap that lock + * unexpectedly as some queue cleanup components like elevator_exit() and + * blk_throtl_exit() need queue lock. + */ void blk_cleanup_queue(struct request_queue *q) { /* @@ -540,6 +545,12 @@ struct request_queue *blk_alloc_queue_node(gfp_t gfp_mask, int node_id) mutex_init(&q->sysfs_lock); spin_lock_init(&q->__queue_lock); + /* + * By default initialize queue_lock to internal lock and driver can + * override it later if need be. + */ + q->queue_lock = &q->__queue_lock; + return q; } EXPORT_SYMBOL(blk_alloc_queue_node); @@ -624,7 +635,10 @@ blk_init_allocated_queue_node(struct request_queue *q, request_fn_proc *rfn, q->unprep_rq_fn = NULL; q->unplug_fn = generic_unplug_device; q->queue_flags = QUEUE_FLAG_DEFAULT; - q->queue_lock = lock; + + /* Override internal queue lock with supplied lock pointer */ + if (lock) + q->queue_lock = lock; /* * This also sets hw/phys segments, boundary and size diff --git a/block/blk-settings.c b/block/blk-settings.c index 36c8c1f2af180..df649fa59ded2 100644 --- a/block/blk-settings.c +++ b/block/blk-settings.c @@ -175,13 +175,6 @@ void blk_queue_make_request(struct request_queue *q, make_request_fn *mfn) blk_set_default_limits(&q->limits); blk_queue_max_hw_sectors(q, BLK_SAFE_MAX_SECTORS); - /* - * If the caller didn't supply a lock, fall back to our embedded - * per-queue locks - */ - if (!q->queue_lock) - q->queue_lock = &q->__queue_lock; - /* * by default assume old behaviour and bounce for any highmem page */ -- GitLab From cd25f54961273c2e4cbd47441e04832468382a5e Mon Sep 17 00:00:00 2001 From: Vivek Goyal Date: Wed, 2 Mar 2011 19:04:50 -0500 Subject: [PATCH 0261/2822] loop: No need to initialize ->queue_lock explicitly before calling blk_cleanup_queue() Now we initialize ->queue_lock at queue allocation time so driver does not have to worry about initializing it before calling blk_cleanup_queue(). Signed-off-by: Jens Axboe --- drivers/block/loop.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/block/loop.c b/drivers/block/loop.c index 49e6a545eb63f..44e18c073c441 100644 --- a/drivers/block/loop.c +++ b/drivers/block/loop.c @@ -1641,9 +1641,6 @@ out: static void loop_free(struct loop_device *lo) { - if (!lo->lo_queue->queue_lock) - lo->lo_queue->queue_lock = &lo->lo_queue->__queue_lock; - blk_cleanup_queue(lo->lo_queue); put_disk(lo->lo_disk); list_del(&lo->lo_list); -- GitLab From da527770007fce8e4541947d47918248286da875 Mon Sep 17 00:00:00 2001 From: Vivek Goyal Date: Wed, 2 Mar 2011 19:05:33 -0500 Subject: [PATCH 0262/2822] block: Move blk_throtl_exit() call to blk_cleanup_queue() Move blk_throtl_exit() in blk_cleanup_queue() as blk_throtl_exit() is written in such a way that it needs queue lock. In blk_release_queue() there is no gurantee that ->queue_lock is still around. Initially blk_throtl_exit() was in blk_cleanup_queue() but Ingo reported one problem. https://lkml.org/lkml/2010/10/23/86 And a quick fix moved blk_throtl_exit() to blk_release_queue(). commit 7ad58c028652753814054f4e3ac58f925e7343f4 Author: Jens Axboe Date: Sat Oct 23 20:40:26 2010 +0200 block: fix use-after-free bug in blk throttle code This patch reverts above change and does not try to shutdown the throtl work in blk_sync_queue(). By avoiding call to throtl_shutdown_timer_wq() from blk_sync_queue(), we should also avoid the problem reported by Ingo. blk_sync_queue() seems to be used only by md driver and it seems to be using it to make sure q->unplug_fn is not called as md registers its own unplug functions and it is about to free up the data structures used by unplug_fn(). Block throttle does not call back into unplug_fn() or into md. So there is no need to cancel blk throttle work. In fact I think cancelling block throttle work is bad because it might happen that some bios are throttled and scheduled to be dispatched later with the help of pending work and if work is cancelled, these bios might never be dispatched. Block layer also uses blk_sync_queue() during blk_cleanup_queue() and blk_release_queue() time. That should be safe as we are also calling blk_throtl_exit() which should make sure all the throttling related data structures are cleaned up. Signed-off-by: Vivek Goyal Signed-off-by: Jens Axboe --- block/blk-core.c | 7 ++++++- block/blk-sysfs.c | 2 -- block/blk-throttle.c | 6 +++--- include/linux/blkdev.h | 2 -- 4 files changed, 9 insertions(+), 8 deletions(-) diff --git a/block/blk-core.c b/block/blk-core.c index bc2b7c5004e17..accff29ad6745 100644 --- a/block/blk-core.c +++ b/block/blk-core.c @@ -380,13 +380,16 @@ EXPORT_SYMBOL(blk_stop_queue); * that its ->make_request_fn will not re-add plugging prior to calling * this function. * + * This function does not cancel any asynchronous activity arising + * out of elevator or throttling code. That would require elevaotor_exit() + * and blk_throtl_exit() to be called with queue lock initialized. + * */ void blk_sync_queue(struct request_queue *q) { del_timer_sync(&q->unplug_timer); del_timer_sync(&q->timeout); cancel_work_sync(&q->unplug_work); - throtl_shutdown_timer_wq(q); } EXPORT_SYMBOL(blk_sync_queue); @@ -469,6 +472,8 @@ void blk_cleanup_queue(struct request_queue *q) if (q->elevator) elevator_exit(q->elevator); + blk_throtl_exit(q); + blk_put_queue(q); } EXPORT_SYMBOL(blk_cleanup_queue); diff --git a/block/blk-sysfs.c b/block/blk-sysfs.c index 41fb69150b4d3..261c75c665ae3 100644 --- a/block/blk-sysfs.c +++ b/block/blk-sysfs.c @@ -471,8 +471,6 @@ static void blk_release_queue(struct kobject *kobj) blk_sync_queue(q); - blk_throtl_exit(q); - if (rl->rq_pool) mempool_destroy(rl->rq_pool); diff --git a/block/blk-throttle.c b/block/blk-throttle.c index a89043a3caa41..c0f6237421656 100644 --- a/block/blk-throttle.c +++ b/block/blk-throttle.c @@ -965,7 +965,7 @@ static void throtl_update_blkio_group_write_iops(void *key, throtl_schedule_delayed_work(td->queue, 0); } -void throtl_shutdown_timer_wq(struct request_queue *q) +static void throtl_shutdown_wq(struct request_queue *q) { struct throtl_data *td = q->td; @@ -1099,7 +1099,7 @@ void blk_throtl_exit(struct request_queue *q) BUG_ON(!td); - throtl_shutdown_timer_wq(q); + throtl_shutdown_wq(q); spin_lock_irq(q->queue_lock); throtl_release_tgs(td); @@ -1129,7 +1129,7 @@ void blk_throtl_exit(struct request_queue *q) * update limits through cgroup and another work got queued, cancel * it. */ - throtl_shutdown_timer_wq(q); + throtl_shutdown_wq(q); throtl_td_free(td); } diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index e3ee74fc59030..23fb92506c31f 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -1144,7 +1144,6 @@ extern int blk_throtl_init(struct request_queue *q); extern void blk_throtl_exit(struct request_queue *q); extern int blk_throtl_bio(struct request_queue *q, struct bio **bio); extern void throtl_schedule_delayed_work(struct request_queue *q, unsigned long delay); -extern void throtl_shutdown_timer_wq(struct request_queue *q); #else /* CONFIG_BLK_DEV_THROTTLING */ static inline int blk_throtl_bio(struct request_queue *q, struct bio **bio) { @@ -1154,7 +1153,6 @@ static inline int blk_throtl_bio(struct request_queue *q, struct bio **bio) static inline int blk_throtl_init(struct request_queue *q) { return 0; } static inline int blk_throtl_exit(struct request_queue *q) { return 0; } static inline void throtl_schedule_delayed_work(struct request_queue *q, unsigned long delay) {} -static inline void throtl_shutdown_timer_wq(struct request_queue *q) {} #endif /* CONFIG_BLK_DEV_THROTTLING */ #define MODULE_ALIAS_BLOCKDEV(major,minor) \ -- GitLab From 6dfad339645247c9deb553e4d68e21211ddc61bd Mon Sep 17 00:00:00 2001 From: Lin Ming Date: Mon, 14 Feb 2011 15:29:34 +0800 Subject: [PATCH 0263/2822] ACPICA: GPE detect optimization - ignore unused GPE registers This optimization will simply ignore GPE registers that contain no enabled GPEs - there is no need to read the register. ACPICA bugzilla 884. http://www.acpica.org/bugzilla/show_bug.cgi?id=884 Signed-off-by: Lin Ming Signed-off-by: Bob Moore Signed-off-by: Len Brown --- drivers/acpi/acpica/evgpe.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/acpi/acpica/evgpe.c b/drivers/acpi/acpica/evgpe.c index 14988a86066fb..67d44ef2fbc1c 100644 --- a/drivers/acpi/acpica/evgpe.c +++ b/drivers/acpi/acpica/evgpe.c @@ -373,6 +373,15 @@ u32 acpi_ev_gpe_detect(struct acpi_gpe_xrupt_info * gpe_xrupt_list) gpe_register_info = &gpe_block->register_info[i]; + /* + * Optimization: If there are no GPEs enabled within this + * register, we can safely ignore the entire register. + */ + if (!(gpe_register_info->enable_for_run | + gpe_register_info->enable_for_wake)) { + continue; + } + /* Read the Status Register */ status = -- GitLab From 64b3db22c04586997ab4be46dd5a5b99f8a2d390 Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Mon, 14 Feb 2011 15:50:42 +0800 Subject: [PATCH 0264/2822] ACPICA: Remove use of unreliable FADT revision field The revision number in the FADT has been found to be completely unreliable and cannot be trusted. Only the table length can be used to infer the actual version. Signed-off-by: Bob Moore Signed-off-by: Lin Ming Signed-off-by: Len Brown --- drivers/acpi/acpica/tbfadt.c | 5 ++++- include/acpi/actbl.h | 16 ++++++++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/drivers/acpi/acpica/tbfadt.c b/drivers/acpi/acpica/tbfadt.c index 428d44e2d1624..6f5588e62c0ac 100644 --- a/drivers/acpi/acpica/tbfadt.c +++ b/drivers/acpi/acpica/tbfadt.c @@ -384,8 +384,11 @@ static void acpi_tb_convert_fadt(void) * * The ACPI 1.0 reserved fields that will be zeroed are the bytes located at * offset 45, 55, 95, and the word located at offset 109, 110. + * + * Note: The FADT revision value is unreliable. Only the length can be + * trusted. */ - if (acpi_gbl_FADT.header.revision < FADT2_REVISION_ID) { + if (acpi_gbl_FADT.header.length <= ACPI_FADT_V2_SIZE) { acpi_gbl_FADT.preferred_profile = 0; acpi_gbl_FADT.pstate_control = 0; acpi_gbl_FADT.cst_control = 0; diff --git a/include/acpi/actbl.h b/include/acpi/actbl.h index 7e42bfee0e296..d41c94885211c 100644 --- a/include/acpi/actbl.h +++ b/include/acpi/actbl.h @@ -343,4 +343,20 @@ struct acpi_table_desc { #include #include +/* + * Sizes of the various flavors of FADT. We need to look closely + * at the FADT length because the version number essentially tells + * us nothing because of many BIOS bugs where the version does not + * match the expected length. In other words, the length of the + * FADT is the bottom line as to what the version really is. + * + * For reference, the values below are as follows: + * FADT V1 size: 0x74 + * FADT V2 size: 0x84 + * FADT V3+ size: 0xF4 + */ +#define ACPI_FADT_V1_SIZE (u32) (ACPI_FADT_OFFSET (flags) + 4) +#define ACPI_FADT_V2_SIZE (u32) (ACPI_FADT_OFFSET (reserved4[0]) + 3) +#define ACPI_FADT_V3_SIZE (u32) (sizeof (struct acpi_table_fadt)) + #endif /* __ACTBL_H__ */ -- GitLab From 1b74dfb2f735454031584dc8162f8f27aa5265bf Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Mon, 14 Feb 2011 15:52:56 +0800 Subject: [PATCH 0265/2822] ACPICA: Clarify a couple of error messages Clarify region error messages with ID= prefix for space id. Signed-off-by: Bob Moore Signed-off-by: Lin Ming Signed-off-by: Len Brown --- drivers/acpi/acpica/exfldio.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/acpi/acpica/exfldio.c b/drivers/acpi/acpica/exfldio.c index 6c79c29f082df..f915a7f3f921e 100644 --- a/drivers/acpi/acpica/exfldio.c +++ b/drivers/acpi/acpica/exfldio.c @@ -280,13 +280,13 @@ acpi_ex_access_region(union acpi_operand_object *obj_desc, if (ACPI_FAILURE(status)) { if (status == AE_NOT_IMPLEMENTED) { ACPI_ERROR((AE_INFO, - "Region %s(0x%X) not implemented", + "Region %s (ID=%u) not implemented", acpi_ut_get_region_name(rgn_desc->region. space_id), rgn_desc->region.space_id)); } else if (status == AE_NOT_EXIST) { ACPI_ERROR((AE_INFO, - "Region %s(0x%X) has no handler", + "Region %s (ID=%u) has no handler", acpi_ut_get_region_name(rgn_desc->region. space_id), rgn_desc->region.space_id)); -- GitLab From a257e07527890a7f95982b9c330efd8d2de3707a Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Mon, 14 Feb 2011 16:00:21 +0800 Subject: [PATCH 0266/2822] ACPICA: Split large utglobal into utdecode.c. utglobal.c contained a lot of code not related to global variables. These utility decode functions are moved to utdecode.c Signed-off-by: Bob Moore Signed-off-by: Lin Ming Signed-off-by: Len Brown --- drivers/acpi/acpica/Makefile | 2 +- drivers/acpi/acpica/aclocal.h | 19 -- drivers/acpi/acpica/utdecode.c | 546 +++++++++++++++++++++++++++++++++ drivers/acpi/acpica/utglobal.c | 483 ----------------------------- 4 files changed, 547 insertions(+), 503 deletions(-) create mode 100644 drivers/acpi/acpica/utdecode.c diff --git a/drivers/acpi/acpica/Makefile b/drivers/acpi/acpica/Makefile index eec2eadd24310..b1706aacbe98b 100644 --- a/drivers/acpi/acpica/Makefile +++ b/drivers/acpi/acpica/Makefile @@ -45,4 +45,4 @@ acpi-y += tbxface.o tbinstal.o tbutils.o tbfind.o tbfadt.o tbxfroot.o acpi-y += utalloc.o utdebug.o uteval.o utinit.o utmisc.o utxface.o \ utcopy.o utdelete.o utglobal.o utmath.o utobject.o \ utstate.o utmutex.o utobject.o utresrc.o utlock.o utids.o \ - utosi.o utxferror.o + utosi.o utxferror.o utdecode.o diff --git a/drivers/acpi/acpica/aclocal.h b/drivers/acpi/acpica/aclocal.h index 54784bb42ceca..01bcab1c5cc44 100644 --- a/drivers/acpi/acpica/aclocal.h +++ b/drivers/acpi/acpica/aclocal.h @@ -89,25 +89,6 @@ union acpi_parse_object; #define ACPI_MAX_MUTEX 7 #define ACPI_NUM_MUTEX ACPI_MAX_MUTEX+1 -#if defined(ACPI_DEBUG_OUTPUT) || defined(ACPI_DEBUGGER) -#ifdef DEFINE_ACPI_GLOBALS - -/* Debug names for the mutexes above */ - -static char *acpi_gbl_mutex_names[ACPI_NUM_MUTEX] = { - "ACPI_MTX_Interpreter", - "ACPI_MTX_Namespace", - "ACPI_MTX_Tables", - "ACPI_MTX_Events", - "ACPI_MTX_Caches", - "ACPI_MTX_Memory", - "ACPI_MTX_CommandComplete", - "ACPI_MTX_CommandReady" -}; - -#endif -#endif - /* Lock structure for reader/writer interfaces */ struct acpi_rw_lock { diff --git a/drivers/acpi/acpica/utdecode.c b/drivers/acpi/acpica/utdecode.c new file mode 100644 index 0000000000000..ce91e59c449f3 --- /dev/null +++ b/drivers/acpi/acpica/utdecode.c @@ -0,0 +1,546 @@ +/****************************************************************************** + * + * Module Name: utdecode - Utility decoding routines (value-to-string) + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2011, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include +#include "accommon.h" +#include "acnamesp.h" + +#define _COMPONENT ACPI_UTILITIES +ACPI_MODULE_NAME("utdecode") + +/******************************************************************************* + * + * FUNCTION: acpi_format_exception + * + * PARAMETERS: Status - The acpi_status code to be formatted + * + * RETURN: A string containing the exception text. A valid pointer is + * always returned. + * + * DESCRIPTION: This function translates an ACPI exception into an ASCII string + * It is here instead of utxface.c so it is always present. + * + ******************************************************************************/ +const char *acpi_format_exception(acpi_status status) +{ + const char *exception = NULL; + + ACPI_FUNCTION_ENTRY(); + + exception = acpi_ut_validate_exception(status); + if (!exception) { + + /* Exception code was not recognized */ + + ACPI_ERROR((AE_INFO, + "Unknown exception code: 0x%8.8X", status)); + + exception = "UNKNOWN_STATUS_CODE"; + } + + return (ACPI_CAST_PTR(const char, exception)); +} + +ACPI_EXPORT_SYMBOL(acpi_format_exception) + +/* + * Properties of the ACPI Object Types, both internal and external. + * The table is indexed by values of acpi_object_type + */ +const u8 acpi_gbl_ns_properties[ACPI_NUM_NS_TYPES] = { + ACPI_NS_NORMAL, /* 00 Any */ + ACPI_NS_NORMAL, /* 01 Number */ + ACPI_NS_NORMAL, /* 02 String */ + ACPI_NS_NORMAL, /* 03 Buffer */ + ACPI_NS_NORMAL, /* 04 Package */ + ACPI_NS_NORMAL, /* 05 field_unit */ + ACPI_NS_NEWSCOPE, /* 06 Device */ + ACPI_NS_NORMAL, /* 07 Event */ + ACPI_NS_NEWSCOPE, /* 08 Method */ + ACPI_NS_NORMAL, /* 09 Mutex */ + ACPI_NS_NORMAL, /* 10 Region */ + ACPI_NS_NEWSCOPE, /* 11 Power */ + ACPI_NS_NEWSCOPE, /* 12 Processor */ + ACPI_NS_NEWSCOPE, /* 13 Thermal */ + ACPI_NS_NORMAL, /* 14 buffer_field */ + ACPI_NS_NORMAL, /* 15 ddb_handle */ + ACPI_NS_NORMAL, /* 16 Debug Object */ + ACPI_NS_NORMAL, /* 17 def_field */ + ACPI_NS_NORMAL, /* 18 bank_field */ + ACPI_NS_NORMAL, /* 19 index_field */ + ACPI_NS_NORMAL, /* 20 Reference */ + ACPI_NS_NORMAL, /* 21 Alias */ + ACPI_NS_NORMAL, /* 22 method_alias */ + ACPI_NS_NORMAL, /* 23 Notify */ + ACPI_NS_NORMAL, /* 24 Address Handler */ + ACPI_NS_NEWSCOPE | ACPI_NS_LOCAL, /* 25 Resource Desc */ + ACPI_NS_NEWSCOPE | ACPI_NS_LOCAL, /* 26 Resource Field */ + ACPI_NS_NEWSCOPE, /* 27 Scope */ + ACPI_NS_NORMAL, /* 28 Extra */ + ACPI_NS_NORMAL, /* 29 Data */ + ACPI_NS_NORMAL /* 30 Invalid */ +}; + +/******************************************************************************* + * + * FUNCTION: acpi_ut_hex_to_ascii_char + * + * PARAMETERS: Integer - Contains the hex digit + * Position - bit position of the digit within the + * integer (multiple of 4) + * + * RETURN: The converted Ascii character + * + * DESCRIPTION: Convert a hex digit to an Ascii character + * + ******************************************************************************/ + +/* Hex to ASCII conversion table */ + +static const char acpi_gbl_hex_to_ascii[] = { + '0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' +}; + +char acpi_ut_hex_to_ascii_char(u64 integer, u32 position) +{ + + return (acpi_gbl_hex_to_ascii[(integer >> position) & 0xF]); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_get_region_name + * + * PARAMETERS: Space ID - ID for the region + * + * RETURN: Decoded region space_id name + * + * DESCRIPTION: Translate a Space ID into a name string (Debug only) + * + ******************************************************************************/ + +/* Region type decoding */ + +const char *acpi_gbl_region_types[ACPI_NUM_PREDEFINED_REGIONS] = { + "SystemMemory", + "SystemIO", + "PCI_Config", + "EmbeddedControl", + "SMBus", + "SystemCMOS", + "PCIBARTarget", + "IPMI", + "DataTable" +}; + +char *acpi_ut_get_region_name(u8 space_id) +{ + + if (space_id >= ACPI_USER_REGION_BEGIN) { + return ("UserDefinedRegion"); + } else if (space_id >= ACPI_NUM_PREDEFINED_REGIONS) { + return ("InvalidSpaceId"); + } + + return (ACPI_CAST_PTR(char, acpi_gbl_region_types[space_id])); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_get_event_name + * + * PARAMETERS: event_id - Fixed event ID + * + * RETURN: Decoded event ID name + * + * DESCRIPTION: Translate a Event ID into a name string (Debug only) + * + ******************************************************************************/ + +/* Event type decoding */ + +static const char *acpi_gbl_event_types[ACPI_NUM_FIXED_EVENTS] = { + "PM_Timer", + "GlobalLock", + "PowerButton", + "SleepButton", + "RealTimeClock", +}; + +char *acpi_ut_get_event_name(u32 event_id) +{ + + if (event_id > ACPI_EVENT_MAX) { + return ("InvalidEventID"); + } + + return (ACPI_CAST_PTR(char, acpi_gbl_event_types[event_id])); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_get_type_name + * + * PARAMETERS: Type - An ACPI object type + * + * RETURN: Decoded ACPI object type name + * + * DESCRIPTION: Translate a Type ID into a name string (Debug only) + * + ******************************************************************************/ + +/* + * Elements of acpi_gbl_ns_type_names below must match + * one-to-one with values of acpi_object_type + * + * The type ACPI_TYPE_ANY (Untyped) is used as a "don't care" when searching; + * when stored in a table it really means that we have thus far seen no + * evidence to indicate what type is actually going to be stored for this entry. + */ +static const char acpi_gbl_bad_type[] = "UNDEFINED"; + +/* Printable names of the ACPI object types */ + +static const char *acpi_gbl_ns_type_names[] = { + /* 00 */ "Untyped", + /* 01 */ "Integer", + /* 02 */ "String", + /* 03 */ "Buffer", + /* 04 */ "Package", + /* 05 */ "FieldUnit", + /* 06 */ "Device", + /* 07 */ "Event", + /* 08 */ "Method", + /* 09 */ "Mutex", + /* 10 */ "Region", + /* 11 */ "Power", + /* 12 */ "Processor", + /* 13 */ "Thermal", + /* 14 */ "BufferField", + /* 15 */ "DdbHandle", + /* 16 */ "DebugObject", + /* 17 */ "RegionField", + /* 18 */ "BankField", + /* 19 */ "IndexField", + /* 20 */ "Reference", + /* 21 */ "Alias", + /* 22 */ "MethodAlias", + /* 23 */ "Notify", + /* 24 */ "AddrHandler", + /* 25 */ "ResourceDesc", + /* 26 */ "ResourceFld", + /* 27 */ "Scope", + /* 28 */ "Extra", + /* 29 */ "Data", + /* 30 */ "Invalid" +}; + +char *acpi_ut_get_type_name(acpi_object_type type) +{ + + if (type > ACPI_TYPE_INVALID) { + return (ACPI_CAST_PTR(char, acpi_gbl_bad_type)); + } + + return (ACPI_CAST_PTR(char, acpi_gbl_ns_type_names[type])); +} + +char *acpi_ut_get_object_type_name(union acpi_operand_object *obj_desc) +{ + + if (!obj_desc) { + return ("[NULL Object Descriptor]"); + } + + return (acpi_ut_get_type_name(obj_desc->common.type)); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_get_node_name + * + * PARAMETERS: Object - A namespace node + * + * RETURN: ASCII name of the node + * + * DESCRIPTION: Validate the node and return the node's ACPI name. + * + ******************************************************************************/ + +char *acpi_ut_get_node_name(void *object) +{ + struct acpi_namespace_node *node = (struct acpi_namespace_node *)object; + + /* Must return a string of exactly 4 characters == ACPI_NAME_SIZE */ + + if (!object) { + return ("NULL"); + } + + /* Check for Root node */ + + if ((object == ACPI_ROOT_OBJECT) || (object == acpi_gbl_root_node)) { + return ("\"\\\" "); + } + + /* Descriptor must be a namespace node */ + + if (ACPI_GET_DESCRIPTOR_TYPE(node) != ACPI_DESC_TYPE_NAMED) { + return ("####"); + } + + /* + * Ensure name is valid. The name was validated/repaired when the node + * was created, but make sure it has not been corrupted. + */ + acpi_ut_repair_name(node->name.ascii); + + /* Return the name */ + + return (node->name.ascii); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_get_descriptor_name + * + * PARAMETERS: Object - An ACPI object + * + * RETURN: Decoded name of the descriptor type + * + * DESCRIPTION: Validate object and return the descriptor type + * + ******************************************************************************/ + +/* Printable names of object descriptor types */ + +static const char *acpi_gbl_desc_type_names[] = { + /* 00 */ "Not a Descriptor", + /* 01 */ "Cached", + /* 02 */ "State-Generic", + /* 03 */ "State-Update", + /* 04 */ "State-Package", + /* 05 */ "State-Control", + /* 06 */ "State-RootParseScope", + /* 07 */ "State-ParseScope", + /* 08 */ "State-WalkScope", + /* 09 */ "State-Result", + /* 10 */ "State-Notify", + /* 11 */ "State-Thread", + /* 12 */ "Walk", + /* 13 */ "Parser", + /* 14 */ "Operand", + /* 15 */ "Node" +}; + +char *acpi_ut_get_descriptor_name(void *object) +{ + + if (!object) { + return ("NULL OBJECT"); + } + + if (ACPI_GET_DESCRIPTOR_TYPE(object) > ACPI_DESC_TYPE_MAX) { + return ("Not a Descriptor"); + } + + return (ACPI_CAST_PTR(char, + acpi_gbl_desc_type_names[ACPI_GET_DESCRIPTOR_TYPE + (object)])); + +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_get_reference_name + * + * PARAMETERS: Object - An ACPI reference object + * + * RETURN: Decoded name of the type of reference + * + * DESCRIPTION: Decode a reference object sub-type to a string. + * + ******************************************************************************/ + +/* Printable names of reference object sub-types */ + +static const char *acpi_gbl_ref_class_names[] = { + /* 00 */ "Local", + /* 01 */ "Argument", + /* 02 */ "RefOf", + /* 03 */ "Index", + /* 04 */ "DdbHandle", + /* 05 */ "Named Object", + /* 06 */ "Debug" +}; + +const char *acpi_ut_get_reference_name(union acpi_operand_object *object) +{ + + if (!object) { + return ("NULL Object"); + } + + if (ACPI_GET_DESCRIPTOR_TYPE(object) != ACPI_DESC_TYPE_OPERAND) { + return ("Not an Operand object"); + } + + if (object->common.type != ACPI_TYPE_LOCAL_REFERENCE) { + return ("Not a Reference object"); + } + + if (object->reference.class > ACPI_REFCLASS_MAX) { + return ("Unknown Reference class"); + } + + return (acpi_gbl_ref_class_names[object->reference.class]); +} + +#if defined(ACPI_DEBUG_OUTPUT) || defined(ACPI_DEBUGGER) +/* + * Strings and procedures used for debug only + */ + +/******************************************************************************* + * + * FUNCTION: acpi_ut_get_mutex_name + * + * PARAMETERS: mutex_id - The predefined ID for this mutex. + * + * RETURN: Decoded name of the internal mutex + * + * DESCRIPTION: Translate a mutex ID into a name string (Debug only) + * + ******************************************************************************/ + +/* Names for internal mutex objects, used for debug output */ + +static char *acpi_gbl_mutex_names[ACPI_NUM_MUTEX] = { + "ACPI_MTX_Interpreter", + "ACPI_MTX_Namespace", + "ACPI_MTX_Tables", + "ACPI_MTX_Events", + "ACPI_MTX_Caches", + "ACPI_MTX_Memory", + "ACPI_MTX_CommandComplete", + "ACPI_MTX_CommandReady" +}; + +char *acpi_ut_get_mutex_name(u32 mutex_id) +{ + + if (mutex_id > ACPI_MAX_MUTEX) { + return ("Invalid Mutex ID"); + } + + return (acpi_gbl_mutex_names[mutex_id]); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_get_notify_name + * + * PARAMETERS: notify_value - Value from the Notify() request + * + * RETURN: Decoded name for the notify value + * + * DESCRIPTION: Translate a Notify Value to a notify namestring. + * + ******************************************************************************/ + +/* Names for Notify() values, used for debug output */ + +static const char *acpi_gbl_notify_value_names[] = { + "Bus Check", + "Device Check", + "Device Wake", + "Eject Request", + "Device Check Light", + "Frequency Mismatch", + "Bus Mode Mismatch", + "Power Fault", + "Capabilities Check", + "Device PLD Check", + "Reserved", + "System Locality Update" +}; + +const char *acpi_ut_get_notify_name(u32 notify_value) +{ + + if (notify_value <= ACPI_NOTIFY_MAX) { + return (acpi_gbl_notify_value_names[notify_value]); + } else if (notify_value <= ACPI_MAX_SYS_NOTIFY) { + return ("Reserved"); + } else { /* Greater or equal to 0x80 */ + + return ("**Device Specific**"); + } +} +#endif + +/******************************************************************************* + * + * FUNCTION: acpi_ut_valid_object_type + * + * PARAMETERS: Type - Object type to be validated + * + * RETURN: TRUE if valid object type, FALSE otherwise + * + * DESCRIPTION: Validate an object type + * + ******************************************************************************/ + +u8 acpi_ut_valid_object_type(acpi_object_type type) +{ + + if (type > ACPI_TYPE_LOCAL_MAX) { + + /* Note: Assumes all TYPEs are contiguous (external/local) */ + + return (FALSE); + } + + return (TRUE); +} diff --git a/drivers/acpi/acpica/utglobal.c b/drivers/acpi/acpica/utglobal.c index 97dd9bbf055ac..fc90978215168 100644 --- a/drivers/acpi/acpica/utglobal.c +++ b/drivers/acpi/acpica/utglobal.c @@ -45,7 +45,6 @@ #include #include "accommon.h" -#include "acnamesp.h" #define _COMPONENT ACPI_UTILITIES ACPI_MODULE_NAME("utglobal") @@ -105,43 +104,6 @@ const char *acpi_gbl_highest_dstate_names[ACPI_NUM_sx_d_METHODS] = { "_S4D" }; -/******************************************************************************* - * - * FUNCTION: acpi_format_exception - * - * PARAMETERS: Status - The acpi_status code to be formatted - * - * RETURN: A string containing the exception text. A valid pointer is - * always returned. - * - * DESCRIPTION: This function translates an ACPI exception into an ASCII string - * It is here instead of utxface.c so it is always present. - * - ******************************************************************************/ - -const char *acpi_format_exception(acpi_status status) -{ - const char *exception = NULL; - - ACPI_FUNCTION_ENTRY(); - - exception = acpi_ut_validate_exception(status); - if (!exception) { - - /* Exception code was not recognized */ - - ACPI_ERROR((AE_INFO, - "Unknown exception code: 0x%8.8X", status)); - - exception = "UNKNOWN_STATUS_CODE"; - dump_stack(); - } - - return (ACPI_CAST_PTR(const char, exception)); -} - -ACPI_EXPORT_SYMBOL(acpi_format_exception) - /******************************************************************************* * * Namespace globals @@ -177,71 +139,6 @@ const struct acpi_predefined_names acpi_gbl_pre_defined_names[] = { {NULL, ACPI_TYPE_ANY, NULL} }; -/* - * Properties of the ACPI Object Types, both internal and external. - * The table is indexed by values of acpi_object_type - */ -const u8 acpi_gbl_ns_properties[] = { - ACPI_NS_NORMAL, /* 00 Any */ - ACPI_NS_NORMAL, /* 01 Number */ - ACPI_NS_NORMAL, /* 02 String */ - ACPI_NS_NORMAL, /* 03 Buffer */ - ACPI_NS_NORMAL, /* 04 Package */ - ACPI_NS_NORMAL, /* 05 field_unit */ - ACPI_NS_NEWSCOPE, /* 06 Device */ - ACPI_NS_NORMAL, /* 07 Event */ - ACPI_NS_NEWSCOPE, /* 08 Method */ - ACPI_NS_NORMAL, /* 09 Mutex */ - ACPI_NS_NORMAL, /* 10 Region */ - ACPI_NS_NEWSCOPE, /* 11 Power */ - ACPI_NS_NEWSCOPE, /* 12 Processor */ - ACPI_NS_NEWSCOPE, /* 13 Thermal */ - ACPI_NS_NORMAL, /* 14 buffer_field */ - ACPI_NS_NORMAL, /* 15 ddb_handle */ - ACPI_NS_NORMAL, /* 16 Debug Object */ - ACPI_NS_NORMAL, /* 17 def_field */ - ACPI_NS_NORMAL, /* 18 bank_field */ - ACPI_NS_NORMAL, /* 19 index_field */ - ACPI_NS_NORMAL, /* 20 Reference */ - ACPI_NS_NORMAL, /* 21 Alias */ - ACPI_NS_NORMAL, /* 22 method_alias */ - ACPI_NS_NORMAL, /* 23 Notify */ - ACPI_NS_NORMAL, /* 24 Address Handler */ - ACPI_NS_NEWSCOPE | ACPI_NS_LOCAL, /* 25 Resource Desc */ - ACPI_NS_NEWSCOPE | ACPI_NS_LOCAL, /* 26 Resource Field */ - ACPI_NS_NEWSCOPE, /* 27 Scope */ - ACPI_NS_NORMAL, /* 28 Extra */ - ACPI_NS_NORMAL, /* 29 Data */ - ACPI_NS_NORMAL /* 30 Invalid */ -}; - -/* Hex to ASCII conversion table */ - -static const char acpi_gbl_hex_to_ascii[] = { - '0', '1', '2', '3', '4', '5', '6', '7', - '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' -}; - -/******************************************************************************* - * - * FUNCTION: acpi_ut_hex_to_ascii_char - * - * PARAMETERS: Integer - Contains the hex digit - * Position - bit position of the digit within the - * integer (multiple of 4) - * - * RETURN: The converted Ascii character - * - * DESCRIPTION: Convert a hex digit to an Ascii character - * - ******************************************************************************/ - -char acpi_ut_hex_to_ascii_char(u64 integer, u32 position) -{ - - return (acpi_gbl_hex_to_ascii[(integer >> position) & 0xF]); -} - /****************************************************************************** * * Event and Hardware globals @@ -339,386 +236,6 @@ struct acpi_fixed_event_info acpi_gbl_fixed_event_info[ACPI_NUM_FIXED_EVENTS] = ACPI_BITMASK_RT_CLOCK_ENABLE}, }; -/******************************************************************************* - * - * FUNCTION: acpi_ut_get_region_name - * - * PARAMETERS: None. - * - * RETURN: Status - * - * DESCRIPTION: Translate a Space ID into a name string (Debug only) - * - ******************************************************************************/ - -/* Region type decoding */ - -const char *acpi_gbl_region_types[ACPI_NUM_PREDEFINED_REGIONS] = { - "SystemMemory", - "SystemIO", - "PCI_Config", - "EmbeddedControl", - "SMBus", - "SystemCMOS", - "PCIBARTarget", - "IPMI", - "DataTable" -}; - -char *acpi_ut_get_region_name(u8 space_id) -{ - - if (space_id >= ACPI_USER_REGION_BEGIN) { - return ("UserDefinedRegion"); - } else if (space_id >= ACPI_NUM_PREDEFINED_REGIONS) { - return ("InvalidSpaceId"); - } - - return (ACPI_CAST_PTR(char, acpi_gbl_region_types[space_id])); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ut_get_event_name - * - * PARAMETERS: None. - * - * RETURN: Status - * - * DESCRIPTION: Translate a Event ID into a name string (Debug only) - * - ******************************************************************************/ - -/* Event type decoding */ - -static const char *acpi_gbl_event_types[ACPI_NUM_FIXED_EVENTS] = { - "PM_Timer", - "GlobalLock", - "PowerButton", - "SleepButton", - "RealTimeClock", -}; - -char *acpi_ut_get_event_name(u32 event_id) -{ - - if (event_id > ACPI_EVENT_MAX) { - return ("InvalidEventID"); - } - - return (ACPI_CAST_PTR(char, acpi_gbl_event_types[event_id])); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ut_get_type_name - * - * PARAMETERS: None. - * - * RETURN: Status - * - * DESCRIPTION: Translate a Type ID into a name string (Debug only) - * - ******************************************************************************/ - -/* - * Elements of acpi_gbl_ns_type_names below must match - * one-to-one with values of acpi_object_type - * - * The type ACPI_TYPE_ANY (Untyped) is used as a "don't care" when searching; - * when stored in a table it really means that we have thus far seen no - * evidence to indicate what type is actually going to be stored for this entry. - */ -static const char acpi_gbl_bad_type[] = "UNDEFINED"; - -/* Printable names of the ACPI object types */ - -static const char *acpi_gbl_ns_type_names[] = { - /* 00 */ "Untyped", - /* 01 */ "Integer", - /* 02 */ "String", - /* 03 */ "Buffer", - /* 04 */ "Package", - /* 05 */ "FieldUnit", - /* 06 */ "Device", - /* 07 */ "Event", - /* 08 */ "Method", - /* 09 */ "Mutex", - /* 10 */ "Region", - /* 11 */ "Power", - /* 12 */ "Processor", - /* 13 */ "Thermal", - /* 14 */ "BufferField", - /* 15 */ "DdbHandle", - /* 16 */ "DebugObject", - /* 17 */ "RegionField", - /* 18 */ "BankField", - /* 19 */ "IndexField", - /* 20 */ "Reference", - /* 21 */ "Alias", - /* 22 */ "MethodAlias", - /* 23 */ "Notify", - /* 24 */ "AddrHandler", - /* 25 */ "ResourceDesc", - /* 26 */ "ResourceFld", - /* 27 */ "Scope", - /* 28 */ "Extra", - /* 29 */ "Data", - /* 30 */ "Invalid" -}; - -char *acpi_ut_get_type_name(acpi_object_type type) -{ - - if (type > ACPI_TYPE_INVALID) { - return (ACPI_CAST_PTR(char, acpi_gbl_bad_type)); - } - - return (ACPI_CAST_PTR(char, acpi_gbl_ns_type_names[type])); -} - -char *acpi_ut_get_object_type_name(union acpi_operand_object *obj_desc) -{ - - if (!obj_desc) { - return ("[NULL Object Descriptor]"); - } - - return (acpi_ut_get_type_name(obj_desc->common.type)); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ut_get_node_name - * - * PARAMETERS: Object - A namespace node - * - * RETURN: Pointer to a string - * - * DESCRIPTION: Validate the node and return the node's ACPI name. - * - ******************************************************************************/ - -char *acpi_ut_get_node_name(void *object) -{ - struct acpi_namespace_node *node = (struct acpi_namespace_node *)object; - - /* Must return a string of exactly 4 characters == ACPI_NAME_SIZE */ - - if (!object) { - return ("NULL"); - } - - /* Check for Root node */ - - if ((object == ACPI_ROOT_OBJECT) || (object == acpi_gbl_root_node)) { - return ("\"\\\" "); - } - - /* Descriptor must be a namespace node */ - - if (ACPI_GET_DESCRIPTOR_TYPE(node) != ACPI_DESC_TYPE_NAMED) { - return ("####"); - } - - /* Name must be a valid ACPI name */ - - if (!acpi_ut_valid_acpi_name(node->name.integer)) { - node->name.integer = acpi_ut_repair_name(node->name.ascii); - } - - /* Return the name */ - - return (node->name.ascii); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ut_get_descriptor_name - * - * PARAMETERS: Object - An ACPI object - * - * RETURN: Pointer to a string - * - * DESCRIPTION: Validate object and return the descriptor type - * - ******************************************************************************/ - -/* Printable names of object descriptor types */ - -static const char *acpi_gbl_desc_type_names[] = { - /* 00 */ "Invalid", - /* 01 */ "Cached", - /* 02 */ "State-Generic", - /* 03 */ "State-Update", - /* 04 */ "State-Package", - /* 05 */ "State-Control", - /* 06 */ "State-RootParseScope", - /* 07 */ "State-ParseScope", - /* 08 */ "State-WalkScope", - /* 09 */ "State-Result", - /* 10 */ "State-Notify", - /* 11 */ "State-Thread", - /* 12 */ "Walk", - /* 13 */ "Parser", - /* 14 */ "Operand", - /* 15 */ "Node" -}; - -char *acpi_ut_get_descriptor_name(void *object) -{ - - if (!object) { - return ("NULL OBJECT"); - } - - if (ACPI_GET_DESCRIPTOR_TYPE(object) > ACPI_DESC_TYPE_MAX) { - return (ACPI_CAST_PTR(char, acpi_gbl_bad_type)); - } - - return (ACPI_CAST_PTR(char, - acpi_gbl_desc_type_names[ACPI_GET_DESCRIPTOR_TYPE - (object)])); - -} - -/******************************************************************************* - * - * FUNCTION: acpi_ut_get_reference_name - * - * PARAMETERS: Object - An ACPI reference object - * - * RETURN: Pointer to a string - * - * DESCRIPTION: Decode a reference object sub-type to a string. - * - ******************************************************************************/ - -/* Printable names of reference object sub-types */ - -static const char *acpi_gbl_ref_class_names[] = { - /* 00 */ "Local", - /* 01 */ "Argument", - /* 02 */ "RefOf", - /* 03 */ "Index", - /* 04 */ "DdbHandle", - /* 05 */ "Named Object", - /* 06 */ "Debug" -}; - -const char *acpi_ut_get_reference_name(union acpi_operand_object *object) -{ - if (!object) - return "NULL Object"; - - if (ACPI_GET_DESCRIPTOR_TYPE(object) != ACPI_DESC_TYPE_OPERAND) - return "Not an Operand object"; - - if (object->common.type != ACPI_TYPE_LOCAL_REFERENCE) - return "Not a Reference object"; - - if (object->reference.class > ACPI_REFCLASS_MAX) - return "Unknown Reference class"; - - return acpi_gbl_ref_class_names[object->reference.class]; -} - -#if defined(ACPI_DEBUG_OUTPUT) || defined(ACPI_DEBUGGER) -/* - * Strings and procedures used for debug only - */ - -/******************************************************************************* - * - * FUNCTION: acpi_ut_get_mutex_name - * - * PARAMETERS: mutex_id - The predefined ID for this mutex. - * - * RETURN: String containing the name of the mutex. Always returns a valid - * pointer. - * - * DESCRIPTION: Translate a mutex ID into a name string (Debug only) - * - ******************************************************************************/ - -char *acpi_ut_get_mutex_name(u32 mutex_id) -{ - - if (mutex_id > ACPI_MAX_MUTEX) { - return ("Invalid Mutex ID"); - } - - return (acpi_gbl_mutex_names[mutex_id]); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ut_get_notify_name - * - * PARAMETERS: notify_value - Value from the Notify() request - * - * RETURN: String corresponding to the Notify Value. - * - * DESCRIPTION: Translate a Notify Value to a notify namestring. - * - ******************************************************************************/ - -/* Names for Notify() values, used for debug output */ - -static const char *acpi_gbl_notify_value_names[] = { - "Bus Check", - "Device Check", - "Device Wake", - "Eject Request", - "Device Check Light", - "Frequency Mismatch", - "Bus Mode Mismatch", - "Power Fault", - "Capabilities Check", - "Device PLD Check", - "Reserved", - "System Locality Update" -}; - -const char *acpi_ut_get_notify_name(u32 notify_value) -{ - - if (notify_value <= ACPI_NOTIFY_MAX) { - return (acpi_gbl_notify_value_names[notify_value]); - } else if (notify_value <= ACPI_MAX_SYS_NOTIFY) { - return ("Reserved"); - } else { /* Greater or equal to 0x80 */ - - return ("**Device Specific**"); - } -} -#endif - -/******************************************************************************* - * - * FUNCTION: acpi_ut_valid_object_type - * - * PARAMETERS: Type - Object type to be validated - * - * RETURN: TRUE if valid object type, FALSE otherwise - * - * DESCRIPTION: Validate an object type - * - ******************************************************************************/ - -u8 acpi_ut_valid_object_type(acpi_object_type type) -{ - - if (type > ACPI_TYPE_LOCAL_MAX) { - - /* Note: Assumes all TYPEs are contiguous (external/local) */ - - return (FALSE); - } - - return (TRUE); -} - /******************************************************************************* * * FUNCTION: acpi_ut_init_globals -- GitLab From d59a3c6b35995615fa9e4f21d63fdf21328c5b6b Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Mon, 14 Feb 2011 16:02:36 +0800 Subject: [PATCH 0267/2822] ACPICA: Fix unresolved name issue for no-debug and no-error-msg cases The _acpi_module_name was left undefined in these cases, but it is actually needed as a parameter to some interfaces. Define _acpi_module_name as a null string in these cases. Acpica BZ 888. http://www.acpica.org/bugzilla/show_bug.cgi?id=888 Signed-off-by: Bob Moore Signed-off-by: Lin Ming Signed-off-by: Len Brown --- include/acpi/acoutput.h | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/include/acpi/acoutput.h b/include/acpi/acoutput.h index ef1cef77d32ba..d7bd661bfae73 100644 --- a/include/acpi/acoutput.h +++ b/include/acpi/acoutput.h @@ -183,13 +183,19 @@ #if defined (ACPI_DEBUG_OUTPUT) || !defined (ACPI_NO_ERROR_MESSAGES) /* - * Module name is included in both debug and non-debug versions primarily for - * error messages. The __FILE__ macro is not very useful for this, because it - * often includes the entire pathname to the module + * The module name is used primarily for error and debug messages. + * The __FILE__ macro is not very useful for this, because it + * usually includes the entire pathname to the module making the + * debug output difficult to read. */ #define ACPI_MODULE_NAME(name) static const char ACPI_UNUSED_VAR _acpi_module_name[] = name; #else +/* + * For the no-debug and no-error-msg cases, we must at least define + * a null module name. + */ #define ACPI_MODULE_NAME(name) +#define _acpi_module_name "" #endif /* -- GitLab From 9ad19ac456a5f097f7cbbfef820b95297d6a934f Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Mon, 14 Feb 2011 16:09:40 +0800 Subject: [PATCH 0268/2822] ACPICA: Split large dsopcode and dsload.c files. Split dsopcode.c into dsargs.c and dscontrol.c. Split dsload.c into dsload2.c. Signed-off-by: Bob Moore Signed-off-by: Lin Ming Signed-off-by: Len Brown --- drivers/acpi/acpica/Makefile | 2 +- drivers/acpi/acpica/acdispat.h | 38 +- drivers/acpi/acpica/dsargs.c | 391 +++++++++++++++++ drivers/acpi/acpica/dscontrol.c | 410 ++++++++++++++++++ drivers/acpi/acpica/dsopcode.c | 725 +------------------------------- drivers/acpi/acpica/dswload.c | 670 +---------------------------- drivers/acpi/acpica/dswload2.c | 720 +++++++++++++++++++++++++++++++ 7 files changed, 1549 insertions(+), 1407 deletions(-) create mode 100644 drivers/acpi/acpica/dsargs.c create mode 100644 drivers/acpi/acpica/dscontrol.c create mode 100644 drivers/acpi/acpica/dswload2.c diff --git a/drivers/acpi/acpica/Makefile b/drivers/acpi/acpica/Makefile index b1706aacbe98b..a1224712fd0c1 100644 --- a/drivers/acpi/acpica/Makefile +++ b/drivers/acpi/acpica/Makefile @@ -10,7 +10,7 @@ obj-y += acpi.o acpi-y := dsfield.o dsmthdat.o dsopcode.o dswexec.o dswscope.o \ dsmethod.o dsobject.o dsutils.o dswload.o dswstate.o \ - dsinit.o + dsinit.o dsargs.o dscontrol.o dswload2.o acpi-y += evevent.o evregion.o evsci.o evxfevnt.o \ evmisc.o evrgnini.o evxface.o evxfregn.o \ diff --git a/drivers/acpi/acpica/acdispat.h b/drivers/acpi/acpica/acdispat.h index 666271b65418b..2d1b7ffa377a0 100644 --- a/drivers/acpi/acpica/acdispat.h +++ b/drivers/acpi/acpica/acdispat.h @@ -48,7 +48,7 @@ #define NAMEOF_ARG_NTE "__A0" /* - * dsopcode - support for late evaluation + * dsargs - execution of dynamic arguments for static objects */ acpi_status acpi_ds_get_buffer_field_arguments(union acpi_operand_object *obj_desc); @@ -62,6 +62,20 @@ acpi_status acpi_ds_get_buffer_arguments(union acpi_operand_object *obj_desc); acpi_status acpi_ds_get_package_arguments(union acpi_operand_object *obj_desc); +/* + * dscontrol - support for execution control opcodes + */ +acpi_status +acpi_ds_exec_begin_control_op(struct acpi_walk_state *walk_state, + union acpi_parse_object *op); + +acpi_status +acpi_ds_exec_end_control_op(struct acpi_walk_state *walk_state, + union acpi_parse_object *op); + +/* + * dsopcode - support for late operand evaluation + */ acpi_status acpi_ds_eval_buffer_field_operands(struct acpi_walk_state *walk_state, union acpi_parse_object *op); @@ -85,17 +99,6 @@ acpi_ds_eval_bank_field_operands(struct acpi_walk_state *walk_state, acpi_status acpi_ds_initialize_region(acpi_handle obj_handle); -/* - * dsctrl - Parser/Interpreter interface, control stack routines - */ -acpi_status -acpi_ds_exec_begin_control_op(struct acpi_walk_state *walk_state, - union acpi_parse_object *op); - -acpi_status -acpi_ds_exec_end_control_op(struct acpi_walk_state *walk_state, - union acpi_parse_object *op); - /* * dsexec - Parser/Interpreter interface, method execution callbacks */ @@ -136,23 +139,26 @@ acpi_ds_init_field_objects(union acpi_parse_object *op, struct acpi_walk_state *walk_state); /* - * dsload - Parser/Interpreter interface, namespace load callbacks + * dsload - Parser/Interpreter interface, pass 1 namespace load callbacks */ +acpi_status +acpi_ds_init_callbacks(struct acpi_walk_state *walk_state, u32 pass_number); + acpi_status acpi_ds_load1_begin_op(struct acpi_walk_state *walk_state, union acpi_parse_object **out_op); acpi_status acpi_ds_load1_end_op(struct acpi_walk_state *walk_state); +/* + * dsload - Parser/Interpreter interface, pass 2 namespace load callbacks + */ acpi_status acpi_ds_load2_begin_op(struct acpi_walk_state *walk_state, union acpi_parse_object **out_op); acpi_status acpi_ds_load2_end_op(struct acpi_walk_state *walk_state); -acpi_status -acpi_ds_init_callbacks(struct acpi_walk_state *walk_state, u32 pass_number); - /* * dsmthdat - method data (locals/args) */ diff --git a/drivers/acpi/acpica/dsargs.c b/drivers/acpi/acpica/dsargs.c new file mode 100644 index 0000000000000..8c7b99728aa23 --- /dev/null +++ b/drivers/acpi/acpica/dsargs.c @@ -0,0 +1,391 @@ +/****************************************************************************** + * + * Module Name: dsargs - Support for execution of dynamic arguments for static + * objects (regions, fields, buffer fields, etc.) + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2011, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include +#include "accommon.h" +#include "acparser.h" +#include "amlcode.h" +#include "acdispat.h" +#include "acnamesp.h" + +#define _COMPONENT ACPI_DISPATCHER +ACPI_MODULE_NAME("dsargs") + +/* Local prototypes */ +static acpi_status +acpi_ds_execute_arguments(struct acpi_namespace_node *node, + struct acpi_namespace_node *scope_node, + u32 aml_length, u8 *aml_start); + +/******************************************************************************* + * + * FUNCTION: acpi_ds_execute_arguments + * + * PARAMETERS: Node - Object NS node + * scope_node - Parent NS node + * aml_length - Length of executable AML + * aml_start - Pointer to the AML + * + * RETURN: Status. + * + * DESCRIPTION: Late (deferred) execution of region or field arguments + * + ******************************************************************************/ + +static acpi_status +acpi_ds_execute_arguments(struct acpi_namespace_node *node, + struct acpi_namespace_node *scope_node, + u32 aml_length, u8 *aml_start) +{ + acpi_status status; + union acpi_parse_object *op; + struct acpi_walk_state *walk_state; + + ACPI_FUNCTION_TRACE(ds_execute_arguments); + + /* Allocate a new parser op to be the root of the parsed tree */ + + op = acpi_ps_alloc_op(AML_INT_EVAL_SUBTREE_OP); + if (!op) { + return_ACPI_STATUS(AE_NO_MEMORY); + } + + /* Save the Node for use in acpi_ps_parse_aml */ + + op->common.node = scope_node; + + /* Create and initialize a new parser state */ + + walk_state = acpi_ds_create_walk_state(0, NULL, NULL, NULL); + if (!walk_state) { + status = AE_NO_MEMORY; + goto cleanup; + } + + status = acpi_ds_init_aml_walk(walk_state, op, NULL, aml_start, + aml_length, NULL, ACPI_IMODE_LOAD_PASS1); + if (ACPI_FAILURE(status)) { + acpi_ds_delete_walk_state(walk_state); + goto cleanup; + } + + /* Mark this parse as a deferred opcode */ + + walk_state->parse_flags = ACPI_PARSE_DEFERRED_OP; + walk_state->deferred_node = node; + + /* Pass1: Parse the entire declaration */ + + status = acpi_ps_parse_aml(walk_state); + if (ACPI_FAILURE(status)) { + goto cleanup; + } + + /* Get and init the Op created above */ + + op->common.node = node; + acpi_ps_delete_parse_tree(op); + + /* Evaluate the deferred arguments */ + + op = acpi_ps_alloc_op(AML_INT_EVAL_SUBTREE_OP); + if (!op) { + return_ACPI_STATUS(AE_NO_MEMORY); + } + + op->common.node = scope_node; + + /* Create and initialize a new parser state */ + + walk_state = acpi_ds_create_walk_state(0, NULL, NULL, NULL); + if (!walk_state) { + status = AE_NO_MEMORY; + goto cleanup; + } + + /* Execute the opcode and arguments */ + + status = acpi_ds_init_aml_walk(walk_state, op, NULL, aml_start, + aml_length, NULL, ACPI_IMODE_EXECUTE); + if (ACPI_FAILURE(status)) { + acpi_ds_delete_walk_state(walk_state); + goto cleanup; + } + + /* Mark this execution as a deferred opcode */ + + walk_state->deferred_node = node; + status = acpi_ps_parse_aml(walk_state); + + cleanup: + acpi_ps_delete_parse_tree(op); + return_ACPI_STATUS(status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ds_get_buffer_field_arguments + * + * PARAMETERS: obj_desc - A valid buffer_field object + * + * RETURN: Status. + * + * DESCRIPTION: Get buffer_field Buffer and Index. This implements the late + * evaluation of these field attributes. + * + ******************************************************************************/ + +acpi_status +acpi_ds_get_buffer_field_arguments(union acpi_operand_object *obj_desc) +{ + union acpi_operand_object *extra_desc; + struct acpi_namespace_node *node; + acpi_status status; + + ACPI_FUNCTION_TRACE_PTR(ds_get_buffer_field_arguments, obj_desc); + + if (obj_desc->common.flags & AOPOBJ_DATA_VALID) { + return_ACPI_STATUS(AE_OK); + } + + /* Get the AML pointer (method object) and buffer_field node */ + + extra_desc = acpi_ns_get_secondary_object(obj_desc); + node = obj_desc->buffer_field.node; + + ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname(ACPI_TYPE_BUFFER_FIELD, + node, NULL)); + + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "[%4.4s] BufferField Arg Init\n", + acpi_ut_get_node_name(node))); + + /* Execute the AML code for the term_arg arguments */ + + status = acpi_ds_execute_arguments(node, node->parent, + extra_desc->extra.aml_length, + extra_desc->extra.aml_start); + return_ACPI_STATUS(status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ds_get_bank_field_arguments + * + * PARAMETERS: obj_desc - A valid bank_field object + * + * RETURN: Status. + * + * DESCRIPTION: Get bank_field bank_value. This implements the late + * evaluation of these field attributes. + * + ******************************************************************************/ + +acpi_status +acpi_ds_get_bank_field_arguments(union acpi_operand_object *obj_desc) +{ + union acpi_operand_object *extra_desc; + struct acpi_namespace_node *node; + acpi_status status; + + ACPI_FUNCTION_TRACE_PTR(ds_get_bank_field_arguments, obj_desc); + + if (obj_desc->common.flags & AOPOBJ_DATA_VALID) { + return_ACPI_STATUS(AE_OK); + } + + /* Get the AML pointer (method object) and bank_field node */ + + extra_desc = acpi_ns_get_secondary_object(obj_desc); + node = obj_desc->bank_field.node; + + ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname + (ACPI_TYPE_LOCAL_BANK_FIELD, node, NULL)); + + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "[%4.4s] BankField Arg Init\n", + acpi_ut_get_node_name(node))); + + /* Execute the AML code for the term_arg arguments */ + + status = acpi_ds_execute_arguments(node, node->parent, + extra_desc->extra.aml_length, + extra_desc->extra.aml_start); + return_ACPI_STATUS(status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ds_get_buffer_arguments + * + * PARAMETERS: obj_desc - A valid Buffer object + * + * RETURN: Status. + * + * DESCRIPTION: Get Buffer length and initializer byte list. This implements + * the late evaluation of these attributes. + * + ******************************************************************************/ + +acpi_status acpi_ds_get_buffer_arguments(union acpi_operand_object *obj_desc) +{ + struct acpi_namespace_node *node; + acpi_status status; + + ACPI_FUNCTION_TRACE_PTR(ds_get_buffer_arguments, obj_desc); + + if (obj_desc->common.flags & AOPOBJ_DATA_VALID) { + return_ACPI_STATUS(AE_OK); + } + + /* Get the Buffer node */ + + node = obj_desc->buffer.node; + if (!node) { + ACPI_ERROR((AE_INFO, + "No pointer back to namespace node in buffer object %p", + obj_desc)); + return_ACPI_STATUS(AE_AML_INTERNAL); + } + + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Buffer Arg Init\n")); + + /* Execute the AML code for the term_arg arguments */ + + status = acpi_ds_execute_arguments(node, node, + obj_desc->buffer.aml_length, + obj_desc->buffer.aml_start); + return_ACPI_STATUS(status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ds_get_package_arguments + * + * PARAMETERS: obj_desc - A valid Package object + * + * RETURN: Status. + * + * DESCRIPTION: Get Package length and initializer byte list. This implements + * the late evaluation of these attributes. + * + ******************************************************************************/ + +acpi_status acpi_ds_get_package_arguments(union acpi_operand_object *obj_desc) +{ + struct acpi_namespace_node *node; + acpi_status status; + + ACPI_FUNCTION_TRACE_PTR(ds_get_package_arguments, obj_desc); + + if (obj_desc->common.flags & AOPOBJ_DATA_VALID) { + return_ACPI_STATUS(AE_OK); + } + + /* Get the Package node */ + + node = obj_desc->package.node; + if (!node) { + ACPI_ERROR((AE_INFO, + "No pointer back to namespace node in package %p", + obj_desc)); + return_ACPI_STATUS(AE_AML_INTERNAL); + } + + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Package Arg Init\n")); + + /* Execute the AML code for the term_arg arguments */ + + status = acpi_ds_execute_arguments(node, node, + obj_desc->package.aml_length, + obj_desc->package.aml_start); + return_ACPI_STATUS(status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ds_get_region_arguments + * + * PARAMETERS: obj_desc - A valid region object + * + * RETURN: Status. + * + * DESCRIPTION: Get region address and length. This implements the late + * evaluation of these region attributes. + * + ******************************************************************************/ + +acpi_status acpi_ds_get_region_arguments(union acpi_operand_object *obj_desc) +{ + struct acpi_namespace_node *node; + acpi_status status; + union acpi_operand_object *extra_desc; + + ACPI_FUNCTION_TRACE_PTR(ds_get_region_arguments, obj_desc); + + if (obj_desc->region.flags & AOPOBJ_DATA_VALID) { + return_ACPI_STATUS(AE_OK); + } + + extra_desc = acpi_ns_get_secondary_object(obj_desc); + if (!extra_desc) { + return_ACPI_STATUS(AE_NOT_EXIST); + } + + /* Get the Region node */ + + node = obj_desc->region.node; + + ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname + (ACPI_TYPE_REGION, node, NULL)); + + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "[%4.4s] OpRegion Arg Init at AML %p\n", + acpi_ut_get_node_name(node), + extra_desc->extra.aml_start)); + + /* Execute the argument AML */ + + status = acpi_ds_execute_arguments(node, node->parent, + extra_desc->extra.aml_length, + extra_desc->extra.aml_start); + return_ACPI_STATUS(status); +} diff --git a/drivers/acpi/acpica/dscontrol.c b/drivers/acpi/acpica/dscontrol.c new file mode 100644 index 0000000000000..26c49fff58da0 --- /dev/null +++ b/drivers/acpi/acpica/dscontrol.c @@ -0,0 +1,410 @@ +/****************************************************************************** + * + * Module Name: dscontrol - Support for execution control opcodes - + * if/else/while/return + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2011, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include +#include "accommon.h" +#include "amlcode.h" +#include "acdispat.h" +#include "acinterp.h" + +#define _COMPONENT ACPI_DISPATCHER +ACPI_MODULE_NAME("dscontrol") + +/******************************************************************************* + * + * FUNCTION: acpi_ds_exec_begin_control_op + * + * PARAMETERS: walk_list - The list that owns the walk stack + * Op - The control Op + * + * RETURN: Status + * + * DESCRIPTION: Handles all control ops encountered during control method + * execution. + * + ******************************************************************************/ +acpi_status +acpi_ds_exec_begin_control_op(struct acpi_walk_state *walk_state, + union acpi_parse_object *op) +{ + acpi_status status = AE_OK; + union acpi_generic_state *control_state; + + ACPI_FUNCTION_NAME(ds_exec_begin_control_op); + + ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "Op=%p Opcode=%2.2X State=%p\n", + op, op->common.aml_opcode, walk_state)); + + switch (op->common.aml_opcode) { + case AML_WHILE_OP: + + /* + * If this is an additional iteration of a while loop, continue. + * There is no need to allocate a new control state. + */ + if (walk_state->control_state) { + if (walk_state->control_state->control. + aml_predicate_start == + (walk_state->parser_state.aml - 1)) { + + /* Reset the state to start-of-loop */ + + walk_state->control_state->common.state = + ACPI_CONTROL_CONDITIONAL_EXECUTING; + break; + } + } + + /*lint -fallthrough */ + + case AML_IF_OP: + + /* + * IF/WHILE: Create a new control state to manage these + * constructs. We need to manage these as a stack, in order + * to handle nesting. + */ + control_state = acpi_ut_create_control_state(); + if (!control_state) { + status = AE_NO_MEMORY; + break; + } + /* + * Save a pointer to the predicate for multiple executions + * of a loop + */ + control_state->control.aml_predicate_start = + walk_state->parser_state.aml - 1; + control_state->control.package_end = + walk_state->parser_state.pkg_end; + control_state->control.opcode = op->common.aml_opcode; + + /* Push the control state on this walk's control stack */ + + acpi_ut_push_generic_state(&walk_state->control_state, + control_state); + break; + + case AML_ELSE_OP: + + /* Predicate is in the state object */ + /* If predicate is true, the IF was executed, ignore ELSE part */ + + if (walk_state->last_predicate) { + status = AE_CTRL_TRUE; + } + + break; + + case AML_RETURN_OP: + + break; + + default: + break; + } + + return (status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ds_exec_end_control_op + * + * PARAMETERS: walk_list - The list that owns the walk stack + * Op - The control Op + * + * RETURN: Status + * + * DESCRIPTION: Handles all control ops encountered during control method + * execution. + * + ******************************************************************************/ + +acpi_status +acpi_ds_exec_end_control_op(struct acpi_walk_state * walk_state, + union acpi_parse_object * op) +{ + acpi_status status = AE_OK; + union acpi_generic_state *control_state; + + ACPI_FUNCTION_NAME(ds_exec_end_control_op); + + switch (op->common.aml_opcode) { + case AML_IF_OP: + + ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "[IF_OP] Op=%p\n", op)); + + /* + * Save the result of the predicate in case there is an + * ELSE to come + */ + walk_state->last_predicate = + (u8)walk_state->control_state->common.value; + + /* + * Pop the control state that was created at the start + * of the IF and free it + */ + control_state = + acpi_ut_pop_generic_state(&walk_state->control_state); + acpi_ut_delete_generic_state(control_state); + break; + + case AML_ELSE_OP: + + break; + + case AML_WHILE_OP: + + ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "[WHILE_OP] Op=%p\n", op)); + + control_state = walk_state->control_state; + if (control_state->common.value) { + + /* Predicate was true, the body of the loop was just executed */ + + /* + * This loop counter mechanism allows the interpreter to escape + * possibly infinite loops. This can occur in poorly written AML + * when the hardware does not respond within a while loop and the + * loop does not implement a timeout. + */ + control_state->control.loop_count++; + if (control_state->control.loop_count > + ACPI_MAX_LOOP_ITERATIONS) { + status = AE_AML_INFINITE_LOOP; + break; + } + + /* + * Go back and evaluate the predicate and maybe execute the loop + * another time + */ + status = AE_CTRL_PENDING; + walk_state->aml_last_while = + control_state->control.aml_predicate_start; + break; + } + + /* Predicate was false, terminate this while loop */ + + ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, + "[WHILE_OP] termination! Op=%p\n", op)); + + /* Pop this control state and free it */ + + control_state = + acpi_ut_pop_generic_state(&walk_state->control_state); + acpi_ut_delete_generic_state(control_state); + break; + + case AML_RETURN_OP: + + ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, + "[RETURN_OP] Op=%p Arg=%p\n", op, + op->common.value.arg)); + + /* + * One optional operand -- the return value + * It can be either an immediate operand or a result that + * has been bubbled up the tree + */ + if (op->common.value.arg) { + + /* Since we have a real Return(), delete any implicit return */ + + acpi_ds_clear_implicit_return(walk_state); + + /* Return statement has an immediate operand */ + + status = + acpi_ds_create_operands(walk_state, + op->common.value.arg); + if (ACPI_FAILURE(status)) { + return (status); + } + + /* + * If value being returned is a Reference (such as + * an arg or local), resolve it now because it may + * cease to exist at the end of the method. + */ + status = + acpi_ex_resolve_to_value(&walk_state->operands[0], + walk_state); + if (ACPI_FAILURE(status)) { + return (status); + } + + /* + * Get the return value and save as the last result + * value. This is the only place where walk_state->return_desc + * is set to anything other than zero! + */ + walk_state->return_desc = walk_state->operands[0]; + } else if (walk_state->result_count) { + + /* Since we have a real Return(), delete any implicit return */ + + acpi_ds_clear_implicit_return(walk_state); + + /* + * The return value has come from a previous calculation. + * + * If value being returned is a Reference (such as + * an arg or local), resolve it now because it may + * cease to exist at the end of the method. + * + * Allow references created by the Index operator to return + * unchanged. + */ + if ((ACPI_GET_DESCRIPTOR_TYPE + (walk_state->results->results.obj_desc[0]) == + ACPI_DESC_TYPE_OPERAND) + && ((walk_state->results->results.obj_desc[0])-> + common.type == ACPI_TYPE_LOCAL_REFERENCE) + && ((walk_state->results->results.obj_desc[0])-> + reference.class != ACPI_REFCLASS_INDEX)) { + status = + acpi_ex_resolve_to_value(&walk_state-> + results->results. + obj_desc[0], + walk_state); + if (ACPI_FAILURE(status)) { + return (status); + } + } + + walk_state->return_desc = + walk_state->results->results.obj_desc[0]; + } else { + /* No return operand */ + + if (walk_state->num_operands) { + acpi_ut_remove_reference(walk_state-> + operands[0]); + } + + walk_state->operands[0] = NULL; + walk_state->num_operands = 0; + walk_state->return_desc = NULL; + } + + ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, + "Completed RETURN_OP State=%p, RetVal=%p\n", + walk_state, walk_state->return_desc)); + + /* End the control method execution right now */ + + status = AE_CTRL_TERMINATE; + break; + + case AML_NOOP_OP: + + /* Just do nothing! */ + break; + + case AML_BREAK_POINT_OP: + + /* + * Set the single-step flag. This will cause the debugger (if present) + * to break to the console within the AML debugger at the start of the + * next AML instruction. + */ + ACPI_DEBUGGER_EXEC(acpi_gbl_cm_single_step = TRUE); + ACPI_DEBUGGER_EXEC(acpi_os_printf + ("**break** Executed AML BreakPoint opcode\n")); + + /* Call to the OSL in case OS wants a piece of the action */ + + status = acpi_os_signal(ACPI_SIGNAL_BREAKPOINT, + "Executed AML Breakpoint opcode"); + break; + + case AML_BREAK_OP: + case AML_CONTINUE_OP: /* ACPI 2.0 */ + + /* Pop and delete control states until we find a while */ + + while (walk_state->control_state && + (walk_state->control_state->control.opcode != + AML_WHILE_OP)) { + control_state = + acpi_ut_pop_generic_state(&walk_state-> + control_state); + acpi_ut_delete_generic_state(control_state); + } + + /* No while found? */ + + if (!walk_state->control_state) { + return (AE_AML_NO_WHILE); + } + + /* Was: walk_state->aml_last_while = walk_state->control_state->Control.aml_predicate_start; */ + + walk_state->aml_last_while = + walk_state->control_state->control.package_end; + + /* Return status depending on opcode */ + + if (op->common.aml_opcode == AML_BREAK_OP) { + status = AE_CTRL_BREAK; + } else { + status = AE_CTRL_CONTINUE; + } + break; + + default: + + ACPI_ERROR((AE_INFO, "Unknown control opcode=0x%X Op=%p", + op->common.aml_opcode, op)); + + status = AE_AML_BAD_OPCODE; + break; + } + + return (status); +} diff --git a/drivers/acpi/acpica/dsopcode.c b/drivers/acpi/acpica/dsopcode.c index bbecf293aeebf..c627a288e0276 100644 --- a/drivers/acpi/acpica/dsopcode.c +++ b/drivers/acpi/acpica/dsopcode.c @@ -1,7 +1,6 @@ /****************************************************************************** * - * Module Name: dsopcode - Dispatcher Op Region support and handling of - * "control" opcodes + * Module Name: dsopcode - Dispatcher suport for regions and fields * *****************************************************************************/ @@ -56,11 +55,6 @@ ACPI_MODULE_NAME("dsopcode") /* Local prototypes */ -static acpi_status -acpi_ds_execute_arguments(struct acpi_namespace_node *node, - struct acpi_namespace_node *scope_node, - u32 aml_length, u8 * aml_start); - static acpi_status acpi_ds_init_buffer_field(u16 aml_opcode, union acpi_operand_object *obj_desc, @@ -69,361 +63,6 @@ acpi_ds_init_buffer_field(u16 aml_opcode, union acpi_operand_object *length_desc, union acpi_operand_object *result_desc); -/******************************************************************************* - * - * FUNCTION: acpi_ds_execute_arguments - * - * PARAMETERS: Node - Object NS node - * scope_node - Parent NS node - * aml_length - Length of executable AML - * aml_start - Pointer to the AML - * - * RETURN: Status. - * - * DESCRIPTION: Late (deferred) execution of region or field arguments - * - ******************************************************************************/ - -static acpi_status -acpi_ds_execute_arguments(struct acpi_namespace_node *node, - struct acpi_namespace_node *scope_node, - u32 aml_length, u8 * aml_start) -{ - acpi_status status; - union acpi_parse_object *op; - struct acpi_walk_state *walk_state; - - ACPI_FUNCTION_TRACE(ds_execute_arguments); - - /* - * Allocate a new parser op to be the root of the parsed tree - */ - op = acpi_ps_alloc_op(AML_INT_EVAL_SUBTREE_OP); - if (!op) { - return_ACPI_STATUS(AE_NO_MEMORY); - } - - /* Save the Node for use in acpi_ps_parse_aml */ - - op->common.node = scope_node; - - /* Create and initialize a new parser state */ - - walk_state = acpi_ds_create_walk_state(0, NULL, NULL, NULL); - if (!walk_state) { - status = AE_NO_MEMORY; - goto cleanup; - } - - status = acpi_ds_init_aml_walk(walk_state, op, NULL, aml_start, - aml_length, NULL, ACPI_IMODE_LOAD_PASS1); - if (ACPI_FAILURE(status)) { - acpi_ds_delete_walk_state(walk_state); - goto cleanup; - } - - /* Mark this parse as a deferred opcode */ - - walk_state->parse_flags = ACPI_PARSE_DEFERRED_OP; - walk_state->deferred_node = node; - - /* Pass1: Parse the entire declaration */ - - status = acpi_ps_parse_aml(walk_state); - if (ACPI_FAILURE(status)) { - goto cleanup; - } - - /* Get and init the Op created above */ - - op->common.node = node; - acpi_ps_delete_parse_tree(op); - - /* Evaluate the deferred arguments */ - - op = acpi_ps_alloc_op(AML_INT_EVAL_SUBTREE_OP); - if (!op) { - return_ACPI_STATUS(AE_NO_MEMORY); - } - - op->common.node = scope_node; - - /* Create and initialize a new parser state */ - - walk_state = acpi_ds_create_walk_state(0, NULL, NULL, NULL); - if (!walk_state) { - status = AE_NO_MEMORY; - goto cleanup; - } - - /* Execute the opcode and arguments */ - - status = acpi_ds_init_aml_walk(walk_state, op, NULL, aml_start, - aml_length, NULL, ACPI_IMODE_EXECUTE); - if (ACPI_FAILURE(status)) { - acpi_ds_delete_walk_state(walk_state); - goto cleanup; - } - - /* Mark this execution as a deferred opcode */ - - walk_state->deferred_node = node; - status = acpi_ps_parse_aml(walk_state); - - cleanup: - acpi_ps_delete_parse_tree(op); - return_ACPI_STATUS(status); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ds_get_buffer_field_arguments - * - * PARAMETERS: obj_desc - A valid buffer_field object - * - * RETURN: Status. - * - * DESCRIPTION: Get buffer_field Buffer and Index. This implements the late - * evaluation of these field attributes. - * - ******************************************************************************/ - -acpi_status -acpi_ds_get_buffer_field_arguments(union acpi_operand_object *obj_desc) -{ - union acpi_operand_object *extra_desc; - struct acpi_namespace_node *node; - acpi_status status; - - ACPI_FUNCTION_TRACE_PTR(ds_get_buffer_field_arguments, obj_desc); - - if (obj_desc->common.flags & AOPOBJ_DATA_VALID) { - return_ACPI_STATUS(AE_OK); - } - - /* Get the AML pointer (method object) and buffer_field node */ - - extra_desc = acpi_ns_get_secondary_object(obj_desc); - node = obj_desc->buffer_field.node; - - ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname - (ACPI_TYPE_BUFFER_FIELD, node, NULL)); - ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "[%4.4s] BufferField Arg Init\n", - acpi_ut_get_node_name(node))); - - /* Execute the AML code for the term_arg arguments */ - - status = acpi_ds_execute_arguments(node, node->parent, - extra_desc->extra.aml_length, - extra_desc->extra.aml_start); - return_ACPI_STATUS(status); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ds_get_bank_field_arguments - * - * PARAMETERS: obj_desc - A valid bank_field object - * - * RETURN: Status. - * - * DESCRIPTION: Get bank_field bank_value. This implements the late - * evaluation of these field attributes. - * - ******************************************************************************/ - -acpi_status -acpi_ds_get_bank_field_arguments(union acpi_operand_object *obj_desc) -{ - union acpi_operand_object *extra_desc; - struct acpi_namespace_node *node; - acpi_status status; - - ACPI_FUNCTION_TRACE_PTR(ds_get_bank_field_arguments, obj_desc); - - if (obj_desc->common.flags & AOPOBJ_DATA_VALID) { - return_ACPI_STATUS(AE_OK); - } - - /* Get the AML pointer (method object) and bank_field node */ - - extra_desc = acpi_ns_get_secondary_object(obj_desc); - node = obj_desc->bank_field.node; - - ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname - (ACPI_TYPE_LOCAL_BANK_FIELD, node, NULL)); - ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "[%4.4s] BankField Arg Init\n", - acpi_ut_get_node_name(node))); - - /* Execute the AML code for the term_arg arguments */ - - status = acpi_ds_execute_arguments(node, node->parent, - extra_desc->extra.aml_length, - extra_desc->extra.aml_start); - return_ACPI_STATUS(status); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ds_get_buffer_arguments - * - * PARAMETERS: obj_desc - A valid Buffer object - * - * RETURN: Status. - * - * DESCRIPTION: Get Buffer length and initializer byte list. This implements - * the late evaluation of these attributes. - * - ******************************************************************************/ - -acpi_status acpi_ds_get_buffer_arguments(union acpi_operand_object *obj_desc) -{ - struct acpi_namespace_node *node; - acpi_status status; - - ACPI_FUNCTION_TRACE_PTR(ds_get_buffer_arguments, obj_desc); - - if (obj_desc->common.flags & AOPOBJ_DATA_VALID) { - return_ACPI_STATUS(AE_OK); - } - - /* Get the Buffer node */ - - node = obj_desc->buffer.node; - if (!node) { - ACPI_ERROR((AE_INFO, - "No pointer back to namespace node in buffer object %p", - obj_desc)); - return_ACPI_STATUS(AE_AML_INTERNAL); - } - - ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Buffer Arg Init\n")); - - /* Execute the AML code for the term_arg arguments */ - - status = acpi_ds_execute_arguments(node, node, - obj_desc->buffer.aml_length, - obj_desc->buffer.aml_start); - return_ACPI_STATUS(status); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ds_get_package_arguments - * - * PARAMETERS: obj_desc - A valid Package object - * - * RETURN: Status. - * - * DESCRIPTION: Get Package length and initializer byte list. This implements - * the late evaluation of these attributes. - * - ******************************************************************************/ - -acpi_status acpi_ds_get_package_arguments(union acpi_operand_object *obj_desc) -{ - struct acpi_namespace_node *node; - acpi_status status; - - ACPI_FUNCTION_TRACE_PTR(ds_get_package_arguments, obj_desc); - - if (obj_desc->common.flags & AOPOBJ_DATA_VALID) { - return_ACPI_STATUS(AE_OK); - } - - /* Get the Package node */ - - node = obj_desc->package.node; - if (!node) { - ACPI_ERROR((AE_INFO, - "No pointer back to namespace node in package %p", - obj_desc)); - return_ACPI_STATUS(AE_AML_INTERNAL); - } - - ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Package Arg Init\n")); - - /* Execute the AML code for the term_arg arguments */ - - status = acpi_ds_execute_arguments(node, node, - obj_desc->package.aml_length, - obj_desc->package.aml_start); - return_ACPI_STATUS(status); -} - -/***************************************************************************** - * - * FUNCTION: acpi_ds_get_region_arguments - * - * PARAMETERS: obj_desc - A valid region object - * - * RETURN: Status. - * - * DESCRIPTION: Get region address and length. This implements the late - * evaluation of these region attributes. - * - ****************************************************************************/ - -acpi_status acpi_ds_get_region_arguments(union acpi_operand_object *obj_desc) -{ - struct acpi_namespace_node *node; - acpi_status status; - union acpi_operand_object *extra_desc; - - ACPI_FUNCTION_TRACE_PTR(ds_get_region_arguments, obj_desc); - - if (obj_desc->region.flags & AOPOBJ_DATA_VALID) { - return_ACPI_STATUS(AE_OK); - } - - extra_desc = acpi_ns_get_secondary_object(obj_desc); - if (!extra_desc) { - return_ACPI_STATUS(AE_NOT_EXIST); - } - - /* Get the Region node */ - - node = obj_desc->region.node; - - ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname - (ACPI_TYPE_REGION, node, NULL)); - - ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "[%4.4s] OpRegion Arg Init at AML %p\n", - acpi_ut_get_node_name(node), - extra_desc->extra.aml_start)); - - /* Execute the argument AML */ - - status = acpi_ds_execute_arguments(node, node->parent, - extra_desc->extra.aml_length, - extra_desc->extra.aml_start); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - /* Validate the region address/length via the host OS */ - - status = acpi_os_validate_address(obj_desc->region.space_id, - obj_desc->region.address, - (acpi_size) obj_desc->region.length, - acpi_ut_get_node_name(node)); - - if (ACPI_FAILURE(status)) { - /* - * Invalid address/length. We will emit an error message and mark - * the region as invalid, so that it will cause an additional error if - * it is ever used. Then return AE_OK. - */ - ACPI_EXCEPTION((AE_INFO, status, - "During address validation of OpRegion [%4.4s]", - node->name.ascii)); - obj_desc->common.flags |= AOPOBJ_INVALID; - status = AE_OK; - } - - return_ACPI_STATUS(status); -} - /******************************************************************************* * * FUNCTION: acpi_ds_initialize_region @@ -826,8 +465,9 @@ acpi_ds_eval_region_operands(struct acpi_walk_state *walk_state, * * RETURN: Status * - * DESCRIPTION: Get region address and length - * Called from acpi_ds_exec_end_op during data_table_region parse tree walk + * DESCRIPTION: Get region address and length. + * Called from acpi_ds_exec_end_op during data_table_region parse + * tree walk. * ******************************************************************************/ @@ -1114,360 +754,3 @@ acpi_ds_eval_bank_field_operands(struct acpi_walk_state *walk_state, acpi_ut_remove_reference(operand_desc); return_ACPI_STATUS(status); } - -/******************************************************************************* - * - * FUNCTION: acpi_ds_exec_begin_control_op - * - * PARAMETERS: walk_list - The list that owns the walk stack - * Op - The control Op - * - * RETURN: Status - * - * DESCRIPTION: Handles all control ops encountered during control method - * execution. - * - ******************************************************************************/ - -acpi_status -acpi_ds_exec_begin_control_op(struct acpi_walk_state *walk_state, - union acpi_parse_object *op) -{ - acpi_status status = AE_OK; - union acpi_generic_state *control_state; - - ACPI_FUNCTION_NAME(ds_exec_begin_control_op); - - ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "Op=%p Opcode=%2.2X State=%p\n", op, - op->common.aml_opcode, walk_state)); - - switch (op->common.aml_opcode) { - case AML_WHILE_OP: - - /* - * If this is an additional iteration of a while loop, continue. - * There is no need to allocate a new control state. - */ - if (walk_state->control_state) { - if (walk_state->control_state->control.aml_predicate_start - == (walk_state->parser_state.aml - 1)) { - - /* Reset the state to start-of-loop */ - - walk_state->control_state->common.state = - ACPI_CONTROL_CONDITIONAL_EXECUTING; - break; - } - } - - /*lint -fallthrough */ - - case AML_IF_OP: - - /* - * IF/WHILE: Create a new control state to manage these - * constructs. We need to manage these as a stack, in order - * to handle nesting. - */ - control_state = acpi_ut_create_control_state(); - if (!control_state) { - status = AE_NO_MEMORY; - break; - } - /* - * Save a pointer to the predicate for multiple executions - * of a loop - */ - control_state->control.aml_predicate_start = - walk_state->parser_state.aml - 1; - control_state->control.package_end = - walk_state->parser_state.pkg_end; - control_state->control.opcode = op->common.aml_opcode; - - /* Push the control state on this walk's control stack */ - - acpi_ut_push_generic_state(&walk_state->control_state, - control_state); - break; - - case AML_ELSE_OP: - - /* Predicate is in the state object */ - /* If predicate is true, the IF was executed, ignore ELSE part */ - - if (walk_state->last_predicate) { - status = AE_CTRL_TRUE; - } - - break; - - case AML_RETURN_OP: - - break; - - default: - break; - } - - return (status); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ds_exec_end_control_op - * - * PARAMETERS: walk_list - The list that owns the walk stack - * Op - The control Op - * - * RETURN: Status - * - * DESCRIPTION: Handles all control ops encountered during control method - * execution. - * - ******************************************************************************/ - -acpi_status -acpi_ds_exec_end_control_op(struct acpi_walk_state * walk_state, - union acpi_parse_object * op) -{ - acpi_status status = AE_OK; - union acpi_generic_state *control_state; - - ACPI_FUNCTION_NAME(ds_exec_end_control_op); - - switch (op->common.aml_opcode) { - case AML_IF_OP: - - ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "[IF_OP] Op=%p\n", op)); - - /* - * Save the result of the predicate in case there is an - * ELSE to come - */ - walk_state->last_predicate = - (u8) walk_state->control_state->common.value; - - /* - * Pop the control state that was created at the start - * of the IF and free it - */ - control_state = - acpi_ut_pop_generic_state(&walk_state->control_state); - acpi_ut_delete_generic_state(control_state); - break; - - case AML_ELSE_OP: - - break; - - case AML_WHILE_OP: - - ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "[WHILE_OP] Op=%p\n", op)); - - control_state = walk_state->control_state; - if (control_state->common.value) { - - /* Predicate was true, the body of the loop was just executed */ - - /* - * This loop counter mechanism allows the interpreter to escape - * possibly infinite loops. This can occur in poorly written AML - * when the hardware does not respond within a while loop and the - * loop does not implement a timeout. - */ - control_state->control.loop_count++; - if (control_state->control.loop_count > - ACPI_MAX_LOOP_ITERATIONS) { - status = AE_AML_INFINITE_LOOP; - break; - } - - /* - * Go back and evaluate the predicate and maybe execute the loop - * another time - */ - status = AE_CTRL_PENDING; - walk_state->aml_last_while = - control_state->control.aml_predicate_start; - break; - } - - /* Predicate was false, terminate this while loop */ - - ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, - "[WHILE_OP] termination! Op=%p\n", op)); - - /* Pop this control state and free it */ - - control_state = - acpi_ut_pop_generic_state(&walk_state->control_state); - acpi_ut_delete_generic_state(control_state); - break; - - case AML_RETURN_OP: - - ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, - "[RETURN_OP] Op=%p Arg=%p\n", op, - op->common.value.arg)); - - /* - * One optional operand -- the return value - * It can be either an immediate operand or a result that - * has been bubbled up the tree - */ - if (op->common.value.arg) { - - /* Since we have a real Return(), delete any implicit return */ - - acpi_ds_clear_implicit_return(walk_state); - - /* Return statement has an immediate operand */ - - status = - acpi_ds_create_operands(walk_state, - op->common.value.arg); - if (ACPI_FAILURE(status)) { - return (status); - } - - /* - * If value being returned is a Reference (such as - * an arg or local), resolve it now because it may - * cease to exist at the end of the method. - */ - status = - acpi_ex_resolve_to_value(&walk_state->operands[0], - walk_state); - if (ACPI_FAILURE(status)) { - return (status); - } - - /* - * Get the return value and save as the last result - * value. This is the only place where walk_state->return_desc - * is set to anything other than zero! - */ - walk_state->return_desc = walk_state->operands[0]; - } else if (walk_state->result_count) { - - /* Since we have a real Return(), delete any implicit return */ - - acpi_ds_clear_implicit_return(walk_state); - - /* - * The return value has come from a previous calculation. - * - * If value being returned is a Reference (such as - * an arg or local), resolve it now because it may - * cease to exist at the end of the method. - * - * Allow references created by the Index operator to return unchanged. - */ - if ((ACPI_GET_DESCRIPTOR_TYPE - (walk_state->results->results.obj_desc[0]) == - ACPI_DESC_TYPE_OPERAND) - && ((walk_state->results->results.obj_desc[0])-> - common.type == ACPI_TYPE_LOCAL_REFERENCE) - && ((walk_state->results->results.obj_desc[0])-> - reference.class != ACPI_REFCLASS_INDEX)) { - status = - acpi_ex_resolve_to_value(&walk_state-> - results->results. - obj_desc[0], - walk_state); - if (ACPI_FAILURE(status)) { - return (status); - } - } - - walk_state->return_desc = - walk_state->results->results.obj_desc[0]; - } else { - /* No return operand */ - - if (walk_state->num_operands) { - acpi_ut_remove_reference(walk_state-> - operands[0]); - } - - walk_state->operands[0] = NULL; - walk_state->num_operands = 0; - walk_state->return_desc = NULL; - } - - ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, - "Completed RETURN_OP State=%p, RetVal=%p\n", - walk_state, walk_state->return_desc)); - - /* End the control method execution right now */ - - status = AE_CTRL_TERMINATE; - break; - - case AML_NOOP_OP: - - /* Just do nothing! */ - break; - - case AML_BREAK_POINT_OP: - - /* - * Set the single-step flag. This will cause the debugger (if present) - * to break to the console within the AML debugger at the start of the - * next AML instruction. - */ - ACPI_DEBUGGER_EXEC(acpi_gbl_cm_single_step = TRUE); - ACPI_DEBUGGER_EXEC(acpi_os_printf - ("**break** Executed AML BreakPoint opcode\n")); - - /* Call to the OSL in case OS wants a piece of the action */ - - status = acpi_os_signal(ACPI_SIGNAL_BREAKPOINT, - "Executed AML Breakpoint opcode"); - break; - - case AML_BREAK_OP: - case AML_CONTINUE_OP: /* ACPI 2.0 */ - - /* Pop and delete control states until we find a while */ - - while (walk_state->control_state && - (walk_state->control_state->control.opcode != - AML_WHILE_OP)) { - control_state = - acpi_ut_pop_generic_state(&walk_state-> - control_state); - acpi_ut_delete_generic_state(control_state); - } - - /* No while found? */ - - if (!walk_state->control_state) { - return (AE_AML_NO_WHILE); - } - - /* Was: walk_state->aml_last_while = walk_state->control_state->Control.aml_predicate_start; */ - - walk_state->aml_last_while = - walk_state->control_state->control.package_end; - - /* Return status depending on opcode */ - - if (op->common.aml_opcode == AML_BREAK_OP) { - status = AE_CTRL_BREAK; - } else { - status = AE_CTRL_CONTINUE; - } - break; - - default: - - ACPI_ERROR((AE_INFO, "Unknown control opcode=0x%X Op=%p", - op->common.aml_opcode, op)); - - status = AE_AML_BAD_OPCODE; - break; - } - - return (status); -} diff --git a/drivers/acpi/acpica/dswload.c b/drivers/acpi/acpica/dswload.c index 52566ff5e9034..23a3b1ab20c1c 100644 --- a/drivers/acpi/acpica/dswload.c +++ b/drivers/acpi/acpica/dswload.c @@ -1,6 +1,6 @@ /****************************************************************************** * - * Module Name: dswload - Dispatcher namespace load callbacks + * Module Name: dswload - Dispatcher first pass namespace load callbacks * *****************************************************************************/ @@ -48,7 +48,6 @@ #include "acdispat.h" #include "acinterp.h" #include "acnamesp.h" -#include "acevents.h" #ifdef ACPI_ASL_COMPILER #include @@ -537,670 +536,3 @@ acpi_status acpi_ds_load1_end_op(struct acpi_walk_state *walk_state) return_ACPI_STATUS(status); } - -/******************************************************************************* - * - * FUNCTION: acpi_ds_load2_begin_op - * - * PARAMETERS: walk_state - Current state of the parse tree walk - * out_op - Wher to return op if a new one is created - * - * RETURN: Status - * - * DESCRIPTION: Descending callback used during the loading of ACPI tables. - * - ******************************************************************************/ - -acpi_status -acpi_ds_load2_begin_op(struct acpi_walk_state *walk_state, - union acpi_parse_object **out_op) -{ - union acpi_parse_object *op; - struct acpi_namespace_node *node; - acpi_status status; - acpi_object_type object_type; - char *buffer_ptr; - u32 flags; - - ACPI_FUNCTION_TRACE(ds_load2_begin_op); - - op = walk_state->op; - ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "Op=%p State=%p\n", op, - walk_state)); - - if (op) { - if ((walk_state->control_state) && - (walk_state->control_state->common.state == - ACPI_CONTROL_CONDITIONAL_EXECUTING)) { - - /* We are executing a while loop outside of a method */ - - status = acpi_ds_exec_begin_op(walk_state, out_op); - return_ACPI_STATUS(status); - } - - /* We only care about Namespace opcodes here */ - - if ((!(walk_state->op_info->flags & AML_NSOPCODE) && - (walk_state->opcode != AML_INT_NAMEPATH_OP)) || - (!(walk_state->op_info->flags & AML_NAMED))) { - return_ACPI_STATUS(AE_OK); - } - - /* Get the name we are going to enter or lookup in the namespace */ - - if (walk_state->opcode == AML_INT_NAMEPATH_OP) { - - /* For Namepath op, get the path string */ - - buffer_ptr = op->common.value.string; - if (!buffer_ptr) { - - /* No name, just exit */ - - return_ACPI_STATUS(AE_OK); - } - } else { - /* Get name from the op */ - - buffer_ptr = ACPI_CAST_PTR(char, &op->named.name); - } - } else { - /* Get the namestring from the raw AML */ - - buffer_ptr = - acpi_ps_get_next_namestring(&walk_state->parser_state); - } - - /* Map the opcode into an internal object type */ - - object_type = walk_state->op_info->object_type; - - ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, - "State=%p Op=%p Type=%X\n", walk_state, op, - object_type)); - - switch (walk_state->opcode) { - case AML_FIELD_OP: - case AML_BANK_FIELD_OP: - case AML_INDEX_FIELD_OP: - - node = NULL; - status = AE_OK; - break; - - case AML_INT_NAMEPATH_OP: - /* - * The name_path is an object reference to an existing object. - * Don't enter the name into the namespace, but look it up - * for use later. - */ - status = - acpi_ns_lookup(walk_state->scope_info, buffer_ptr, - object_type, ACPI_IMODE_EXECUTE, - ACPI_NS_SEARCH_PARENT, walk_state, &(node)); - break; - - case AML_SCOPE_OP: - - /* Special case for Scope(\) -> refers to the Root node */ - - if (op && (op->named.node == acpi_gbl_root_node)) { - node = op->named.node; - - status = - acpi_ds_scope_stack_push(node, object_type, - walk_state); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - } else { - /* - * The Path is an object reference to an existing object. - * Don't enter the name into the namespace, but look it up - * for use later. - */ - status = - acpi_ns_lookup(walk_state->scope_info, buffer_ptr, - object_type, ACPI_IMODE_EXECUTE, - ACPI_NS_SEARCH_PARENT, walk_state, - &(node)); - if (ACPI_FAILURE(status)) { -#ifdef ACPI_ASL_COMPILER - if (status == AE_NOT_FOUND) { - status = AE_OK; - } else { - ACPI_ERROR_NAMESPACE(buffer_ptr, - status); - } -#else - ACPI_ERROR_NAMESPACE(buffer_ptr, status); -#endif - return_ACPI_STATUS(status); - } - } - - /* - * We must check to make sure that the target is - * one of the opcodes that actually opens a scope - */ - switch (node->type) { - case ACPI_TYPE_ANY: - case ACPI_TYPE_LOCAL_SCOPE: /* Scope */ - case ACPI_TYPE_DEVICE: - case ACPI_TYPE_POWER: - case ACPI_TYPE_PROCESSOR: - case ACPI_TYPE_THERMAL: - - /* These are acceptable types */ - break; - - case ACPI_TYPE_INTEGER: - case ACPI_TYPE_STRING: - case ACPI_TYPE_BUFFER: - - /* - * These types we will allow, but we will change the type. - * This enables some existing code of the form: - * - * Name (DEB, 0) - * Scope (DEB) { ... } - */ - ACPI_WARNING((AE_INFO, - "Type override - [%4.4s] had invalid type (%s) " - "for Scope operator, changed to type ANY\n", - acpi_ut_get_node_name(node), - acpi_ut_get_type_name(node->type))); - - node->type = ACPI_TYPE_ANY; - walk_state->scope_info->common.value = ACPI_TYPE_ANY; - break; - - default: - - /* All other types are an error */ - - ACPI_ERROR((AE_INFO, - "Invalid type (%s) for target of " - "Scope operator [%4.4s] (Cannot override)", - acpi_ut_get_type_name(node->type), - acpi_ut_get_node_name(node))); - - return (AE_AML_OPERAND_TYPE); - } - break; - - default: - - /* All other opcodes */ - - if (op && op->common.node) { - - /* This op/node was previously entered into the namespace */ - - node = op->common.node; - - if (acpi_ns_opens_scope(object_type)) { - status = - acpi_ds_scope_stack_push(node, object_type, - walk_state); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - } - - return_ACPI_STATUS(AE_OK); - } - - /* - * Enter the named type into the internal namespace. We enter the name - * as we go downward in the parse tree. Any necessary subobjects that - * involve arguments to the opcode must be created as we go back up the - * parse tree later. - * - * Note: Name may already exist if we are executing a deferred opcode. - */ - if (walk_state->deferred_node) { - - /* This name is already in the namespace, get the node */ - - node = walk_state->deferred_node; - status = AE_OK; - break; - } - - flags = ACPI_NS_NO_UPSEARCH; - if (walk_state->pass_number == ACPI_IMODE_EXECUTE) { - - /* Execution mode, node cannot already exist, node is temporary */ - - flags |= ACPI_NS_ERROR_IF_FOUND; - - if (! - (walk_state-> - parse_flags & ACPI_PARSE_MODULE_LEVEL)) { - flags |= ACPI_NS_TEMPORARY; - } - } - - /* Add new entry or lookup existing entry */ - - status = - acpi_ns_lookup(walk_state->scope_info, buffer_ptr, - object_type, ACPI_IMODE_LOAD_PASS2, flags, - walk_state, &node); - - if (ACPI_SUCCESS(status) && (flags & ACPI_NS_TEMPORARY)) { - ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, - "***New Node [%4.4s] %p is temporary\n", - acpi_ut_get_node_name(node), node)); - } - break; - } - - if (ACPI_FAILURE(status)) { - ACPI_ERROR_NAMESPACE(buffer_ptr, status); - return_ACPI_STATUS(status); - } - - if (!op) { - - /* Create a new op */ - - op = acpi_ps_alloc_op(walk_state->opcode); - if (!op) { - return_ACPI_STATUS(AE_NO_MEMORY); - } - - /* Initialize the new op */ - - if (node) { - op->named.name = node->name.integer; - } - *out_op = op; - } - - /* - * Put the Node in the "op" object that the parser uses, so we - * can get it again quickly when this scope is closed - */ - op->common.node = node; - return_ACPI_STATUS(status); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ds_load2_end_op - * - * PARAMETERS: walk_state - Current state of the parse tree walk - * - * RETURN: Status - * - * DESCRIPTION: Ascending callback used during the loading of the namespace, - * both control methods and everything else. - * - ******************************************************************************/ - -acpi_status acpi_ds_load2_end_op(struct acpi_walk_state *walk_state) -{ - union acpi_parse_object *op; - acpi_status status = AE_OK; - acpi_object_type object_type; - struct acpi_namespace_node *node; - union acpi_parse_object *arg; - struct acpi_namespace_node *new_node; -#ifndef ACPI_NO_METHOD_EXECUTION - u32 i; - u8 region_space; -#endif - - ACPI_FUNCTION_TRACE(ds_load2_end_op); - - op = walk_state->op; - ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "Opcode [%s] Op %p State %p\n", - walk_state->op_info->name, op, walk_state)); - - /* Check if opcode had an associated namespace object */ - - if (!(walk_state->op_info->flags & AML_NSOBJECT)) { - return_ACPI_STATUS(AE_OK); - } - - if (op->common.aml_opcode == AML_SCOPE_OP) { - ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, - "Ending scope Op=%p State=%p\n", op, - walk_state)); - } - - object_type = walk_state->op_info->object_type; - - /* - * Get the Node/name from the earlier lookup - * (It was saved in the *op structure) - */ - node = op->common.node; - - /* - * Put the Node on the object stack (Contains the ACPI Name of - * this object) - */ - walk_state->operands[0] = (void *)node; - walk_state->num_operands = 1; - - /* Pop the scope stack */ - - if (acpi_ns_opens_scope(object_type) && - (op->common.aml_opcode != AML_INT_METHODCALL_OP)) { - ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, - "(%s) Popping scope for Op %p\n", - acpi_ut_get_type_name(object_type), op)); - - status = acpi_ds_scope_stack_pop(walk_state); - if (ACPI_FAILURE(status)) { - goto cleanup; - } - } - - /* - * Named operations are as follows: - * - * AML_ALIAS - * AML_BANKFIELD - * AML_CREATEBITFIELD - * AML_CREATEBYTEFIELD - * AML_CREATEDWORDFIELD - * AML_CREATEFIELD - * AML_CREATEQWORDFIELD - * AML_CREATEWORDFIELD - * AML_DATA_REGION - * AML_DEVICE - * AML_EVENT - * AML_FIELD - * AML_INDEXFIELD - * AML_METHOD - * AML_METHODCALL - * AML_MUTEX - * AML_NAME - * AML_NAMEDFIELD - * AML_OPREGION - * AML_POWERRES - * AML_PROCESSOR - * AML_SCOPE - * AML_THERMALZONE - */ - - ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, - "Create-Load [%s] State=%p Op=%p NamedObj=%p\n", - acpi_ps_get_opcode_name(op->common.aml_opcode), - walk_state, op, node)); - - /* Decode the opcode */ - - arg = op->common.value.arg; - - switch (walk_state->op_info->type) { -#ifndef ACPI_NO_METHOD_EXECUTION - - case AML_TYPE_CREATE_FIELD: - /* - * Create the field object, but the field buffer and index must - * be evaluated later during the execution phase - */ - status = acpi_ds_create_buffer_field(op, walk_state); - break; - - case AML_TYPE_NAMED_FIELD: - /* - * If we are executing a method, initialize the field - */ - if (walk_state->method_node) { - status = acpi_ds_init_field_objects(op, walk_state); - } - - switch (op->common.aml_opcode) { - case AML_INDEX_FIELD_OP: - - status = - acpi_ds_create_index_field(op, - (acpi_handle) arg-> - common.node, walk_state); - break; - - case AML_BANK_FIELD_OP: - - status = - acpi_ds_create_bank_field(op, arg->common.node, - walk_state); - break; - - case AML_FIELD_OP: - - status = - acpi_ds_create_field(op, arg->common.node, - walk_state); - break; - - default: - /* All NAMED_FIELD opcodes must be handled above */ - break; - } - break; - - case AML_TYPE_NAMED_SIMPLE: - - status = acpi_ds_create_operands(walk_state, arg); - if (ACPI_FAILURE(status)) { - goto cleanup; - } - - switch (op->common.aml_opcode) { - case AML_PROCESSOR_OP: - - status = acpi_ex_create_processor(walk_state); - break; - - case AML_POWER_RES_OP: - - status = acpi_ex_create_power_resource(walk_state); - break; - - case AML_MUTEX_OP: - - status = acpi_ex_create_mutex(walk_state); - break; - - case AML_EVENT_OP: - - status = acpi_ex_create_event(walk_state); - break; - - case AML_ALIAS_OP: - - status = acpi_ex_create_alias(walk_state); - break; - - default: - /* Unknown opcode */ - - status = AE_OK; - goto cleanup; - } - - /* Delete operands */ - - for (i = 1; i < walk_state->num_operands; i++) { - acpi_ut_remove_reference(walk_state->operands[i]); - walk_state->operands[i] = NULL; - } - - break; -#endif /* ACPI_NO_METHOD_EXECUTION */ - - case AML_TYPE_NAMED_COMPLEX: - - switch (op->common.aml_opcode) { -#ifndef ACPI_NO_METHOD_EXECUTION - case AML_REGION_OP: - case AML_DATA_REGION_OP: - - if (op->common.aml_opcode == AML_REGION_OP) { - region_space = (acpi_adr_space_type) - ((op->common.value.arg)->common.value. - integer); - } else { - region_space = REGION_DATA_TABLE; - } - - /* - * The op_region is not fully parsed at this time. The only valid - * argument is the space_id. (We must save the address of the - * AML of the address and length operands) - * - * If we have a valid region, initialize it. The namespace is - * unlocked at this point. - * - * Need to unlock interpreter if it is locked (if we are running - * a control method), in order to allow _REG methods to be run - * during acpi_ev_initialize_region. - */ - if (walk_state->method_node) { - /* - * Executing a method: initialize the region and unlock - * the interpreter - */ - status = - acpi_ex_create_region(op->named.data, - op->named.length, - region_space, - walk_state); - if (ACPI_FAILURE(status)) { - return (status); - } - - acpi_ex_exit_interpreter(); - } - - status = - acpi_ev_initialize_region - (acpi_ns_get_attached_object(node), FALSE); - if (walk_state->method_node) { - acpi_ex_enter_interpreter(); - } - - if (ACPI_FAILURE(status)) { - /* - * If AE_NOT_EXIST is returned, it is not fatal - * because many regions get created before a handler - * is installed for said region. - */ - if (AE_NOT_EXIST == status) { - status = AE_OK; - } - } - break; - - case AML_NAME_OP: - - status = acpi_ds_create_node(walk_state, node, op); - break; - - case AML_METHOD_OP: - /* - * method_op pkg_length name_string method_flags term_list - * - * Note: We must create the method node/object pair as soon as we - * see the method declaration. This allows later pass1 parsing - * of invocations of the method (need to know the number of - * arguments.) - */ - ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, - "LOADING-Method: State=%p Op=%p NamedObj=%p\n", - walk_state, op, op->named.node)); - - if (!acpi_ns_get_attached_object(op->named.node)) { - walk_state->operands[0] = - ACPI_CAST_PTR(void, op->named.node); - walk_state->num_operands = 1; - - status = - acpi_ds_create_operands(walk_state, - op->common.value. - arg); - if (ACPI_SUCCESS(status)) { - status = - acpi_ex_create_method(op->named. - data, - op->named. - length, - walk_state); - } - walk_state->operands[0] = NULL; - walk_state->num_operands = 0; - - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - } - break; - -#endif /* ACPI_NO_METHOD_EXECUTION */ - - default: - /* All NAMED_COMPLEX opcodes must be handled above */ - break; - } - break; - - case AML_CLASS_INTERNAL: - - /* case AML_INT_NAMEPATH_OP: */ - break; - - case AML_CLASS_METHOD_CALL: - - ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, - "RESOLVING-MethodCall: State=%p Op=%p NamedObj=%p\n", - walk_state, op, node)); - - /* - * Lookup the method name and save the Node - */ - status = - acpi_ns_lookup(walk_state->scope_info, - arg->common.value.string, ACPI_TYPE_ANY, - ACPI_IMODE_LOAD_PASS2, - ACPI_NS_SEARCH_PARENT | - ACPI_NS_DONT_OPEN_SCOPE, walk_state, - &(new_node)); - if (ACPI_SUCCESS(status)) { - /* - * Make sure that what we found is indeed a method - * We didn't search for a method on purpose, to see if the name - * would resolve - */ - if (new_node->type != ACPI_TYPE_METHOD) { - status = AE_AML_OPERAND_TYPE; - } - - /* We could put the returned object (Node) on the object stack for - * later, but for now, we will put it in the "op" object that the - * parser uses, so we can get it again at the end of this scope - */ - op->common.node = new_node; - } else { - ACPI_ERROR_NAMESPACE(arg->common.value.string, status); - } - break; - - default: - break; - } - - cleanup: - - /* Remove the Node pushed at the very beginning */ - - walk_state->operands[0] = NULL; - walk_state->num_operands = 0; - return_ACPI_STATUS(status); -} diff --git a/drivers/acpi/acpica/dswload2.c b/drivers/acpi/acpica/dswload2.c new file mode 100644 index 0000000000000..4be4e921dfe1b --- /dev/null +++ b/drivers/acpi/acpica/dswload2.c @@ -0,0 +1,720 @@ +/****************************************************************************** + * + * Module Name: dswload2 - Dispatcher second pass namespace load callbacks + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2011, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include +#include "accommon.h" +#include "acparser.h" +#include "amlcode.h" +#include "acdispat.h" +#include "acinterp.h" +#include "acnamesp.h" +#include "acevents.h" + +#define _COMPONENT ACPI_DISPATCHER +ACPI_MODULE_NAME("dswload2") + +/******************************************************************************* + * + * FUNCTION: acpi_ds_load2_begin_op + * + * PARAMETERS: walk_state - Current state of the parse tree walk + * out_op - Wher to return op if a new one is created + * + * RETURN: Status + * + * DESCRIPTION: Descending callback used during the loading of ACPI tables. + * + ******************************************************************************/ +acpi_status +acpi_ds_load2_begin_op(struct acpi_walk_state *walk_state, + union acpi_parse_object **out_op) +{ + union acpi_parse_object *op; + struct acpi_namespace_node *node; + acpi_status status; + acpi_object_type object_type; + char *buffer_ptr; + u32 flags; + + ACPI_FUNCTION_TRACE(ds_load2_begin_op); + + op = walk_state->op; + ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "Op=%p State=%p\n", op, + walk_state)); + + if (op) { + if ((walk_state->control_state) && + (walk_state->control_state->common.state == + ACPI_CONTROL_CONDITIONAL_EXECUTING)) { + + /* We are executing a while loop outside of a method */ + + status = acpi_ds_exec_begin_op(walk_state, out_op); + return_ACPI_STATUS(status); + } + + /* We only care about Namespace opcodes here */ + + if ((!(walk_state->op_info->flags & AML_NSOPCODE) && + (walk_state->opcode != AML_INT_NAMEPATH_OP)) || + (!(walk_state->op_info->flags & AML_NAMED))) { + return_ACPI_STATUS(AE_OK); + } + + /* Get the name we are going to enter or lookup in the namespace */ + + if (walk_state->opcode == AML_INT_NAMEPATH_OP) { + + /* For Namepath op, get the path string */ + + buffer_ptr = op->common.value.string; + if (!buffer_ptr) { + + /* No name, just exit */ + + return_ACPI_STATUS(AE_OK); + } + } else { + /* Get name from the op */ + + buffer_ptr = ACPI_CAST_PTR(char, &op->named.name); + } + } else { + /* Get the namestring from the raw AML */ + + buffer_ptr = + acpi_ps_get_next_namestring(&walk_state->parser_state); + } + + /* Map the opcode into an internal object type */ + + object_type = walk_state->op_info->object_type; + + ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, + "State=%p Op=%p Type=%X\n", walk_state, op, + object_type)); + + switch (walk_state->opcode) { + case AML_FIELD_OP: + case AML_BANK_FIELD_OP: + case AML_INDEX_FIELD_OP: + + node = NULL; + status = AE_OK; + break; + + case AML_INT_NAMEPATH_OP: + /* + * The name_path is an object reference to an existing object. + * Don't enter the name into the namespace, but look it up + * for use later. + */ + status = + acpi_ns_lookup(walk_state->scope_info, buffer_ptr, + object_type, ACPI_IMODE_EXECUTE, + ACPI_NS_SEARCH_PARENT, walk_state, &(node)); + break; + + case AML_SCOPE_OP: + + /* Special case for Scope(\) -> refers to the Root node */ + + if (op && (op->named.node == acpi_gbl_root_node)) { + node = op->named.node; + + status = + acpi_ds_scope_stack_push(node, object_type, + walk_state); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + } else { + /* + * The Path is an object reference to an existing object. + * Don't enter the name into the namespace, but look it up + * for use later. + */ + status = + acpi_ns_lookup(walk_state->scope_info, buffer_ptr, + object_type, ACPI_IMODE_EXECUTE, + ACPI_NS_SEARCH_PARENT, walk_state, + &(node)); + if (ACPI_FAILURE(status)) { +#ifdef ACPI_ASL_COMPILER + if (status == AE_NOT_FOUND) { + status = AE_OK; + } else { + ACPI_ERROR_NAMESPACE(buffer_ptr, + status); + } +#else + ACPI_ERROR_NAMESPACE(buffer_ptr, status); +#endif + return_ACPI_STATUS(status); + } + } + + /* + * We must check to make sure that the target is + * one of the opcodes that actually opens a scope + */ + switch (node->type) { + case ACPI_TYPE_ANY: + case ACPI_TYPE_LOCAL_SCOPE: /* Scope */ + case ACPI_TYPE_DEVICE: + case ACPI_TYPE_POWER: + case ACPI_TYPE_PROCESSOR: + case ACPI_TYPE_THERMAL: + + /* These are acceptable types */ + break; + + case ACPI_TYPE_INTEGER: + case ACPI_TYPE_STRING: + case ACPI_TYPE_BUFFER: + + /* + * These types we will allow, but we will change the type. + * This enables some existing code of the form: + * + * Name (DEB, 0) + * Scope (DEB) { ... } + */ + ACPI_WARNING((AE_INFO, + "Type override - [%4.4s] had invalid type (%s) " + "for Scope operator, changed to type ANY\n", + acpi_ut_get_node_name(node), + acpi_ut_get_type_name(node->type))); + + node->type = ACPI_TYPE_ANY; + walk_state->scope_info->common.value = ACPI_TYPE_ANY; + break; + + default: + + /* All other types are an error */ + + ACPI_ERROR((AE_INFO, + "Invalid type (%s) for target of " + "Scope operator [%4.4s] (Cannot override)", + acpi_ut_get_type_name(node->type), + acpi_ut_get_node_name(node))); + + return (AE_AML_OPERAND_TYPE); + } + break; + + default: + + /* All other opcodes */ + + if (op && op->common.node) { + + /* This op/node was previously entered into the namespace */ + + node = op->common.node; + + if (acpi_ns_opens_scope(object_type)) { + status = + acpi_ds_scope_stack_push(node, object_type, + walk_state); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + } + + return_ACPI_STATUS(AE_OK); + } + + /* + * Enter the named type into the internal namespace. We enter the name + * as we go downward in the parse tree. Any necessary subobjects that + * involve arguments to the opcode must be created as we go back up the + * parse tree later. + * + * Note: Name may already exist if we are executing a deferred opcode. + */ + if (walk_state->deferred_node) { + + /* This name is already in the namespace, get the node */ + + node = walk_state->deferred_node; + status = AE_OK; + break; + } + + flags = ACPI_NS_NO_UPSEARCH; + if (walk_state->pass_number == ACPI_IMODE_EXECUTE) { + + /* Execution mode, node cannot already exist, node is temporary */ + + flags |= ACPI_NS_ERROR_IF_FOUND; + + if (! + (walk_state-> + parse_flags & ACPI_PARSE_MODULE_LEVEL)) { + flags |= ACPI_NS_TEMPORARY; + } + } + + /* Add new entry or lookup existing entry */ + + status = + acpi_ns_lookup(walk_state->scope_info, buffer_ptr, + object_type, ACPI_IMODE_LOAD_PASS2, flags, + walk_state, &node); + + if (ACPI_SUCCESS(status) && (flags & ACPI_NS_TEMPORARY)) { + ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, + "***New Node [%4.4s] %p is temporary\n", + acpi_ut_get_node_name(node), node)); + } + break; + } + + if (ACPI_FAILURE(status)) { + ACPI_ERROR_NAMESPACE(buffer_ptr, status); + return_ACPI_STATUS(status); + } + + if (!op) { + + /* Create a new op */ + + op = acpi_ps_alloc_op(walk_state->opcode); + if (!op) { + return_ACPI_STATUS(AE_NO_MEMORY); + } + + /* Initialize the new op */ + + if (node) { + op->named.name = node->name.integer; + } + *out_op = op; + } + + /* + * Put the Node in the "op" object that the parser uses, so we + * can get it again quickly when this scope is closed + */ + op->common.node = node; + return_ACPI_STATUS(status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ds_load2_end_op + * + * PARAMETERS: walk_state - Current state of the parse tree walk + * + * RETURN: Status + * + * DESCRIPTION: Ascending callback used during the loading of the namespace, + * both control methods and everything else. + * + ******************************************************************************/ + +acpi_status acpi_ds_load2_end_op(struct acpi_walk_state *walk_state) +{ + union acpi_parse_object *op; + acpi_status status = AE_OK; + acpi_object_type object_type; + struct acpi_namespace_node *node; + union acpi_parse_object *arg; + struct acpi_namespace_node *new_node; +#ifndef ACPI_NO_METHOD_EXECUTION + u32 i; + u8 region_space; +#endif + + ACPI_FUNCTION_TRACE(ds_load2_end_op); + + op = walk_state->op; + ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "Opcode [%s] Op %p State %p\n", + walk_state->op_info->name, op, walk_state)); + + /* Check if opcode had an associated namespace object */ + + if (!(walk_state->op_info->flags & AML_NSOBJECT)) { + return_ACPI_STATUS(AE_OK); + } + + if (op->common.aml_opcode == AML_SCOPE_OP) { + ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, + "Ending scope Op=%p State=%p\n", op, + walk_state)); + } + + object_type = walk_state->op_info->object_type; + + /* + * Get the Node/name from the earlier lookup + * (It was saved in the *op structure) + */ + node = op->common.node; + + /* + * Put the Node on the object stack (Contains the ACPI Name of + * this object) + */ + walk_state->operands[0] = (void *)node; + walk_state->num_operands = 1; + + /* Pop the scope stack */ + + if (acpi_ns_opens_scope(object_type) && + (op->common.aml_opcode != AML_INT_METHODCALL_OP)) { + ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, + "(%s) Popping scope for Op %p\n", + acpi_ut_get_type_name(object_type), op)); + + status = acpi_ds_scope_stack_pop(walk_state); + if (ACPI_FAILURE(status)) { + goto cleanup; + } + } + + /* + * Named operations are as follows: + * + * AML_ALIAS + * AML_BANKFIELD + * AML_CREATEBITFIELD + * AML_CREATEBYTEFIELD + * AML_CREATEDWORDFIELD + * AML_CREATEFIELD + * AML_CREATEQWORDFIELD + * AML_CREATEWORDFIELD + * AML_DATA_REGION + * AML_DEVICE + * AML_EVENT + * AML_FIELD + * AML_INDEXFIELD + * AML_METHOD + * AML_METHODCALL + * AML_MUTEX + * AML_NAME + * AML_NAMEDFIELD + * AML_OPREGION + * AML_POWERRES + * AML_PROCESSOR + * AML_SCOPE + * AML_THERMALZONE + */ + + ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, + "Create-Load [%s] State=%p Op=%p NamedObj=%p\n", + acpi_ps_get_opcode_name(op->common.aml_opcode), + walk_state, op, node)); + + /* Decode the opcode */ + + arg = op->common.value.arg; + + switch (walk_state->op_info->type) { +#ifndef ACPI_NO_METHOD_EXECUTION + + case AML_TYPE_CREATE_FIELD: + /* + * Create the field object, but the field buffer and index must + * be evaluated later during the execution phase + */ + status = acpi_ds_create_buffer_field(op, walk_state); + break; + + case AML_TYPE_NAMED_FIELD: + /* + * If we are executing a method, initialize the field + */ + if (walk_state->method_node) { + status = acpi_ds_init_field_objects(op, walk_state); + } + + switch (op->common.aml_opcode) { + case AML_INDEX_FIELD_OP: + + status = + acpi_ds_create_index_field(op, + (acpi_handle) arg-> + common.node, walk_state); + break; + + case AML_BANK_FIELD_OP: + + status = + acpi_ds_create_bank_field(op, arg->common.node, + walk_state); + break; + + case AML_FIELD_OP: + + status = + acpi_ds_create_field(op, arg->common.node, + walk_state); + break; + + default: + /* All NAMED_FIELD opcodes must be handled above */ + break; + } + break; + + case AML_TYPE_NAMED_SIMPLE: + + status = acpi_ds_create_operands(walk_state, arg); + if (ACPI_FAILURE(status)) { + goto cleanup; + } + + switch (op->common.aml_opcode) { + case AML_PROCESSOR_OP: + + status = acpi_ex_create_processor(walk_state); + break; + + case AML_POWER_RES_OP: + + status = acpi_ex_create_power_resource(walk_state); + break; + + case AML_MUTEX_OP: + + status = acpi_ex_create_mutex(walk_state); + break; + + case AML_EVENT_OP: + + status = acpi_ex_create_event(walk_state); + break; + + case AML_ALIAS_OP: + + status = acpi_ex_create_alias(walk_state); + break; + + default: + /* Unknown opcode */ + + status = AE_OK; + goto cleanup; + } + + /* Delete operands */ + + for (i = 1; i < walk_state->num_operands; i++) { + acpi_ut_remove_reference(walk_state->operands[i]); + walk_state->operands[i] = NULL; + } + + break; +#endif /* ACPI_NO_METHOD_EXECUTION */ + + case AML_TYPE_NAMED_COMPLEX: + + switch (op->common.aml_opcode) { +#ifndef ACPI_NO_METHOD_EXECUTION + case AML_REGION_OP: + case AML_DATA_REGION_OP: + + if (op->common.aml_opcode == AML_REGION_OP) { + region_space = (acpi_adr_space_type) + ((op->common.value.arg)->common.value. + integer); + } else { + region_space = REGION_DATA_TABLE; + } + + /* + * The op_region is not fully parsed at this time. The only valid + * argument is the space_id. (We must save the address of the + * AML of the address and length operands) + * + * If we have a valid region, initialize it. The namespace is + * unlocked at this point. + * + * Need to unlock interpreter if it is locked (if we are running + * a control method), in order to allow _REG methods to be run + * during acpi_ev_initialize_region. + */ + if (walk_state->method_node) { + /* + * Executing a method: initialize the region and unlock + * the interpreter + */ + status = + acpi_ex_create_region(op->named.data, + op->named.length, + region_space, + walk_state); + if (ACPI_FAILURE(status)) { + return (status); + } + + acpi_ex_exit_interpreter(); + } + + status = + acpi_ev_initialize_region + (acpi_ns_get_attached_object(node), FALSE); + if (walk_state->method_node) { + acpi_ex_enter_interpreter(); + } + + if (ACPI_FAILURE(status)) { + /* + * If AE_NOT_EXIST is returned, it is not fatal + * because many regions get created before a handler + * is installed for said region. + */ + if (AE_NOT_EXIST == status) { + status = AE_OK; + } + } + break; + + case AML_NAME_OP: + + status = acpi_ds_create_node(walk_state, node, op); + break; + + case AML_METHOD_OP: + /* + * method_op pkg_length name_string method_flags term_list + * + * Note: We must create the method node/object pair as soon as we + * see the method declaration. This allows later pass1 parsing + * of invocations of the method (need to know the number of + * arguments.) + */ + ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, + "LOADING-Method: State=%p Op=%p NamedObj=%p\n", + walk_state, op, op->named.node)); + + if (!acpi_ns_get_attached_object(op->named.node)) { + walk_state->operands[0] = + ACPI_CAST_PTR(void, op->named.node); + walk_state->num_operands = 1; + + status = + acpi_ds_create_operands(walk_state, + op->common.value. + arg); + if (ACPI_SUCCESS(status)) { + status = + acpi_ex_create_method(op->named. + data, + op->named. + length, + walk_state); + } + walk_state->operands[0] = NULL; + walk_state->num_operands = 0; + + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + } + break; + +#endif /* ACPI_NO_METHOD_EXECUTION */ + + default: + /* All NAMED_COMPLEX opcodes must be handled above */ + break; + } + break; + + case AML_CLASS_INTERNAL: + + /* case AML_INT_NAMEPATH_OP: */ + break; + + case AML_CLASS_METHOD_CALL: + + ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, + "RESOLVING-MethodCall: State=%p Op=%p NamedObj=%p\n", + walk_state, op, node)); + + /* + * Lookup the method name and save the Node + */ + status = + acpi_ns_lookup(walk_state->scope_info, + arg->common.value.string, ACPI_TYPE_ANY, + ACPI_IMODE_LOAD_PASS2, + ACPI_NS_SEARCH_PARENT | + ACPI_NS_DONT_OPEN_SCOPE, walk_state, + &(new_node)); + if (ACPI_SUCCESS(status)) { + /* + * Make sure that what we found is indeed a method + * We didn't search for a method on purpose, to see if the name + * would resolve + */ + if (new_node->type != ACPI_TYPE_METHOD) { + status = AE_AML_OPERAND_TYPE; + } + + /* We could put the returned object (Node) on the object stack for + * later, but for now, we will put it in the "op" object that the + * parser uses, so we can get it again at the end of this scope + */ + op->common.node = new_node; + } else { + ACPI_ERROR_NAMESPACE(arg->common.value.string, status); + } + break; + + default: + break; + } + + cleanup: + + /* Remove the Node pushed at the very beginning */ + + walk_state->operands[0] = NULL; + walk_state->num_operands = 0; + return_ACPI_STATUS(status); +} -- GitLab From 47863b9cbec29f137b3a7718ec851be879b41137 Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Mon, 14 Feb 2011 16:11:43 +0800 Subject: [PATCH 0269/2822] ACPICA: Add support for FunctionalFixedHW in acpi_ut_get_region_name Was missing this region type. Signed-off-by: Bob Moore Signed-off-by: Lin Ming Signed-off-by: Len Brown --- drivers/acpi/acpica/utdecode.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/acpi/acpica/utdecode.c b/drivers/acpi/acpica/utdecode.c index ce91e59c449f3..136a814cec69d 100644 --- a/drivers/acpi/acpica/utdecode.c +++ b/drivers/acpi/acpica/utdecode.c @@ -179,6 +179,8 @@ char *acpi_ut_get_region_name(u8 space_id) if (space_id >= ACPI_USER_REGION_BEGIN) { return ("UserDefinedRegion"); + } else if (space_id == ACPI_ADR_SPACE_FIXED_HARDWARE) { + return ("FunctionalFixedHW"); } else if (space_id >= ACPI_NUM_PREDEFINED_REGIONS) { return ("InvalidSpaceId"); } -- GitLab From ef09c4f578147464524041cbe3205bb25f900598 Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Mon, 14 Feb 2011 16:13:25 +0800 Subject: [PATCH 0270/2822] ACPICA: Add mechanism to defer _REG methods for some installed handlers The memory/io/pci/dataTable regions must always be available. For any user installed handlers for these spaces, defer execution of _REG methods until acpi_enable_subsystem. This prevents any chicken/egg problems and ensures that no methods are executed until all of these regions are ready and available. Signed-off-by: Bob Moore Signed-off-by: Lin Ming Signed-off-by: Len Brown --- drivers/acpi/acpica/acglobal.h | 4 ++++ drivers/acpi/acpica/evregion.c | 2 ++ drivers/acpi/acpica/evxfregn.c | 34 ++++++++++++++++++++++++++++++++-- drivers/acpi/acpica/utglobal.c | 1 + 4 files changed, 39 insertions(+), 2 deletions(-) diff --git a/drivers/acpi/acpica/acglobal.h b/drivers/acpi/acpica/acglobal.h index 82a1bd283db84..d69750b83b365 100644 --- a/drivers/acpi/acpica/acglobal.h +++ b/drivers/acpi/acpica/acglobal.h @@ -273,6 +273,10 @@ ACPI_EXTERN u32 acpi_gbl_owner_id_mask[ACPI_NUM_OWNERID_MASKS]; ACPI_EXTERN u8 acpi_gbl_last_owner_id_index; ACPI_EXTERN u8 acpi_gbl_next_owner_id_offset; +/* Initialization sequencing */ + +ACPI_EXTERN u8 acpi_gbl_reg_methods_executed; + /* Misc */ ACPI_EXTERN u32 acpi_gbl_original_mode; diff --git a/drivers/acpi/acpica/evregion.c b/drivers/acpi/acpica/evregion.c index 785a5ee64585e..bea7223d7a710 100644 --- a/drivers/acpi/acpica/evregion.c +++ b/drivers/acpi/acpica/evregion.c @@ -231,6 +231,8 @@ acpi_status acpi_ev_initialize_op_regions(void) } } + acpi_gbl_reg_methods_executed = TRUE; + (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); return_ACPI_STATUS(status); } diff --git a/drivers/acpi/acpica/evxfregn.c b/drivers/acpi/acpica/evxfregn.c index eb73867637123..c85c8c45599d9 100644 --- a/drivers/acpi/acpica/evxfregn.c +++ b/drivers/acpi/acpica/evxfregn.c @@ -110,9 +110,39 @@ acpi_install_address_space_handler(acpi_handle device, goto unlock_and_exit; } - /* Run all _REG methods for this address space */ + /* + * For the default space_iDs, (the IDs for which there are default region handlers + * installed) Only execute the _REG methods if the global initialization _REG + * methods have already been run (via acpi_initialize_objects). In other words, + * we will defer the execution of the _REG methods for these space_iDs until + * execution of acpi_initialize_objects. This is done because we need the handlers + * for the default spaces (mem/io/pci/table) to be installed before we can run + * any control methods (or _REG methods). There is known BIOS code that depends + * on this. + * + * For all other space_iDs, we can safely execute the _REG methods immediately. + * This means that for IDs like embedded_controller, this function should be called + * only after acpi_enable_subsystem has been called. + */ + switch (space_id) { + case ACPI_ADR_SPACE_SYSTEM_MEMORY: + case ACPI_ADR_SPACE_SYSTEM_IO: + case ACPI_ADR_SPACE_PCI_CONFIG: + case ACPI_ADR_SPACE_DATA_TABLE: + + if (acpi_gbl_reg_methods_executed) { + + /* Run all _REG methods for this address space */ + + status = acpi_ev_execute_reg_methods(node, space_id); + } + break; + + default: - status = acpi_ev_execute_reg_methods(node, space_id); + status = acpi_ev_execute_reg_methods(node, space_id); + break; + } unlock_and_exit: (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); diff --git a/drivers/acpi/acpica/utglobal.c b/drivers/acpi/acpica/utglobal.c index fc90978215168..833a38a9c9052 100644 --- a/drivers/acpi/acpica/utglobal.c +++ b/drivers/acpi/acpica/utglobal.c @@ -323,6 +323,7 @@ acpi_status acpi_ut_init_globals(void) acpi_gbl_db_output_flags = ACPI_DB_CONSOLE_OUTPUT; acpi_gbl_osi_data = 0; acpi_gbl_osi_mutex = NULL; + acpi_gbl_reg_methods_executed = FALSE; /* Hardware oriented */ -- GitLab From 589c7a39ae2f2b74fd13ae344ca1dcca61da6bca Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Mon, 14 Feb 2011 16:15:21 +0800 Subject: [PATCH 0271/2822] ACPICA: Update version to 20110211. Version 20110211. Signed-off-by: Bob Moore Signed-off-by: Lin Ming Signed-off-by: Len Brown --- include/acpi/acpixf.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/acpi/acpixf.h b/include/acpi/acpixf.h index e46ec95a8adac..ec908540d3460 100644 --- a/include/acpi/acpixf.h +++ b/include/acpi/acpixf.h @@ -47,7 +47,7 @@ /* Current ACPICA subsystem version in YYYYMMDD format */ -#define ACPI_CA_VERSION 0x20110112 +#define ACPI_CA_VERSION 0x20110211 #include "actypes.h" #include "actbl.h" -- GitLab From 4fdfbe8506fa236f3c4cc915b24e70f84a6f768a Mon Sep 17 00:00:00 2001 From: Durgadoss R Date: Thu, 20 Jan 2011 02:40:56 +0530 Subject: [PATCH 0272/2822] Thermal_Framework-Fix_crash_during_hwmon_unregister This patch fixes the following bug: The thermal framework creates a temp*_crit interface, only when the get_crit_temp pointer is defined. But during the _unregister_ path, without checking for the function definition, it is trying to remove the temp*_crit interface. Signed-off-by: Durgadoss R Signed-off-by: Len Brown --- drivers/thermal/thermal_sys.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/thermal/thermal_sys.c b/drivers/thermal/thermal_sys.c index 713b7ea4a6070..fc6f2a5bde013 100644 --- a/drivers/thermal/thermal_sys.c +++ b/drivers/thermal/thermal_sys.c @@ -560,7 +560,8 @@ thermal_remove_hwmon_sysfs(struct thermal_zone_device *tz) tz->hwmon = NULL; device_remove_file(hwmon->device, &tz->temp_input.attr); - device_remove_file(hwmon->device, &tz->temp_crit.attr); + if (tz->ops->get_crit_temp) + device_remove_file(hwmon->device, &tz->temp_crit.attr); mutex_lock(&thermal_list_lock); list_del(&tz->hwmon_node); -- GitLab From 6430c9c12a7dbb8f60f0d8294b73b3c0bb03f64f Mon Sep 17 00:00:00 2001 From: Jan Beulich Date: Thu, 17 Feb 2011 16:33:53 +0000 Subject: [PATCH 0273/2822] ACPI: use __init where possible in processor driver Use __init for several functions, remove an unnecessary export and a stray use of __ref. Signed-off-by: Jan Beulich Signed-off-by: Len Brown --- drivers/acpi/processor_core.c | 9 ++++----- drivers/acpi/processor_driver.c | 4 ++-- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c index 3c1a2fec8cda7..ac77dde391994 100644 --- a/drivers/acpi/processor_core.c +++ b/drivers/acpi/processor_core.c @@ -19,7 +19,7 @@ #define _COMPONENT ACPI_PROCESSOR_COMPONENT ACPI_MODULE_NAME("processor_core"); -static int set_no_mwait(const struct dmi_system_id *id) +static int __init set_no_mwait(const struct dmi_system_id *id) { printk(KERN_NOTICE PREFIX "%s detected - " "disabling mwait for CPU C-states\n", id->ident); @@ -27,7 +27,7 @@ static int set_no_mwait(const struct dmi_system_id *id) return 0; } -static struct dmi_system_id __cpuinitdata processor_idle_dmi_table[] = { +static struct dmi_system_id __initdata processor_idle_dmi_table[] = { { set_no_mwait, "Extensa 5220", { DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"), @@ -183,7 +183,7 @@ int acpi_get_cpuid(acpi_handle handle, int type, u32 acpi_id) EXPORT_SYMBOL_GPL(acpi_get_cpuid); #endif -static bool processor_physically_present(acpi_handle handle) +static bool __init processor_physically_present(acpi_handle handle) { int cpuid, type; u32 acpi_id; @@ -323,9 +323,8 @@ void acpi_processor_set_pdc(acpi_handle handle) kfree(obj_list->pointer); kfree(obj_list); } -EXPORT_SYMBOL_GPL(acpi_processor_set_pdc); -static acpi_status +static acpi_status __init early_init_pdc(acpi_handle handle, u32 lvl, void *context, void **rv) { if (processor_physically_present(handle) == false) diff --git a/drivers/acpi/processor_driver.c b/drivers/acpi/processor_driver.c index 360a74e6add03..a4e0f1ba6040c 100644 --- a/drivers/acpi/processor_driver.c +++ b/drivers/acpi/processor_driver.c @@ -635,8 +635,8 @@ int acpi_processor_device_add(acpi_handle handle, struct acpi_device **device) return 0; } -static void __ref acpi_processor_hotplug_notify(acpi_handle handle, - u32 event, void *data) +static void acpi_processor_hotplug_notify(acpi_handle handle, + u32 event, void *data) { struct acpi_processor *pr; struct acpi_device *device = NULL; -- GitLab From af10f941ab7807d8b0bb3c66e679d8a6bbbe7485 Mon Sep 17 00:00:00 2001 From: Jan Beulich Date: Thu, 17 Feb 2011 16:36:24 +0000 Subject: [PATCH 0274/2822] ACPI: use __cpuinit for the acpi_processor_set_pdc() call tree Once acpi_map_lsapic() in ia64 follows how x86 treats it wrt section placement, the whole tree from acpi_processor_set_pdc() can become __cpuinit. Signed-off-by: Jan Beulich Acked-by: Tony Luck Signed-off-by: Len Brown --- arch/ia64/kernel/acpi.c | 9 +++++++-- drivers/acpi/processor_core.c | 8 ++++---- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/arch/ia64/kernel/acpi.c b/arch/ia64/kernel/acpi.c index 90ebceb899a08..522642d6a5030 100644 --- a/arch/ia64/kernel/acpi.c +++ b/arch/ia64/kernel/acpi.c @@ -803,7 +803,7 @@ int acpi_isa_irq_to_gsi(unsigned isa_irq, u32 *gsi) * ACPI based hotplug CPU support */ #ifdef CONFIG_ACPI_HOTPLUG_CPU -static +static __cpuinit int acpi_map_cpu2node(acpi_handle handle, int cpu, int physid) { #ifdef CONFIG_ACPI_NUMA @@ -878,7 +878,7 @@ __init void prefill_possible_map(void) set_cpu_possible(i, true); } -int acpi_map_lsapic(acpi_handle handle, int *pcpu) +static int __cpuinit _acpi_map_lsapic(acpi_handle handle, int *pcpu) { struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; union acpi_object *obj; @@ -929,6 +929,11 @@ int acpi_map_lsapic(acpi_handle handle, int *pcpu) return (0); } +/* wrapper to silence section mismatch warning */ +int __ref acpi_map_lsapic(acpi_handle handle, int *pcpu) +{ + return _acpi_map_lsapic(handle, pcpu); +} EXPORT_SYMBOL(acpi_map_lsapic); int acpi_unmap_lsapic(int cpu) diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c index ac77dde391994..25bf17da69fd8 100644 --- a/drivers/acpi/processor_core.c +++ b/drivers/acpi/processor_core.c @@ -223,7 +223,7 @@ static bool __init processor_physically_present(acpi_handle handle) return true; } -static void acpi_set_pdc_bits(u32 *buf) +static void __cpuinit acpi_set_pdc_bits(u32 *buf) { buf[0] = ACPI_PDC_REVISION_ID; buf[1] = 1; @@ -235,7 +235,7 @@ static void acpi_set_pdc_bits(u32 *buf) arch_acpi_set_pdc_bits(buf); } -static struct acpi_object_list *acpi_processor_alloc_pdc(void) +static struct acpi_object_list *__cpuinit acpi_processor_alloc_pdc(void) { struct acpi_object_list *obj_list; union acpi_object *obj; @@ -278,7 +278,7 @@ static struct acpi_object_list *acpi_processor_alloc_pdc(void) * _PDC is required for a BIOS-OS handshake for most of the newer * ACPI processor features. */ -static int +static int __cpuinit acpi_processor_eval_pdc(acpi_handle handle, struct acpi_object_list *pdc_in) { acpi_status status = AE_OK; @@ -306,7 +306,7 @@ acpi_processor_eval_pdc(acpi_handle handle, struct acpi_object_list *pdc_in) return status; } -void acpi_processor_set_pdc(acpi_handle handle) +void __cpuinit acpi_processor_set_pdc(acpi_handle handle) { struct acpi_object_list *obj_list; -- GitLab From 198868f35de99e7197829314076e5465c37e4cc5 Mon Sep 17 00:00:00 2001 From: Mingming Cao Date: Sat, 5 Mar 2011 11:52:45 -0500 Subject: [PATCH 0275/2822] ext4: Use single thread to perform DIO unwritten convertion While running ext4 testing on multiple core, we found there are per cpu ext4-dio-unwritten threads processing conversion from unwritten extents to written for IOs completed from async direct IO patch. Per filesystem is enough, we don't need per cpu threads to work on conversion. Signed-off-by: Mingming Cao --- fs/ext4/super.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/ext4/super.c b/fs/ext4/super.c index 9eaec22aa088e..b357c2700d726 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c @@ -3514,7 +3514,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) percpu_counter_set(&sbi->s_dirtyblocks_counter, 0); no_journal: - EXT4_SB(sb)->dio_unwritten_wq = create_workqueue("ext4-dio-unwritten"); + EXT4_SB(sb)->dio_unwritten_wq = create_singlethread_workqueue("ext4-dio-unwritten"); if (!EXT4_SB(sb)->dio_unwritten_wq) { printk(KERN_ERR "EXT4-fs: failed to create DIO workqueue\n"); goto failed_mount_wq; -- GitLab From f44ad7e91dd12bed0959b3e715f4f3ab84951a59 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Thu, 3 Mar 2011 15:47:14 +0530 Subject: [PATCH 0276/2822] dw_dmac: Remove compilation dependency from AVR32 and put on HAVE_CLK This driver will now be used in atleast two platforms AVR32 & ARM. And there is no actual hardware dependency of this driver over AVR32 or ARM. So this dependency can be removed altogether. Also dw_dmac driver uses clk framework and must have compilation dependency on HAVE_CLK Signed-off-by: Viresh Kumar Signed-off-by: Vinod Koul --- drivers/dma/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig index 76f6472ba315f..d700895cb40f1 100644 --- a/drivers/dma/Kconfig +++ b/drivers/dma/Kconfig @@ -82,7 +82,7 @@ config INTEL_IOP_ADMA config DW_DMAC tristate "Synopsys DesignWare AHB DMA support" - depends on AVR32 + depends on HAVE_CLK select DMA_ENGINE default y if CPU_AT32AP7000 help -- GitLab From cb689a706d17ef19a61735670ded60466dd015fa Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Thu, 3 Mar 2011 15:47:15 +0530 Subject: [PATCH 0277/2822] dw_dmac: Replace module_init() with subsys_initcall() In some cases users of dw_dmac are initialized before dw_dmac, and if they try to use dw_dmac, they simply fail. So its better we register init() routine of driver using subsys_initcall() instead of module_init(), so that dma driver is available at the earliest possible. Signed-off-by: Viresh Kumar Signed-off-by: Vinod Koul --- drivers/dma/dw_dmac.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/dma/dw_dmac.c b/drivers/dma/dw_dmac.c index 08dab3badad2d..064a1830a76b1 100644 --- a/drivers/dma/dw_dmac.c +++ b/drivers/dma/dw_dmac.c @@ -1455,7 +1455,7 @@ static int __init dw_init(void) { return platform_driver_probe(&dw_driver, dw_probe); } -module_init(dw_init); +subsys_initcall(dw_init); static void __exit dw_exit(void) { -- GitLab From f336e42f73d93b74fd21bf9176ee6c7ab8b195c5 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Thu, 3 Mar 2011 15:47:16 +0530 Subject: [PATCH 0278/2822] dw_dmac: Move single descriptor from dwc->queue to dwc->active_list in dwc_complete_all dwc_complete_all and other routines was removing all descriptors from dwc->queue and pushing them to dwc->active_list. Only one was required to be removed. Also we are calling dwc_dostart, once list is fixed. Signed-off-by: Viresh Kumar Signed-off-by: Vinod Koul --- drivers/dma/dw_dmac.c | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/drivers/dma/dw_dmac.c b/drivers/dma/dw_dmac.c index 064a1830a76b1..942b50f57f21e 100644 --- a/drivers/dma/dw_dmac.c +++ b/drivers/dma/dw_dmac.c @@ -87,11 +87,6 @@ static struct dw_desc *dwc_first_active(struct dw_dma_chan *dwc) return list_entry(dwc->active_list.next, struct dw_desc, desc_node); } -static struct dw_desc *dwc_first_queued(struct dw_dma_chan *dwc) -{ - return list_entry(dwc->queue.next, struct dw_desc, desc_node); -} - static struct dw_desc *dwc_desc_get(struct dw_dma_chan *dwc) { struct dw_desc *desc, *_desc; @@ -262,10 +257,11 @@ static void dwc_complete_all(struct dw_dma *dw, struct dw_dma_chan *dwc) * Submit queued descriptors ASAP, i.e. before we go through * the completed ones. */ - if (!list_empty(&dwc->queue)) - dwc_dostart(dwc, dwc_first_queued(dwc)); list_splice_init(&dwc->active_list, &list); - list_splice_init(&dwc->queue, &dwc->active_list); + if (!list_empty(&dwc->queue)) { + list_move(dwc->queue.next, &dwc->active_list); + dwc_dostart(dwc, dwc_first_active(dwc)); + } list_for_each_entry_safe(desc, _desc, &list, desc_node) dwc_descriptor_complete(dwc, desc); @@ -325,8 +321,8 @@ static void dwc_scan_descriptors(struct dw_dma *dw, struct dw_dma_chan *dwc) cpu_relax(); if (!list_empty(&dwc->queue)) { - dwc_dostart(dwc, dwc_first_queued(dwc)); - list_splice_init(&dwc->queue, &dwc->active_list); + list_move(dwc->queue.next, &dwc->active_list); + dwc_dostart(dwc, dwc_first_active(dwc)); } } @@ -352,7 +348,7 @@ static void dwc_handle_error(struct dw_dma *dw, struct dw_dma_chan *dwc) */ bad_desc = dwc_first_active(dwc); list_del_init(&bad_desc->desc_node); - list_splice_init(&dwc->queue, dwc->active_list.prev); + list_move(dwc->queue.next, dwc->active_list.prev); /* Clear the error flag and try to restart the controller */ dma_writel(dw, CLEAR.ERROR, dwc->mask); @@ -547,8 +543,8 @@ static dma_cookie_t dwc_tx_submit(struct dma_async_tx_descriptor *tx) if (list_empty(&dwc->active_list)) { dev_vdbg(chan2dev(tx->chan), "tx_submit: started %u\n", desc->txd.cookie); - dwc_dostart(dwc, desc); list_add_tail(&desc->desc_node, &dwc->active_list); + dwc_dostart(dwc, dwc_first_active(dwc)); } else { dev_vdbg(chan2dev(tx->chan), "tx_submit: queued %u\n", desc->txd.cookie); -- GitLab From 569432efa7975f5795efb8142134f5a098942381 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Thu, 3 Mar 2011 15:47:17 +0530 Subject: [PATCH 0279/2822] dw_dmac: Calling dwc_scan_descriptors from dwc_tx_status() after taking lock Lock must be taken before calling dwc_scan_descriptors, as this may access/modify shared data and queues. dwc_tx_status wasn't taking lock before calling this routine. This patch add code that takes lock before calling dwc_scan_descriptors. Signed-off-by: Viresh Kumar Signed-off-by: Vinod Koul --- drivers/dma/dw_dmac.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/dma/dw_dmac.c b/drivers/dma/dw_dmac.c index 942b50f57f21e..2b0d5e99ae714 100644 --- a/drivers/dma/dw_dmac.c +++ b/drivers/dma/dw_dmac.c @@ -836,7 +836,9 @@ dwc_tx_status(struct dma_chan *chan, ret = dma_async_is_complete(cookie, last_complete, last_used); if (ret != DMA_SUCCESS) { + spin_lock_bh(&dwc->lock); dwc_scan_descriptors(to_dw_dma(chan->device), dwc); + spin_unlock_bh(&dwc->lock); last_complete = dwc->completed; last_used = chan->cookie; -- GitLab From a02274564dd78f7edde3c9ff197ed44f2f8a5a81 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Thu, 3 Mar 2011 15:47:18 +0530 Subject: [PATCH 0280/2822] dw_dmac: Adding support for 64 bit access width for memcpy xfers Signed-off-by: Viresh Kumar Signed-off-by: Vinod Koul --- drivers/dma/dw_dmac.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/dma/dw_dmac.c b/drivers/dma/dw_dmac.c index 2b0d5e99ae714..e5d97bf9264af 100644 --- a/drivers/dma/dw_dmac.c +++ b/drivers/dma/dw_dmac.c @@ -583,7 +583,9 @@ dwc_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dest, dma_addr_t src, * We can be a lot more clever here, but this should take care * of the most common optimization. */ - if (!((src | dest | len) & 3)) + if (!((src | dest | len) & 7)) + src_width = dst_width = 3; + else if (!((src | dest | len) & 3)) src_width = dst_width = 2; else if (!((src | dest | len) & 1)) src_width = dst_width = 1; -- GitLab From 418e74070662e1ae7d9bb5202f773d35c9a7f05e Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Fri, 4 Mar 2011 15:42:50 +0530 Subject: [PATCH 0281/2822] dw_dmac: Change value of DWC_MAX_COUNT to 4095. Every descriptor can transfer a maximum count of 4095 (12 bits, in control reg), So we must have DWC_MAX_COUNT as 4095 instead of 2048. Signed-off-by: Viresh Kumar Signed-off-by: Vinod Koul --- drivers/dma/dw_dmac.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/dma/dw_dmac.c b/drivers/dma/dw_dmac.c index e5d97bf9264af..711ebe954f5b3 100644 --- a/drivers/dma/dw_dmac.c +++ b/drivers/dma/dw_dmac.c @@ -47,14 +47,13 @@ /* * This is configuration-dependent and usually a funny size like 4095. - * Let's round it down to the nearest power of two. * * Note that this is a transfer count, i.e. if we transfer 32-bit - * words, we can do 8192 bytes per descriptor. + * words, we can do 16380 bytes per descriptor. * * This parameter is also system-specific. */ -#define DWC_MAX_COUNT 2048U +#define DWC_MAX_COUNT 4095U /* * Number of descriptors to allocate for each channel. This should be -- GitLab From e518076ef8cb56adb558ff56ad5bfa0cd9f3abd9 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Thu, 3 Mar 2011 15:47:20 +0530 Subject: [PATCH 0282/2822] dw_dmac: Mark all tx_descriptors with DMA_CRTL_ACK after xfer finish dwc_desc_get checks all descriptors for DMA_CTRL_ACK before allocating them for transfers. And descriptors are not marked with DMA_CRTL_ACK after transfer finishes. Thus descriptor once used is not usable again. This patch marks descriptors with DMA_CRTL_ACK after dma xfer finishes Signed-off-by: Viresh Kumar Signed-off-by: Vinod Koul --- drivers/dma/dw_dmac.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/dma/dw_dmac.c b/drivers/dma/dw_dmac.c index 711ebe954f5b3..6ab440e532bf8 100644 --- a/drivers/dma/dw_dmac.c +++ b/drivers/dma/dw_dmac.c @@ -198,6 +198,7 @@ dwc_descriptor_complete(struct dw_dma_chan *dwc, struct dw_desc *desc) dma_async_tx_callback callback; void *param; struct dma_async_tx_descriptor *txd = &desc->txd; + struct dw_desc *child; dev_vdbg(chan2dev(&dwc->chan), "descriptor %u complete\n", txd->cookie); @@ -206,6 +207,12 @@ dwc_descriptor_complete(struct dw_dma_chan *dwc, struct dw_desc *desc) param = txd->callback_param; dwc_sync_desc_for_cpu(dwc, desc); + + /* async_tx_ack */ + list_for_each_entry(child, &desc->tx_list, desc_node) + async_tx_ack(&child->txd); + async_tx_ack(&desc->txd); + list_splice_init(&desc->tx_list, &dwc->free_list); list_move(&desc->desc_node, &dwc->free_list); -- GitLab From b0c3130d69bda5cd91aa3b3f08e7878df49fde69 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Thu, 3 Mar 2011 15:47:21 +0530 Subject: [PATCH 0283/2822] dw_dmac: Pass Channel Allocation Order from platform_data In SPEAr Platform channels 4-7 have more Fifo depth. So we must get better channel first. This patch introduces concept of channel allocation order in dw_dmac. If user doesn't pass anything or 0, than normal (ascending) channel allocation will follow, else channels will be allocated in descending order. Signed-off-by: Viresh Kumar Signed-off-by: Vinod Koul --- drivers/dma/dw_dmac.c | 6 +++++- include/linux/dw_dmac.h | 3 +++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/drivers/dma/dw_dmac.c b/drivers/dma/dw_dmac.c index 6ab440e532bf8..f413e123405a2 100644 --- a/drivers/dma/dw_dmac.c +++ b/drivers/dma/dw_dmac.c @@ -1319,7 +1319,11 @@ static int __init dw_probe(struct platform_device *pdev) dwc->chan.device = &dw->dma; dwc->chan.cookie = dwc->completed = 1; dwc->chan.chan_id = i; - list_add_tail(&dwc->chan.device_node, &dw->dma.channels); + if (pdata->chan_allocation_order == CHAN_ALLOCATION_ASCENDING) + list_add_tail(&dwc->chan.device_node, + &dw->dma.channels); + else + list_add(&dwc->chan.device_node, &dw->dma.channels); dwc->ch_regs = &__dw_regs(dw)->CHAN[i]; spin_lock_init(&dwc->lock); diff --git a/include/linux/dw_dmac.h b/include/linux/dw_dmac.h index deec66b37180c..a18c498984d91 100644 --- a/include/linux/dw_dmac.h +++ b/include/linux/dw_dmac.h @@ -22,6 +22,9 @@ struct dw_dma_platform_data { unsigned int nr_channels; bool is_private; +#define CHAN_ALLOCATION_ASCENDING 0 /* zero to seven */ +#define CHAN_ALLOCATION_DESCENDING 1 /* seven to zero */ + unsigned char chan_allocation_order; }; /** -- GitLab From 93317e8e35b77633d589fe0e132291195757d785 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Thu, 3 Mar 2011 15:47:22 +0530 Subject: [PATCH 0284/2822] dw_dmac: Pass Channel Priority from platform_data In Synopsys designware, channel priority is programmable. This patch adds support for passing channel priority through platform data. By default Ascending channel priority will be followed, i.e. channel 0 will get highest priority and channel 7 will get lowest. Signed-off-by: Viresh Kumar Signed-off-by: Vinod Koul --- drivers/dma/dw_dmac.c | 11 ++++++++++- drivers/dma/dw_dmac_regs.h | 3 +++ include/linux/dw_dmac.h | 4 +++- 3 files changed, 16 insertions(+), 2 deletions(-) diff --git a/drivers/dma/dw_dmac.c b/drivers/dma/dw_dmac.c index f413e123405a2..318a342fc7ece 100644 --- a/drivers/dma/dw_dmac.c +++ b/drivers/dma/dw_dmac.c @@ -901,8 +901,11 @@ static int dwc_alloc_chan_resources(struct dma_chan *chan) BUG_ON(!dws->dma_dev || dws->dma_dev != dw->dma.dev); cfghi = dws->cfg_hi; - cfglo = dws->cfg_lo; + cfglo = dws->cfg_lo & ~DWC_CFGL_CH_PRIOR_MASK; } + + cfglo |= DWC_CFGL_CH_PRIOR(dwc->priority); + channel_writel(dwc, CFG_LO, cfglo); channel_writel(dwc, CFG_HI, cfghi); @@ -1325,6 +1328,12 @@ static int __init dw_probe(struct platform_device *pdev) else list_add(&dwc->chan.device_node, &dw->dma.channels); + /* 7 is highest priority & 0 is lowest. */ + if (pdata->chan_priority == CHAN_PRIORITY_ASCENDING) + dwc->priority = 7 - i; + else + dwc->priority = i; + dwc->ch_regs = &__dw_regs(dw)->CHAN[i]; spin_lock_init(&dwc->lock); dwc->mask = 1 << i; diff --git a/drivers/dma/dw_dmac_regs.h b/drivers/dma/dw_dmac_regs.h index d9a939f67f461..6a8e6d35f3593 100644 --- a/drivers/dma/dw_dmac_regs.h +++ b/drivers/dma/dw_dmac_regs.h @@ -101,6 +101,8 @@ struct dw_dma_regs { #define DWC_CTLH_BLOCK_TS_MASK 0x00000fff /* Bitfields in CFG_LO. Platform-configurable bits are in */ +#define DWC_CFGL_CH_PRIOR_MASK (0x7 << 5) /* priority mask */ +#define DWC_CFGL_CH_PRIOR(x) ((x) << 5) /* priority */ #define DWC_CFGL_CH_SUSP (1 << 8) /* pause xfer */ #define DWC_CFGL_FIFO_EMPTY (1 << 9) /* pause xfer */ #define DWC_CFGL_HS_DST (1 << 10) /* handshake w/dst */ @@ -134,6 +136,7 @@ struct dw_dma_chan { struct dma_chan chan; void __iomem *ch_regs; u8 mask; + u8 priority; spinlock_t lock; diff --git a/include/linux/dw_dmac.h b/include/linux/dw_dmac.h index a18c498984d91..64c76da571efb 100644 --- a/include/linux/dw_dmac.h +++ b/include/linux/dw_dmac.h @@ -25,6 +25,9 @@ struct dw_dma_platform_data { #define CHAN_ALLOCATION_ASCENDING 0 /* zero to seven */ #define CHAN_ALLOCATION_DESCENDING 1 /* seven to zero */ unsigned char chan_allocation_order; +#define CHAN_PRIORITY_ASCENDING 0 /* chan0 highest */ +#define CHAN_PRIORITY_DESCENDING 1 /* chan7 highest */ + unsigned char chan_priority; }; /** @@ -70,7 +73,6 @@ struct dw_dma_slave { #define DWC_CFGH_DST_PER(x) ((x) << 11) /* Platform-configurable bits in CFG_LO */ -#define DWC_CFGL_PRIO(x) ((x) << 5) /* priority */ #define DWC_CFGL_LOCK_CH_XFER (0 << 12) /* scope of LOCK_CH */ #define DWC_CFGL_LOCK_CH_BLOCK (1 << 12) #define DWC_CFGL_LOCK_CH_XACT (2 << 12) -- GitLab From 59c22fc11d12b69da36c6585a38229863ba0bb16 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Thu, 3 Mar 2011 15:47:23 +0530 Subject: [PATCH 0285/2822] dw_dmac: Changing type of src_master and dest_master to u8. src_master & dest_master don't required u32 as they have values limited to u8 only. Also their description is missing from doc style comment. This patch fixes above mentioned issues. Signed-off-by: Viresh Kumar Signed-off-by: Vinod Koul --- include/linux/dw_dmac.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/include/linux/dw_dmac.h b/include/linux/dw_dmac.h index 64c76da571efb..3ba2f066ff46f 100644 --- a/include/linux/dw_dmac.h +++ b/include/linux/dw_dmac.h @@ -53,6 +53,8 @@ enum dw_dma_slave_width { * @reg_width: peripheral register width * @cfg_hi: Platform-specific initializer for the CFG_HI register * @cfg_lo: Platform-specific initializer for the CFG_LO register + * @src_master: src master for transfers on allocated channel. + * @dst_master: dest master for transfers on allocated channel. */ struct dw_dma_slave { struct device *dma_dev; @@ -61,8 +63,8 @@ struct dw_dma_slave { enum dw_dma_slave_width reg_width; u32 cfg_hi; u32 cfg_lo; - int src_master; - int dst_master; + u8 src_master; + u8 dst_master; }; /* Platform-configurable bits in CFG_HI */ -- GitLab From ee66509d7f354eecb45ac99f21ea6aa8650dea7e Mon Sep 17 00:00:00 2001 From: Viresh KUMAR Date: Fri, 4 Mar 2011 15:42:51 +0530 Subject: [PATCH 0286/2822] dw_dmac: Allow src/dst msize & flow controller to be configured at runtime Msize or Burst Size is peripheral dependent in case of prep_slave_sg and cyclic_prep transfers, and in case of memcpy transfers it is platform dependent. So msize configuration must come from platform data. Also some peripherals (ex: JPEG), need to be flow controller for dma transfers, so this information in case of slave_sg & cyclic_prep transfers must come from platform data. Signed-off-by: Viresh Kumar Signed-off-by: Vinod Koul --- drivers/dma/dw_dmac.c | 14 ++++++++------ drivers/dma/dw_dmac_regs.h | 1 + include/linux/dw_dmac.h | 30 ++++++++++++++++++++++++++++++ 3 files changed, 39 insertions(+), 6 deletions(-) diff --git a/drivers/dma/dw_dmac.c b/drivers/dma/dw_dmac.c index 318a342fc7ece..90ea08a53d626 100644 --- a/drivers/dma/dw_dmac.c +++ b/drivers/dma/dw_dmac.c @@ -36,9 +36,11 @@ struct dw_dma_slave *__slave = (private); \ int dms = __slave ? __slave->dst_master : 0; \ int sms = __slave ? __slave->src_master : 1; \ + u8 smsize = __slave ? __slave->src_msize : 0; \ + u8 dmsize = __slave ? __slave->dst_msize : 0; \ \ - (DWC_CTLL_DST_MSIZE(0) \ - | DWC_CTLL_SRC_MSIZE(0) \ + (DWC_CTLL_DST_MSIZE(dmsize) \ + | DWC_CTLL_SRC_MSIZE(smsize) \ | DWC_CTLL_LLP_D_EN \ | DWC_CTLL_LLP_S_EN \ | DWC_CTLL_DMS(dms) \ @@ -683,7 +685,7 @@ dwc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, | DWC_CTLL_DST_WIDTH(reg_width) | DWC_CTLL_DST_FIX | DWC_CTLL_SRC_INC - | DWC_CTLL_FC_M2P); + | DWC_CTLL_FC(dws->fc)); reg = dws->tx_reg; for_each_sg(sgl, sg, sg_len, i) { struct dw_desc *desc; @@ -728,7 +730,7 @@ dwc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, | DWC_CTLL_SRC_WIDTH(reg_width) | DWC_CTLL_DST_INC | DWC_CTLL_SRC_FIX - | DWC_CTLL_FC_P2M); + | DWC_CTLL_FC(dws->fc)); reg = dws->rx_reg; for_each_sg(sgl, sg, sg_len, i) { @@ -1146,7 +1148,7 @@ struct dw_cyclic_desc *dw_dma_cyclic_prep(struct dma_chan *chan, | DWC_CTLL_SRC_WIDTH(reg_width) | DWC_CTLL_DST_FIX | DWC_CTLL_SRC_INC - | DWC_CTLL_FC_M2P + | DWC_CTLL_FC(dws->fc) | DWC_CTLL_INT_EN); break; case DMA_FROM_DEVICE: @@ -1157,7 +1159,7 @@ struct dw_cyclic_desc *dw_dma_cyclic_prep(struct dma_chan *chan, | DWC_CTLL_DST_WIDTH(reg_width) | DWC_CTLL_DST_INC | DWC_CTLL_SRC_FIX - | DWC_CTLL_FC_P2M + | DWC_CTLL_FC(dws->fc) | DWC_CTLL_INT_EN); break; default: diff --git a/drivers/dma/dw_dmac_regs.h b/drivers/dma/dw_dmac_regs.h index 6a8e6d35f3593..9a32964bf795f 100644 --- a/drivers/dma/dw_dmac_regs.h +++ b/drivers/dma/dw_dmac_regs.h @@ -86,6 +86,7 @@ struct dw_dma_regs { #define DWC_CTLL_SRC_MSIZE(n) ((n)<<14) #define DWC_CTLL_S_GATH_EN (1 << 17) /* src gather, !FIX */ #define DWC_CTLL_D_SCAT_EN (1 << 18) /* dst scatter, !FIX */ +#define DWC_CTLL_FC(n) ((n) << 20) #define DWC_CTLL_FC_M2M (0 << 20) /* mem-to-mem */ #define DWC_CTLL_FC_M2P (1 << 20) /* mem-to-periph */ #define DWC_CTLL_FC_P2M (2 << 20) /* periph-to-mem */ diff --git a/include/linux/dw_dmac.h b/include/linux/dw_dmac.h index 3ba2f066ff46f..6998d9376ef90 100644 --- a/include/linux/dw_dmac.h +++ b/include/linux/dw_dmac.h @@ -42,6 +42,30 @@ enum dw_dma_slave_width { DW_DMA_SLAVE_WIDTH_32BIT, }; +/* bursts size */ +enum dw_dma_msize { + DW_DMA_MSIZE_1, + DW_DMA_MSIZE_4, + DW_DMA_MSIZE_8, + DW_DMA_MSIZE_16, + DW_DMA_MSIZE_32, + DW_DMA_MSIZE_64, + DW_DMA_MSIZE_128, + DW_DMA_MSIZE_256, +}; + +/* flow controller */ +enum dw_dma_fc { + DW_DMA_FC_D_M2M, + DW_DMA_FC_D_M2P, + DW_DMA_FC_D_P2M, + DW_DMA_FC_D_P2P, + DW_DMA_FC_P_P2M, + DW_DMA_FC_SP_P2P, + DW_DMA_FC_P_M2P, + DW_DMA_FC_DP_P2P, +}; + /** * struct dw_dma_slave - Controller-specific information about a slave * @@ -55,6 +79,9 @@ enum dw_dma_slave_width { * @cfg_lo: Platform-specific initializer for the CFG_LO register * @src_master: src master for transfers on allocated channel. * @dst_master: dest master for transfers on allocated channel. + * @src_msize: src burst size. + * @dst_msize: dest burst size. + * @fc: flow controller for DMA transfer */ struct dw_dma_slave { struct device *dma_dev; @@ -65,6 +92,9 @@ struct dw_dma_slave { u32 cfg_lo; u8 src_master; u8 dst_master; + u8 src_msize; + u8 dst_msize; + u8 fc; }; /* Platform-configurable bits in CFG_HI */ -- GitLab From e51dc53b8c7fa2d9ac4ef8f317f5dfe07a79e65a Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Thu, 3 Mar 2011 15:47:25 +0530 Subject: [PATCH 0287/2822] dw_dmac: Setting Default Burst length for transfers as 16. This patch sets default Burst length for all transfer to 16. This will enhance performance when user doesn't have any chan->private data. Signed-off-by: Viresh Kumar Signed-off-by: Vinod Koul --- drivers/dma/dw_dmac.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/dma/dw_dmac.c b/drivers/dma/dw_dmac.c index 90ea08a53d626..9c25c7d099e49 100644 --- a/drivers/dma/dw_dmac.c +++ b/drivers/dma/dw_dmac.c @@ -36,8 +36,8 @@ struct dw_dma_slave *__slave = (private); \ int dms = __slave ? __slave->dst_master : 0; \ int sms = __slave ? __slave->src_master : 1; \ - u8 smsize = __slave ? __slave->src_msize : 0; \ - u8 dmsize = __slave ? __slave->dst_msize : 0; \ + u8 smsize = __slave ? __slave->src_msize : DW_DMA_MSIZE_16; \ + u8 dmsize = __slave ? __slave->dst_msize : DW_DMA_MSIZE_16; \ \ (DWC_CTLL_DST_MSIZE(dmsize) \ | DWC_CTLL_SRC_MSIZE(smsize) \ -- GitLab From 1c5b0538c719f52cface39f699fb5d39a50149d6 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Thu, 3 Mar 2011 15:47:26 +0530 Subject: [PATCH 0288/2822] avr32: at32ap700x: Specify DMA Flow Controller, Src and Dst msize Now that the dw_dmac DMA driver supports configurable Flow Controller, source and destination burst or msize, we need to specify which ones to use. Msize or burst size was previously hardcoded to 1, Flow controller was DMA for both M2P & P2M transfers. Signed-off-by: Viresh Kumar Signed-off-by: Vinod Koul --- arch/avr32/mach-at32ap/at32ap700x.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/arch/avr32/mach-at32ap/at32ap700x.c b/arch/avr32/mach-at32ap/at32ap700x.c index 2747cde8c9a71..b4aaebd8780c2 100644 --- a/arch/avr32/mach-at32ap/at32ap700x.c +++ b/arch/avr32/mach-at32ap/at32ap700x.c @@ -2050,6 +2050,9 @@ at32_add_device_ac97c(unsigned int id, struct ac97c_platform_data *data, rx_dws->cfg_lo &= ~(DWC_CFGL_HS_DST_POL | DWC_CFGL_HS_SRC_POL); rx_dws->src_master = 0; rx_dws->dst_master = 1; + rx_dws->src_msize = DW_DMA_MSIZE_1; + rx_dws->dst_msize = DW_DMA_MSIZE_1; + rx_dws->fc = DW_DMA_FC_D_P2M; } /* Check if DMA slave interface for playback should be configured. */ @@ -2060,6 +2063,9 @@ at32_add_device_ac97c(unsigned int id, struct ac97c_platform_data *data, tx_dws->cfg_lo &= ~(DWC_CFGL_HS_DST_POL | DWC_CFGL_HS_SRC_POL); rx_dws->src_master = 0; rx_dws->dst_master = 1; + tx_dws->src_msize = DW_DMA_MSIZE_1; + tx_dws->dst_msize = DW_DMA_MSIZE_1; + tx_dws->fc = DW_DMA_FC_D_M2P; } if (platform_device_add_data(pdev, data, @@ -2134,6 +2140,9 @@ at32_add_device_abdac(unsigned int id, struct atmel_abdac_pdata *data) dws->cfg_lo &= ~(DWC_CFGL_HS_DST_POL | DWC_CFGL_HS_SRC_POL); dws->src_master = 0; dws->dst_master = 1; + dws->src_msize = DW_DMA_MSIZE_1; + dws->dst_msize = DW_DMA_MSIZE_1; + dws->fc = DW_DMA_FC_D_M2P; if (platform_device_add_data(pdev, data, sizeof(struct atmel_abdac_pdata))) -- GitLab From 29782da5f0206335e2325508ba4fee0d624ddab6 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Fri, 4 Mar 2011 14:58:32 +0530 Subject: [PATCH 0289/2822] dmaengine/dw_dmac fix: use readl & writel instead of __raw_readl & __raw_writel On ARMv7 cores, device memory mapped as Normal Non-cacheable, may not guarantee ordered access causing failures in device drivers that do not use the mandatory memory barriers. readl & writel versions contain necessary memory barriers for this. commit 79f64dbf68c8a9779a7e9a25e0a9f0217a25b57a: "ARM: 6273/1: Add barriers to the I/O accessors if ARM_DMA_MEM_BUFFERABLE" can be referred for more information on this. Signed-off-by: Viresh Kumar Signed-off-by: Vinod Koul --- drivers/dma/dw_dmac_regs.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/dma/dw_dmac_regs.h b/drivers/dma/dw_dmac_regs.h index 9a32964bf795f..720f821527f8a 100644 --- a/drivers/dma/dw_dmac_regs.h +++ b/drivers/dma/dw_dmac_regs.h @@ -159,9 +159,9 @@ __dwc_regs(struct dw_dma_chan *dwc) } #define channel_readl(dwc, name) \ - __raw_readl(&(__dwc_regs(dwc)->name)) + readl(&(__dwc_regs(dwc)->name)) #define channel_writel(dwc, name, val) \ - __raw_writel((val), &(__dwc_regs(dwc)->name)) + writel((val), &(__dwc_regs(dwc)->name)) static inline struct dw_dma_chan *to_dw_dma_chan(struct dma_chan *chan) { @@ -185,9 +185,9 @@ static inline struct dw_dma_regs __iomem *__dw_regs(struct dw_dma *dw) } #define dma_readl(dw, name) \ - __raw_readl(&(__dw_regs(dw)->name)) + readl(&(__dw_regs(dw)->name)) #define dma_writel(dw, name, val) \ - __raw_writel((val), &(__dw_regs(dw)->name)) + writel((val), &(__dw_regs(dw)->name)) #define channel_set_bit(dw, reg, mask) \ dma_writel(dw, reg, ((mask) << 8) | (mask)) -- GitLab From 0b863b333f529c7ddd8bee58e6696a7254417a05 Mon Sep 17 00:00:00 2001 From: Rakib Mullick Date: Sun, 6 Mar 2011 17:26:10 +0600 Subject: [PATCH 0290/2822] drivers, pch_dma: Fix warning when CONFIG_PM=n. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When CONFIG_PM=n, we get the following warning: drivers/dma/pch_dma.c:741: warning: ‘pch_dma_suspend’ defined but not used drivers/dma/pch_dma.c:755: warning: ‘pch_dma_resume’ defined but not used To fix it, wrap pch_dma_{suspend,resume} and pch_dma_{save,restore}_regs functions with CONFIG_PM. Signed-off-by: Rakib Mullick Signed-off-by: Vinod Koul --- drivers/dma/pch_dma.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/dma/pch_dma.c b/drivers/dma/pch_dma.c index b1dfba7e37b4e..8d8fef1480a93 100644 --- a/drivers/dma/pch_dma.c +++ b/drivers/dma/pch_dma.c @@ -693,6 +693,7 @@ static irqreturn_t pd_irq(int irq, void *devid) return ret; } +#ifdef CONFIG_PM static void pch_dma_save_regs(struct pch_dma *pd) { struct pch_dma_chan *pd_chan; @@ -770,6 +771,7 @@ static int pch_dma_resume(struct pci_dev *pdev) return 0; } +#endif static int __devinit pch_dma_probe(struct pci_dev *pdev, const struct pci_device_id *id) -- GitLab From 4f10700a2e4bb2ff3d3a80f08412e21109e6d4b5 Mon Sep 17 00:00:00 2001 From: Dave Chinner Date: Mon, 7 Mar 2011 10:00:35 +1100 Subject: [PATCH 0291/2822] xfs: Convert linux-2.6/ files to new logging interface Convert the files in fs/xfs/linux-2.6/ to use the new xfs_ logging format that replaces the old Irix inherited cmn_err() interfaces. While there, also convert naked printk calls to use the relevant xfs logging function to standardise output format. Signed-off-by: Dave Chinner Reviewed-by: Alex Elder Reviewed-by: Christoph Hellwig --- fs/xfs/linux-2.6/kmem.c | 9 +-- fs/xfs/linux-2.6/xfs_aops.c | 6 +- fs/xfs/linux-2.6/xfs_buf.c | 17 +++-- fs/xfs/linux-2.6/xfs_super.c | 127 +++++++++++++++------------------- fs/xfs/linux-2.6/xfs_sync.c | 5 +- fs/xfs/linux-2.6/xfs_sysctl.c | 2 +- 6 files changed, 76 insertions(+), 90 deletions(-) diff --git a/fs/xfs/linux-2.6/kmem.c b/fs/xfs/linux-2.6/kmem.c index 666c9db48eb63..a907de565db3b 100644 --- a/fs/xfs/linux-2.6/kmem.c +++ b/fs/xfs/linux-2.6/kmem.c @@ -23,6 +23,7 @@ #include #include "time.h" #include "kmem.h" +#include "xfs_message.h" /* * Greedy allocation. May fail and may return vmalloced memory. @@ -56,8 +57,8 @@ kmem_alloc(size_t size, unsigned int __nocast flags) if (ptr || (flags & (KM_MAYFAIL|KM_NOSLEEP))) return ptr; if (!(++retries % 100)) - printk(KERN_ERR "XFS: possible memory allocation " - "deadlock in %s (mode:0x%x)\n", + xfs_err(NULL, + "possible memory allocation deadlock in %s (mode:0x%x)", __func__, lflags); congestion_wait(BLK_RW_ASYNC, HZ/50); } while (1); @@ -112,8 +113,8 @@ kmem_zone_alloc(kmem_zone_t *zone, unsigned int __nocast flags) if (ptr || (flags & (KM_MAYFAIL|KM_NOSLEEP))) return ptr; if (!(++retries % 100)) - printk(KERN_ERR "XFS: possible memory allocation " - "deadlock in %s (mode:0x%x)\n", + xfs_err(NULL, + "possible memory allocation deadlock in %s (mode:0x%x)", __func__, lflags); congestion_wait(BLK_RW_ASYNC, HZ/50); } while (1); diff --git a/fs/xfs/linux-2.6/xfs_aops.c b/fs/xfs/linux-2.6/xfs_aops.c index ec7bbb5645b63..8c5c872774560 100644 --- a/fs/xfs/linux-2.6/xfs_aops.c +++ b/fs/xfs/linux-2.6/xfs_aops.c @@ -854,7 +854,7 @@ xfs_aops_discard_page( if (XFS_FORCED_SHUTDOWN(ip->i_mount)) goto out_invalidate; - xfs_fs_cmn_err(CE_ALERT, ip->i_mount, + xfs_alert(ip->i_mount, "page discard on page %p, inode 0x%llx, offset %llu.", page, ip->i_ino, offset); @@ -872,7 +872,7 @@ xfs_aops_discard_page( if (error) { /* something screwed, just bail */ if (!XFS_FORCED_SHUTDOWN(ip->i_mount)) { - xfs_fs_cmn_err(CE_ALERT, ip->i_mount, + xfs_alert(ip->i_mount, "page discard unable to remove delalloc mapping."); } break; @@ -1411,7 +1411,7 @@ xfs_vm_write_failed( if (error) { /* something screwed, just bail */ if (!XFS_FORCED_SHUTDOWN(ip->i_mount)) { - xfs_fs_cmn_err(CE_ALERT, ip->i_mount, + xfs_alert(ip->i_mount, "xfs_vm_write_failed: unable to clean up ino %lld", ip->i_ino); } diff --git a/fs/xfs/linux-2.6/xfs_buf.c b/fs/xfs/linux-2.6/xfs_buf.c index ac1c7e8378ddd..3cc671c8a67f4 100644 --- a/fs/xfs/linux-2.6/xfs_buf.c +++ b/fs/xfs/linux-2.6/xfs_buf.c @@ -401,9 +401,8 @@ _xfs_buf_lookup_pages( * handle buffer allocation failures we can't do much. */ if (!(++retries % 100)) - printk(KERN_ERR - "XFS: possible memory allocation " - "deadlock in %s (mode:0x%x)\n", + xfs_err(NULL, + "possible memory allocation deadlock in %s (mode:0x%x)", __func__, gfp_mask); XFS_STATS_INC(xb_page_retries); @@ -615,8 +614,8 @@ xfs_buf_get( if (!(bp->b_flags & XBF_MAPPED)) { error = _xfs_buf_map_pages(bp, flags); if (unlikely(error)) { - printk(KERN_WARNING "%s: failed to map pages\n", - __func__); + xfs_warn(target->bt_mount, + "%s: failed to map pages\n", __func__); goto no_buffer; } } @@ -850,8 +849,8 @@ xfs_buf_get_uncached( error = _xfs_buf_map_pages(bp, XBF_MAPPED); if (unlikely(error)) { - printk(KERN_WARNING "%s: failed to map pages\n", - __func__); + xfs_warn(target->bt_mount, + "%s: failed to map pages\n", __func__); goto fail_free_mem; } @@ -1617,8 +1616,8 @@ xfs_setsize_buftarg_flags( btp->bt_smask = sectorsize - 1; if (set_blocksize(btp->bt_bdev, sectorsize)) { - printk(KERN_WARNING - "XFS: Cannot set_blocksize to %u on device %s\n", + xfs_warn(btp->bt_mount, + "Cannot set_blocksize to %u on device %s\n", sectorsize, XFS_BUFTARG_NAME(btp)); return EINVAL; } diff --git a/fs/xfs/linux-2.6/xfs_super.c b/fs/xfs/linux-2.6/xfs_super.c index 7ec1fb8c13164..818c4cf2de863 100644 --- a/fs/xfs/linux-2.6/xfs_super.c +++ b/fs/xfs/linux-2.6/xfs_super.c @@ -172,6 +172,15 @@ xfs_parseargs( int iosize = 0; __uint8_t iosizelog = 0; + /* + * set up the mount name first so all the errors will refer to the + * correct device. + */ + mp->m_fsname = kstrndup(sb->s_id, MAXNAMELEN, GFP_KERNEL); + if (!mp->m_fsname) + return ENOMEM; + mp->m_fsname_len = strlen(mp->m_fsname) + 1; + /* * Copy binary VFS mount flags we are interested in. */ @@ -208,24 +217,21 @@ xfs_parseargs( if (!strcmp(this_char, MNTOPT_LOGBUFS)) { if (!value || !*value) { - cmn_err(CE_WARN, - "XFS: %s option requires an argument", + xfs_warn(mp, "%s option requires an argument", this_char); return EINVAL; } mp->m_logbufs = simple_strtoul(value, &eov, 10); } else if (!strcmp(this_char, MNTOPT_LOGBSIZE)) { if (!value || !*value) { - cmn_err(CE_WARN, - "XFS: %s option requires an argument", + xfs_warn(mp, "%s option requires an argument", this_char); return EINVAL; } mp->m_logbsize = suffix_strtoul(value, &eov, 10); } else if (!strcmp(this_char, MNTOPT_LOGDEV)) { if (!value || !*value) { - cmn_err(CE_WARN, - "XFS: %s option requires an argument", + xfs_warn(mp, "%s option requires an argument", this_char); return EINVAL; } @@ -233,14 +239,12 @@ xfs_parseargs( if (!mp->m_logname) return ENOMEM; } else if (!strcmp(this_char, MNTOPT_MTPT)) { - cmn_err(CE_WARN, - "XFS: %s option not allowed on this system", + xfs_warn(mp, "%s option not allowed on this system", this_char); return EINVAL; } else if (!strcmp(this_char, MNTOPT_RTDEV)) { if (!value || !*value) { - cmn_err(CE_WARN, - "XFS: %s option requires an argument", + xfs_warn(mp, "%s option requires an argument", this_char); return EINVAL; } @@ -249,8 +253,7 @@ xfs_parseargs( return ENOMEM; } else if (!strcmp(this_char, MNTOPT_BIOSIZE)) { if (!value || !*value) { - cmn_err(CE_WARN, - "XFS: %s option requires an argument", + xfs_warn(mp, "%s option requires an argument", this_char); return EINVAL; } @@ -258,8 +261,7 @@ xfs_parseargs( iosizelog = ffs(iosize) - 1; } else if (!strcmp(this_char, MNTOPT_ALLOCSIZE)) { if (!value || !*value) { - cmn_err(CE_WARN, - "XFS: %s option requires an argument", + xfs_warn(mp, "%s option requires an argument", this_char); return EINVAL; } @@ -281,16 +283,14 @@ xfs_parseargs( mp->m_flags |= XFS_MOUNT_SWALLOC; } else if (!strcmp(this_char, MNTOPT_SUNIT)) { if (!value || !*value) { - cmn_err(CE_WARN, - "XFS: %s option requires an argument", + xfs_warn(mp, "%s option requires an argument", this_char); return EINVAL; } dsunit = simple_strtoul(value, &eov, 10); } else if (!strcmp(this_char, MNTOPT_SWIDTH)) { if (!value || !*value) { - cmn_err(CE_WARN, - "XFS: %s option requires an argument", + xfs_warn(mp, "%s option requires an argument", this_char); return EINVAL; } @@ -298,8 +298,7 @@ xfs_parseargs( } else if (!strcmp(this_char, MNTOPT_64BITINODE)) { mp->m_flags &= ~XFS_MOUNT_SMALL_INUMS; #if !XFS_BIG_INUMS - cmn_err(CE_WARN, - "XFS: %s option not allowed on this system", + xfs_warn(mp, "%s option not allowed on this system", this_char); return EINVAL; #endif @@ -357,20 +356,19 @@ xfs_parseargs( } else if (!strcmp(this_char, MNTOPT_NODELAYLOG)) { mp->m_flags &= ~XFS_MOUNT_DELAYLOG; } else if (!strcmp(this_char, "ihashsize")) { - cmn_err(CE_WARN, - "XFS: ihashsize no longer used, option is deprecated."); + xfs_warn(mp, + "ihashsize no longer used, option is deprecated."); } else if (!strcmp(this_char, "osyncisdsync")) { - cmn_err(CE_WARN, - "XFS: osyncisdsync has no effect, option is deprecated."); + xfs_warn(mp, + "osyncisdsync has no effect, option is deprecated."); } else if (!strcmp(this_char, "osyncisosync")) { - cmn_err(CE_WARN, - "XFS: osyncisosync has no effect, option is deprecated."); + xfs_warn(mp, + "osyncisosync has no effect, option is deprecated."); } else if (!strcmp(this_char, "irixsgid")) { - cmn_err(CE_WARN, - "XFS: irixsgid is now a sysctl(2) variable, option is deprecated."); + xfs_warn(mp, + "irixsgid is now a sysctl(2) variable, option is deprecated."); } else { - cmn_err(CE_WARN, - "XFS: unknown mount option [%s].", this_char); + xfs_warn(mp, "unknown mount option [%s].", this_char); return EINVAL; } } @@ -380,40 +378,37 @@ xfs_parseargs( */ if ((mp->m_flags & XFS_MOUNT_NORECOVERY) && !(mp->m_flags & XFS_MOUNT_RDONLY)) { - cmn_err(CE_WARN, "XFS: no-recovery mounts must be read-only."); + xfs_warn(mp, "no-recovery mounts must be read-only."); return EINVAL; } if ((mp->m_flags & XFS_MOUNT_NOALIGN) && (dsunit || dswidth)) { - cmn_err(CE_WARN, - "XFS: sunit and swidth options incompatible with the noalign option"); + xfs_warn(mp, + "sunit and swidth options incompatible with the noalign option"); return EINVAL; } #ifndef CONFIG_XFS_QUOTA if (XFS_IS_QUOTA_RUNNING(mp)) { - cmn_err(CE_WARN, - "XFS: quota support not available in this kernel."); + xfs_warn(mp, "quota support not available in this kernel."); return EINVAL; } #endif if ((mp->m_qflags & (XFS_GQUOTA_ACCT | XFS_GQUOTA_ACTIVE)) && (mp->m_qflags & (XFS_PQUOTA_ACCT | XFS_PQUOTA_ACTIVE))) { - cmn_err(CE_WARN, - "XFS: cannot mount with both project and group quota"); + xfs_warn(mp, "cannot mount with both project and group quota"); return EINVAL; } if ((dsunit && !dswidth) || (!dsunit && dswidth)) { - cmn_err(CE_WARN, - "XFS: sunit and swidth must be specified together"); + xfs_warn(mp, "sunit and swidth must be specified together"); return EINVAL; } if (dsunit && (dswidth % dsunit != 0)) { - cmn_err(CE_WARN, - "XFS: stripe width (%d) must be a multiple of the stripe unit (%d)", + xfs_warn(mp, + "stripe width (%d) must be a multiple of the stripe unit (%d)", dswidth, dsunit); return EINVAL; } @@ -439,8 +434,7 @@ done: mp->m_logbufs != 0 && (mp->m_logbufs < XLOG_MIN_ICLOGS || mp->m_logbufs > XLOG_MAX_ICLOGS)) { - cmn_err(CE_WARN, - "XFS: invalid logbufs value: %d [not %d-%d]", + xfs_warn(mp, "invalid logbufs value: %d [not %d-%d]", mp->m_logbufs, XLOG_MIN_ICLOGS, XLOG_MAX_ICLOGS); return XFS_ERROR(EINVAL); } @@ -449,22 +443,16 @@ done: (mp->m_logbsize < XLOG_MIN_RECORD_BSIZE || mp->m_logbsize > XLOG_MAX_RECORD_BSIZE || !is_power_of_2(mp->m_logbsize))) { - cmn_err(CE_WARN, - "XFS: invalid logbufsize: %d [not 16k,32k,64k,128k or 256k]", + xfs_warn(mp, + "invalid logbufsize: %d [not 16k,32k,64k,128k or 256k]", mp->m_logbsize); return XFS_ERROR(EINVAL); } - mp->m_fsname = kstrndup(sb->s_id, MAXNAMELEN, GFP_KERNEL); - if (!mp->m_fsname) - return ENOMEM; - mp->m_fsname_len = strlen(mp->m_fsname) + 1; - if (iosizelog) { if (iosizelog > XFS_MAX_IO_LOG || iosizelog < XFS_MIN_IO_LOG) { - cmn_err(CE_WARN, - "XFS: invalid log iosize: %d [not %d-%d]", + xfs_warn(mp, "invalid log iosize: %d [not %d-%d]", iosizelog, XFS_MIN_IO_LOG, XFS_MAX_IO_LOG); return XFS_ERROR(EINVAL); @@ -611,7 +599,7 @@ xfs_blkdev_get( mp); if (IS_ERR(*bdevp)) { error = PTR_ERR(*bdevp); - printk("XFS: Invalid device [%s], error=%d\n", name, error); + xfs_warn(mp, "Invalid device [%s], error=%d\n", name, error); } return -error; @@ -665,23 +653,23 @@ xfs_mountfs_check_barriers(xfs_mount_t *mp) int error; if (mp->m_logdev_targp != mp->m_ddev_targp) { - xfs_fs_cmn_err(CE_NOTE, mp, + xfs_notice(mp, "Disabling barriers, not supported with external log device"); mp->m_flags &= ~XFS_MOUNT_BARRIER; return; } if (xfs_readonly_buftarg(mp->m_ddev_targp)) { - xfs_fs_cmn_err(CE_NOTE, mp, - "Disabling barriers, underlying device is readonly"); + xfs_notice(mp, + "Disabling barriers, underlying device is readonly"); mp->m_flags &= ~XFS_MOUNT_BARRIER; return; } error = xfs_barrier_test(mp); if (error) { - xfs_fs_cmn_err(CE_NOTE, mp, - "Disabling barriers, trial barrier write failed"); + xfs_notice(mp, + "Disabling barriers, trial barrier write failed"); mp->m_flags &= ~XFS_MOUNT_BARRIER; return; } @@ -744,8 +732,8 @@ xfs_open_devices( goto out_close_logdev; if (rtdev == ddev || rtdev == logdev) { - cmn_err(CE_WARN, - "XFS: Cannot mount filesystem with identical rtdev and ddev/logdev."); + xfs_warn(mp, + "Cannot mount filesystem with identical rtdev and ddev/logdev."); error = EINVAL; goto out_close_rtdev; } @@ -1346,8 +1334,8 @@ xfs_fs_remount( * options that we can't actually change. */ #if 0 - printk(KERN_INFO - "XFS: mount option \"%s\" not supported for remount\n", p); + xfs_info(mp, + "mount option \"%s\" not supported for remount\n", p); return -EINVAL; #else break; @@ -1368,8 +1356,7 @@ xfs_fs_remount( if (mp->m_update_flags) { error = xfs_mount_log_sb(mp, mp->m_update_flags); if (error) { - cmn_err(CE_WARN, - "XFS: failed to write sb changes"); + xfs_warn(mp, "failed to write sb changes"); return error; } mp->m_update_flags = 0; @@ -1453,15 +1440,15 @@ xfs_finish_flags( mp->m_logbsize = mp->m_sb.sb_logsunit; } else if (mp->m_logbsize > 0 && mp->m_logbsize < mp->m_sb.sb_logsunit) { - cmn_err(CE_WARN, - "XFS: logbuf size must be greater than or equal to log stripe size"); + xfs_warn(mp, + "logbuf size must be greater than or equal to log stripe size"); return XFS_ERROR(EINVAL); } } else { /* Fail a mount if the logbuf is larger than 32K */ if (mp->m_logbsize > XLOG_BIG_RECORD_BSIZE) { - cmn_err(CE_WARN, - "XFS: logbuf size for version 1 logs must be 16K or 32K"); + xfs_warn(mp, + "logbuf size for version 1 logs must be 16K or 32K"); return XFS_ERROR(EINVAL); } } @@ -1478,8 +1465,8 @@ xfs_finish_flags( * prohibit r/w mounts of read-only filesystems */ if ((mp->m_sb.sb_flags & XFS_SBF_READONLY) && !ronly) { - cmn_err(CE_WARN, - "XFS: cannot mount a read-only filesystem as read-write"); + xfs_warn(mp, + "cannot mount a read-only filesystem as read-write"); return XFS_ERROR(EROFS); } diff --git a/fs/xfs/linux-2.6/xfs_sync.c b/fs/xfs/linux-2.6/xfs_sync.c index e22f0057d21fa..6c10f1d2e3d3a 100644 --- a/fs/xfs/linux-2.6/xfs_sync.c +++ b/fs/xfs/linux-2.6/xfs_sync.c @@ -425,8 +425,7 @@ xfs_quiesce_attr( /* Push the superblock and write an unmount record */ error = xfs_log_sbcount(mp, 1); if (error) - xfs_fs_cmn_err(CE_WARN, mp, - "xfs_attr_quiesce: failed to log sb changes. " + xfs_warn(mp, "xfs_attr_quiesce: failed to log sb changes. " "Frozen image may not be consistent."); xfs_log_unmount_write(mp); xfs_unmountfs_writesb(mp); @@ -806,7 +805,7 @@ xfs_reclaim_inode( * pass on the error. */ if (error && error != EAGAIN && !XFS_FORCED_SHUTDOWN(ip->i_mount)) { - xfs_fs_cmn_err(CE_WARN, ip->i_mount, + xfs_warn(ip->i_mount, "inode 0x%llx background reclaim flush failed with %d", (long long)ip->i_ino, error); } diff --git a/fs/xfs/linux-2.6/xfs_sysctl.c b/fs/xfs/linux-2.6/xfs_sysctl.c index ee3cee097e7eb..ee2d2adaa4381 100644 --- a/fs/xfs/linux-2.6/xfs_sysctl.c +++ b/fs/xfs/linux-2.6/xfs_sysctl.c @@ -37,7 +37,7 @@ xfs_stats_clear_proc_handler( ret = proc_dointvec_minmax(ctl, write, buffer, lenp, ppos); if (!ret && write && *valp) { - printk("XFS Clearing xfsstats\n"); + xfs_notice(NULL, "Clearing xfsstats"); for_each_possible_cpu(c) { preempt_disable(); /* save vn_active, it's a universal truth! */ -- GitLab From a0fa2b679ecd15b4bdbb46cd2420b6affde91cf9 Mon Sep 17 00:00:00 2001 From: Dave Chinner Date: Mon, 7 Mar 2011 10:01:35 +1100 Subject: [PATCH 0292/2822] xfs: Convert xlog_warn to new logging interface Convert the xfs log operations to use the new error logging interfaces. This removes the xlog_{warn,panic} wrappers and makes almost all errors emit the device they belong to instead of just refering to "XFS". Signed-off-by: Dave Chinner Reviewed-by: Alex Elder Reviewed-by: Christoph Hellwig --- fs/xfs/quota/xfs_dquot.c | 10 +- fs/xfs/quota/xfs_qm.c | 2 +- fs/xfs/xfs_log.c | 124 +++++++++++----------- fs/xfs/xfs_log_priv.h | 4 - fs/xfs/xfs_log_recover.c | 223 +++++++++++++++++++-------------------- fs/xfs/xfs_quota.h | 3 +- 6 files changed, 177 insertions(+), 189 deletions(-) diff --git a/fs/xfs/quota/xfs_dquot.c b/fs/xfs/quota/xfs_dquot.c index d22aa3103106c..773adc80d6b47 100644 --- a/fs/xfs/quota/xfs_dquot.c +++ b/fs/xfs/quota/xfs_dquot.c @@ -544,9 +544,10 @@ xfs_qm_dqtobp( /* * A simple sanity check in case we got a corrupted dquot... */ - if (xfs_qm_dqcheck(ddq, id, dqp->dq_flags & XFS_DQ_ALLTYPES, + error = xfs_qm_dqcheck(mp, ddq, id, dqp->dq_flags & XFS_DQ_ALLTYPES, flags & (XFS_QMOPT_DQREPAIR|XFS_QMOPT_DOWARN), - "dqtobp")) { + "dqtobp"); + if (error) { if (!(flags & XFS_QMOPT_DQREPAIR)) { xfs_trans_brelse(tp, bp); return XFS_ERROR(EIO); @@ -1207,8 +1208,9 @@ xfs_qm_dqflush( /* * A simple sanity check in case we got a corrupted dquot.. */ - if (xfs_qm_dqcheck(&dqp->q_core, be32_to_cpu(ddqp->d_id), 0, - XFS_QMOPT_DOWARN, "dqflush (incore copy)")) { + error = xfs_qm_dqcheck(mp, &dqp->q_core, be32_to_cpu(ddqp->d_id), 0, + XFS_QMOPT_DOWARN, "dqflush (incore copy)"); + if (error) { xfs_buf_relse(bp); xfs_dqfunlock(dqp); xfs_force_shutdown(mp, SHUTDOWN_CORRUPT_INCORE); diff --git a/fs/xfs/quota/xfs_qm.c b/fs/xfs/quota/xfs_qm.c index f517963aec071..dd5cc5738a2c9 100644 --- a/fs/xfs/quota/xfs_qm.c +++ b/fs/xfs/quota/xfs_qm.c @@ -1292,7 +1292,7 @@ xfs_qm_reset_dqcounts( * output any warnings because it's perfectly possible to * find uninitialised dquot blks. See comment in xfs_qm_dqcheck. */ - (void) xfs_qm_dqcheck(ddq, id+j, type, XFS_QMOPT_DQREPAIR, + (void) xfs_qm_dqcheck(mp, ddq, id+j, type, XFS_QMOPT_DQREPAIR, "xfs_quotacheck"); ddq->d_bcount = 0; ddq->d_icount = 0; diff --git a/fs/xfs/xfs_log.c b/fs/xfs/xfs_log.c index ae6fef1ff563e..25efa9b8a6029 100644 --- a/fs/xfs/xfs_log.c +++ b/fs/xfs/xfs_log.c @@ -374,11 +374,10 @@ xfs_log_mount( int error; if (!(mp->m_flags & XFS_MOUNT_NORECOVERY)) - cmn_err(CE_NOTE, "XFS mounting filesystem %s", mp->m_fsname); + xfs_notice(mp, "Mounting Filesystem"); else { - cmn_err(CE_NOTE, - "Mounting filesystem \"%s\" in no-recovery mode. Filesystem will be inconsistent.", - mp->m_fsname); + xfs_notice(mp, +"Mounting filesystem in no-recovery mode. Filesystem will be inconsistent."); ASSERT(mp->m_flags & XFS_MOUNT_RDONLY); } @@ -393,7 +392,7 @@ xfs_log_mount( */ error = xfs_trans_ail_init(mp); if (error) { - cmn_err(CE_WARN, "XFS: AIL initialisation failed: error %d", error); + xfs_warn(mp, "AIL initialisation failed: error %d", error); goto out_free_log; } mp->m_log->l_ailp = mp->m_ail; @@ -413,7 +412,8 @@ xfs_log_mount( if (readonly) mp->m_flags |= XFS_MOUNT_RDONLY; if (error) { - cmn_err(CE_WARN, "XFS: log mount/recovery failed: error %d", error); + xfs_warn(mp, "log mount/recovery failed: error %d", + error); goto out_destroy_ail; } } @@ -542,10 +542,8 @@ xfs_log_unmount_write(xfs_mount_t *mp) */ } - if (error) { - xfs_fs_cmn_err(CE_ALERT, mp, - "xfs_log_unmount: unmount record failed"); - } + if (error) + xfs_alert(mp, "%s: unmount record failed", __func__); spin_lock(&log->l_icloglock); @@ -852,7 +850,7 @@ xlog_space_left( * In this case we just want to return the size of the * log as the amount of space left. */ - xfs_fs_cmn_err(CE_ALERT, log->l_mp, + xfs_alert(log->l_mp, "xlog_space_left: head behind tail\n" " tail_cycle = %d, tail_bytes = %d\n" " GH cycle = %d, GH bytes = %d", @@ -1001,7 +999,7 @@ xlog_alloc_log(xfs_mount_t *mp, log = kmem_zalloc(sizeof(xlog_t), KM_MAYFAIL); if (!log) { - xlog_warn("XFS: Log allocation failed: No memory!"); + xfs_warn(mp, "Log allocation failed: No memory!"); goto out; } @@ -1029,24 +1027,24 @@ xlog_alloc_log(xfs_mount_t *mp, if (xfs_sb_version_hassector(&mp->m_sb)) { log2_size = mp->m_sb.sb_logsectlog; if (log2_size < BBSHIFT) { - xlog_warn("XFS: Log sector size too small " - "(0x%x < 0x%x)", log2_size, BBSHIFT); + xfs_warn(mp, "Log sector size too small (0x%x < 0x%x)", + log2_size, BBSHIFT); goto out_free_log; } log2_size -= BBSHIFT; if (log2_size > mp->m_sectbb_log) { - xlog_warn("XFS: Log sector size too large " - "(0x%x > 0x%x)", log2_size, mp->m_sectbb_log); + xfs_warn(mp, "Log sector size too large (0x%x > 0x%x)", + log2_size, mp->m_sectbb_log); goto out_free_log; } /* for larger sector sizes, must have v2 or external log */ if (log2_size && log->l_logBBstart > 0 && !xfs_sb_version_haslogv2(&mp->m_sb)) { - - xlog_warn("XFS: log sector size (0x%x) invalid " - "for configuration.", log2_size); + xfs_warn(mp, + "log sector size (0x%x) invalid for configuration.", + log2_size); goto out_free_log; } } @@ -1563,38 +1561,36 @@ xlog_print_tic_res( "SWAPEXT" }; - xfs_fs_cmn_err(CE_WARN, mp, - "xfs_log_write: reservation summary:\n" - " trans type = %s (%u)\n" - " unit res = %d bytes\n" - " current res = %d bytes\n" - " total reg = %u bytes (o/flow = %u bytes)\n" - " ophdrs = %u (ophdr space = %u bytes)\n" - " ophdr + reg = %u bytes\n" - " num regions = %u\n", - ((ticket->t_trans_type <= 0 || - ticket->t_trans_type > XFS_TRANS_TYPE_MAX) ? - "bad-trans-type" : trans_type_str[ticket->t_trans_type-1]), - ticket->t_trans_type, - ticket->t_unit_res, - ticket->t_curr_res, - ticket->t_res_arr_sum, ticket->t_res_o_flow, - ticket->t_res_num_ophdrs, ophdr_spc, - ticket->t_res_arr_sum + - ticket->t_res_o_flow + ophdr_spc, - ticket->t_res_num); + xfs_warn(mp, + "xfs_log_write: reservation summary:\n" + " trans type = %s (%u)\n" + " unit res = %d bytes\n" + " current res = %d bytes\n" + " total reg = %u bytes (o/flow = %u bytes)\n" + " ophdrs = %u (ophdr space = %u bytes)\n" + " ophdr + reg = %u bytes\n" + " num regions = %u\n", + ((ticket->t_trans_type <= 0 || + ticket->t_trans_type > XFS_TRANS_TYPE_MAX) ? + "bad-trans-type" : trans_type_str[ticket->t_trans_type-1]), + ticket->t_trans_type, + ticket->t_unit_res, + ticket->t_curr_res, + ticket->t_res_arr_sum, ticket->t_res_o_flow, + ticket->t_res_num_ophdrs, ophdr_spc, + ticket->t_res_arr_sum + + ticket->t_res_o_flow + ophdr_spc, + ticket->t_res_num); for (i = 0; i < ticket->t_res_num; i++) { - uint r_type = ticket->t_res_arr[i].r_type; - cmn_err(CE_WARN, - "region[%u]: %s - %u bytes\n", - i, + uint r_type = ticket->t_res_arr[i].r_type; + xfs_warn(mp, "region[%u]: %s - %u bytes\n", i, ((r_type <= 0 || r_type > XLOG_REG_TYPE_MAX) ? "bad-rtype" : res_type_str[r_type-1]), ticket->t_res_arr[i].r_len); } - xfs_cmn_err(XFS_PTAG_LOGRES, CE_ALERT, mp, + xfs_alert_tag(mp, XFS_PTAG_LOGRES, "xfs_log_write: reservation ran out. Need to up reservation"); xfs_force_shutdown(mp, SHUTDOWN_CORRUPT_INCORE); } @@ -1682,7 +1678,7 @@ xlog_write_setup_ophdr( case XFS_LOG: break; default: - xfs_fs_cmn_err(CE_WARN, log->l_mp, + xfs_warn(log->l_mp, "Bad XFS transaction clientid 0x%x in ticket 0x%p", ophdr->oh_clientid, ticket); return NULL; @@ -2264,7 +2260,7 @@ xlog_state_do_callback( if (repeats > 5000) { flushcnt += repeats; repeats = 0; - xfs_fs_cmn_err(CE_WARN, log->l_mp, + xfs_warn(log->l_mp, "%s: possible infinite loop (%d iterations)", __func__, flushcnt); } @@ -3052,10 +3048,8 @@ xfs_log_force( int error; error = _xfs_log_force(mp, flags, NULL); - if (error) { - xfs_fs_cmn_err(CE_WARN, mp, "xfs_log_force: " - "error %d returned.", error); - } + if (error) + xfs_warn(mp, "%s: error %d returned.", __func__, error); } /* @@ -3204,10 +3198,8 @@ xfs_log_force_lsn( int error; error = _xfs_log_force_lsn(mp, lsn, flags, NULL); - if (error) { - xfs_fs_cmn_err(CE_WARN, mp, "xfs_log_force: " - "error %d returned.", error); - } + if (error) + xfs_warn(mp, "%s: error %d returned.", __func__, error); } /* @@ -3412,7 +3404,7 @@ xlog_verify_dest_ptr( } if (!good_ptr) - xlog_panic("xlog_verify_dest_ptr: invalid ptr"); + xfs_emerg(log->l_mp, "%s: invalid ptr", __func__); } STATIC void @@ -3448,16 +3440,16 @@ xlog_verify_tail_lsn(xlog_t *log, blocks = log->l_logBBsize - (log->l_prev_block - BLOCK_LSN(tail_lsn)); if (blocks < BTOBB(iclog->ic_offset)+BTOBB(log->l_iclog_hsize)) - xlog_panic("xlog_verify_tail_lsn: ran out of log space"); + xfs_emerg(log->l_mp, "%s: ran out of log space", __func__); } else { ASSERT(CYCLE_LSN(tail_lsn)+1 == log->l_prev_cycle); if (BLOCK_LSN(tail_lsn) == log->l_prev_block) - xlog_panic("xlog_verify_tail_lsn: tail wrapped"); + xfs_emerg(log->l_mp, "%s: tail wrapped", __func__); blocks = BLOCK_LSN(tail_lsn) - log->l_prev_block; if (blocks < BTOBB(iclog->ic_offset) + 1) - xlog_panic("xlog_verify_tail_lsn: ran out of log space"); + xfs_emerg(log->l_mp, "%s: ran out of log space", __func__); } } /* xlog_verify_tail_lsn */ @@ -3497,22 +3489,23 @@ xlog_verify_iclog(xlog_t *log, icptr = log->l_iclog; for (i=0; i < log->l_iclog_bufs; i++) { if (icptr == NULL) - xlog_panic("xlog_verify_iclog: invalid ptr"); + xfs_emerg(log->l_mp, "%s: invalid ptr", __func__); icptr = icptr->ic_next; } if (icptr != log->l_iclog) - xlog_panic("xlog_verify_iclog: corrupt iclog ring"); + xfs_emerg(log->l_mp, "%s: corrupt iclog ring", __func__); spin_unlock(&log->l_icloglock); /* check log magic numbers */ if (be32_to_cpu(iclog->ic_header.h_magicno) != XLOG_HEADER_MAGIC_NUM) - xlog_panic("xlog_verify_iclog: invalid magic num"); + xfs_emerg(log->l_mp, "%s: invalid magic num", __func__); ptr = (xfs_caddr_t) &iclog->ic_header; for (ptr += BBSIZE; ptr < ((xfs_caddr_t)&iclog->ic_header) + count; ptr += BBSIZE) { if (be32_to_cpu(*(__be32 *)ptr) == XLOG_HEADER_MAGIC_NUM) - xlog_panic("xlog_verify_iclog: unexpected magic num"); + xfs_emerg(log->l_mp, "%s: unexpected magic num", + __func__); } /* check fields */ @@ -3542,9 +3535,10 @@ xlog_verify_iclog(xlog_t *log, } } if (clientid != XFS_TRANSACTION && clientid != XFS_LOG) - cmn_err(CE_WARN, "xlog_verify_iclog: " - "invalid clientid %d op 0x%p offset 0x%lx", - clientid, ophead, (unsigned long)field_offset); + xfs_warn(log->l_mp, + "%s: invalid clientid %d op 0x%p offset 0x%lx", + __func__, clientid, ophead, + (unsigned long)field_offset); /* check length */ field_offset = (__psint_t) diff --git a/fs/xfs/xfs_log_priv.h b/fs/xfs/xfs_log_priv.h index d5f8be8f4bf60..15dbf1f9c2be6 100644 --- a/fs/xfs/xfs_log_priv.h +++ b/fs/xfs/xfs_log_priv.h @@ -87,10 +87,6 @@ static inline uint xlog_get_client_id(__be32 i) return be32_to_cpu(i) >> 24; } -#define xlog_panic(args...) cmn_err(CE_PANIC, ## args) -#define xlog_exit(args...) cmn_err(CE_PANIC, ## args) -#define xlog_warn(args...) cmn_err(CE_WARN, ## args) - /* * In core log state */ diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c index aa0ebb7769033..0c4a5618e7af7 100644 --- a/fs/xfs/xfs_log_recover.c +++ b/fs/xfs/xfs_log_recover.c @@ -92,7 +92,7 @@ xlog_get_bp( int nbblks) { if (!xlog_buf_bbcount_valid(log, nbblks)) { - xlog_warn("XFS: Invalid block length (0x%x) given for buffer", + xfs_warn(log->l_mp, "Invalid block length (0x%x) for buffer", nbblks); XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_HIGH, log->l_mp); return NULL; @@ -160,7 +160,7 @@ xlog_bread_noalign( int error; if (!xlog_buf_bbcount_valid(log, nbblks)) { - xlog_warn("XFS: Invalid block length (0x%x) given for buffer", + xfs_warn(log->l_mp, "Invalid block length (0x%x) for buffer", nbblks); XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_HIGH, log->l_mp); return EFSCORRUPTED; @@ -219,7 +219,7 @@ xlog_bwrite( int error; if (!xlog_buf_bbcount_valid(log, nbblks)) { - xlog_warn("XFS: Invalid block length (0x%x) given for buffer", + xfs_warn(log->l_mp, "Invalid block length (0x%x) for buffer", nbblks); XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_HIGH, log->l_mp); return EFSCORRUPTED; @@ -254,9 +254,9 @@ xlog_header_check_dump( xfs_mount_t *mp, xlog_rec_header_t *head) { - cmn_err(CE_DEBUG, "%s: SB : uuid = %pU, fmt = %d\n", + xfs_debug(mp, "%s: SB : uuid = %pU, fmt = %d\n", __func__, &mp->m_sb.sb_uuid, XLOG_FMT); - cmn_err(CE_DEBUG, " log : uuid = %pU, fmt = %d\n", + xfs_debug(mp, " log : uuid = %pU, fmt = %d\n", &head->h_fs_uuid, be32_to_cpu(head->h_fmt)); } #else @@ -279,15 +279,15 @@ xlog_header_check_recover( * a dirty log created in IRIX. */ if (unlikely(be32_to_cpu(head->h_fmt) != XLOG_FMT)) { - xlog_warn( - "XFS: dirty log written in incompatible format - can't recover"); + xfs_warn(mp, + "dirty log written in incompatible format - can't recover"); xlog_header_check_dump(mp, head); XFS_ERROR_REPORT("xlog_header_check_recover(1)", XFS_ERRLEVEL_HIGH, mp); return XFS_ERROR(EFSCORRUPTED); } else if (unlikely(!uuid_equal(&mp->m_sb.sb_uuid, &head->h_fs_uuid))) { - xlog_warn( - "XFS: dirty log entry has mismatched uuid - can't recover"); + xfs_warn(mp, + "dirty log entry has mismatched uuid - can't recover"); xlog_header_check_dump(mp, head); XFS_ERROR_REPORT("xlog_header_check_recover(2)", XFS_ERRLEVEL_HIGH, mp); @@ -312,9 +312,9 @@ xlog_header_check_mount( * h_fs_uuid is nil, we assume this log was last mounted * by IRIX and continue. */ - xlog_warn("XFS: nil uuid in log - IRIX style log"); + xfs_warn(mp, "nil uuid in log - IRIX style log"); } else if (unlikely(!uuid_equal(&mp->m_sb.sb_uuid, &head->h_fs_uuid))) { - xlog_warn("XFS: log has mismatched uuid - can't recover"); + xfs_warn(mp, "log has mismatched uuid - can't recover"); xlog_header_check_dump(mp, head); XFS_ERROR_REPORT("xlog_header_check_mount", XFS_ERRLEVEL_HIGH, mp); @@ -490,8 +490,8 @@ xlog_find_verify_log_record( for (i = (*last_blk) - 1; i >= 0; i--) { if (i < start_blk) { /* valid log record not found */ - xlog_warn( - "XFS: Log inconsistent (didn't find previous header)"); + xfs_warn(log->l_mp, + "Log inconsistent (didn't find previous header)"); ASSERT(0); error = XFS_ERROR(EIO); goto out; @@ -591,12 +591,12 @@ xlog_find_head( * mkfs etc write a dummy unmount record to a fresh * log so we can store the uuid in there */ - xlog_warn("XFS: totally zeroed log"); + xfs_warn(log->l_mp, "totally zeroed log"); } return 0; } else if (error) { - xlog_warn("XFS: empty log check failed"); + xfs_warn(log->l_mp, "empty log check failed"); return error; } @@ -819,7 +819,7 @@ validate_head: xlog_put_bp(bp); if (error) - xlog_warn("XFS: failed to find log head"); + xfs_warn(log->l_mp, "failed to find log head"); return error; } @@ -912,7 +912,7 @@ xlog_find_tail( } } if (!found) { - xlog_warn("XFS: xlog_find_tail: couldn't find sync record"); + xfs_warn(log->l_mp, "%s: couldn't find sync record", __func__); ASSERT(0); return XFS_ERROR(EIO); } @@ -1028,7 +1028,7 @@ done: xlog_put_bp(bp); if (error) - xlog_warn("XFS: failed to locate log tail"); + xfs_warn(log->l_mp, "failed to locate log tail"); return error; } @@ -1092,7 +1092,8 @@ xlog_find_zeroed( * the first block must be 1. If it's not, maybe we're * not looking at a log... Bail out. */ - xlog_warn("XFS: Log inconsistent or not a log (last==0, first!=1)"); + xfs_warn(log->l_mp, + "Log inconsistent or not a log (last==0, first!=1)"); return XFS_ERROR(EINVAL); } @@ -1506,8 +1507,8 @@ xlog_recover_add_to_trans( if (list_empty(&trans->r_itemq)) { /* we need to catch log corruptions here */ if (*(uint *)dp != XFS_TRANS_HEADER_MAGIC) { - xlog_warn("XFS: xlog_recover_add_to_trans: " - "bad header magic number"); + xfs_warn(log->l_mp, "%s: bad header magic number", + __func__); ASSERT(0); return XFS_ERROR(EIO); } @@ -1534,8 +1535,8 @@ xlog_recover_add_to_trans( if (item->ri_total == 0) { /* first region to be added */ if (in_f->ilf_size == 0 || in_f->ilf_size > XLOG_MAX_REGIONS_IN_ITEM) { - xlog_warn( - "XFS: bad number of regions (%d) in inode log format", + xfs_warn(log->l_mp, + "bad number of regions (%d) in inode log format", in_f->ilf_size); ASSERT(0); return XFS_ERROR(EIO); @@ -1592,8 +1593,9 @@ xlog_recover_reorder_trans( list_move_tail(&item->ri_list, &trans->r_itemq); break; default: - xlog_warn( - "XFS: xlog_recover_reorder_trans: unrecognized type of log operation"); + xfs_warn(log->l_mp, + "%s: unrecognized type of log operation", + __func__); ASSERT(0); return XFS_ERROR(EIO); } @@ -1803,8 +1805,9 @@ xlog_recover_do_inode_buffer( logged_nextp = item->ri_buf[item_index].i_addr + next_unlinked_offset - reg_buf_offset; if (unlikely(*logged_nextp == 0)) { - xfs_fs_cmn_err(CE_ALERT, mp, - "bad inode buffer log record (ptr = 0x%p, bp = 0x%p). XFS trying to replay bad (0) inode di_next_unlinked field", + xfs_alert(mp, + "Bad inode buffer log record (ptr = 0x%p, bp = 0x%p). " + "Trying to replay bad (0) inode di_next_unlinked field.", item, bp); XFS_ERROR_REPORT("xlog_recover_do_inode_buf", XFS_ERRLEVEL_LOW, mp); @@ -1863,17 +1866,17 @@ xlog_recover_do_reg_buffer( if (buf_f->blf_flags & (XFS_BLF_UDQUOT_BUF|XFS_BLF_PDQUOT_BUF|XFS_BLF_GDQUOT_BUF)) { if (item->ri_buf[i].i_addr == NULL) { - cmn_err(CE_ALERT, + xfs_alert(mp, "XFS: NULL dquot in %s.", __func__); goto next; } if (item->ri_buf[i].i_len < sizeof(xfs_disk_dquot_t)) { - cmn_err(CE_ALERT, + xfs_alert(mp, "XFS: dquot too small (%d) in %s.", item->ri_buf[i].i_len, __func__); goto next; } - error = xfs_qm_dqcheck(item->ri_buf[i].i_addr, + error = xfs_qm_dqcheck(mp, item->ri_buf[i].i_addr, -1, 0, XFS_QMOPT_DOWARN, "dquot_buf_recover"); if (error) @@ -1898,6 +1901,7 @@ xlog_recover_do_reg_buffer( */ int xfs_qm_dqcheck( + struct xfs_mount *mp, xfs_disk_dquot_t *ddq, xfs_dqid_t id, uint type, /* used only when IO_dorepair is true */ @@ -1924,14 +1928,14 @@ xfs_qm_dqcheck( */ if (be16_to_cpu(ddq->d_magic) != XFS_DQUOT_MAGIC) { if (flags & XFS_QMOPT_DOWARN) - cmn_err(CE_ALERT, + xfs_alert(mp, "%s : XFS dquot ID 0x%x, magic 0x%x != 0x%x", str, id, be16_to_cpu(ddq->d_magic), XFS_DQUOT_MAGIC); errs++; } if (ddq->d_version != XFS_DQUOT_VERSION) { if (flags & XFS_QMOPT_DOWARN) - cmn_err(CE_ALERT, + xfs_alert(mp, "%s : XFS dquot ID 0x%x, version 0x%x != 0x%x", str, id, ddq->d_version, XFS_DQUOT_VERSION); errs++; @@ -1941,7 +1945,7 @@ xfs_qm_dqcheck( ddq->d_flags != XFS_DQ_PROJ && ddq->d_flags != XFS_DQ_GROUP) { if (flags & XFS_QMOPT_DOWARN) - cmn_err(CE_ALERT, + xfs_alert(mp, "%s : XFS dquot ID 0x%x, unknown flags 0x%x", str, id, ddq->d_flags); errs++; @@ -1949,7 +1953,7 @@ xfs_qm_dqcheck( if (id != -1 && id != be32_to_cpu(ddq->d_id)) { if (flags & XFS_QMOPT_DOWARN) - cmn_err(CE_ALERT, + xfs_alert(mp, "%s : ondisk-dquot 0x%p, ID mismatch: " "0x%x expected, found id 0x%x", str, ddq, id, be32_to_cpu(ddq->d_id)); @@ -1962,9 +1966,8 @@ xfs_qm_dqcheck( be64_to_cpu(ddq->d_blk_softlimit)) { if (!ddq->d_btimer) { if (flags & XFS_QMOPT_DOWARN) - cmn_err(CE_ALERT, - "%s : Dquot ID 0x%x (0x%p) " - "BLK TIMER NOT STARTED", + xfs_alert(mp, + "%s : Dquot ID 0x%x (0x%p) BLK TIMER NOT STARTED", str, (int)be32_to_cpu(ddq->d_id), ddq); errs++; } @@ -1974,9 +1977,8 @@ xfs_qm_dqcheck( be64_to_cpu(ddq->d_ino_softlimit)) { if (!ddq->d_itimer) { if (flags & XFS_QMOPT_DOWARN) - cmn_err(CE_ALERT, - "%s : Dquot ID 0x%x (0x%p) " - "INODE TIMER NOT STARTED", + xfs_alert(mp, + "%s : Dquot ID 0x%x (0x%p) INODE TIMER NOT STARTED", str, (int)be32_to_cpu(ddq->d_id), ddq); errs++; } @@ -1986,9 +1988,8 @@ xfs_qm_dqcheck( be64_to_cpu(ddq->d_rtb_softlimit)) { if (!ddq->d_rtbtimer) { if (flags & XFS_QMOPT_DOWARN) - cmn_err(CE_ALERT, - "%s : Dquot ID 0x%x (0x%p) " - "RTBLK TIMER NOT STARTED", + xfs_alert(mp, + "%s : Dquot ID 0x%x (0x%p) RTBLK TIMER NOT STARTED", str, (int)be32_to_cpu(ddq->d_id), ddq); errs++; } @@ -1999,7 +2000,7 @@ xfs_qm_dqcheck( return errs; if (flags & XFS_QMOPT_DOWARN) - cmn_err(CE_NOTE, "Re-initializing dquot ID 0x%x", id); + xfs_notice(mp, "Re-initializing dquot ID 0x%x", id); /* * Typically, a repair is only requested by quotacheck. @@ -2218,9 +2219,9 @@ xlog_recover_inode_pass2( */ if (unlikely(be16_to_cpu(dip->di_magic) != XFS_DINODE_MAGIC)) { xfs_buf_relse(bp); - xfs_fs_cmn_err(CE_ALERT, mp, - "xfs_inode_recover: Bad inode magic number, dino ptr = 0x%p, dino bp = 0x%p, ino = %Ld", - dip, bp, in_f->ilf_ino); + xfs_alert(mp, + "%s: Bad inode magic number, dip = 0x%p, dino bp = 0x%p, ino = %Ld", + __func__, dip, bp, in_f->ilf_ino); XFS_ERROR_REPORT("xlog_recover_inode_pass2(1)", XFS_ERRLEVEL_LOW, mp); error = EFSCORRUPTED; @@ -2229,9 +2230,9 @@ xlog_recover_inode_pass2( dicp = item->ri_buf[1].i_addr; if (unlikely(dicp->di_magic != XFS_DINODE_MAGIC)) { xfs_buf_relse(bp); - xfs_fs_cmn_err(CE_ALERT, mp, - "xfs_inode_recover: Bad inode log record, rec ptr 0x%p, ino %Ld", - item, in_f->ilf_ino); + xfs_alert(mp, + "%s: Bad inode log record, rec ptr 0x%p, ino %Ld", + __func__, item, in_f->ilf_ino); XFS_ERROR_REPORT("xlog_recover_inode_pass2(2)", XFS_ERRLEVEL_LOW, mp); error = EFSCORRUPTED; @@ -2263,9 +2264,10 @@ xlog_recover_inode_pass2( XFS_CORRUPTION_ERROR("xlog_recover_inode_pass2(3)", XFS_ERRLEVEL_LOW, mp, dicp); xfs_buf_relse(bp); - xfs_fs_cmn_err(CE_ALERT, mp, - "xfs_inode_recover: Bad regular inode log record, rec ptr 0x%p, ino ptr = 0x%p, ino bp = 0x%p, ino %Ld", - item, dip, bp, in_f->ilf_ino); + xfs_alert(mp, + "%s: Bad regular inode log record, rec ptr 0x%p, " + "ino ptr = 0x%p, ino bp = 0x%p, ino %Ld", + __func__, item, dip, bp, in_f->ilf_ino); error = EFSCORRUPTED; goto error; } @@ -2276,9 +2278,10 @@ xlog_recover_inode_pass2( XFS_CORRUPTION_ERROR("xlog_recover_inode_pass2(4)", XFS_ERRLEVEL_LOW, mp, dicp); xfs_buf_relse(bp); - xfs_fs_cmn_err(CE_ALERT, mp, - "xfs_inode_recover: Bad dir inode log record, rec ptr 0x%p, ino ptr = 0x%p, ino bp = 0x%p, ino %Ld", - item, dip, bp, in_f->ilf_ino); + xfs_alert(mp, + "%s: Bad dir inode log record, rec ptr 0x%p, " + "ino ptr = 0x%p, ino bp = 0x%p, ino %Ld", + __func__, item, dip, bp, in_f->ilf_ino); error = EFSCORRUPTED; goto error; } @@ -2287,9 +2290,10 @@ xlog_recover_inode_pass2( XFS_CORRUPTION_ERROR("xlog_recover_inode_pass2(5)", XFS_ERRLEVEL_LOW, mp, dicp); xfs_buf_relse(bp); - xfs_fs_cmn_err(CE_ALERT, mp, - "xfs_inode_recover: Bad inode log record, rec ptr 0x%p, dino ptr 0x%p, dino bp 0x%p, ino %Ld, total extents = %d, nblocks = %Ld", - item, dip, bp, in_f->ilf_ino, + xfs_alert(mp, + "%s: Bad inode log record, rec ptr 0x%p, dino ptr 0x%p, " + "dino bp 0x%p, ino %Ld, total extents = %d, nblocks = %Ld", + __func__, item, dip, bp, in_f->ilf_ino, dicp->di_nextents + dicp->di_anextents, dicp->di_nblocks); error = EFSCORRUPTED; @@ -2299,8 +2303,9 @@ xlog_recover_inode_pass2( XFS_CORRUPTION_ERROR("xlog_recover_inode_pass2(6)", XFS_ERRLEVEL_LOW, mp, dicp); xfs_buf_relse(bp); - xfs_fs_cmn_err(CE_ALERT, mp, - "xfs_inode_recover: Bad inode log rec ptr 0x%p, dino ptr 0x%p, dino bp 0x%p, ino %Ld, forkoff 0x%x", + xfs_alert(mp, + "%s: Bad inode log record, rec ptr 0x%p, dino ptr 0x%p, " + "dino bp 0x%p, ino %Ld, forkoff 0x%x", __func__, item, dip, bp, in_f->ilf_ino, dicp->di_forkoff); error = EFSCORRUPTED; goto error; @@ -2309,9 +2314,9 @@ xlog_recover_inode_pass2( XFS_CORRUPTION_ERROR("xlog_recover_inode_pass2(7)", XFS_ERRLEVEL_LOW, mp, dicp); xfs_buf_relse(bp); - xfs_fs_cmn_err(CE_ALERT, mp, - "xfs_inode_recover: Bad inode log record length %d, rec ptr 0x%p", - item->ri_buf[1].i_len, item); + xfs_alert(mp, + "%s: Bad inode log record length %d, rec ptr 0x%p", + __func__, item->ri_buf[1].i_len, item); error = EFSCORRUPTED; goto error; } @@ -2398,7 +2403,7 @@ xlog_recover_inode_pass2( break; default: - xlog_warn("XFS: xlog_recover_inode_pass2: Invalid flag"); + xfs_warn(log->l_mp, "%s: Invalid flag", __func__); ASSERT(0); xfs_buf_relse(bp); error = EIO; @@ -2467,13 +2472,11 @@ xlog_recover_dquot_pass2( recddq = item->ri_buf[1].i_addr; if (recddq == NULL) { - cmn_err(CE_ALERT, - "XFS: NULL dquot in %s.", __func__); + xfs_alert(log->l_mp, "NULL dquot in %s.", __func__); return XFS_ERROR(EIO); } if (item->ri_buf[1].i_len < sizeof(xfs_disk_dquot_t)) { - cmn_err(CE_ALERT, - "XFS: dquot too small (%d) in %s.", + xfs_alert(log->l_mp, "dquot too small (%d) in %s.", item->ri_buf[1].i_len, __func__); return XFS_ERROR(EIO); } @@ -2498,12 +2501,10 @@ xlog_recover_dquot_pass2( */ dq_f = item->ri_buf[0].i_addr; ASSERT(dq_f); - if ((error = xfs_qm_dqcheck(recddq, - dq_f->qlf_id, - 0, XFS_QMOPT_DOWARN, - "xlog_recover_dquot_pass2 (log copy)"))) { + error = xfs_qm_dqcheck(mp, recddq, dq_f->qlf_id, 0, XFS_QMOPT_DOWARN, + "xlog_recover_dquot_pass2 (log copy)"); + if (error) return XFS_ERROR(EIO); - } ASSERT(dq_f->qlf_len == 1); error = xfs_read_buf(mp, mp->m_ddev_targp, @@ -2523,8 +2524,9 @@ xlog_recover_dquot_pass2( * was among a chunk of dquots created earlier, and we did some * minimal initialization then. */ - if (xfs_qm_dqcheck(ddq, dq_f->qlf_id, 0, XFS_QMOPT_DOWARN, - "xlog_recover_dquot_pass2")) { + error = xfs_qm_dqcheck(mp, ddq, dq_f->qlf_id, 0, XFS_QMOPT_DOWARN, + "xlog_recover_dquot_pass2"); + if (error) { xfs_buf_relse(bp); return XFS_ERROR(EIO); } @@ -2676,9 +2678,8 @@ xlog_recover_commit_pass1( /* nothing to do in pass 1 */ return 0; default: - xlog_warn( - "XFS: invalid item type (%d) xlog_recover_commit_pass1", - ITEM_TYPE(item)); + xfs_warn(log->l_mp, "%s: invalid item type (%d)", + __func__, ITEM_TYPE(item)); ASSERT(0); return XFS_ERROR(EIO); } @@ -2707,9 +2708,8 @@ xlog_recover_commit_pass2( /* nothing to do in pass2 */ return 0; default: - xlog_warn( - "XFS: invalid item type (%d) xlog_recover_commit_pass2", - ITEM_TYPE(item)); + xfs_warn(log->l_mp, "%s: invalid item type (%d)", + __func__, ITEM_TYPE(item)); ASSERT(0); return XFS_ERROR(EIO); } @@ -2751,10 +2751,11 @@ xlog_recover_commit_trans( STATIC int xlog_recover_unmount_trans( + struct log *log, xlog_recover_t *trans) { /* Do nothing now */ - xlog_warn("XFS: xlog_recover_unmount_trans: Unmount LR"); + xfs_warn(log->l_mp, "%s: Unmount LR", __func__); return 0; } @@ -2797,8 +2798,8 @@ xlog_recover_process_data( dp += sizeof(xlog_op_header_t); if (ohead->oh_clientid != XFS_TRANSACTION && ohead->oh_clientid != XFS_LOG) { - xlog_warn( - "XFS: xlog_recover_process_data: bad clientid"); + xfs_warn(log->l_mp, "%s: bad clientid 0x%x", + __func__, ohead->oh_clientid); ASSERT(0); return (XFS_ERROR(EIO)); } @@ -2811,8 +2812,8 @@ xlog_recover_process_data( be64_to_cpu(rhead->h_lsn)); } else { if (dp + be32_to_cpu(ohead->oh_len) > lp) { - xlog_warn( - "XFS: xlog_recover_process_data: bad length"); + xfs_warn(log->l_mp, "%s: bad length 0x%x", + __func__, be32_to_cpu(ohead->oh_len)); WARN_ON(1); return (XFS_ERROR(EIO)); } @@ -2825,7 +2826,7 @@ xlog_recover_process_data( trans, pass); break; case XLOG_UNMOUNT_TRANS: - error = xlog_recover_unmount_trans(trans); + error = xlog_recover_unmount_trans(log, trans); break; case XLOG_WAS_CONT_TRANS: error = xlog_recover_add_to_cont_trans(log, @@ -2833,8 +2834,8 @@ xlog_recover_process_data( be32_to_cpu(ohead->oh_len)); break; case XLOG_START_TRANS: - xlog_warn( - "XFS: xlog_recover_process_data: bad transaction"); + xfs_warn(log->l_mp, "%s: bad transaction", + __func__); ASSERT(0); error = XFS_ERROR(EIO); break; @@ -2844,8 +2845,8 @@ xlog_recover_process_data( dp, be32_to_cpu(ohead->oh_len)); break; default: - xlog_warn( - "XFS: xlog_recover_process_data: bad flag"); + xfs_warn(log->l_mp, "%s: bad flag 0x%x", + __func__, flags); ASSERT(0); error = XFS_ERROR(EIO); break; @@ -3030,8 +3031,7 @@ xlog_recover_clear_agi_bucket( out_abort: xfs_trans_cancel(tp, XFS_TRANS_ABORT); out_error: - xfs_fs_cmn_err(CE_WARN, mp, "xlog_recover_clear_agi_bucket: " - "failed to clear agi %d. Continuing.", agno); + xfs_warn(mp, "%s: failed to clear agi %d. Continuing.", __func__, agno); return; } @@ -3282,7 +3282,7 @@ xlog_valid_rec_header( if (unlikely( (!rhead->h_version || (be32_to_cpu(rhead->h_version) & (~XLOG_VERSION_OKBITS))))) { - xlog_warn("XFS: %s: unrecognised log version (%d).", + xfs_warn(log->l_mp, "%s: unrecognised log version (%d).", __func__, be32_to_cpu(rhead->h_version)); return XFS_ERROR(EIO); } @@ -3740,10 +3740,9 @@ xlog_recover( return error; } - cmn_err(CE_NOTE, - "Starting XFS recovery on filesystem: %s (logdev: %s)", - log->l_mp->m_fsname, log->l_mp->m_logname ? - log->l_mp->m_logname : "internal"); + xfs_notice(log->l_mp, "Starting recovery (logdev: %s)", + log->l_mp->m_logname ? log->l_mp->m_logname + : "internal"); error = xlog_do_recover(log, head_blk, tail_blk); log->l_flags |= XLOG_RECOVERY_NEEDED; @@ -3776,9 +3775,7 @@ xlog_recover_finish( int error; error = xlog_recover_process_efis(log); if (error) { - cmn_err(CE_ALERT, - "Failed to recover EFIs on filesystem: %s", - log->l_mp->m_fsname); + xfs_alert(log->l_mp, "Failed to recover EFIs"); return error; } /* @@ -3793,15 +3790,12 @@ xlog_recover_finish( xlog_recover_check_summary(log); - cmn_err(CE_NOTE, - "Ending XFS recovery on filesystem: %s (logdev: %s)", - log->l_mp->m_fsname, log->l_mp->m_logname ? - log->l_mp->m_logname : "internal"); + xfs_notice(log->l_mp, "Ending recovery (logdev: %s)", + log->l_mp->m_logname ? log->l_mp->m_logname + : "internal"); log->l_flags &= ~XLOG_RECOVERY_NEEDED; } else { - cmn_err(CE_DEBUG, - "Ending clean XFS mount for filesystem: %s\n", - log->l_mp->m_fsname); + xfs_info(log->l_mp, "Ending clean mount"); } return 0; } @@ -3834,10 +3828,8 @@ xlog_recover_check_summary( for (agno = 0; agno < mp->m_sb.sb_agcount; agno++) { error = xfs_read_agf(mp, NULL, agno, 0, &agfbp); if (error) { - xfs_fs_cmn_err(CE_ALERT, mp, - "xlog_recover_check_summary(agf)" - "agf read failed agno %d error %d", - agno, error); + xfs_alert(mp, "%s agf read failed agno %d error %d", + __func__, agno, error); } else { agfp = XFS_BUF_TO_AGF(agfbp); freeblks += be32_to_cpu(agfp->agf_freeblks) + @@ -3846,7 +3838,10 @@ xlog_recover_check_summary( } error = xfs_read_agi(mp, NULL, agno, &agibp); - if (!error) { + if (error) { + xfs_alert(mp, "%s agi read failed agno %d error %d", + __func__, agno, error); + } else { struct xfs_agi *agi = XFS_BUF_TO_AGI(agibp); itotal += be32_to_cpu(agi->agi_count); diff --git a/fs/xfs/xfs_quota.h b/fs/xfs/xfs_quota.h index 9bb6eda4cd215..a595f29567fed 100644 --- a/fs/xfs/xfs_quota.h +++ b/fs/xfs/xfs_quota.h @@ -382,7 +382,8 @@ static inline int xfs_qm_sync(struct xfs_mount *mp, int flags) xfs_trans_reserve_quota_bydquots(tp, mp, ud, gd, nb, ni, \ f | XFS_QMOPT_RES_REGBLKS) -extern int xfs_qm_dqcheck(xfs_disk_dquot_t *, xfs_dqid_t, uint, uint, char *); +extern int xfs_qm_dqcheck(struct xfs_mount *, xfs_disk_dquot_t *, + xfs_dqid_t, uint, uint, char *); extern int xfs_mount_reset_sbqflags(struct xfs_mount *); #endif /* __KERNEL__ */ -- GitLab From 6a19d9393a5402e69fc52f5da8a828b8499a8265 Mon Sep 17 00:00:00 2001 From: Dave Chinner Date: Mon, 7 Mar 2011 10:02:35 +1100 Subject: [PATCH 0293/2822] xfs: convert xfs_cmn_err to xfs_alert_tag Continue the conversion of the old cmn_err interface be converting all the conditional panic tag errors to xfs_alert_tag() and then removing xfs_cmn_err(). Signed-off-by: Dave Chinner Reviewed-by: Alex Elder Reviewed-by: Christoph Hellwig --- fs/xfs/support/debug.c | 28 ---------------------------- fs/xfs/support/debug.h | 2 -- fs/xfs/xfs_bmap.c | 2 +- fs/xfs/xfs_error.c | 5 ++--- fs/xfs/xfs_error.h | 6 ++---- fs/xfs/xfs_inode.c | 40 ++++++++++++++++++++-------------------- fs/xfs/xfs_iomap.c | 2 +- fs/xfs/xfs_rw.c | 23 +++++++++-------------- fs/xfs/xfs_trans_ail.c | 2 +- 9 files changed, 36 insertions(+), 74 deletions(-) diff --git a/fs/xfs/support/debug.c b/fs/xfs/support/debug.c index 0df88897ef844..feaca739d5ccc 100644 --- a/fs/xfs/support/debug.c +++ b/fs/xfs/support/debug.c @@ -64,34 +64,6 @@ xfs_fs_cmn_err( BUG_ON(strncmp(lvl, KERN_EMERG, strlen(KERN_EMERG)) == 0); } -/* All callers to xfs_cmn_err use CE_ALERT, so don't bother testing lvl */ -void -xfs_cmn_err( - int panic_tag, - const char *lvl, - struct xfs_mount *mp, - const char *fmt, - ...) -{ - struct va_format vaf; - va_list args; - int do_panic = 0; - - if (xfs_panic_mask && (xfs_panic_mask & panic_tag)) { - printk(KERN_ALERT "XFS: Transforming an alert into a BUG."); - do_panic = 1; - } - - va_start(args, fmt); - vaf.fmt = fmt; - vaf.va = &args; - - printk(KERN_ALERT "Filesystem %s: %pV", mp->m_fsname, &vaf); - va_end(args); - - BUG_ON(do_panic); -} - void assfail(char *expr, char *file, int line) { diff --git a/fs/xfs/support/debug.h b/fs/xfs/support/debug.h index 05699f67d4752..eaeaa17ef4b81 100644 --- a/fs/xfs/support/debug.h +++ b/fs/xfs/support/debug.h @@ -33,8 +33,6 @@ void cmn_err(const char *lvl, const char *fmt, ...) __attribute__ ((format (printf, 2, 3))); void xfs_fs_cmn_err( const char *lvl, struct xfs_mount *mp, const char *fmt, ...) __attribute__ ((format (printf, 3, 4))); -void xfs_cmn_err( int panic_tag, const char *lvl, struct xfs_mount *mp, - const char *fmt, ...) __attribute__ ((format (printf, 4, 5))); extern void assfail(char *expr, char *f, int l); diff --git a/fs/xfs/xfs_bmap.c b/fs/xfs/xfs_bmap.c index e7b441db0530d..451b4484795d0 100644 --- a/fs/xfs/xfs_bmap.c +++ b/fs/xfs/xfs_bmap.c @@ -3526,7 +3526,7 @@ xfs_bmap_search_extents( if (unlikely(!(gotp->br_startblock) && (*lastxp != NULLEXTNUM) && !(XFS_IS_REALTIME_INODE(ip) && fork == XFS_DATA_FORK))) { - xfs_cmn_err(XFS_PTAG_FSBLOCK_ZERO, CE_ALERT, ip->i_mount, + xfs_alert_tag(ip->i_mount, XFS_PTAG_FSBLOCK_ZERO, "Access to block zero in inode %llu " "start_block: %llx start_off: %llx " "blkcnt: %llx extent-state: %x lastx: %x\n", diff --git a/fs/xfs/xfs_error.c b/fs/xfs/xfs_error.c index 4c7db74a05f70..34f0e2d264eaa 100644 --- a/fs/xfs/xfs_error.c +++ b/fs/xfs/xfs_error.c @@ -162,9 +162,8 @@ xfs_error_report( inst_t *ra) { if (level <= xfs_error_level) { - xfs_cmn_err(XFS_PTAG_ERROR_REPORT, - CE_ALERT, mp, - "XFS internal error %s at line %d of file %s. Caller 0x%p\n", + xfs_alert_tag(mp, XFS_PTAG_ERROR_REPORT, + "Internal error %s at line %d of file %s. Caller 0x%p\n", tag, linenum, filename, ra); xfs_stack_trace(); diff --git a/fs/xfs/xfs_error.h b/fs/xfs/xfs_error.h index 10dce5475f022..e1ba2d2565b32 100644 --- a/fs/xfs/xfs_error.h +++ b/fs/xfs/xfs_error.h @@ -145,10 +145,8 @@ extern int xfs_errortag_clearall(struct xfs_mount *mp, int loud); #endif /* DEBUG */ /* - * XFS panic tags -- allow a call to xfs_cmn_err() be turned into - * a panic by setting xfs_panic_mask in a - * sysctl. update xfs_max[XFS_PARAM] if - * more are added. + * XFS panic tags -- allow a call to xfs_alert_tag() be turned into + * a panic by setting xfs_panic_mask in a sysctl. */ #define XFS_NO_PTAG 0 #define XFS_PTAG_IFLUSH 0x00000001 diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c index c39278b6c871e..bf9ca579365cc 100644 --- a/fs/xfs/xfs_inode.c +++ b/fs/xfs/xfs_inode.c @@ -2940,16 +2940,16 @@ xfs_iflush_int( if (XFS_TEST_ERROR(be16_to_cpu(dip->di_magic) != XFS_DINODE_MAGIC, mp, XFS_ERRTAG_IFLUSH_1, XFS_RANDOM_IFLUSH_1)) { - xfs_cmn_err(XFS_PTAG_IFLUSH, CE_ALERT, mp, - "xfs_iflush: Bad inode %Lu magic number 0x%x, ptr 0x%p", - ip->i_ino, be16_to_cpu(dip->di_magic), dip); + xfs_alert_tag(mp, XFS_PTAG_IFLUSH, + "%s: Bad inode %Lu magic number 0x%x, ptr 0x%p", + __func__, ip->i_ino, be16_to_cpu(dip->di_magic), dip); goto corrupt_out; } if (XFS_TEST_ERROR(ip->i_d.di_magic != XFS_DINODE_MAGIC, mp, XFS_ERRTAG_IFLUSH_2, XFS_RANDOM_IFLUSH_2)) { - xfs_cmn_err(XFS_PTAG_IFLUSH, CE_ALERT, mp, - "xfs_iflush: Bad inode %Lu, ptr 0x%p, magic number 0x%x", - ip->i_ino, ip, ip->i_d.di_magic); + xfs_alert_tag(mp, XFS_PTAG_IFLUSH, + "%s: Bad inode %Lu, ptr 0x%p, magic number 0x%x", + __func__, ip->i_ino, ip, ip->i_d.di_magic); goto corrupt_out; } if ((ip->i_d.di_mode & S_IFMT) == S_IFREG) { @@ -2957,9 +2957,9 @@ xfs_iflush_int( (ip->i_d.di_format != XFS_DINODE_FMT_EXTENTS) && (ip->i_d.di_format != XFS_DINODE_FMT_BTREE), mp, XFS_ERRTAG_IFLUSH_3, XFS_RANDOM_IFLUSH_3)) { - xfs_cmn_err(XFS_PTAG_IFLUSH, CE_ALERT, mp, - "xfs_iflush: Bad regular inode %Lu, ptr 0x%p", - ip->i_ino, ip); + xfs_alert_tag(mp, XFS_PTAG_IFLUSH, + "%s: Bad regular inode %Lu, ptr 0x%p", + __func__, ip->i_ino, ip); goto corrupt_out; } } else if ((ip->i_d.di_mode & S_IFMT) == S_IFDIR) { @@ -2968,28 +2968,28 @@ xfs_iflush_int( (ip->i_d.di_format != XFS_DINODE_FMT_BTREE) && (ip->i_d.di_format != XFS_DINODE_FMT_LOCAL), mp, XFS_ERRTAG_IFLUSH_4, XFS_RANDOM_IFLUSH_4)) { - xfs_cmn_err(XFS_PTAG_IFLUSH, CE_ALERT, mp, - "xfs_iflush: Bad directory inode %Lu, ptr 0x%p", - ip->i_ino, ip); + xfs_alert_tag(mp, XFS_PTAG_IFLUSH, + "%s: Bad directory inode %Lu, ptr 0x%p", + __func__, ip->i_ino, ip); goto corrupt_out; } } if (XFS_TEST_ERROR(ip->i_d.di_nextents + ip->i_d.di_anextents > ip->i_d.di_nblocks, mp, XFS_ERRTAG_IFLUSH_5, XFS_RANDOM_IFLUSH_5)) { - xfs_cmn_err(XFS_PTAG_IFLUSH, CE_ALERT, mp, - "xfs_iflush: detected corrupt incore inode %Lu, total extents = %d, nblocks = %Ld, ptr 0x%p", - ip->i_ino, + xfs_alert_tag(mp, XFS_PTAG_IFLUSH, + "%s: detected corrupt incore inode %Lu, " + "total extents = %d, nblocks = %Ld, ptr 0x%p", + __func__, ip->i_ino, ip->i_d.di_nextents + ip->i_d.di_anextents, - ip->i_d.di_nblocks, - ip); + ip->i_d.di_nblocks, ip); goto corrupt_out; } if (XFS_TEST_ERROR(ip->i_d.di_forkoff > mp->m_sb.sb_inodesize, mp, XFS_ERRTAG_IFLUSH_6, XFS_RANDOM_IFLUSH_6)) { - xfs_cmn_err(XFS_PTAG_IFLUSH, CE_ALERT, mp, - "xfs_iflush: bad inode %Lu, forkoff 0x%x, ptr 0x%p", - ip->i_ino, ip->i_d.di_forkoff, ip); + xfs_alert_tag(mp, XFS_PTAG_IFLUSH, + "%s: bad inode %Lu, forkoff 0x%x, ptr 0x%p", + __func__, ip->i_ino, ip->i_d.di_forkoff, ip); goto corrupt_out; } /* diff --git a/fs/xfs/xfs_iomap.c b/fs/xfs/xfs_iomap.c index 8a0f044750c32..812646fe1b3e1 100644 --- a/fs/xfs/xfs_iomap.c +++ b/fs/xfs/xfs_iomap.c @@ -105,7 +105,7 @@ xfs_cmn_err_fsblock_zero( xfs_inode_t *ip, xfs_bmbt_irec_t *imap) { - xfs_cmn_err(XFS_PTAG_FSBLOCK_ZERO, CE_ALERT, ip->i_mount, + xfs_alert_tag(ip->i_mount, XFS_PTAG_FSBLOCK_ZERO, "Access to block zero in inode %llu " "start_block: %llx start_off: %llx " "blkcnt: %llx extent-state: %x\n", diff --git a/fs/xfs/xfs_rw.c b/fs/xfs/xfs_rw.c index ccd3adf640ee3..ae6f49613412b 100644 --- a/fs/xfs/xfs_rw.c +++ b/fs/xfs/xfs_rw.c @@ -69,25 +69,20 @@ xfs_do_force_shutdown( return; if (flags & SHUTDOWN_CORRUPT_INCORE) { - xfs_cmn_err(XFS_PTAG_SHUTDOWN_CORRUPT, CE_ALERT, mp, - "Corruption of in-memory data detected. Shutting down filesystem: %s", - mp->m_fsname); - if (XFS_ERRLEVEL_HIGH <= xfs_error_level) { + xfs_alert_tag(mp, XFS_PTAG_SHUTDOWN_CORRUPT, + "Corruption of in-memory data detected. Shutting down filesystem"); + if (XFS_ERRLEVEL_HIGH <= xfs_error_level) xfs_stack_trace(); - } } else if (!(flags & SHUTDOWN_FORCE_UMOUNT)) { if (logerror) { - xfs_cmn_err(XFS_PTAG_SHUTDOWN_LOGERROR, CE_ALERT, mp, - "Log I/O Error Detected. Shutting down filesystem: %s", - mp->m_fsname); + xfs_alert_tag(mp, XFS_PTAG_SHUTDOWN_LOGERROR, + "Log I/O Error Detected. Shutting down filesystem"); } else if (flags & SHUTDOWN_DEVICE_REQ) { - xfs_cmn_err(XFS_PTAG_SHUTDOWN_IOERROR, CE_ALERT, mp, - "All device paths lost. Shutting down filesystem: %s", - mp->m_fsname); + xfs_alert_tag(mp, XFS_PTAG_SHUTDOWN_IOERROR, + "All device paths lost. Shutting down filesystem"); } else if (!(flags & SHUTDOWN_REMOTE_REQ)) { - xfs_cmn_err(XFS_PTAG_SHUTDOWN_IOERROR, CE_ALERT, mp, - "I/O Error Detected. Shutting down filesystem: %s", - mp->m_fsname); + xfs_alert_tag(mp, XFS_PTAG_SHUTDOWN_IOERROR, + "I/O Error Detected. Shutting down filesystem"); } } if (!(flags & SHUTDOWN_FORCE_UMOUNT)) { diff --git a/fs/xfs/xfs_trans_ail.c b/fs/xfs/xfs_trans_ail.c index c5bbbc45db91e..12aff9584e299 100644 --- a/fs/xfs/xfs_trans_ail.c +++ b/fs/xfs/xfs_trans_ail.c @@ -563,7 +563,7 @@ xfs_trans_ail_delete_bulk( spin_unlock(&ailp->xa_lock); if (!XFS_FORCED_SHUTDOWN(mp)) { - xfs_cmn_err(XFS_PTAG_AILDELETE, CE_ALERT, mp, + xfs_alert_tag(mp, XFS_PTAG_AILDELETE, "%s: attempting to delete a log item that is not in the AIL", __func__); xfs_force_shutdown(mp, SHUTDOWN_CORRUPT_INCORE); -- GitLab From 65333b4c3d46909872796321d15f179cb0e32028 Mon Sep 17 00:00:00 2001 From: Dave Chinner Date: Mon, 7 Mar 2011 10:03:35 +1100 Subject: [PATCH 0294/2822] xfs: kill xfs_fs_repair_cmn_err() macro MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In certain cases of inode corruption, the xfs_fs_repair_cmn_err() macro is used to output an extra message in the corruption report. That extra message is "unmount and run xfs_repair", which really applies to any corruption report. Each case that this macro is called (except one) a following call to xfs_corruption_error() is made to optionally dump more information about the error. Hence, move the output of "run xfs_repair" to xfs_corruption_error() so that it is output on all corruption reports. Also, convert the callers of the repair macro that don't call xfs_corruption_error() to call it, hence provide consiѕtent error reporting for all cases where xfs_fs_repair_cmn_err() used to be called. Signed-off-by: Dave Chinner Reviewed-by: Alex Elder Reviewed-by: Christoph Hellwig --- fs/xfs/xfs_bmap.c | 7 +++---- fs/xfs/xfs_error.c | 1 + fs/xfs/xfs_error.h | 3 --- fs/xfs/xfs_inode.c | 37 +++++++++++++++---------------------- 4 files changed, 19 insertions(+), 29 deletions(-) diff --git a/fs/xfs/xfs_bmap.c b/fs/xfs/xfs_bmap.c index 451b4484795d0..ded532dc0699b 100644 --- a/fs/xfs/xfs_bmap.c +++ b/fs/xfs/xfs_bmap.c @@ -4200,12 +4200,11 @@ xfs_bmap_read_extents( num_recs = xfs_btree_get_numrecs(block); if (unlikely(i + num_recs > room)) { ASSERT(i + num_recs <= room); - xfs_fs_repair_cmn_err(CE_WARN, ip->i_mount, + xfs_warn(ip->i_mount, "corrupt dinode %Lu, (btree extents).", (unsigned long long) ip->i_ino); - XFS_ERROR_REPORT("xfs_bmap_read_extents(1)", - XFS_ERRLEVEL_LOW, - ip->i_mount); + XFS_CORRUPTION_ERROR("xfs_bmap_read_extents(1)", + XFS_ERRLEVEL_LOW, ip->i_mount, block); goto error0; } XFS_WANT_CORRUPTED_GOTO( diff --git a/fs/xfs/xfs_error.c b/fs/xfs/xfs_error.c index 34f0e2d264eaa..03028906f00ef 100644 --- a/fs/xfs/xfs_error.c +++ b/fs/xfs/xfs_error.c @@ -183,4 +183,5 @@ xfs_corruption_error( if (level <= xfs_error_level) xfs_hex_dump(p, 16); xfs_error_report(tag, level, mp, filename, linenum, ra); + xfs_alert(mp, "Corruption detected. Unmount and run xfs_repair"); } diff --git a/fs/xfs/xfs_error.h b/fs/xfs/xfs_error.h index e1ba2d2565b32..4c8b5007000af 100644 --- a/fs/xfs/xfs_error.h +++ b/fs/xfs/xfs_error.h @@ -162,9 +162,6 @@ struct xfs_mount; extern void xfs_hex_dump(void *p, int length); -#define xfs_fs_repair_cmn_err(level, mp, fmt, args...) \ - xfs_fs_cmn_err(level, mp, fmt " Unmount and run xfs_repair.", ## args) - #define xfs_fs_mount_cmn_err(f, fmt, args...) \ do { \ if (!(f & XFS_MFSI_QUIET)) \ diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c index bf9ca579365cc..55169bbfc820c 100644 --- a/fs/xfs/xfs_inode.c +++ b/fs/xfs/xfs_inode.c @@ -317,7 +317,7 @@ xfs_iformat( if (unlikely(be32_to_cpu(dip->di_nextents) + be16_to_cpu(dip->di_anextents) > be64_to_cpu(dip->di_nblocks))) { - xfs_fs_repair_cmn_err(CE_WARN, ip->i_mount, + xfs_warn(ip->i_mount, "corrupt dinode %Lu, extent total = %d, nblocks = %Lu.", (unsigned long long)ip->i_ino, (int)(be32_to_cpu(dip->di_nextents) + @@ -330,8 +330,7 @@ xfs_iformat( } if (unlikely(dip->di_forkoff > ip->i_mount->m_sb.sb_inodesize)) { - xfs_fs_repair_cmn_err(CE_WARN, ip->i_mount, - "corrupt dinode %Lu, forkoff = 0x%x.", + xfs_warn(ip->i_mount, "corrupt dinode %Lu, forkoff = 0x%x.", (unsigned long long)ip->i_ino, dip->di_forkoff); XFS_CORRUPTION_ERROR("xfs_iformat(2)", XFS_ERRLEVEL_LOW, @@ -341,7 +340,7 @@ xfs_iformat( if (unlikely((ip->i_d.di_flags & XFS_DIFLAG_REALTIME) && !ip->i_mount->m_rtdev_targp)) { - xfs_fs_repair_cmn_err(CE_WARN, ip->i_mount, + xfs_warn(ip->i_mount, "corrupt dinode %Lu, has realtime flag set.", ip->i_ino); XFS_CORRUPTION_ERROR("xfs_iformat(realtime)", @@ -373,9 +372,8 @@ xfs_iformat( * no local regular files yet */ if (unlikely((be16_to_cpu(dip->di_mode) & S_IFMT) == S_IFREG)) { - xfs_fs_repair_cmn_err(CE_WARN, ip->i_mount, - "corrupt inode %Lu " - "(local format for regular file).", + xfs_warn(ip->i_mount, + "corrupt inode %Lu (local format for regular file).", (unsigned long long) ip->i_ino); XFS_CORRUPTION_ERROR("xfs_iformat(4)", XFS_ERRLEVEL_LOW, @@ -385,9 +383,8 @@ xfs_iformat( di_size = be64_to_cpu(dip->di_size); if (unlikely(di_size > XFS_DFORK_DSIZE(dip, ip->i_mount))) { - xfs_fs_repair_cmn_err(CE_WARN, ip->i_mount, - "corrupt inode %Lu " - "(bad size %Ld for local inode).", + xfs_warn(ip->i_mount, + "corrupt inode %Lu (bad size %Ld for local inode).", (unsigned long long) ip->i_ino, (long long) di_size); XFS_CORRUPTION_ERROR("xfs_iformat(5)", @@ -431,9 +428,8 @@ xfs_iformat( size = be16_to_cpu(atp->hdr.totsize); if (unlikely(size < sizeof(struct xfs_attr_sf_hdr))) { - xfs_fs_repair_cmn_err(CE_WARN, ip->i_mount, - "corrupt inode %Lu " - "(bad attr fork size %Ld).", + xfs_warn(ip->i_mount, + "corrupt inode %Lu (bad attr fork size %Ld).", (unsigned long long) ip->i_ino, (long long) size); XFS_CORRUPTION_ERROR("xfs_iformat(8)", @@ -488,9 +484,8 @@ xfs_iformat_local( * kmem_alloc() or memcpy() below. */ if (unlikely(size > XFS_DFORK_SIZE(dip, ip->i_mount, whichfork))) { - xfs_fs_repair_cmn_err(CE_WARN, ip->i_mount, - "corrupt inode %Lu " - "(bad size %d for local fork, size = %d).", + xfs_warn(ip->i_mount, + "corrupt inode %Lu (bad size %d for local fork, size = %d).", (unsigned long long) ip->i_ino, size, XFS_DFORK_SIZE(dip, ip->i_mount, whichfork)); XFS_CORRUPTION_ERROR("xfs_iformat_local", XFS_ERRLEVEL_LOW, @@ -547,8 +542,7 @@ xfs_iformat_extents( * kmem_alloc() or memcpy() below. */ if (unlikely(size < 0 || size > XFS_DFORK_SIZE(dip, ip->i_mount, whichfork))) { - xfs_fs_repair_cmn_err(CE_WARN, ip->i_mount, - "corrupt inode %Lu ((a)extents = %d).", + xfs_warn(ip->i_mount, "corrupt inode %Lu ((a)extents = %d).", (unsigned long long) ip->i_ino, nex); XFS_CORRUPTION_ERROR("xfs_iformat_extents(1)", XFS_ERRLEVEL_LOW, ip->i_mount, dip); @@ -623,11 +617,10 @@ xfs_iformat_btree( || XFS_BMDR_SPACE_CALC(nrecs) > XFS_DFORK_SIZE(dip, ip->i_mount, whichfork) || XFS_IFORK_NEXTENTS(ip, whichfork) > ip->i_d.di_nblocks)) { - xfs_fs_repair_cmn_err(CE_WARN, ip->i_mount, - "corrupt inode %Lu (btree).", + xfs_warn(ip->i_mount, "corrupt inode %Lu (btree).", (unsigned long long) ip->i_ino); - XFS_ERROR_REPORT("xfs_iformat_btree", XFS_ERRLEVEL_LOW, - ip->i_mount); + XFS_CORRUPTION_ERROR("xfs_iformat_btree", XFS_ERRLEVEL_LOW, + ip->i_mount, dip); return XFS_ERROR(EFSCORRUPTED); } -- GitLab From af34e09da42801c97f39f768c715f5511d914b52 Mon Sep 17 00:00:00 2001 From: Dave Chinner Date: Mon, 7 Mar 2011 10:04:35 +1100 Subject: [PATCH 0295/2822] xfs: kill xfs_fs_mount_cmn_err() macro The xfs_fs_mount_cmn_err() hides a simple check as to whether the mount path should output an error or not. Remove the macro and open code the check. Signed-off-by: Dave Chinner Reviewed-by: Alex Elder Reviewed-by: Christoph Hellwig --- fs/xfs/xfs_error.h | 6 ---- fs/xfs/xfs_mount.c | 72 +++++++++++++++++++++++++++------------------- 2 files changed, 43 insertions(+), 35 deletions(-) diff --git a/fs/xfs/xfs_error.h b/fs/xfs/xfs_error.h index 4c8b5007000af..e8360514c250d 100644 --- a/fs/xfs/xfs_error.h +++ b/fs/xfs/xfs_error.h @@ -162,10 +162,4 @@ struct xfs_mount; extern void xfs_hex_dump(void *p, int length); -#define xfs_fs_mount_cmn_err(f, fmt, args...) \ - do { \ - if (!(f & XFS_MFSI_QUIET)) \ - cmn_err(CE_WARN, "XFS: " fmt, ## args); \ - } while (0) - #endif /* __XFS_ERROR_H__ */ diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c index d447aef84bc3a..1b43ad3d6ddb1 100644 --- a/fs/xfs/xfs_mount.c +++ b/fs/xfs/xfs_mount.c @@ -311,6 +311,8 @@ xfs_mount_validate_sb( xfs_sb_t *sbp, int flags) { + int loud = !(flags & XFS_MFSI_QUIET); + /* * If the log device and data device have the * same device number, the log is internal. @@ -319,28 +321,32 @@ xfs_mount_validate_sb( * a volume filesystem in a non-volume manner. */ if (sbp->sb_magicnum != XFS_SB_MAGIC) { - xfs_fs_mount_cmn_err(flags, "bad magic number"); + if (loud) + xfs_warn(mp, "bad magic number"); return XFS_ERROR(EWRONGFS); } if (!xfs_sb_good_version(sbp)) { - xfs_fs_mount_cmn_err(flags, "bad version"); + if (loud) + xfs_warn(mp, "bad version"); return XFS_ERROR(EWRONGFS); } if (unlikely( sbp->sb_logstart == 0 && mp->m_logdev_targp == mp->m_ddev_targp)) { - xfs_fs_mount_cmn_err(flags, - "filesystem is marked as having an external log; " - "specify logdev on the\nmount command line."); + if (loud) + xfs_warn(mp, + "filesystem is marked as having an external log; " + "specify logdev on the mount command line."); return XFS_ERROR(EINVAL); } if (unlikely( sbp->sb_logstart != 0 && mp->m_logdev_targp != mp->m_ddev_targp)) { - xfs_fs_mount_cmn_err(flags, - "filesystem is marked as having an internal log; " - "do not specify logdev on\nthe mount command line."); + if (loud) + xfs_warn(mp, + "filesystem is marked as having an internal log; " + "do not specify logdev on the mount command line."); return XFS_ERROR(EINVAL); } @@ -369,7 +375,8 @@ xfs_mount_validate_sb( (sbp->sb_rextsize * sbp->sb_blocksize > XFS_MAX_RTEXTSIZE) || (sbp->sb_rextsize * sbp->sb_blocksize < XFS_MIN_RTEXTSIZE) || (sbp->sb_imax_pct > 100 /* zero sb_imax_pct is valid */))) { - xfs_fs_mount_cmn_err(flags, "SB sanity check 1 failed"); + if (loud) + xfs_warn(mp, "SB sanity check 1 failed"); return XFS_ERROR(EFSCORRUPTED); } @@ -382,7 +389,8 @@ xfs_mount_validate_sb( (xfs_drfsbno_t)sbp->sb_agcount * sbp->sb_agblocks || sbp->sb_dblocks < (xfs_drfsbno_t)(sbp->sb_agcount - 1) * sbp->sb_agblocks + XFS_MIN_AG_BLOCKS)) { - xfs_fs_mount_cmn_err(flags, "SB sanity check 2 failed"); + if (loud) + xfs_warn(mp, "SB sanity check 2 failed"); return XFS_ERROR(EFSCORRUPTED); } @@ -390,12 +398,12 @@ xfs_mount_validate_sb( * Until this is fixed only page-sized or smaller data blocks work. */ if (unlikely(sbp->sb_blocksize > PAGE_SIZE)) { - xfs_fs_mount_cmn_err(flags, - "file system with blocksize %d bytes", - sbp->sb_blocksize); - xfs_fs_mount_cmn_err(flags, - "only pagesize (%ld) or less will currently work.", - PAGE_SIZE); + if (loud) { + xfs_warn(mp, + "File system with blocksize %d bytes. " + "Only pagesize (%ld) or less will currently work.", + sbp->sb_blocksize, PAGE_SIZE); + } return XFS_ERROR(ENOSYS); } @@ -409,21 +417,23 @@ xfs_mount_validate_sb( case 2048: break; default: - xfs_fs_mount_cmn_err(flags, - "inode size of %d bytes not supported", - sbp->sb_inodesize); + if (loud) + xfs_warn(mp, "inode size of %d bytes not supported", + sbp->sb_inodesize); return XFS_ERROR(ENOSYS); } if (xfs_sb_validate_fsb_count(sbp, sbp->sb_dblocks) || xfs_sb_validate_fsb_count(sbp, sbp->sb_rblocks)) { - xfs_fs_mount_cmn_err(flags, - "file system too large to be mounted on this system."); + if (loud) + xfs_warn(mp, + "file system too large to be mounted on this system."); return XFS_ERROR(EFBIG); } if (unlikely(sbp->sb_inprogress)) { - xfs_fs_mount_cmn_err(flags, "file system busy"); + if (loud) + xfs_warn(mp, "file system busy"); return XFS_ERROR(EFSCORRUPTED); } @@ -431,8 +441,9 @@ xfs_mount_validate_sb( * Version 1 directory format has never worked on Linux. */ if (unlikely(!xfs_sb_version_hasdirv2(sbp))) { - xfs_fs_mount_cmn_err(flags, - "file system using version 1 directory format"); + if (loud) + xfs_warn(mp, + "file system using version 1 directory format"); return XFS_ERROR(ENOSYS); } @@ -673,6 +684,7 @@ xfs_readsb(xfs_mount_t *mp, int flags) unsigned int sector_size; xfs_buf_t *bp; int error; + int loud = !(flags & XFS_MFSI_QUIET); ASSERT(mp->m_sb_bp == NULL); ASSERT(mp->m_ddev_targp != NULL); @@ -688,7 +700,8 @@ reread: bp = xfs_buf_read_uncached(mp, mp->m_ddev_targp, XFS_SB_DADDR, sector_size, 0); if (!bp) { - xfs_fs_mount_cmn_err(flags, "SB buffer read failed"); + if (loud) + xfs_warn(mp, "SB buffer read failed"); return EIO; } @@ -699,7 +712,8 @@ reread: xfs_sb_from_disk(&mp->m_sb, XFS_BUF_TO_SBP(bp)); error = xfs_mount_validate_sb(mp, &(mp->m_sb), flags); if (error) { - xfs_fs_mount_cmn_err(flags, "SB validate failed"); + if (loud) + xfs_warn(mp, "SB validate failed"); goto release_buf; } @@ -707,9 +721,9 @@ reread: * We must be able to do sector-sized and sector-aligned IO. */ if (sector_size > mp->m_sb.sb_sectsize) { - xfs_fs_mount_cmn_err(flags, - "device supports only %u byte sectors (not %u)", - sector_size, mp->m_sb.sb_sectsize); + if (loud) + xfs_warn(mp, "device supports %u byte sectors (not %u)", + sector_size, mp->m_sb.sb_sectsize); error = ENOSYS; goto release_buf; } -- GitLab From 5348778699bba92bf28b79863e09e7181d8cf95c Mon Sep 17 00:00:00 2001 From: Dave Chinner Date: Mon, 7 Mar 2011 10:05:35 +1100 Subject: [PATCH 0296/2822] xfs: convert xfs_fs_cmn_err to new error logging API Continue to clean up the error logging code by converting all the callers of xfs_fs_cmn_err() to the new API. Once done, remove the unused old API function. Signed-off-by: Dave Chinner Reviewed-by: Alex Elder Reviewed-by: Christoph Hellwig --- fs/xfs/quota/xfs_dquot.c | 4 ++-- fs/xfs/quota/xfs_dquot_item.c | 5 ++--- fs/xfs/quota/xfs_qm.c | 13 ++++++------ fs/xfs/support/debug.c | 20 ------------------ fs/xfs/support/debug.h | 2 -- fs/xfs/xfs_bmap.c | 2 +- fs/xfs/xfs_dfrag.c | 4 ++-- fs/xfs/xfs_dir2.c | 2 +- fs/xfs/xfs_fsops.c | 6 +++--- fs/xfs/xfs_ialloc.c | 39 +++++++++++++++-------------------- fs/xfs/xfs_inode.c | 17 +++++++-------- fs/xfs/xfs_mount.c | 16 +++++++------- fs/xfs/xfs_vnodeops.c | 8 +++---- 13 files changed, 53 insertions(+), 85 deletions(-) diff --git a/fs/xfs/quota/xfs_dquot.c b/fs/xfs/quota/xfs_dquot.c index 773adc80d6b47..e1ff7e5076704 100644 --- a/fs/xfs/quota/xfs_dquot.c +++ b/fs/xfs/quota/xfs_dquot.c @@ -1393,8 +1393,8 @@ xfs_qm_dqpurge( */ error = xfs_qm_dqflush(dqp, SYNC_WAIT); if (error) - xfs_fs_cmn_err(CE_WARN, mp, - "xfs_qm_dqpurge: dquot %p flush failed", dqp); + xfs_warn(mp, "%s: dquot %p flush failed", + __func__, dqp); xfs_dqflock(dqp); } ASSERT(atomic_read(&dqp->q_pincount) == 0); diff --git a/fs/xfs/quota/xfs_dquot_item.c b/fs/xfs/quota/xfs_dquot_item.c index 2a1f3dc10a02d..9e0e2fa3f2c8c 100644 --- a/fs/xfs/quota/xfs_dquot_item.c +++ b/fs/xfs/quota/xfs_dquot_item.c @@ -136,9 +136,8 @@ xfs_qm_dquot_logitem_push( */ error = xfs_qm_dqflush(dqp, 0); if (error) - xfs_fs_cmn_err(CE_WARN, dqp->q_mount, - "xfs_qm_dquot_logitem_push: push error %d on dqp %p", - error, dqp); + xfs_warn(dqp->q_mount, "%s: push error %d on dqp %p", + __func__, error, dqp); xfs_dqunlock(dqp); } diff --git a/fs/xfs/quota/xfs_qm.c b/fs/xfs/quota/xfs_qm.c index dd5cc5738a2c9..e34dce1ce5421 100644 --- a/fs/xfs/quota/xfs_qm.c +++ b/fs/xfs/quota/xfs_qm.c @@ -402,14 +402,13 @@ xfs_qm_mount_quotas( * off, but the on disk superblock doesn't know that ! */ ASSERT(!(XFS_IS_QUOTA_RUNNING(mp))); - xfs_fs_cmn_err(CE_ALERT, mp, - "XFS mount_quotas: Superblock update failed!"); + xfs_alert(mp, "%s: Superblock update failed!", + __func__); } } if (error) { - xfs_fs_cmn_err(CE_WARN, mp, - "Failed to initialize disk quotas."); + xfs_warn(mp, "Failed to initialize disk quotas."); return; } @@ -1257,7 +1256,7 @@ xfs_qm_qino_alloc( xfs_mod_sb(tp, sbfields); if ((error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES))) { - xfs_fs_cmn_err(CE_ALERT, mp, "XFS qino_alloc failed!"); + xfs_alert(mp, "%s failed (error %d)!", __func__, error); return error; } return 0; @@ -1930,8 +1929,8 @@ again: */ error = xfs_qm_dqflush(dqp, 0); if (error) { - xfs_fs_cmn_err(CE_WARN, mp, - "xfs_qm_dqreclaim: dquot %p flush failed", dqp); + xfs_warn(mp, "%s: dquot %p flush failed", + __func__, dqp); } goto dqunlock; } diff --git a/fs/xfs/support/debug.c b/fs/xfs/support/debug.c index feaca739d5ccc..a1c7141af481a 100644 --- a/fs/xfs/support/debug.c +++ b/fs/xfs/support/debug.c @@ -44,26 +44,6 @@ cmn_err( BUG_ON(strncmp(lvl, KERN_EMERG, strlen(KERN_EMERG)) == 0); } -void -xfs_fs_cmn_err( - const char *lvl, - struct xfs_mount *mp, - const char *fmt, - ...) -{ - struct va_format vaf; - va_list args; - - va_start(args, fmt); - vaf.fmt = fmt; - vaf.va = &args; - - printk("%sFilesystem %s: %pV", lvl, mp->m_fsname, &vaf); - va_end(args); - - BUG_ON(strncmp(lvl, KERN_EMERG, strlen(KERN_EMERG)) == 0); -} - void assfail(char *expr, char *file, int line) { diff --git a/fs/xfs/support/debug.h b/fs/xfs/support/debug.h index eaeaa17ef4b81..4a082b9a1161b 100644 --- a/fs/xfs/support/debug.h +++ b/fs/xfs/support/debug.h @@ -31,8 +31,6 @@ struct xfs_mount; void cmn_err(const char *lvl, const char *fmt, ...) __attribute__ ((format (printf, 2, 3))); -void xfs_fs_cmn_err( const char *lvl, struct xfs_mount *mp, - const char *fmt, ...) __attribute__ ((format (printf, 3, 4))); extern void assfail(char *expr, char *f, int l); diff --git a/fs/xfs/xfs_bmap.c b/fs/xfs/xfs_bmap.c index ded532dc0699b..92612f6b4b3e0 100644 --- a/fs/xfs/xfs_bmap.c +++ b/fs/xfs/xfs_bmap.c @@ -6150,7 +6150,7 @@ xfs_bmap_punch_delalloc_range( if (error) { /* something screwed, just bail */ if (!XFS_FORCED_SHUTDOWN(ip->i_mount)) { - xfs_fs_cmn_err(CE_ALERT, ip->i_mount, + xfs_alert(ip->i_mount, "Failed delalloc mapping lookup ino %lld fsb %lld.", ip->i_ino, start_fsb); } diff --git a/fs/xfs/xfs_dfrag.c b/fs/xfs/xfs_dfrag.c index e60490bc00a61..be628677c2884 100644 --- a/fs/xfs/xfs_dfrag.c +++ b/fs/xfs/xfs_dfrag.c @@ -270,9 +270,9 @@ xfs_swap_extents( /* check inode formats now that data is flushed */ error = xfs_swap_extents_check_format(ip, tip); if (error) { - xfs_fs_cmn_err(CE_NOTE, mp, + xfs_notice(mp, "%s: inode 0x%llx format is incompatible for exchanging.", - __FILE__, ip->i_ino); + __func__, ip->i_ino); goto out_unlock; } diff --git a/fs/xfs/xfs_dir2.c b/fs/xfs/xfs_dir2.c index a1321bc7f1921..dba7a71cedf3e 100644 --- a/fs/xfs/xfs_dir2.c +++ b/fs/xfs/xfs_dir2.c @@ -159,7 +159,7 @@ xfs_dir_ino_validate( XFS_AGINO_TO_INO(mp, agno, agino) == ino; if (unlikely(XFS_TEST_ERROR(!ino_ok, mp, XFS_ERRTAG_DIR_INO_VALIDATE, XFS_RANDOM_DIR_INO_VALIDATE))) { - xfs_fs_cmn_err(CE_WARN, mp, "Invalid inode number 0x%Lx", + xfs_warn(mp, "Invalid inode number 0x%Lx", (unsigned long long) ino); XFS_ERROR_REPORT("xfs_dir_ino_validate", XFS_ERRLEVEL_LOW, mp); return XFS_ERROR(EFSCORRUPTED); diff --git a/fs/xfs/xfs_fsops.c b/fs/xfs/xfs_fsops.c index 85668efb3e3e0..9153d2c77caf2 100644 --- a/fs/xfs/xfs_fsops.c +++ b/fs/xfs/xfs_fsops.c @@ -385,8 +385,8 @@ xfs_growfs_data_private( XFS_AGB_TO_DADDR(mp, agno, XFS_SB_BLOCK(mp)), XFS_FSS_TO_BB(mp, 1), 0, &bp); if (error) { - xfs_fs_cmn_err(CE_WARN, mp, - "error %d reading secondary superblock for ag %d", + xfs_warn(mp, + "error %d reading secondary superblock for ag %d", error, agno); break; } @@ -399,7 +399,7 @@ xfs_growfs_data_private( if (!(error = xfs_bwrite(mp, bp))) { continue; } else { - xfs_fs_cmn_err(CE_WARN, mp, + xfs_warn(mp, "write error %d updating secondary superblock for ag %d", error, agno); break; /* no point in continuing */ diff --git a/fs/xfs/xfs_ialloc.c b/fs/xfs/xfs_ialloc.c index 0626a32c3447a..fc3a2cb2c075f 100644 --- a/fs/xfs/xfs_ialloc.c +++ b/fs/xfs/xfs_ialloc.c @@ -1218,10 +1218,9 @@ xfs_imap_lookup( error = xfs_ialloc_read_agi(mp, tp, agno, &agbp); if (error) { - xfs_fs_cmn_err(CE_ALERT, mp, "xfs_imap: " - "xfs_ialloc_read_agi() returned " - "error %d, agno %d", - error, agno); + xfs_alert(mp, + "%s: xfs_ialloc_read_agi() returned error %d, agno %d", + __func__, error, agno); return error; } @@ -1299,24 +1298,21 @@ xfs_imap( if (flags & XFS_IGET_UNTRUSTED) return XFS_ERROR(EINVAL); if (agno >= mp->m_sb.sb_agcount) { - xfs_fs_cmn_err(CE_ALERT, mp, - "xfs_imap: agno (%d) >= " - "mp->m_sb.sb_agcount (%d)", - agno, mp->m_sb.sb_agcount); + xfs_alert(mp, + "%s: agno (%d) >= mp->m_sb.sb_agcount (%d)", + __func__, agno, mp->m_sb.sb_agcount); } if (agbno >= mp->m_sb.sb_agblocks) { - xfs_fs_cmn_err(CE_ALERT, mp, - "xfs_imap: agbno (0x%llx) >= " - "mp->m_sb.sb_agblocks (0x%lx)", - (unsigned long long) agbno, - (unsigned long) mp->m_sb.sb_agblocks); + xfs_alert(mp, + "%s: agbno (0x%llx) >= mp->m_sb.sb_agblocks (0x%lx)", + __func__, (unsigned long long)agbno, + (unsigned long)mp->m_sb.sb_agblocks); } if (ino != XFS_AGINO_TO_INO(mp, agno, agino)) { - xfs_fs_cmn_err(CE_ALERT, mp, - "xfs_imap: ino (0x%llx) != " - "XFS_AGINO_TO_INO(mp, agno, agino) " - "(0x%llx)", - ino, XFS_AGINO_TO_INO(mp, agno, agino)); + xfs_alert(mp, + "%s: ino (0x%llx) != XFS_AGINO_TO_INO() (0x%llx)", + __func__, ino, + XFS_AGINO_TO_INO(mp, agno, agino)); } xfs_stack_trace(); #endif /* DEBUG */ @@ -1388,10 +1384,9 @@ out_map: */ if ((imap->im_blkno + imap->im_len) > XFS_FSB_TO_BB(mp, mp->m_sb.sb_dblocks)) { - xfs_fs_cmn_err(CE_ALERT, mp, "xfs_imap: " - "(imap->im_blkno (0x%llx) + imap->im_len (0x%llx)) > " - " XFS_FSB_TO_BB(mp, mp->m_sb.sb_dblocks) (0x%llx)", - (unsigned long long) imap->im_blkno, + xfs_alert(mp, + "%s: (im_blkno (0x%llx) + im_len (0x%llx)) > sb_dblocks (0x%llx)", + __func__, (unsigned long long) imap->im_blkno, (unsigned long long) imap->im_len, XFS_FSB_TO_BB(mp, mp->m_sb.sb_dblocks)); return XFS_ERROR(EINVAL); diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c index 55169bbfc820c..d820ada49b182 100644 --- a/fs/xfs/xfs_inode.c +++ b/fs/xfs/xfs_inode.c @@ -110,8 +110,8 @@ xfs_inobp_check( dip = (xfs_dinode_t *)xfs_buf_offset(bp, i * mp->m_sb.sb_inodesize); if (!dip->di_next_unlinked) { - xfs_fs_cmn_err(CE_ALERT, mp, - "Detected a bogus zero next_unlinked field in incore inode buffer 0x%p. About to pop an ASSERT.", + xfs_alert(mp, + "Detected bogus zero next_unlinked field in incore inode buffer 0x%p.", bp); ASSERT(dip->di_next_unlinked); } @@ -806,11 +806,9 @@ xfs_iread( */ if (be16_to_cpu(dip->di_magic) != XFS_DINODE_MAGIC) { #ifdef DEBUG - xfs_fs_cmn_err(CE_ALERT, mp, "xfs_iread: " - "dip->di_magic (0x%x) != " - "XFS_DINODE_MAGIC (0x%x)", - be16_to_cpu(dip->di_magic), - XFS_DINODE_MAGIC); + xfs_alert(mp, + "%s: dip->di_magic (0x%x) != XFS_DINODE_MAGIC (0x%x)", + __func__, be16_to_cpu(dip->di_magic), XFS_DINODE_MAGIC); #endif /* DEBUG */ error = XFS_ERROR(EINVAL); goto out_brelse; @@ -828,9 +826,8 @@ xfs_iread( error = xfs_iformat(ip, dip); if (error) { #ifdef DEBUG - xfs_fs_cmn_err(CE_ALERT, mp, "xfs_iread: " - "xfs_iformat() returned error %d", - error); + xfs_alert(mp, "%s: xfs_iformat() returned error %d", + __func__, error); #endif /* DEBUG */ goto out_brelse; } diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c index 1b43ad3d6ddb1..e39b082eb0490 100644 --- a/fs/xfs/xfs_mount.c +++ b/fs/xfs/xfs_mount.c @@ -881,8 +881,9 @@ xfs_update_alignment(xfs_mount_t *mp) if (mp->m_flags & XFS_MOUNT_RETERR) { return XFS_ERROR(EINVAL); } - xfs_fs_cmn_err(CE_WARN, mp, -"stripe alignment turned off: sunit(%d)/swidth(%d) incompatible with agsize(%d)", + xfs_warn(mp, + "stripe alignment turned off: sunit(%d)/swidth(%d) " + "incompatible with agsize(%d)", mp->m_dalign, mp->m_swidth, sbp->sb_agblocks); @@ -892,9 +893,9 @@ xfs_update_alignment(xfs_mount_t *mp) mp->m_swidth = XFS_BB_TO_FSBT(mp, mp->m_swidth); } else { if (mp->m_flags & XFS_MOUNT_RETERR) { - xfs_fs_cmn_err(CE_WARN, mp, -"stripe alignment turned off: sunit(%d) less than bsize(%d)", - mp->m_dalign, + xfs_warn(mp, + "stripe alignment turned off: sunit(%d) less than bsize(%d)", + mp->m_dalign, mp->m_blockmask +1); return XFS_ERROR(EINVAL); } @@ -1100,7 +1101,7 @@ xfs_mount_reset_sbqflags( return 0; #ifdef QUOTADEBUG - xfs_fs_cmn_err(CE_NOTE, mp, "Writing superblock quota changes"); + xfs_notice(mp, "Writing superblock quota changes"); #endif tp = xfs_trans_alloc(mp, XFS_TRANS_QM_SBCHANGE); @@ -1108,8 +1109,7 @@ xfs_mount_reset_sbqflags( XFS_DEFAULT_LOG_COUNT); if (error) { xfs_trans_cancel(tp, 0); - xfs_fs_cmn_err(CE_ALERT, mp, - "xfs_mount_reset_sbqflags: Superblock update failed!"); + xfs_alert(mp, "%s: Superblock update failed!", __func__); return error; } diff --git a/fs/xfs/xfs_vnodeops.c b/fs/xfs/xfs_vnodeops.c index 258d4f98eb9bb..e919ae1e9c659 100644 --- a/fs/xfs/xfs_vnodeops.c +++ b/fs/xfs/xfs_vnodeops.c @@ -1208,12 +1208,12 @@ xfs_inactive( */ error = xfs_bmap_finish(&tp, &free_list, &committed); if (error) - xfs_fs_cmn_err(CE_NOTE, mp, "xfs_inactive: " - "xfs_bmap_finish() returned error %d", error); + xfs_notice(mp, "%s: xfs_bmap_finish returned error %d", + __func__, error); error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES); if (error) - xfs_fs_cmn_err(CE_NOTE, mp, "xfs_inactive: " - "xfs_trans_commit() returned error %d", error); + xfs_notice(mp, "%s: xfs_trans_commit returned error %d", + __func__, error); } /* -- GitLab From 6d4a8ecb344bddbbb8c71deb4dcea0be6955cfc3 Mon Sep 17 00:00:00 2001 From: Dave Chinner Date: Mon, 7 Mar 2011 10:06:35 +1100 Subject: [PATCH 0297/2822] xfs: rename xfs_cmn_err_fsblock_zero() The "cmn_err" part of the function name is no longer relevant. Rename the function to xfs_alert_fsblock_zero() to match the new logging API. Signed-off-by: Dave Chinner Reviewed-by: Alex Elder Reviewed-by: Christoph Hellwig --- fs/xfs/xfs_iomap.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/fs/xfs/xfs_iomap.c b/fs/xfs/xfs_iomap.c index 812646fe1b3e1..091d82b94c4de 100644 --- a/fs/xfs/xfs_iomap.c +++ b/fs/xfs/xfs_iomap.c @@ -101,7 +101,7 @@ xfs_iomap_eof_align_last_fsb( } STATIC int -xfs_cmn_err_fsblock_zero( +xfs_alert_fsblock_zero( xfs_inode_t *ip, xfs_bmbt_irec_t *imap) { @@ -246,7 +246,7 @@ xfs_iomap_write_direct( } if (!(imap->br_startblock || XFS_IS_REALTIME_INODE(ip))) { - error = xfs_cmn_err_fsblock_zero(ip, imap); + error = xfs_alert_fsblock_zero(ip, imap); goto error_out; } @@ -464,7 +464,7 @@ retry: } if (!(imap[0].br_startblock || XFS_IS_REALTIME_INODE(ip))) - return xfs_cmn_err_fsblock_zero(ip, &imap[0]); + return xfs_alert_fsblock_zero(ip, &imap[0]); *ret_imap = imap[0]; return 0; @@ -614,7 +614,7 @@ xfs_iomap_write_allocate( * covers at least part of the callers request */ if (!(imap->br_startblock || XFS_IS_REALTIME_INODE(ip))) - return xfs_cmn_err_fsblock_zero(ip, imap); + return xfs_alert_fsblock_zero(ip, imap); if ((offset_fsb >= imap->br_startoff) && (offset_fsb < (imap->br_startoff + @@ -724,7 +724,7 @@ xfs_iomap_write_unwritten( return XFS_ERROR(error); if (!(imap.br_startblock || XFS_IS_REALTIME_INODE(ip))) - return xfs_cmn_err_fsblock_zero(ip, &imap); + return xfs_alert_fsblock_zero(ip, &imap); if ((numblks_fsb = imap.br_blockcount) == 0) { /* -- GitLab From 8221112b4377a3b69f2016b5cc3c550d51dd3139 Mon Sep 17 00:00:00 2001 From: Dave Chinner Date: Mon, 7 Mar 2011 10:07:35 +1100 Subject: [PATCH 0298/2822] xfs: convert the quota debug prints to new API Signed-off-by: Dave Chinner Reviewed-by: Alex Elder Reviewed-by: Christoph Hellwig --- fs/xfs/quota/xfs_qm_syscalls.c | 27 ++++++++++++--------------- 1 file changed, 12 insertions(+), 15 deletions(-) diff --git a/fs/xfs/quota/xfs_qm_syscalls.c b/fs/xfs/quota/xfs_qm_syscalls.c index bdebc183223e5..603ab867259e1 100644 --- a/fs/xfs/quota/xfs_qm_syscalls.c +++ b/fs/xfs/quota/xfs_qm_syscalls.c @@ -41,12 +41,6 @@ #include "xfs_qm.h" #include "xfs_trace.h" -#ifdef DEBUG -# define qdprintk(s, args...) cmn_err(CE_DEBUG, s, ## args) -#else -# define qdprintk(s, args...) do { } while (0) -#endif - STATIC int xfs_qm_log_quotaoff(xfs_mount_t *, xfs_qoff_logitem_t **, uint); STATIC int xfs_qm_log_quotaoff_end(xfs_mount_t *, xfs_qoff_logitem_t *, uint); @@ -294,7 +288,8 @@ xfs_qm_scall_trunc_qfiles( int error = 0, error2 = 0; if (!xfs_sb_version_hasquota(&mp->m_sb) || flags == 0) { - qdprintk("qtrunc flags=%x m_qflags=%x\n", flags, mp->m_qflags); + xfs_debug(mp, "%s: flags=%x m_qflags=%x\n", + __func__, flags, mp->m_qflags); return XFS_ERROR(EINVAL); } @@ -331,7 +326,8 @@ xfs_qm_scall_quotaon( sbflags = 0; if (flags == 0) { - qdprintk("quotaon: zero flags, m_qflags=%x\n", mp->m_qflags); + xfs_debug(mp, "%s: zero flags, m_qflags=%x\n", + __func__, mp->m_qflags); return XFS_ERROR(EINVAL); } @@ -352,8 +348,9 @@ xfs_qm_scall_quotaon( (flags & XFS_GQUOTA_ACCT) == 0 && (mp->m_sb.sb_qflags & XFS_GQUOTA_ACCT) == 0 && (flags & XFS_OQUOTA_ENFD))) { - qdprintk("Can't enforce without acct, flags=%x sbflags=%x\n", - flags, mp->m_sb.sb_qflags); + xfs_debug(mp, + "%s: Can't enforce without acct, flags=%x sbflags=%x\n", + __func__, flags, mp->m_sb.sb_qflags); return XFS_ERROR(EINVAL); } /* @@ -541,7 +538,7 @@ xfs_qm_scall_setqlim( q->qi_bsoftlimit = soft; } } else { - qdprintk("blkhard %Ld < blksoft %Ld\n", hard, soft); + xfs_debug(mp, "blkhard %Ld < blksoft %Ld\n", hard, soft); } hard = (newlim->d_fieldmask & FS_DQ_RTBHARD) ? (xfs_qcnt_t) XFS_BB_TO_FSB(mp, newlim->d_rtb_hardlimit) : @@ -557,7 +554,7 @@ xfs_qm_scall_setqlim( q->qi_rtbsoftlimit = soft; } } else { - qdprintk("rtbhard %Ld < rtbsoft %Ld\n", hard, soft); + xfs_debug(mp, "rtbhard %Ld < rtbsoft %Ld\n", hard, soft); } hard = (newlim->d_fieldmask & FS_DQ_IHARD) ? @@ -574,7 +571,7 @@ xfs_qm_scall_setqlim( q->qi_isoftlimit = soft; } } else { - qdprintk("ihard %Ld < isoft %Ld\n", hard, soft); + xfs_debug(mp, "ihard %Ld < isoft %Ld\n", hard, soft); } /* @@ -1137,8 +1134,8 @@ xfs_qm_internalqcheck_adjust( if (ino == mp->m_sb.sb_uquotino || ino == mp->m_sb.sb_gquotino) { *res = BULKSTAT_RV_NOTHING; - qdprintk("internalqcheck: ino=%llu, uqino=%llu, gqino=%llu\n", - (unsigned long long) ino, + xfs_debug(mp, "%s: ino=%llu, uqino=%llu, gqino=%llu\n", + __func__, (unsigned long long) ino, (unsigned long long) mp->m_sb.sb_uquotino, (unsigned long long) mp->m_sb.sb_gquotino); return XFS_ERROR(EINVAL); -- GitLab From 0b932cccbdc09a72aa370456a59b40ecd6b10baf Mon Sep 17 00:00:00 2001 From: Dave Chinner Date: Mon, 7 Mar 2011 10:08:35 +1100 Subject: [PATCH 0299/2822] xfs: Convert remaining cmn_err() callers to new API Once converted, kill the remainder of the cmn_err() interface. Signed-off-by: Dave Chinner Reviewed-by: Alex Elder Reviewed-by: Christoph Hellwig --- fs/xfs/quota/xfs_dquot.c | 34 ++++++++++--------- fs/xfs/quota/xfs_qm.c | 27 +++++++-------- fs/xfs/quota/xfs_qm_bhv.c | 3 +- fs/xfs/quota/xfs_qm_syscalls.c | 58 +++++++++++++++++--------------- fs/xfs/quota/xfs_trans_dquot.c | 5 +-- fs/xfs/support/debug.c | 26 --------------- fs/xfs/support/debug.h | 12 ------- fs/xfs/xfs_bmap.c | 6 ++-- fs/xfs/xfs_buf_item.c | 15 +++++---- fs/xfs/xfs_da_btree.c | 9 +++-- fs/xfs/xfs_dir2_node.c | 25 ++++++-------- fs/xfs/xfs_error.c | 16 ++++----- fs/xfs/xfs_ialloc.c | 43 ++++++++++-------------- fs/xfs/xfs_inode.c | 30 ++++++++--------- fs/xfs/xfs_mount.c | 60 ++++++++++++++-------------------- fs/xfs/xfs_rtalloc.c | 8 ++--- fs/xfs/xfs_rtalloc.h | 2 +- fs/xfs/xfs_rw.c | 17 +++++----- fs/xfs/xfs_trans_buf.c | 6 ++-- fs/xfs/xfs_vnodeops.c | 5 ++- 20 files changed, 169 insertions(+), 238 deletions(-) diff --git a/fs/xfs/quota/xfs_dquot.c b/fs/xfs/quota/xfs_dquot.c index e1ff7e5076704..7e24164785033 100644 --- a/fs/xfs/quota/xfs_dquot.c +++ b/fs/xfs/quota/xfs_dquot.c @@ -828,7 +828,7 @@ xfs_qm_dqget( if (xfs_do_dqerror) { if ((xfs_dqerror_target == mp->m_ddev_targp) && (xfs_dqreq_num++ % xfs_dqerror_mod) == 0) { - cmn_err(CE_DEBUG, "Returning error in dqget"); + xfs_debug(mp, "Returning error in dqget"); return (EIO); } } @@ -1427,36 +1427,38 @@ xfs_qm_dqpurge( void xfs_qm_dqprint(xfs_dquot_t *dqp) { - cmn_err(CE_DEBUG, "-----------KERNEL DQUOT----------------"); - cmn_err(CE_DEBUG, "---- dquotID = %d", + struct xfs_mount *mp = dqp->q_mount; + + xfs_debug(mp, "-----------KERNEL DQUOT----------------"); + xfs_debug(mp, "---- dquotID = %d", (int)be32_to_cpu(dqp->q_core.d_id)); - cmn_err(CE_DEBUG, "---- type = %s", DQFLAGTO_TYPESTR(dqp)); - cmn_err(CE_DEBUG, "---- fs = 0x%p", dqp->q_mount); - cmn_err(CE_DEBUG, "---- blkno = 0x%x", (int) dqp->q_blkno); - cmn_err(CE_DEBUG, "---- boffset = 0x%x", (int) dqp->q_bufoffset); - cmn_err(CE_DEBUG, "---- blkhlimit = %Lu (0x%x)", + xfs_debug(mp, "---- type = %s", DQFLAGTO_TYPESTR(dqp)); + xfs_debug(mp, "---- fs = 0x%p", dqp->q_mount); + xfs_debug(mp, "---- blkno = 0x%x", (int) dqp->q_blkno); + xfs_debug(mp, "---- boffset = 0x%x", (int) dqp->q_bufoffset); + xfs_debug(mp, "---- blkhlimit = %Lu (0x%x)", be64_to_cpu(dqp->q_core.d_blk_hardlimit), (int)be64_to_cpu(dqp->q_core.d_blk_hardlimit)); - cmn_err(CE_DEBUG, "---- blkslimit = %Lu (0x%x)", + xfs_debug(mp, "---- blkslimit = %Lu (0x%x)", be64_to_cpu(dqp->q_core.d_blk_softlimit), (int)be64_to_cpu(dqp->q_core.d_blk_softlimit)); - cmn_err(CE_DEBUG, "---- inohlimit = %Lu (0x%x)", + xfs_debug(mp, "---- inohlimit = %Lu (0x%x)", be64_to_cpu(dqp->q_core.d_ino_hardlimit), (int)be64_to_cpu(dqp->q_core.d_ino_hardlimit)); - cmn_err(CE_DEBUG, "---- inoslimit = %Lu (0x%x)", + xfs_debug(mp, "---- inoslimit = %Lu (0x%x)", be64_to_cpu(dqp->q_core.d_ino_softlimit), (int)be64_to_cpu(dqp->q_core.d_ino_softlimit)); - cmn_err(CE_DEBUG, "---- bcount = %Lu (0x%x)", + xfs_debug(mp, "---- bcount = %Lu (0x%x)", be64_to_cpu(dqp->q_core.d_bcount), (int)be64_to_cpu(dqp->q_core.d_bcount)); - cmn_err(CE_DEBUG, "---- icount = %Lu (0x%x)", + xfs_debug(mp, "---- icount = %Lu (0x%x)", be64_to_cpu(dqp->q_core.d_icount), (int)be64_to_cpu(dqp->q_core.d_icount)); - cmn_err(CE_DEBUG, "---- btimer = %d", + xfs_debug(mp, "---- btimer = %d", (int)be32_to_cpu(dqp->q_core.d_btimer)); - cmn_err(CE_DEBUG, "---- itimer = %d", + xfs_debug(mp, "---- itimer = %d", (int)be32_to_cpu(dqp->q_core.d_itimer)); - cmn_err(CE_DEBUG, "---------------------------"); + xfs_debug(mp, "---------------------------"); } #endif diff --git a/fs/xfs/quota/xfs_qm.c b/fs/xfs/quota/xfs_qm.c index e34dce1ce5421..254ee062bd7dd 100644 --- a/fs/xfs/quota/xfs_qm.c +++ b/fs/xfs/quota/xfs_qm.c @@ -80,7 +80,7 @@ xfs_qm_dquot_list_print( int i = 0; list_for_each_entry(dqp, &mp->m_quotainfo->qi_dqlist_lock, qi_mplist) { - cmn_err(CE_DEBUG, " %d. \"%d (%s)\" " + xfs_debug(mp, " %d. \"%d (%s)\" " "bcnt = %lld, icnt = %lld, refs = %d", i++, be32_to_cpu(dqp->q_core.d_id), DQFLAGTO_TYPESTR(dqp), @@ -205,7 +205,7 @@ xfs_qm_destroy( list_for_each_entry_safe(dqp, n, &xqm->qm_dqfrlist, q_freelist) { xfs_dqlock(dqp); #ifdef QUOTADEBUG - cmn_err(CE_DEBUG, "FREELIST destroy 0x%p", dqp); + xfs_debug(dqp->q_mount, "FREELIST destroy 0x%p", dqp); #endif list_del_init(&dqp->q_freelist); xfs_Gqm->qm_dqfrlist_cnt--; @@ -341,9 +341,7 @@ xfs_qm_mount_quotas( * quotas immediately. */ if (mp->m_sb.sb_rextents) { - cmn_err(CE_NOTE, - "Cannot turn on quotas for realtime filesystem %s", - mp->m_fsname); + xfs_notice(mp, "Cannot turn on quotas for realtime filesystem"); mp->m_qflags = 0; goto write_changes; } @@ -1668,7 +1666,7 @@ xfs_qm_quotacheck( */ ASSERT(list_empty(&mp->m_quotainfo->qi_dqlist)); - cmn_err(CE_NOTE, "XFS quotacheck %s: Please wait.", mp->m_fsname); + xfs_notice(mp, "Quotacheck needed: Please wait."); /* * First we go thru all the dquots on disk, USR and GRP/PRJ, and reset @@ -1746,9 +1744,9 @@ xfs_qm_quotacheck( error_return: if (error) { - cmn_err(CE_WARN, "XFS quotacheck %s: Unsuccessful (Error %d): " - "Disabling quotas.", - mp->m_fsname, error); + xfs_warn(mp, + "Quotacheck: Unsuccessful (Error %d): Disabling quotas.", + error); /* * We must turn off quotas. */ @@ -1756,12 +1754,11 @@ xfs_qm_quotacheck( ASSERT(xfs_Gqm != NULL); xfs_qm_destroy_quotainfo(mp); if (xfs_mount_reset_sbqflags(mp)) { - cmn_err(CE_WARN, "XFS quotacheck %s: " - "Failed to reset quota flags.", mp->m_fsname); + xfs_warn(mp, + "Quotacheck: Failed to reset quota flags."); } - } else { - cmn_err(CE_NOTE, "XFS quotacheck %s: Done.", mp->m_fsname); - } + } else + xfs_notice(mp, "Quotacheck: Done."); return (error); } @@ -2107,7 +2104,7 @@ xfs_qm_write_sb_changes( int error; #ifdef QUOTADEBUG - cmn_err(CE_NOTE, "Writing superblock quota changes :%s", mp->m_fsname); + xfs_notice(mp, "Writing superblock quota changes"); #endif tp = xfs_trans_alloc(mp, XFS_TRANS_QM_SBCHANGE); if ((error = xfs_trans_reserve(tp, 0, diff --git a/fs/xfs/quota/xfs_qm_bhv.c b/fs/xfs/quota/xfs_qm_bhv.c index 45b5cb1788abb..774d7ec6df8e8 100644 --- a/fs/xfs/quota/xfs_qm_bhv.c +++ b/fs/xfs/quota/xfs_qm_bhv.c @@ -119,8 +119,7 @@ xfs_qm_newmount( (gquotaondisk && !XFS_IS_GQUOTA_ON(mp)) || (!gquotaondisk && XFS_IS_OQUOTA_ON(mp))) && xfs_dev_is_read_only(mp, "changing quota state")) { - cmn_err(CE_WARN, - "XFS: please mount with%s%s%s%s.", + xfs_warn(mp, "please mount with%s%s%s%s.", (!quotaondisk ? "out quota" : ""), (uquotaondisk ? " usrquota" : ""), (pquotaondisk ? " prjquota" : ""), diff --git a/fs/xfs/quota/xfs_qm_syscalls.c b/fs/xfs/quota/xfs_qm_syscalls.c index 603ab867259e1..c82f06778a27d 100644 --- a/fs/xfs/quota/xfs_qm_syscalls.c +++ b/fs/xfs/quota/xfs_qm_syscalls.c @@ -936,10 +936,11 @@ struct mutex qcheck_lock; #define DQTEST_LIST_PRINT(l, NXT, title) \ { \ xfs_dqtest_t *dqp; int i = 0;\ - cmn_err(CE_DEBUG, "%s (#%d)", title, (int) (l)->qh_nelems); \ + xfs_debug(NULL, "%s (#%d)", title, (int) (l)->qh_nelems); \ for (dqp = (xfs_dqtest_t *)(l)->qh_next; dqp != NULL; \ dqp = (xfs_dqtest_t *)dqp->NXT) { \ - cmn_err(CE_DEBUG, " %d. \"%d (%s)\" bcnt = %d, icnt = %d", \ + xfs_debug(dqp->q_mount, \ + " %d. \"%d (%s)\" bcnt = %d, icnt = %d", \ ++i, dqp->d_id, DQFLAGTO_TYPESTR(dqp), \ dqp->d_bcount, dqp->d_icount); } \ } @@ -963,16 +964,17 @@ xfs_qm_hashinsert(xfs_dqhash_t *h, xfs_dqtest_t *dqp) } STATIC void xfs_qm_dqtest_print( - xfs_dqtest_t *d) + struct xfs_mount *mp, + struct dqtest *d) { - cmn_err(CE_DEBUG, "-----------DQTEST DQUOT----------------"); - cmn_err(CE_DEBUG, "---- dquot ID = %d", d->d_id); - cmn_err(CE_DEBUG, "---- fs = 0x%p", d->q_mount); - cmn_err(CE_DEBUG, "---- bcount = %Lu (0x%x)", + xfs_debug(mp, "-----------DQTEST DQUOT----------------"); + xfs_debug(mp, "---- dquot ID = %d", d->d_id); + xfs_debug(mp, "---- fs = 0x%p", d->q_mount); + xfs_debug(mp, "---- bcount = %Lu (0x%x)", d->d_bcount, (int)d->d_bcount); - cmn_err(CE_DEBUG, "---- icount = %Lu (0x%x)", + xfs_debug(mp, "---- icount = %Lu (0x%x)", d->d_icount, (int)d->d_icount); - cmn_err(CE_DEBUG, "---------------------------"); + xfs_debug(mp, "---------------------------"); } STATIC void @@ -986,12 +988,14 @@ xfs_qm_dqtest_failed( { qmtest_nfails++; if (error) - cmn_err(CE_DEBUG, "quotacheck failed id=%d, err=%d\nreason: %s", - d->d_id, error, reason); + xfs_debug(dqp->q_mount, + "quotacheck failed id=%d, err=%d\nreason: %s", + d->d_id, error, reason); else - cmn_err(CE_DEBUG, "quotacheck failed id=%d (%s) [%d != %d]", - d->d_id, reason, (int)a, (int)b); - xfs_qm_dqtest_print(d); + xfs_debug(dqp->q_mount, + "quotacheck failed id=%d (%s) [%d != %d]", + d->d_id, reason, (int)a, (int)b); + xfs_qm_dqtest_print(dqp->q_mount, d); if (dqp) xfs_qm_dqprint(dqp); } @@ -1018,9 +1022,9 @@ xfs_dqtest_cmp2( be64_to_cpu(dqp->q_core.d_bcount) >= be64_to_cpu(dqp->q_core.d_blk_softlimit)) { if (!dqp->q_core.d_btimer && dqp->q_core.d_id) { - cmn_err(CE_DEBUG, - "%d [%s] [0x%p] BLK TIMER NOT STARTED", - d->d_id, DQFLAGTO_TYPESTR(d), d->q_mount); + xfs_debug(dqp->q_mount, + "%d [%s] BLK TIMER NOT STARTED", + d->d_id, DQFLAGTO_TYPESTR(d)); err++; } } @@ -1028,16 +1032,16 @@ xfs_dqtest_cmp2( be64_to_cpu(dqp->q_core.d_icount) >= be64_to_cpu(dqp->q_core.d_ino_softlimit)) { if (!dqp->q_core.d_itimer && dqp->q_core.d_id) { - cmn_err(CE_DEBUG, - "%d [%s] [0x%p] INO TIMER NOT STARTED", - d->d_id, DQFLAGTO_TYPESTR(d), d->q_mount); + xfs_debug(dqp->q_mount, + "%d [%s] INO TIMER NOT STARTED", + d->d_id, DQFLAGTO_TYPESTR(d)); err++; } } #ifdef QUOTADEBUG if (!err) { - cmn_err(CE_DEBUG, "%d [%s] [0x%p] qchecked", - d->d_id, DQFLAGTO_TYPESTR(d), d->q_mount); + xfs_debug(dqp->q_mount, "%d [%s] qchecked", + d->d_id, DQFLAGTO_TYPESTR(d)); } #endif return (err); @@ -1220,12 +1224,12 @@ xfs_qm_internalqcheck( xfs_qm_internalqcheck_adjust, 0, NULL, &done); if (error) { - cmn_err(CE_DEBUG, "Bulkstat returned error 0x%x", error); + xfs_debug(mp, "Bulkstat returned error 0x%x", error); break; } } while (!done); - cmn_err(CE_DEBUG, "Checking results against system dquots"); + xfs_debug(mp, "Checking results against system dquots"); for (i = 0; i < qmtest_hashmask; i++) { xfs_dqtest_t *d, *n; xfs_dqhash_t *h; @@ -1243,10 +1247,10 @@ xfs_qm_internalqcheck( } if (qmtest_nfails) { - cmn_err(CE_DEBUG, "******** quotacheck failed ********"); - cmn_err(CE_DEBUG, "failures = %d", qmtest_nfails); + xfs_debug(mp, "******** quotacheck failed ********"); + xfs_debug(mp, "failures = %d", qmtest_nfails); } else { - cmn_err(CE_DEBUG, "******** quotacheck successful! ********"); + xfs_debug(mp, "******** quotacheck successful! ********"); } kmem_free(qmtest_udqtab); kmem_free(qmtest_gdqtab); diff --git a/fs/xfs/quota/xfs_trans_dquot.c b/fs/xfs/quota/xfs_trans_dquot.c index 7de91d1b75c06..2a36487313319 100644 --- a/fs/xfs/quota/xfs_trans_dquot.c +++ b/fs/xfs/quota/xfs_trans_dquot.c @@ -643,8 +643,9 @@ xfs_trans_dqresv( (XFS_IS_OQUOTA_ENFORCED(dqp->q_mount) && (XFS_QM_ISPDQ(dqp) || XFS_QM_ISGDQ(dqp))))) { #ifdef QUOTADEBUG - cmn_err(CE_DEBUG, "BLK Res: nblks=%ld + resbcount=%Ld" - " > hardlimit=%Ld?", nblks, *resbcountp, hardlimit); + xfs_debug(mp, + "BLK Res: nblks=%ld + resbcount=%Ld > hardlimit=%Ld?", + nblks, *resbcountp, hardlimit); #endif if (nblks > 0) { /* diff --git a/fs/xfs/support/debug.c b/fs/xfs/support/debug.c index a1c7141af481a..79fae3b33bdd3 100644 --- a/fs/xfs/support/debug.c +++ b/fs/xfs/support/debug.c @@ -18,32 +18,6 @@ #include #include "debug.h" -/* xfs_mount.h drags a lot of crap in, sorry.. */ -#include "xfs_sb.h" -#include "xfs_inum.h" -#include "xfs_ag.h" -#include "xfs_mount.h" -#include "xfs_error.h" - -void -cmn_err( - const char *lvl, - const char *fmt, - ...) -{ - struct va_format vaf; - va_list args; - - va_start(args, fmt); - vaf.fmt = fmt; - vaf.va = &args; - - printk("%s%pV", lvl, &vaf); - va_end(args); - - BUG_ON(strncmp(lvl, KERN_EMERG, strlen(KERN_EMERG)) == 0); -} - void assfail(char *expr, char *file, int line) { diff --git a/fs/xfs/support/debug.h b/fs/xfs/support/debug.h index 4a082b9a1161b..db36be48a43e4 100644 --- a/fs/xfs/support/debug.h +++ b/fs/xfs/support/debug.h @@ -20,18 +20,6 @@ #include -struct xfs_mount; - -#define CE_DEBUG KERN_DEBUG -#define CE_CONT KERN_INFO -#define CE_NOTE KERN_NOTICE -#define CE_WARN KERN_WARNING -#define CE_ALERT KERN_ALERT -#define CE_PANIC KERN_EMERG - -void cmn_err(const char *lvl, const char *fmt, ...) - __attribute__ ((format (printf, 2, 3))); - extern void assfail(char *expr, char *f, int l); #define ASSERT_ALWAYS(expr) \ diff --git a/fs/xfs/xfs_bmap.c b/fs/xfs/xfs_bmap.c index 92612f6b4b3e0..fa00788de2f54 100644 --- a/fs/xfs/xfs_bmap.c +++ b/fs/xfs/xfs_bmap.c @@ -5778,7 +5778,7 @@ xfs_check_block( else thispa = XFS_BMBT_PTR_ADDR(mp, block, j, dmxr); if (*thispa == *pp) { - cmn_err(CE_WARN, "%s: thispa(%d) == pp(%d) %Ld", + xfs_warn(mp, "%s: thispa(%d) == pp(%d) %Ld", __func__, j, i, (unsigned long long)be64_to_cpu(*thispa)); panic("%s: ptrs are equal in node\n", @@ -5943,11 +5943,11 @@ xfs_bmap_check_leaf_extents( return; error0: - cmn_err(CE_WARN, "%s: at error0", __func__); + xfs_warn(mp, "%s: at error0", __func__); if (bp_release) xfs_trans_brelse(NULL, bp); error_norelse: - cmn_err(CE_WARN, "%s: BAD after btree leaves for %d extents", + xfs_warn(mp, "%s: BAD after btree leaves for %d extents", __func__, i); panic("%s: CORRUPTED BTREE OR SOMETHING", __func__); return; diff --git a/fs/xfs/xfs_buf_item.c b/fs/xfs/xfs_buf_item.c index 6f8c21ce0d6d9..e5413d96f1af9 100644 --- a/fs/xfs/xfs_buf_item.c +++ b/fs/xfs/xfs_buf_item.c @@ -130,10 +130,12 @@ xfs_buf_item_log_check( orig = bip->bli_orig; buffer = XFS_BUF_PTR(bp); for (x = 0; x < XFS_BUF_COUNT(bp); x++) { - if (orig[x] != buffer[x] && !btst(bip->bli_logged, x)) - cmn_err(CE_PANIC, - "xfs_buf_item_log_check bip %x buffer %x orig %x index %d", - bip, bp, orig, x); + if (orig[x] != buffer[x] && !btst(bip->bli_logged, x)) { + xfs_emerg(bp->b_mount, + "%s: bip %x buffer %x orig %x index %d", + __func__, bip, bp, orig, x); + ASSERT(0); + } } } #else @@ -983,10 +985,9 @@ xfs_buf_iodone_callbacks( if (XFS_BUF_TARGET(bp) != lasttarg || time_after(jiffies, (lasttime + 5*HZ))) { lasttime = jiffies; - cmn_err(CE_ALERT, "Device %s, XFS metadata write error" - " block 0x%llx in %s", + xfs_alert(mp, "Device %s: metadata write error block 0x%llx", XFS_BUFTARG_NAME(XFS_BUF_TARGET(bp)), - (__uint64_t)XFS_BUF_ADDR(bp), mp->m_fsname); + (__uint64_t)XFS_BUF_ADDR(bp)); } lasttarg = XFS_BUF_TARGET(bp); diff --git a/fs/xfs/xfs_da_btree.c b/fs/xfs/xfs_da_btree.c index 1c00bedb3175c..6102ac6d1dffb 100644 --- a/fs/xfs/xfs_da_btree.c +++ b/fs/xfs/xfs_da_btree.c @@ -1995,13 +1995,12 @@ xfs_da_do_buf( error = mappedbno == -2 ? 0 : XFS_ERROR(EFSCORRUPTED); if (unlikely(error == EFSCORRUPTED)) { if (xfs_error_level >= XFS_ERRLEVEL_LOW) { - cmn_err(CE_ALERT, "xfs_da_do_buf: bno %lld\n", - (long long)bno); - cmn_err(CE_ALERT, "dir: inode %lld\n", + xfs_alert(mp, "%s: bno %lld dir: inode %lld", + __func__, (long long)bno, (long long)dp->i_ino); for (i = 0; i < nmap; i++) { - cmn_err(CE_ALERT, - "[%02d] br_startoff %lld br_startblock %lld br_blockcount %lld br_state %d\n", + xfs_alert(mp, +"[%02d] br_startoff %lld br_startblock %lld br_blockcount %lld br_state %d", i, (long long)mapp[i].br_startoff, (long long)mapp[i].br_startblock, diff --git a/fs/xfs/xfs_dir2_node.c b/fs/xfs/xfs_dir2_node.c index f9a0864b696af..a0aab7d3294fd 100644 --- a/fs/xfs/xfs_dir2_node.c +++ b/fs/xfs/xfs_dir2_node.c @@ -899,10 +899,9 @@ xfs_dir2_leafn_rebalance( if(blk2->index < 0) { state->inleaf = 1; blk2->index = 0; - cmn_err(CE_ALERT, - "xfs_dir2_leafn_rebalance: picked the wrong leaf? reverting original leaf: " - "blk1->index %d\n", - blk1->index); + xfs_alert(args->dp->i_mount, + "%s: picked the wrong leaf? reverting original leaf: blk1->index %d\n", + __func__, blk1->index); } } @@ -1641,26 +1640,22 @@ xfs_dir2_node_addname_int( } if (unlikely(xfs_dir2_db_to_fdb(mp, dbno) != fbno)) { - cmn_err(CE_ALERT, - "xfs_dir2_node_addname_int: dir ino " - "%llu needed freesp block %lld for\n" - " data block %lld, got %lld\n" - " ifbno %llu lastfbno %d\n", - (unsigned long long)dp->i_ino, + xfs_alert(mp, + "%s: dir ino " "%llu needed freesp block %lld for\n" + " data block %lld, got %lld ifbno %llu lastfbno %d", + __func__, (unsigned long long)dp->i_ino, (long long)xfs_dir2_db_to_fdb(mp, dbno), (long long)dbno, (long long)fbno, (unsigned long long)ifbno, lastfbno); if (fblk) { - cmn_err(CE_ALERT, - " fblk 0x%p blkno %llu " - "index %d magic 0x%x\n", + xfs_alert(mp, + " fblk 0x%p blkno %llu index %d magic 0x%x", fblk, (unsigned long long)fblk->blkno, fblk->index, fblk->magic); } else { - cmn_err(CE_ALERT, - " ... fblk is NULL\n"); + xfs_alert(mp, " ... fblk is NULL"); } XFS_ERROR_REPORT("xfs_dir2_node_addname_int", XFS_ERRLEVEL_LOW, mp); diff --git a/fs/xfs/xfs_error.c b/fs/xfs/xfs_error.c index 03028906f00ef..39f06336b99dd 100644 --- a/fs/xfs/xfs_error.c +++ b/fs/xfs/xfs_error.c @@ -48,7 +48,7 @@ xfs_error_trap(int e) break; if (e != xfs_etrap[i]) continue; - cmn_err(CE_NOTE, "xfs_error_trap: error %d", e); + xfs_notice(NULL, "%s: error %d", __func__, e); BUG(); break; } @@ -74,7 +74,7 @@ xfs_error_test(int error_tag, int *fsidp, char *expression, for (i = 0; i < XFS_NUM_INJECT_ERROR; i++) { if (xfs_etest[i] == error_tag && xfs_etest_fsid[i] == fsid) { - cmn_err(CE_WARN, + xfs_warn(NULL, "Injecting error (%s) at file %s, line %d, on filesystem \"%s\"", expression, file, line, xfs_etest_fsname[i]); return 1; @@ -95,14 +95,14 @@ xfs_errortag_add(int error_tag, xfs_mount_t *mp) for (i = 0; i < XFS_NUM_INJECT_ERROR; i++) { if (xfs_etest_fsid[i] == fsid && xfs_etest[i] == error_tag) { - cmn_err(CE_WARN, "XFS error tag #%d on", error_tag); + xfs_warn(mp, "error tag #%d on", error_tag); return 0; } } for (i = 0; i < XFS_NUM_INJECT_ERROR; i++) { if (xfs_etest[i] == 0) { - cmn_err(CE_WARN, "Turned on XFS error tag #%d", + xfs_warn(mp, "Turned on XFS error tag #%d", error_tag); xfs_etest[i] = error_tag; xfs_etest_fsid[i] = fsid; @@ -114,7 +114,7 @@ xfs_errortag_add(int error_tag, xfs_mount_t *mp) } } - cmn_err(CE_WARN, "error tag overflow, too many turned on"); + xfs_warn(mp, "error tag overflow, too many turned on"); return 1; } @@ -133,7 +133,7 @@ xfs_errortag_clearall(xfs_mount_t *mp, int loud) if ((fsid == 0LL || xfs_etest_fsid[i] == fsid) && xfs_etest[i] != 0) { cleared = 1; - cmn_err(CE_WARN, "Clearing XFS error tag #%d", + xfs_warn(mp, "Clearing XFS error tag #%d", xfs_etest[i]); xfs_etest[i] = 0; xfs_etest_fsid[i] = 0LL; @@ -144,9 +144,7 @@ xfs_errortag_clearall(xfs_mount_t *mp, int loud) } if (loud || cleared) - cmn_err(CE_WARN, - "Cleared all XFS error tags for filesystem \"%s\"", - mp->m_fsname); + xfs_warn(mp, "Cleared all XFS error tags for filesystem"); return 0; } diff --git a/fs/xfs/xfs_ialloc.c b/fs/xfs/xfs_ialloc.c index fc3a2cb2c075f..84ebeec166421 100644 --- a/fs/xfs/xfs_ialloc.c +++ b/fs/xfs/xfs_ialloc.c @@ -1055,28 +1055,23 @@ xfs_difree( */ agno = XFS_INO_TO_AGNO(mp, inode); if (agno >= mp->m_sb.sb_agcount) { - cmn_err(CE_WARN, - "xfs_difree: agno >= mp->m_sb.sb_agcount (%d >= %d) on %s. Returning EINVAL.", - agno, mp->m_sb.sb_agcount, mp->m_fsname); + xfs_warn(mp, "%s: agno >= mp->m_sb.sb_agcount (%d >= %d).", + __func__, agno, mp->m_sb.sb_agcount); ASSERT(0); return XFS_ERROR(EINVAL); } agino = XFS_INO_TO_AGINO(mp, inode); if (inode != XFS_AGINO_TO_INO(mp, agno, agino)) { - cmn_err(CE_WARN, - "xfs_difree: inode != XFS_AGINO_TO_INO() " - "(%llu != %llu) on %s. Returning EINVAL.", - (unsigned long long)inode, - (unsigned long long)XFS_AGINO_TO_INO(mp, agno, agino), - mp->m_fsname); + xfs_warn(mp, "%s: inode != XFS_AGINO_TO_INO() (%llu != %llu).", + __func__, (unsigned long long)inode, + (unsigned long long)XFS_AGINO_TO_INO(mp, agno, agino)); ASSERT(0); return XFS_ERROR(EINVAL); } agbno = XFS_AGINO_TO_AGBNO(mp, agino); if (agbno >= mp->m_sb.sb_agblocks) { - cmn_err(CE_WARN, - "xfs_difree: agbno >= mp->m_sb.sb_agblocks (%d >= %d) on %s. Returning EINVAL.", - agbno, mp->m_sb.sb_agblocks, mp->m_fsname); + xfs_warn(mp, "%s: agbno >= mp->m_sb.sb_agblocks (%d >= %d).", + __func__, agbno, mp->m_sb.sb_agblocks); ASSERT(0); return XFS_ERROR(EINVAL); } @@ -1085,9 +1080,8 @@ xfs_difree( */ error = xfs_ialloc_read_agi(mp, tp, agno, &agbp); if (error) { - cmn_err(CE_WARN, - "xfs_difree: xfs_ialloc_read_agi() returned an error %d on %s. Returning error.", - error, mp->m_fsname); + xfs_warn(mp, "%s: xfs_ialloc_read_agi() returned error %d.", + __func__, error); return error; } agi = XFS_BUF_TO_AGI(agbp); @@ -1106,17 +1100,15 @@ xfs_difree( * Look for the entry describing this inode. */ if ((error = xfs_inobt_lookup(cur, agino, XFS_LOOKUP_LE, &i))) { - cmn_err(CE_WARN, - "xfs_difree: xfs_inobt_lookup returned() an error %d on %s. Returning error.", - error, mp->m_fsname); + xfs_warn(mp, "%s: xfs_inobt_lookup() returned error %d.", + __func__, error); goto error0; } XFS_WANT_CORRUPTED_GOTO(i == 1, error0); error = xfs_inobt_get_rec(cur, &rec, &i); if (error) { - cmn_err(CE_WARN, - "xfs_difree: xfs_inobt_get_rec() returned an error %d on %s. Returning error.", - error, mp->m_fsname); + xfs_warn(mp, "%s: xfs_inobt_get_rec() returned error %d.", + __func__, error); goto error0; } XFS_WANT_CORRUPTED_GOTO(i == 1, error0); @@ -1157,8 +1149,8 @@ xfs_difree( xfs_trans_mod_sb(tp, XFS_TRANS_SB_IFREE, -(ilen - 1)); if ((error = xfs_btree_delete(cur, &i))) { - cmn_err(CE_WARN, "xfs_difree: xfs_btree_delete returned an error %d on %s.\n", - error, mp->m_fsname); + xfs_warn(mp, "%s: xfs_btree_delete returned error %d.", + __func__, error); goto error0; } @@ -1170,9 +1162,8 @@ xfs_difree( error = xfs_inobt_update(cur, &rec); if (error) { - cmn_err(CE_WARN, - "xfs_difree: xfs_inobt_update returned an error %d on %s.", - error, mp->m_fsname); + xfs_warn(mp, "%s: xfs_inobt_update returned error %d.", + __func__, error); goto error0; } diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c index d820ada49b182..da871f5322368 100644 --- a/fs/xfs/xfs_inode.c +++ b/fs/xfs/xfs_inode.c @@ -142,10 +142,9 @@ xfs_imap_to_bp( (int)imap->im_len, buf_flags, &bp); if (error) { if (error != EAGAIN) { - cmn_err(CE_WARN, - "xfs_imap_to_bp: xfs_trans_read_buf()returned " - "an error %d on %s. Returning error.", - error, mp->m_fsname); + xfs_warn(mp, + "%s: xfs_trans_read_buf() returned error %d.", + __func__, error); } else { ASSERT(buf_flags & XBF_TRYLOCK); } @@ -180,12 +179,11 @@ xfs_imap_to_bp( XFS_CORRUPTION_ERROR("xfs_imap_to_bp", XFS_ERRLEVEL_HIGH, mp, dip); #ifdef DEBUG - cmn_err(CE_PANIC, - "Device %s - bad inode magic/vsn " - "daddr %lld #%d (magic=%x)", - XFS_BUFTARG_NAME(mp->m_ddev_targp), + xfs_emerg(mp, + "bad inode magic/vsn daddr %lld #%d (magic=%x)", (unsigned long long)imap->im_blkno, i, be16_to_cpu(dip->di_magic)); + ASSERT(0); #endif xfs_trans_brelse(tp, bp); return XFS_ERROR(EFSCORRUPTED); @@ -1811,9 +1809,8 @@ xfs_iunlink_remove( */ error = xfs_itobp(mp, tp, ip, &dip, &ibp, XBF_LOCK); if (error) { - cmn_err(CE_WARN, - "xfs_iunlink_remove: xfs_itobp() returned an error %d on %s. Returning error.", - error, mp->m_fsname); + xfs_warn(mp, "%s: xfs_itobp() returned error %d.", + __func__, error); return error; } next_agino = be32_to_cpu(dip->di_next_unlinked); @@ -1858,9 +1855,9 @@ xfs_iunlink_remove( error = xfs_inotobp(mp, tp, next_ino, &last_dip, &last_ibp, &last_offset, 0); if (error) { - cmn_err(CE_WARN, - "xfs_iunlink_remove: xfs_inotobp() returned an error %d on %s. Returning error.", - error, mp->m_fsname); + xfs_warn(mp, + "%s: xfs_inotobp() returned error %d.", + __func__, error); return error; } next_agino = be32_to_cpu(last_dip->di_next_unlinked); @@ -1873,9 +1870,8 @@ xfs_iunlink_remove( */ error = xfs_itobp(mp, tp, ip, &dip, &ibp, XBF_LOCK); if (error) { - cmn_err(CE_WARN, - "xfs_iunlink_remove: xfs_itobp() returned an error %d on %s. Returning error.", - error, mp->m_fsname); + xfs_warn(mp, "%s: xfs_itobp(2) returned error %d.", + __func__, error); return error; } next_agino = be32_to_cpu(dip->di_next_unlinked); diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c index e39b082eb0490..bb3f9a7b24ed7 100644 --- a/fs/xfs/xfs_mount.c +++ b/fs/xfs/xfs_mount.c @@ -133,9 +133,7 @@ xfs_uuid_mount( return 0; if (uuid_is_nil(uuid)) { - cmn_err(CE_WARN, - "XFS: Filesystem %s has nil UUID - can't mount", - mp->m_fsname); + xfs_warn(mp, "Filesystem has nil UUID - can't mount"); return XFS_ERROR(EINVAL); } @@ -163,8 +161,7 @@ xfs_uuid_mount( out_duplicate: mutex_unlock(&xfs_uuid_table_mutex); - cmn_err(CE_WARN, "XFS: Filesystem %s has duplicate UUID - can't mount", - mp->m_fsname); + xfs_warn(mp, "Filesystem has duplicate UUID - can't mount"); return XFS_ERROR(EINVAL); } @@ -867,8 +864,7 @@ xfs_update_alignment(xfs_mount_t *mp) if ((BBTOB(mp->m_dalign) & mp->m_blockmask) || (BBTOB(mp->m_swidth) & mp->m_blockmask)) { if (mp->m_flags & XFS_MOUNT_RETERR) { - cmn_err(CE_WARN, - "XFS: alignment check 1 failed"); + xfs_warn(mp, "alignment check 1 failed"); return XFS_ERROR(EINVAL); } mp->m_dalign = mp->m_swidth = 0; @@ -1041,14 +1037,14 @@ xfs_check_sizes(xfs_mount_t *mp) d = (xfs_daddr_t)XFS_FSB_TO_BB(mp, mp->m_sb.sb_dblocks); if (XFS_BB_TO_FSB(mp, d) != mp->m_sb.sb_dblocks) { - cmn_err(CE_WARN, "XFS: filesystem size mismatch detected"); + xfs_warn(mp, "filesystem size mismatch detected"); return XFS_ERROR(EFBIG); } bp = xfs_buf_read_uncached(mp, mp->m_ddev_targp, d - XFS_FSS_TO_BB(mp, 1), BBTOB(XFS_FSS_TO_BB(mp, 1)), 0); if (!bp) { - cmn_err(CE_WARN, "XFS: last sector read failed"); + xfs_warn(mp, "last sector read failed"); return EIO; } xfs_buf_relse(bp); @@ -1056,14 +1052,14 @@ xfs_check_sizes(xfs_mount_t *mp) if (mp->m_logdev_targp != mp->m_ddev_targp) { d = (xfs_daddr_t)XFS_FSB_TO_BB(mp, mp->m_sb.sb_logblocks); if (XFS_BB_TO_FSB(mp, d) != mp->m_sb.sb_logblocks) { - cmn_err(CE_WARN, "XFS: log size mismatch detected"); + xfs_warn(mp, "log size mismatch detected"); return XFS_ERROR(EFBIG); } bp = xfs_buf_read_uncached(mp, mp->m_logdev_targp, d - XFS_FSB_TO_BB(mp, 1), XFS_FSB_TO_B(mp, 1), 0); if (!bp) { - cmn_err(CE_WARN, "XFS: log device read failed"); + xfs_warn(mp, "log device read failed"); return EIO; } xfs_buf_relse(bp); @@ -1175,8 +1171,7 @@ xfs_mountfs( * transaction subsystem is online. */ if (xfs_sb_has_mismatched_features2(sbp)) { - cmn_err(CE_WARN, - "XFS: correcting sb_features alignment problem"); + xfs_warn(mp, "correcting sb_features alignment problem"); sbp->sb_features2 |= sbp->sb_bad_features2; sbp->sb_bad_features2 = sbp->sb_features2; mp->m_update_flags |= XFS_SB_FEATURES2 | XFS_SB_BAD_FEATURES2; @@ -1255,7 +1250,7 @@ xfs_mountfs( */ error = xfs_rtmount_init(mp); if (error) { - cmn_err(CE_WARN, "XFS: RT mount failed"); + xfs_warn(mp, "RT mount failed"); goto out_remove_uuid; } @@ -1286,12 +1281,12 @@ xfs_mountfs( INIT_RADIX_TREE(&mp->m_perag_tree, GFP_ATOMIC); error = xfs_initialize_perag(mp, sbp->sb_agcount, &mp->m_maxagi); if (error) { - cmn_err(CE_WARN, "XFS: Failed per-ag init: %d", error); + xfs_warn(mp, "Failed per-ag init: %d", error); goto out_remove_uuid; } if (!sbp->sb_logblocks) { - cmn_err(CE_WARN, "XFS: no log defined"); + xfs_warn(mp, "no log defined"); XFS_ERROR_REPORT("xfs_mountfs", XFS_ERRLEVEL_LOW, mp); error = XFS_ERROR(EFSCORRUPTED); goto out_free_perag; @@ -1304,7 +1299,7 @@ xfs_mountfs( XFS_FSB_TO_DADDR(mp, sbp->sb_logstart), XFS_FSB_TO_BB(mp, sbp->sb_logblocks)); if (error) { - cmn_err(CE_WARN, "XFS: log mount failed"); + xfs_warn(mp, "log mount failed"); goto out_free_perag; } @@ -1341,16 +1336,14 @@ xfs_mountfs( */ error = xfs_iget(mp, NULL, sbp->sb_rootino, 0, XFS_ILOCK_EXCL, &rip); if (error) { - cmn_err(CE_WARN, "XFS: failed to read root inode"); + xfs_warn(mp, "failed to read root inode"); goto out_log_dealloc; } ASSERT(rip != NULL); if (unlikely((rip->i_d.di_mode & S_IFMT) != S_IFDIR)) { - cmn_err(CE_WARN, "XFS: corrupted root inode"); - cmn_err(CE_WARN, "Device %s - root %llu is not a directory", - XFS_BUFTARG_NAME(mp->m_ddev_targp), + xfs_warn(mp, "corrupted root inode %llu: not a directory", (unsigned long long)rip->i_ino); xfs_iunlock(rip, XFS_ILOCK_EXCL); XFS_ERROR_REPORT("xfs_mountfs_int(2)", XFS_ERRLEVEL_LOW, @@ -1370,7 +1363,7 @@ xfs_mountfs( /* * Free up the root inode. */ - cmn_err(CE_WARN, "XFS: failed to read RT inodes"); + xfs_warn(mp, "failed to read RT inodes"); goto out_rele_rip; } @@ -1382,7 +1375,7 @@ xfs_mountfs( if (mp->m_update_flags && !(mp->m_flags & XFS_MOUNT_RDONLY)) { error = xfs_mount_log_sb(mp, mp->m_update_flags); if (error) { - cmn_err(CE_WARN, "XFS: failed to write sb changes"); + xfs_warn(mp, "failed to write sb changes"); goto out_rtunmount; } } @@ -1403,10 +1396,7 @@ xfs_mountfs( * quotachecked license. */ if (mp->m_sb.sb_qflags & XFS_ALL_QUOTA_ACCT) { - cmn_err(CE_NOTE, - "XFS: resetting qflags for filesystem %s", - mp->m_fsname); - + xfs_notice(mp, "resetting quota flags"); error = xfs_mount_reset_sbqflags(mp); if (error) return error; @@ -1420,7 +1410,7 @@ xfs_mountfs( */ error = xfs_log_mount_finish(mp); if (error) { - cmn_err(CE_WARN, "XFS: log mount finish failed"); + xfs_warn(mp, "log mount finish failed"); goto out_rtunmount; } @@ -1449,8 +1439,8 @@ xfs_mountfs( resblks = xfs_default_resblks(mp); error = xfs_reserve_blocks(mp, &resblks, NULL); if (error) - cmn_err(CE_WARN, "XFS: Unable to allocate reserve " - "blocks. Continuing without a reserve pool."); + xfs_warn(mp, + "Unable to allocate reserve blocks. Continuing without reserve pool."); } return 0; @@ -1539,12 +1529,12 @@ xfs_unmountfs( resblks = 0; error = xfs_reserve_blocks(mp, &resblks, NULL); if (error) - cmn_err(CE_WARN, "XFS: Unable to free reserved block pool. " + xfs_warn(mp, "Unable to free reserved block pool. " "Freespace may not be correct on next mount."); error = xfs_log_sbcount(mp, 1); if (error) - cmn_err(CE_WARN, "XFS: Unable to update superblock counters. " + xfs_warn(mp, "Unable to update superblock counters. " "Freespace may not be correct on next mount."); xfs_unmountfs_writesb(mp); xfs_unmountfs_wait(mp); /* wait for async bufs */ @@ -2027,10 +2017,8 @@ xfs_dev_is_read_only( if (xfs_readonly_buftarg(mp->m_ddev_targp) || xfs_readonly_buftarg(mp->m_logdev_targp) || (mp->m_rtdev_targp && xfs_readonly_buftarg(mp->m_rtdev_targp))) { - cmn_err(CE_NOTE, - "XFS: %s required on read-only device.", message); - cmn_err(CE_NOTE, - "XFS: write access unavailable, cannot proceed."); + xfs_notice(mp, "%s required on read-only device.", message); + xfs_notice(mp, "write access unavailable, cannot proceed."); return EROFS; } return 0; diff --git a/fs/xfs/xfs_rtalloc.c b/fs/xfs/xfs_rtalloc.c index fbff89344badd..8f76fdff4f468 100644 --- a/fs/xfs/xfs_rtalloc.c +++ b/fs/xfs/xfs_rtalloc.c @@ -2210,8 +2210,8 @@ xfs_rtmount_init( if (sbp->sb_rblocks == 0) return 0; if (mp->m_rtdev_targp == NULL) { - cmn_err(CE_WARN, - "XFS: This filesystem has a realtime volume, use rtdev=device option"); + xfs_warn(mp, + "Filesystem has a realtime volume, use rtdev=device option"); return XFS_ERROR(ENODEV); } mp->m_rsumlevels = sbp->sb_rextslog + 1; @@ -2225,7 +2225,7 @@ xfs_rtmount_init( */ d = (xfs_daddr_t)XFS_FSB_TO_BB(mp, mp->m_sb.sb_rblocks); if (XFS_BB_TO_FSB(mp, d) != mp->m_sb.sb_rblocks) { - cmn_err(CE_WARN, "XFS: realtime mount -- %llu != %llu", + xfs_warn(mp, "realtime mount -- %llu != %llu", (unsigned long long) XFS_BB_TO_FSB(mp, d), (unsigned long long) mp->m_sb.sb_rblocks); return XFS_ERROR(EFBIG); @@ -2234,7 +2234,7 @@ xfs_rtmount_init( d - XFS_FSB_TO_BB(mp, 1), XFS_FSB_TO_B(mp, 1), 0); if (!bp) { - cmn_err(CE_WARN, "XFS: realtime device size check failed"); + xfs_warn(mp, "realtime device size check failed"); return EIO; } xfs_buf_relse(bp); diff --git a/fs/xfs/xfs_rtalloc.h b/fs/xfs/xfs_rtalloc.h index ff614c29b4414..09e1f4f35e971 100644 --- a/fs/xfs/xfs_rtalloc.h +++ b/fs/xfs/xfs_rtalloc.h @@ -154,7 +154,7 @@ xfs_rtmount_init( if (mp->m_sb.sb_rblocks == 0) return 0; - cmn_err(CE_WARN, "XFS: Not built with CONFIG_XFS_RT"); + xfs_warn(mp, "Not built with CONFIG_XFS_RT"); return ENOSYS; } # define xfs_rtmount_inodes(m) (((mp)->m_sb.sb_rblocks == 0)? 0 : (ENOSYS)) diff --git a/fs/xfs/xfs_rw.c b/fs/xfs/xfs_rw.c index ae6f49613412b..d6d6fdfe9422b 100644 --- a/fs/xfs/xfs_rw.c +++ b/fs/xfs/xfs_rw.c @@ -49,9 +49,9 @@ xfs_do_force_shutdown( logerror = flags & SHUTDOWN_LOG_IO_ERROR; if (!(flags & SHUTDOWN_FORCE_UMOUNT)) { - cmn_err(CE_NOTE, "xfs_force_shutdown(%s,0x%x) called from " - "line %d of file %s. Return address = 0x%p", - mp->m_fsname, flags, lnnum, fname, __return_address); + xfs_notice(mp, + "%s(0x%x) called from line %d of file %s. Return address = 0x%p", + __func__, flags, lnnum, fname, __return_address); } /* * No need to duplicate efforts. @@ -86,8 +86,8 @@ xfs_do_force_shutdown( } } if (!(flags & SHUTDOWN_FORCE_UMOUNT)) { - cmn_err(CE_ALERT, "Please umount the filesystem, " - "and rectify the problem(s)"); + xfs_alert(mp, + "Please umount the filesystem and rectify the problem(s)"); } } @@ -101,10 +101,9 @@ xfs_ioerror_alert( xfs_buf_t *bp, xfs_daddr_t blkno) { - cmn_err(CE_ALERT, - "I/O error in filesystem (\"%s\") meta-data dev %s block 0x%llx" - " (\"%s\") error %d buf count %zd", - (!mp || !mp->m_fsname) ? "(fs name not set)" : mp->m_fsname, + xfs_alert(mp, + "I/O error occurred: meta-data dev %s block 0x%llx" + " (\"%s\") error %d buf count %zd", XFS_BUFTARG_NAME(XFS_BUF_TARGET(bp)), (__uint64_t)blkno, func, XFS_BUF_GETERROR(bp), XFS_BUF_COUNT(bp)); diff --git a/fs/xfs/xfs_trans_buf.c b/fs/xfs/xfs_trans_buf.c index c47918c302a50..3bea66132334c 100644 --- a/fs/xfs/xfs_trans_buf.c +++ b/fs/xfs/xfs_trans_buf.c @@ -305,7 +305,7 @@ xfs_trans_read_buf( if (xfs_error_target == target) { if (((xfs_req_num++) % xfs_error_mod) == 0) { xfs_buf_relse(bp); - cmn_err(CE_DEBUG, "Returning error!\n"); + xfs_debug(mp, "Returning error!"); return XFS_ERROR(EIO); } } @@ -403,7 +403,7 @@ xfs_trans_read_buf( xfs_force_shutdown(tp->t_mountp, SHUTDOWN_META_IO_ERROR); xfs_buf_relse(bp); - cmn_err(CE_DEBUG, "Returning trans error!\n"); + xfs_debug(mp, "Returning trans error!"); return XFS_ERROR(EIO); } } @@ -427,7 +427,7 @@ shutdown_abort: */ #if defined(DEBUG) if (XFS_BUF_ISSTALE(bp) && XFS_BUF_ISDELAYWRITE(bp)) - cmn_err(CE_NOTE, "about to pop assert, bp == 0x%p", bp); + xfs_notice(mp, "about to pop assert, bp == 0x%p", bp); #endif ASSERT((XFS_BUF_BFLAGS(bp) & (XBF_STALE|XBF_DELWRI)) != (XBF_STALE|XBF_DELWRI)); diff --git a/fs/xfs/xfs_vnodeops.c b/fs/xfs/xfs_vnodeops.c index e919ae1e9c659..37d8146ee15b2 100644 --- a/fs/xfs/xfs_vnodeops.c +++ b/fs/xfs/xfs_vnodeops.c @@ -1189,9 +1189,8 @@ xfs_inactive( * inode might be lost for a long time or forever. */ if (!XFS_FORCED_SHUTDOWN(mp)) { - cmn_err(CE_NOTE, - "xfs_inactive: xfs_ifree() returned an error = %d on %s", - error, mp->m_fsname); + xfs_notice(mp, "%s: xfs_ifree returned error %d", + __func__, error); xfs_force_shutdown(mp, SHUTDOWN_META_IO_ERROR); } xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES|XFS_TRANS_ABORT); -- GitLab From 9130090b5f04f7e7bc29b944e0b1ba494fff3f98 Mon Sep 17 00:00:00 2001 From: Dave Chinner Date: Mon, 7 Mar 2011 10:09:35 +1100 Subject: [PATCH 0300/2822] xfs: kill support/debug.[ch] The remaining functionality in debug.[ch] is effectively just assert handling, conditional debug definitions and hex dumping. The hex dumping and assert function can be moved into the new printk module, while the rest can be moved into top-level header files. This allows fs/xfs/support/debug.[ch] to be completely removed from the codebase. Signed-off-by: Dave Chinner Reviewed-by: Alex Elder Reviewed-by: Christoph Hellwig --- fs/xfs/Makefile | 4 +-- fs/xfs/linux-2.6/xfs_linux.h | 22 ++++++++++++++++- fs/xfs/linux-2.6/xfs_message.c | 14 +++++++++++ fs/xfs/linux-2.6/xfs_message.h | 4 +++ fs/xfs/support/debug.c | 33 ------------------------- fs/xfs/support/debug.h | 45 ---------------------------------- fs/xfs/xfs_error.h | 4 --- 7 files changed, 40 insertions(+), 86 deletions(-) delete mode 100644 fs/xfs/support/debug.c delete mode 100644 fs/xfs/support/debug.h diff --git a/fs/xfs/Makefile b/fs/xfs/Makefile index 077784ed6a7f5..fee7901841e38 100644 --- a/fs/xfs/Makefile +++ b/fs/xfs/Makefile @@ -111,6 +111,4 @@ xfs-y += $(addprefix $(XFS_LINUX)/, \ xfs_xattr.o) # Objects in support/ -xfs-y += $(addprefix support/, \ - debug.o \ - uuid.o) +xfs-y += support/uuid.o diff --git a/fs/xfs/linux-2.6/xfs_linux.h b/fs/xfs/linux-2.6/xfs_linux.h index 1189bfcbcd3ef..244be9cbfe78d 100644 --- a/fs/xfs/linux-2.6/xfs_linux.h +++ b/fs/xfs/linux-2.6/xfs_linux.h @@ -39,7 +39,6 @@ #include #include -#include #include #include @@ -281,4 +280,25 @@ static inline __uint64_t howmany_64(__uint64_t x, __uint32_t y) #define __arch_pack #endif +#define ASSERT_ALWAYS(expr) \ + (unlikely(expr) ? (void)0 : assfail(#expr, __FILE__, __LINE__)) + +#ifndef DEBUG +#define ASSERT(expr) ((void)0) + +#ifndef STATIC +# define STATIC static noinline +#endif + +#else /* DEBUG */ + +#define ASSERT(expr) \ + (unlikely(expr) ? (void)0 : assfail(#expr, __FILE__, __LINE__)) + +#ifndef STATIC +# define STATIC noinline +#endif + +#endif /* DEBUG */ + #endif /* __XFS_LINUX__ */ diff --git a/fs/xfs/linux-2.6/xfs_message.c b/fs/xfs/linux-2.6/xfs_message.c index 6f3368eec25db..8fe8cf69d809d 100644 --- a/fs/xfs/linux-2.6/xfs_message.c +++ b/fs/xfs/linux-2.6/xfs_message.c @@ -117,3 +117,17 @@ xfs_alert_tag( return r; } + +void +assfail(char *expr, char *file, int line) +{ + xfs_emerg(NULL, "Assertion failed: %s, file: %s, line: %d", + expr, file, line); + BUG(); +} + +void +xfs_hex_dump(void *p, int length) +{ + print_hex_dump(KERN_ALERT, "", DUMP_PREFIX_ADDRESS, 16, 1, p, length, 1); +} diff --git a/fs/xfs/linux-2.6/xfs_message.h b/fs/xfs/linux-2.6/xfs_message.h index 8d2df01753040..e77ffa16745b2 100644 --- a/fs/xfs/linux-2.6/xfs_message.h +++ b/fs/xfs/linux-2.6/xfs_message.h @@ -31,4 +31,8 @@ extern int xfs_debug(const struct xfs_mount *mp, const char *fmt, ...) #define xfs_debug(mp, fmt, ...) (0) #endif +extern void assfail(char *expr, char *f, int l); + +extern void xfs_hex_dump(void *p, int length); + #endif /* __XFS_MESSAGE_H */ diff --git a/fs/xfs/support/debug.c b/fs/xfs/support/debug.c deleted file mode 100644 index 79fae3b33bdd3..0000000000000 --- a/fs/xfs/support/debug.c +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (c) 2000-2003,2005 Silicon Graphics, Inc. - * All Rights Reserved. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it would be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ -#include -#include "debug.h" - -void -assfail(char *expr, char *file, int line) -{ - printk(KERN_CRIT "Assertion failed: %s, file: %s, line: %d\n", expr, - file, line); - BUG(); -} - -void -xfs_hex_dump(void *p, int length) -{ - print_hex_dump(KERN_ALERT, "", DUMP_PREFIX_ADDRESS, 16, 1, p, length, 1); -} diff --git a/fs/xfs/support/debug.h b/fs/xfs/support/debug.h deleted file mode 100644 index db36be48a43e4..0000000000000 --- a/fs/xfs/support/debug.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (c) 2000-2005 Silicon Graphics, Inc. - * All Rights Reserved. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it would be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ -#ifndef __XFS_SUPPORT_DEBUG_H__ -#define __XFS_SUPPORT_DEBUG_H__ - -#include - -extern void assfail(char *expr, char *f, int l); - -#define ASSERT_ALWAYS(expr) \ - (unlikely(expr) ? (void)0 : assfail(#expr, __FILE__, __LINE__)) - -#ifndef DEBUG -#define ASSERT(expr) ((void)0) - -#ifndef STATIC -# define STATIC static noinline -#endif - -#else /* DEBUG */ - -#define ASSERT(expr) \ - (unlikely(expr) ? (void)0 : assfail(#expr, __FILE__, __LINE__)) - -#ifndef STATIC -# define STATIC noinline -#endif - -#endif /* DEBUG */ -#endif /* __XFS_SUPPORT_DEBUG_H__ */ diff --git a/fs/xfs/xfs_error.h b/fs/xfs/xfs_error.h index e8360514c250d..079a367f44eeb 100644 --- a/fs/xfs/xfs_error.h +++ b/fs/xfs/xfs_error.h @@ -158,8 +158,4 @@ extern int xfs_errortag_clearall(struct xfs_mount *mp, int loud); #define XFS_PTAG_SHUTDOWN_LOGERROR 0x00000040 #define XFS_PTAG_FSBLOCK_ZERO 0x00000080 -struct xfs_mount; - -extern void xfs_hex_dump(void *p, int length); - #endif /* __XFS_ERROR_H__ */ -- GitLab From 93803e0140c6216b68fe926ccc611297120da273 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Mon, 7 Mar 2011 08:59:06 +0100 Subject: [PATCH 0301/2822] cfq-iosched: fix race in cfq_set_request() We need to hold the queue lock over the reference increment, it's not atomic anymore. Signed-off-by: Jens Axboe --- block/cfq-iosched.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c index 3202c7e87fb3d..fb2141ec205ca 100644 --- a/block/cfq-iosched.c +++ b/block/cfq-iosched.c @@ -3675,12 +3675,11 @@ new_queue: cfqq->allocated[rw]++; - spin_unlock_irqrestore(q->queue_lock, flags); - cfqq->ref++; rq->elevator_private[0] = cic; rq->elevator_private[1] = cfqq; rq->elevator_private[2] = cfq_ref_get_cfqg(cfqq->cfqg); + spin_unlock_irqrestore(q->queue_lock, flags); return 0; queue_fail: -- GitLab From ef8a41df8c140f10108de75b01b6369d6e49113c Mon Sep 17 00:00:00 2001 From: Shaohua Li Date: Mon, 7 Mar 2011 09:26:29 +0100 Subject: [PATCH 0302/2822] cfq-iosched: give busy sync queue no dispatch limit If there are a sync and an async queue and the sync queue's think time is small, we can ignore the sync queue's dispatch quantum. Because the sync queue will always preempt the async queue, we don't need to care about async's latency. This can fix a performance regression of aiostress test, which is introduced by commit f8ae6e3eb825. The issue should exist even without the commit, but the commit amplifies the impact. The initial post does the same optimization for RT queue too, but since I have no real workload for it, Vivek suggests to drop it. Signed-off-by: Shaohua Li Reviewed-by: Gui Jianfeng Signed-off-by: Jens Axboe --- block/cfq-iosched.c | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c index fb2141ec205ca..135b1a48da23f 100644 --- a/block/cfq-iosched.c +++ b/block/cfq-iosched.c @@ -237,6 +237,7 @@ struct cfq_data { struct rb_root prio_trees[CFQ_PRIO_LISTS]; unsigned int busy_queues; + unsigned int busy_sync_queues; int rq_in_driver; int rq_in_flight[2]; @@ -1344,6 +1345,8 @@ static void cfq_add_cfqq_rr(struct cfq_data *cfqd, struct cfq_queue *cfqq) BUG_ON(cfq_cfqq_on_rr(cfqq)); cfq_mark_cfqq_on_rr(cfqq); cfqd->busy_queues++; + if (cfq_cfqq_sync(cfqq)) + cfqd->busy_sync_queues++; cfq_resort_rr_list(cfqd, cfqq); } @@ -1370,6 +1373,8 @@ static void cfq_del_cfqq_rr(struct cfq_data *cfqd, struct cfq_queue *cfqq) cfq_group_service_tree_del(cfqd, cfqq->cfqg); BUG_ON(!cfqd->busy_queues); cfqd->busy_queues--; + if (cfq_cfqq_sync(cfqq)) + cfqd->busy_sync_queues--; } /* @@ -2377,22 +2382,39 @@ static bool cfq_may_dispatch(struct cfq_data *cfqd, struct cfq_queue *cfqq) * Does this cfqq already have too much IO in flight? */ if (cfqq->dispatched >= max_dispatch) { + bool promote_sync = false; /* * idle queue must always only have a single IO in flight */ if (cfq_class_idle(cfqq)) return false; + /* + * If there is only one sync queue, and its think time is + * small, we can ignore async queue here and give the sync + * queue no dispatch limit. The reason is a sync queue can + * preempt async queue, limiting the sync queue doesn't make + * sense. This is useful for aiostress test. + */ + if (cfq_cfqq_sync(cfqq) && cfqd->busy_sync_queues == 1) { + struct cfq_io_context *cic = RQ_CIC(cfqq->next_rq); + + if (sample_valid(cic->ttime_samples) && + cic->ttime_mean < cfqd->cfq_slice_idle) + promote_sync = true; + } + /* * We have other queues, don't allow more IO from this one */ - if (cfqd->busy_queues > 1 && cfq_slice_used_soon(cfqd, cfqq)) + if (cfqd->busy_queues > 1 && cfq_slice_used_soon(cfqd, cfqq) && + !promote_sync) return false; /* * Sole queue user, no limit */ - if (cfqd->busy_queues == 1) + if (cfqd->busy_queues == 1 || promote_sync) max_dispatch = -1; else /* -- GitLab From a60327107b56573c305ecc78e471dbdbb4d2f426 Mon Sep 17 00:00:00 2001 From: Gui Jianfeng Date: Mon, 7 Mar 2011 09:28:09 +0100 Subject: [PATCH 0303/2822] cfq-iosched: Fix update_vdisktime logic The update_vdisktime logic is broken since commit b54ce60eb7f61f8e314b8b241b0469eda3bb1d42, st->min_vdisktime never makes a progress. Fix it. Thanks Vivek for pointing it out. Signed-off-by: Gui Jianfeng Acked-by: Vivek Goyal Signed-off-by: Jens Axboe --- block/cfq-iosched.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c index 135b1a48da23f..938ae52aa9278 100644 --- a/block/cfq-iosched.c +++ b/block/cfq-iosched.c @@ -557,15 +557,13 @@ static inline u64 min_vdisktime(u64 min_vdisktime, u64 vdisktime) static void update_min_vdisktime(struct cfq_rb_root *st) { - u64 vdisktime = st->min_vdisktime; struct cfq_group *cfqg; if (st->left) { cfqg = rb_entry_cfqg(st->left); - vdisktime = min_vdisktime(vdisktime, cfqg->vdisktime); + st->min_vdisktime = max_vdisktime(st->min_vdisktime, + cfqg->vdisktime); } - - st->min_vdisktime = max_vdisktime(st->min_vdisktime, vdisktime); } /* -- GitLab From f32cb53219a956b96a4cd1ee7c6b1b8a48d40e9f Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Mon, 17 Jan 2011 15:45:59 +0900 Subject: [PATCH 0304/2822] locks: use assign_type() Signed-off-by: Namhyung Kim Signed-off-by: J. Bruce Fields --- fs/locks.c | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/fs/locks.c b/fs/locks.c index 0f3998291f78e..2c2d3b804d62c 100644 --- a/fs/locks.c +++ b/fs/locks.c @@ -415,17 +415,7 @@ static int flock64_to_posix_lock(struct file *filp, struct file_lock *fl, fl->fl_ops = NULL; fl->fl_lmops = NULL; - switch (l->l_type) { - case F_RDLCK: - case F_WRLCK: - case F_UNLCK: - fl->fl_type = l->l_type; - break; - default: - return -EINVAL; - } - - return (0); + return assign_type(fl, l->l_type); } #endif -- GitLab From 35079582e72efcabf7c70f3d3ee4f96e6f196606 Mon Sep 17 00:00:00 2001 From: Shan Wei Date: Fri, 14 Jan 2011 17:35:59 +0800 Subject: [PATCH 0305/2822] nfsd: kill unused macro definition These macros had never been used for several years. So, remove them. Signed-off-by: Shan Wei Signed-off-by: J. Bruce Fields --- fs/nfsd/export.c | 1 - fs/nfsd/nfs4idmap.c | 1 - fs/nfsd/nfs4state.c | 2 +- 3 files changed, 1 insertion(+), 3 deletions(-) diff --git a/fs/nfsd/export.c b/fs/nfsd/export.c index 8b31e5f8795de..ad000aeb21a2a 100644 --- a/fs/nfsd/export.c +++ b/fs/nfsd/export.c @@ -299,7 +299,6 @@ svc_expkey_update(struct svc_expkey *new, struct svc_expkey *old) #define EXPORT_HASHBITS 8 #define EXPORT_HASHMAX (1<< EXPORT_HASHBITS) -#define EXPORT_HASHMASK (EXPORT_HASHMAX -1) static struct cache_head *export_table[EXPORT_HASHMAX]; diff --git a/fs/nfsd/nfs4idmap.c b/fs/nfsd/nfs4idmap.c index 6d2c397d458b6..55780a22fdbdc 100644 --- a/fs/nfsd/nfs4idmap.c +++ b/fs/nfsd/nfs4idmap.c @@ -63,7 +63,6 @@ struct ent { #define ENT_HASHBITS 8 #define ENT_HASHMAX (1 << ENT_HASHBITS) -#define ENT_HASHMASK (ENT_HASHMAX - 1) static void ent_init(struct cache_head *cnew, struct cache_head *citm) diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index 54b60bfceb8d0..c4f2b0f63e46b 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c @@ -148,7 +148,7 @@ static struct list_head ownerstr_hashtbl[OWNER_HASH_SIZE]; /* hash table for nfs4_file */ #define FILE_HASH_BITS 8 #define FILE_HASH_SIZE (1 << FILE_HASH_BITS) -#define FILE_HASH_MASK (FILE_HASH_SIZE - 1) + /* hash table for (open)nfs4_stateid */ #define STATEID_HASH_BITS 10 #define STATEID_HASH_SIZE (1 << STATEID_HASH_BITS) -- GitLab From 46d4cef9cf54f2f8b15216e3f6dad69750c69e0c Mon Sep 17 00:00:00 2001 From: Jesper Juhl Date: Sun, 6 Mar 2011 00:30:35 +0100 Subject: [PATCH 0306/2822] NFSD, VFS: Remove dead code in nfsd_rename() Currently we have the following code in fs/nfsd/vfs.c::nfsd_rename() : ... host_err = nfsd_break_lease(odentry->d_inode); if (host_err) goto out_drop_write; if (ndentry->d_inode) { host_err = nfsd_break_lease(ndentry->d_inode); if (host_err) goto out_drop_write; } if (host_err) goto out_drop_write; ... 'host_err' is guaranteed to be 0 by the time we test 'ndentry->d_inode'. If 'host_err' becomes != 0 inside the 'if' statement, then we goto 'out_drop_write'. So, after the 'if' statement there is no way that 'host_err' can be anything but 0, so the test afterwards is just dead code. This patch removes the dead code. Signed-off-by: Jesper Juhl Signed-off-by: J. Bruce Fields --- fs/nfsd/vfs.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c index da1d9701f8e44..9cc626b70fb68 100644 --- a/fs/nfsd/vfs.c +++ b/fs/nfsd/vfs.c @@ -1749,8 +1749,6 @@ nfsd_rename(struct svc_rqst *rqstp, struct svc_fh *ffhp, char *fname, int flen, if (host_err) goto out_drop_write; } - if (host_err) - goto out_drop_write; host_err = vfs_rename(fdir, odentry, tdir, ndentry); if (!host_err) { host_err = commit_metadata(tfhp); -- GitLab From 540c8cb6a576f34a9a0b04467f46bb6e67a1f852 Mon Sep 17 00:00:00 2001 From: Kevin Coffman Date: Wed, 2 Mar 2011 19:51:41 -0500 Subject: [PATCH 0307/2822] gss:krb5 only include enctype numbers in gm_upcall_enctypes Make the value in gm_upcall_enctypes just the enctype values. This allows the values to be used more easily elsewhere. Signed-off-by: Kevin Coffman Signed-off-by: J. Bruce Fields --- net/sunrpc/auth_gss/auth_gss.c | 2 +- net/sunrpc/auth_gss/gss_krb5_mech.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c index 45dbf1521b9a8..f3914d0c50795 100644 --- a/net/sunrpc/auth_gss/auth_gss.c +++ b/net/sunrpc/auth_gss/auth_gss.c @@ -417,7 +417,7 @@ static void gss_encode_v1_msg(struct gss_upcall_msg *gss_msg, gss_msg->msg.len += len; } if (mech->gm_upcall_enctypes) { - len = sprintf(p, mech->gm_upcall_enctypes); + len = sprintf(p, "enctypes=%s ", mech->gm_upcall_enctypes); p += len; gss_msg->msg.len += len; } diff --git a/net/sunrpc/auth_gss/gss_krb5_mech.c b/net/sunrpc/auth_gss/gss_krb5_mech.c index f375decc024b4..9022f0a6503e3 100644 --- a/net/sunrpc/auth_gss/gss_krb5_mech.c +++ b/net/sunrpc/auth_gss/gss_krb5_mech.c @@ -750,7 +750,7 @@ static struct gss_api_mech gss_kerberos_mech = { .gm_ops = &gss_kerberos_ops, .gm_pf_num = ARRAY_SIZE(gss_kerberos_pfs), .gm_pfs = gss_kerberos_pfs, - .gm_upcall_enctypes = "enctypes=18,17,16,23,3,1,2 ", + .gm_upcall_enctypes = "18,17,16,23,3,1,2", }; static int __init init_kerberos_module(void) -- GitLab From b0b0c0a26e846ae6646af9f59a3d2ea06b49cbc7 Mon Sep 17 00:00:00 2001 From: Kevin Coffman Date: Wed, 2 Mar 2011 19:51:42 -0500 Subject: [PATCH 0308/2822] nfsd: add proc file listing kernel's gss_krb5 enctypes Add a new proc file which lists the encryption types supported by the kernel's gss_krb5 code. Newer MIT Kerberos libraries support the assertion of acceptor subkeys. This enctype information allows user-land (svcgssd) to request that the Kerberos libraries limit the encryption types that it uses when generating the subkeys. Signed-off-by: Kevin Coffman Signed-off-by: J. Bruce Fields --- fs/nfsd/nfsctl.c | 31 ++++++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c index 33b3e2b06779d..35dcfa8eba219 100644 --- a/fs/nfsd/nfsctl.c +++ b/fs/nfsd/nfsctl.c @@ -12,13 +12,14 @@ #include #include #include +#include #include "idmap.h" #include "nfsd.h" #include "cache.h" /* - * We have a single directory with 9 nodes in it. + * We have a single directory with several nodes in it. */ enum { NFSD_Root = 1, @@ -42,6 +43,7 @@ enum { NFSD_Versions, NFSD_Ports, NFSD_MaxBlkSize, + NFSD_SupportedEnctypes, /* * The below MUST come last. Otherwise we leave a hole in nfsd_files[] * with !CONFIG_NFSD_V4 and simple_fill_super() goes oops @@ -187,6 +189,32 @@ static struct file_operations export_features_operations = { .release = single_release, }; +static int supported_enctypes_show(struct seq_file *m, void *v) +{ + struct gss_api_mech *k5mech; + + k5mech = gss_mech_get_by_name("krb5"); + if (k5mech == NULL) + goto out; + if (k5mech->gm_upcall_enctypes != NULL) + seq_printf(m, k5mech->gm_upcall_enctypes); + gss_mech_put(k5mech); +out: + return 0; +} + +static int supported_enctypes_open(struct inode *inode, struct file *file) +{ + return single_open(file, supported_enctypes_show, NULL); +} + +static struct file_operations supported_enctypes_ops = { + .open = supported_enctypes_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + extern int nfsd_pool_stats_open(struct inode *inode, struct file *file); extern int nfsd_pool_stats_release(struct inode *inode, struct file *file); @@ -1397,6 +1425,7 @@ static int nfsd_fill_super(struct super_block * sb, void * data, int silent) [NFSD_Versions] = {"versions", &transaction_ops, S_IWUSR|S_IRUSR}, [NFSD_Ports] = {"portlist", &transaction_ops, S_IWUSR|S_IRUGO}, [NFSD_MaxBlkSize] = {"max_block_size", &transaction_ops, S_IWUSR|S_IRUGO}, + [NFSD_SupportedEnctypes] = {"supported_krb5_enctypes", &supported_enctypes_ops, S_IRUGO}, #ifdef CONFIG_NFSD_V4 [NFSD_Leasetime] = {"nfsv4leasetime", &transaction_ops, S_IWUSR|S_IRUSR}, [NFSD_Gracetime] = {"nfsv4gracetime", &transaction_ops, S_IWUSR|S_IRUSR}, -- GitLab From 5ece3cafbd88d4da5c734e1810c4a2e6474b57b2 Mon Sep 17 00:00:00 2001 From: Mi Jinlong Date: Fri, 18 Feb 2011 09:08:31 +0800 Subject: [PATCH 0309/2822] nfsd41: modify the members value of nfsd4_op_flags The members of nfsd4_op_flags, (ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS) equals to ALLOWED_AS_FIRST_OP, maybe that's not what we want. OP_PUTROOTFH with op_flags = ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS, can't appears as the first operation with out SEQUENCE ops. This patch modify the wrong value of ALLOWED_WITHOUT_FH etc which was introduced by f9bb94c4. Cc: stable@kernel.org Reviewed-by: Benny Halevy Signed-off-by: Mi Jinlong Signed-off-by: J. Bruce Fields --- fs/nfsd/nfs4proc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c index db52546143d12..5fcb1396a7e32 100644 --- a/fs/nfsd/nfs4proc.c +++ b/fs/nfsd/nfs4proc.c @@ -984,8 +984,8 @@ typedef __be32(*nfsd4op_func)(struct svc_rqst *, struct nfsd4_compound_state *, void *); enum nfsd4_op_flags { ALLOWED_WITHOUT_FH = 1 << 0, /* No current filehandle required */ - ALLOWED_ON_ABSENT_FS = 2 << 0, /* ops processed on absent fs */ - ALLOWED_AS_FIRST_OP = 3 << 0, /* ops reqired first in compound */ + ALLOWED_ON_ABSENT_FS = 1 << 1, /* ops processed on absent fs */ + ALLOWED_AS_FIRST_OP = 1 << 2, /* ops reqired first in compound */ }; struct nfsd4_operation { -- GitLab From 231d704b4ab7491473c0b1a9cd0c6e0d1cba85b9 Mon Sep 17 00:00:00 2001 From: Vivek Goyal Date: Mon, 7 Mar 2011 21:05:14 +0100 Subject: [PATCH 0310/2822] blk-throttle: process limit change only through one function With the help of cgroup interface one can go and upate the bps/iops limits of existing group. Once the limits are udpated, a thread is woken up to see if some blocked group needs recalculation based on new limits and needs to be requeued. There was also a piece of code where I was checking for group limit update when a fresh bio comes in. This patch gets rid of that piece of code and keeps processing the limit change at one place throtl_process_limit_change(). It just keeps the code simple and easy to understand. Signed-off-by: Vivek Goyal Signed-off-by: Jens Axboe --- block/blk-throttle.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/block/blk-throttle.c b/block/blk-throttle.c index 061dee66e2a62..a29f09240c0fa 100644 --- a/block/blk-throttle.c +++ b/block/blk-throttle.c @@ -1009,14 +1009,8 @@ int blk_throtl_bio(struct request_queue *q, struct bio **biop) /* * There is already another bio queued in same dir. No * need to update dispatch time. - * Still update the disptime if rate limits on this group - * were changed. */ - if (!tg->limits_changed) - update_disptime = false; - else - tg->limits_changed = false; - + update_disptime = false; goto queue_bio; } -- GitLab From de701c74a34005e637e1ca2634fbf28fd1debba2 Mon Sep 17 00:00:00 2001 From: Vivek Goyal Date: Mon, 7 Mar 2011 21:09:32 +0100 Subject: [PATCH 0311/2822] blk-throttle: Some cleanups and race fixes in limit update code When throttle group limits are updated through cgroups, a thread is woken up to process these updates. While reviewing that code, oleg noted couple of race conditions existed in the code and he also suggested that code can be simplified. This patch fixes the races simplifies the code based on Oleg's suggestions: - Use xchg(). - Introduced a common function throtl_update_blkio_group_common() which is shared now by all iops/bps update functions. Reviewed-by: Oleg Nesterov Reviewed-by: Paul E. McKenney Signed-off-by: Vivek Goyal Fixed a merge issue, throtl_schedule_delayed_work() takes throtl_data as the argument now, not the queue. Signed-off-by: Jens Axboe --- block/blk-throttle.c | 96 ++++++++++++++++++-------------------------- 1 file changed, 40 insertions(+), 56 deletions(-) diff --git a/block/blk-throttle.c b/block/blk-throttle.c index a29f09240c0fa..32dd3e4b041d7 100644 --- a/block/blk-throttle.c +++ b/block/blk-throttle.c @@ -102,7 +102,7 @@ struct throtl_data /* Work for dispatching throttled bios */ struct delayed_work throtl_work; - atomic_t limits_changed; + bool limits_changed; }; enum tg_state_flags { @@ -201,6 +201,7 @@ static struct throtl_grp * throtl_find_alloc_tg(struct throtl_data *td, RB_CLEAR_NODE(&tg->rb_node); bio_list_init(&tg->bio_lists[0]); bio_list_init(&tg->bio_lists[1]); + td->limits_changed = false; /* * Take the initial reference that will be released on destroy @@ -737,34 +738,27 @@ static void throtl_process_limit_change(struct throtl_data *td) struct throtl_grp *tg; struct hlist_node *pos, *n; - if (!atomic_read(&td->limits_changed)) + if (!td->limits_changed) return; - throtl_log(td, "limit changed =%d", atomic_read(&td->limits_changed)); + xchg(&td->limits_changed, false); - /* - * Make sure updates from throtl_update_blkio_group_read_bps() group - * of functions to tg->limits_changed are visible. We do not - * want update td->limits_changed to be visible but update to - * tg->limits_changed not being visible yet on this cpu. Hence - * the read barrier. - */ - smp_rmb(); + throtl_log(td, "limits changed"); hlist_for_each_entry_safe(tg, pos, n, &td->tg_list, tg_node) { - if (throtl_tg_on_rr(tg) && tg->limits_changed) { - throtl_log_tg(td, tg, "limit change rbps=%llu wbps=%llu" - " riops=%u wiops=%u", tg->bps[READ], - tg->bps[WRITE], tg->iops[READ], - tg->iops[WRITE]); + if (!tg->limits_changed) + continue; + + if (!xchg(&tg->limits_changed, false)) + continue; + + throtl_log_tg(td, tg, "limit change rbps=%llu wbps=%llu" + " riops=%u wiops=%u", tg->bps[READ], tg->bps[WRITE], + tg->iops[READ], tg->iops[WRITE]); + + if (throtl_tg_on_rr(tg)) tg_update_disptime(td, tg); - tg->limits_changed = false; - } } - - smp_mb__before_atomic_dec(); - atomic_dec(&td->limits_changed); - smp_mb__after_atomic_dec(); } /* Dispatch throttled bios. Should be called without queue lock held. */ @@ -898,6 +892,15 @@ void throtl_unlink_blkio_group(void *key, struct blkio_group *blkg) spin_unlock_irqrestore(td->queue->queue_lock, flags); } +static void throtl_update_blkio_group_common(struct throtl_data *td, + struct throtl_grp *tg) +{ + xchg(&tg->limits_changed, true); + xchg(&td->limits_changed, true); + /* Schedule a work now to process the limit change */ + throtl_schedule_delayed_work(td, 0); +} + /* * For all update functions, key should be a valid pointer because these * update functions are called under blkcg_lock, that means, blkg is @@ -911,61 +914,40 @@ static void throtl_update_blkio_group_read_bps(void *key, struct blkio_group *blkg, u64 read_bps) { struct throtl_data *td = key; + struct throtl_grp *tg = tg_of_blkg(blkg); - tg_of_blkg(blkg)->bps[READ] = read_bps; - /* Make sure read_bps is updated before setting limits_changed */ - smp_wmb(); - tg_of_blkg(blkg)->limits_changed = true; - - /* Make sure tg->limits_changed is updated before td->limits_changed */ - smp_mb__before_atomic_inc(); - atomic_inc(&td->limits_changed); - smp_mb__after_atomic_inc(); - - /* Schedule a work now to process the limit change */ - throtl_schedule_delayed_work(td, 0); + tg->bps[READ] = read_bps; + throtl_update_blkio_group_common(td, tg); } static void throtl_update_blkio_group_write_bps(void *key, struct blkio_group *blkg, u64 write_bps) { struct throtl_data *td = key; + struct throtl_grp *tg = tg_of_blkg(blkg); - tg_of_blkg(blkg)->bps[WRITE] = write_bps; - smp_wmb(); - tg_of_blkg(blkg)->limits_changed = true; - smp_mb__before_atomic_inc(); - atomic_inc(&td->limits_changed); - smp_mb__after_atomic_inc(); - throtl_schedule_delayed_work(td, 0); + tg->bps[WRITE] = write_bps; + throtl_update_blkio_group_common(td, tg); } static void throtl_update_blkio_group_read_iops(void *key, struct blkio_group *blkg, unsigned int read_iops) { struct throtl_data *td = key; + struct throtl_grp *tg = tg_of_blkg(blkg); - tg_of_blkg(blkg)->iops[READ] = read_iops; - smp_wmb(); - tg_of_blkg(blkg)->limits_changed = true; - smp_mb__before_atomic_inc(); - atomic_inc(&td->limits_changed); - smp_mb__after_atomic_inc(); - throtl_schedule_delayed_work(td, 0); + tg->iops[READ] = read_iops; + throtl_update_blkio_group_common(td, tg); } static void throtl_update_blkio_group_write_iops(void *key, struct blkio_group *blkg, unsigned int write_iops) { struct throtl_data *td = key; + struct throtl_grp *tg = tg_of_blkg(blkg); - tg_of_blkg(blkg)->iops[WRITE] = write_iops; - smp_wmb(); - tg_of_blkg(blkg)->limits_changed = true; - smp_mb__before_atomic_inc(); - atomic_inc(&td->limits_changed); - smp_mb__after_atomic_inc(); - throtl_schedule_delayed_work(td, 0); + tg->iops[WRITE] = write_iops; + throtl_update_blkio_group_common(td, tg); } static void throtl_shutdown_wq(struct request_queue *q) @@ -1012,6 +994,7 @@ int blk_throtl_bio(struct request_queue *q, struct bio **biop) */ update_disptime = false; goto queue_bio; + } /* Bio is with-in rate limit of group */ @@ -1052,7 +1035,7 @@ int blk_throtl_init(struct request_queue *q) INIT_HLIST_HEAD(&td->tg_list); td->tg_service_tree = THROTL_RB_ROOT; - atomic_set(&td->limits_changed, 0); + td->limits_changed = false; /* Init root group */ tg = &td->root_tg; @@ -1064,6 +1047,7 @@ int blk_throtl_init(struct request_queue *q) /* Practically unlimited BW */ tg->bps[0] = tg->bps[1] = -1; tg->iops[0] = tg->iops[1] = -1; + td->limits_changed = false; /* * Set root group reference to 2. One reference will be dropped when -- GitLab From b9652c2d127e994748d4bffc45369ed423d5ae8d Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Fri, 4 Mar 2011 22:44:27 -0700 Subject: [PATCH 0312/2822] ARM: tegra: add devices.c entries for audio For I2S, DAS, PCM devices Signed-off-by: Stephen Warren Signed-off-by: Olof Johansson --- arch/arm/mach-tegra/devices.c | 70 ++++++++++++++++++++++++ arch/arm/mach-tegra/devices.h | 4 ++ arch/arm/mach-tegra/include/mach/iomap.h | 3 + 3 files changed, 77 insertions(+) diff --git a/arch/arm/mach-tegra/devices.c b/arch/arm/mach-tegra/devices.c index 682e6d33108cd..1528f9daef1f2 100644 --- a/arch/arm/mach-tegra/devices.c +++ b/arch/arm/mach-tegra/devices.c @@ -503,3 +503,73 @@ struct platform_device tegra_uarte_device = { .coherent_dma_mask = DMA_BIT_MASK(32), }, }; + +static struct resource i2s_resource1[] = { + [0] = { + .start = INT_I2S1, + .end = INT_I2S1, + .flags = IORESOURCE_IRQ + }, + [1] = { + .start = TEGRA_DMA_REQ_SEL_I2S_1, + .end = TEGRA_DMA_REQ_SEL_I2S_1, + .flags = IORESOURCE_DMA + }, + [2] = { + .start = TEGRA_I2S1_BASE, + .end = TEGRA_I2S1_BASE + TEGRA_I2S1_SIZE - 1, + .flags = IORESOURCE_MEM + } +}; + +static struct resource i2s_resource2[] = { + [0] = { + .start = INT_I2S2, + .end = INT_I2S2, + .flags = IORESOURCE_IRQ + }, + [1] = { + .start = TEGRA_DMA_REQ_SEL_I2S2_1, + .end = TEGRA_DMA_REQ_SEL_I2S2_1, + .flags = IORESOURCE_DMA + }, + [2] = { + .start = TEGRA_I2S2_BASE, + .end = TEGRA_I2S2_BASE + TEGRA_I2S2_SIZE - 1, + .flags = IORESOURCE_MEM + } +}; + +struct platform_device tegra_i2s_device1 = { + .name = "tegra-i2s", + .id = 0, + .resource = i2s_resource1, + .num_resources = ARRAY_SIZE(i2s_resource1), +}; + +struct platform_device tegra_i2s_device2 = { + .name = "tegra-i2s", + .id = 1, + .resource = i2s_resource2, + .num_resources = ARRAY_SIZE(i2s_resource2), +}; + +static struct resource tegra_das_resources[] = { + [0] = { + .start = TEGRA_APB_MISC_DAS_BASE, + .end = TEGRA_APB_MISC_DAS_BASE + TEGRA_APB_MISC_DAS_SIZE - 1, + .flags = IORESOURCE_MEM, + }, +}; + +struct platform_device tegra_das_device = { + .name = "tegra-das", + .id = -1, + .num_resources = ARRAY_SIZE(tegra_das_resources), + .resource = tegra_das_resources, +}; + +struct platform_device tegra_pcm_device = { + .name = "tegra-pcm-audio", + .id = -1, +}; diff --git a/arch/arm/mach-tegra/devices.h b/arch/arm/mach-tegra/devices.h index 888810c37ee9d..4a7dc0a097d60 100644 --- a/arch/arm/mach-tegra/devices.h +++ b/arch/arm/mach-tegra/devices.h @@ -42,5 +42,9 @@ extern struct platform_device tegra_uartc_device; extern struct platform_device tegra_uartd_device; extern struct platform_device tegra_uarte_device; extern struct platform_device tegra_pmu_device; +extern struct platform_device tegra_i2s_device1; +extern struct platform_device tegra_i2s_device2; +extern struct platform_device tegra_das_device; +extern struct platform_device tegra_pcm_device; #endif diff --git a/arch/arm/mach-tegra/include/mach/iomap.h b/arch/arm/mach-tegra/include/mach/iomap.h index 691cdabd69cfd..19dec3ac0854a 100644 --- a/arch/arm/mach-tegra/include/mach/iomap.h +++ b/arch/arm/mach-tegra/include/mach/iomap.h @@ -122,6 +122,9 @@ #define TEGRA_APB_MISC_BASE 0x70000000 #define TEGRA_APB_MISC_SIZE SZ_4K +#define TEGRA_APB_MISC_DAS_BASE 0x70000c00 +#define TEGRA_APB_MISC_DAS_SIZE SZ_128 + #define TEGRA_AC97_BASE 0x70002000 #define TEGRA_AC97_SIZE SZ_512 -- GitLab From 986afbe493b09846dffbe5c1bf9a428a839b6ca2 Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Fri, 4 Mar 2011 22:44:28 -0700 Subject: [PATCH 0313/2822] ARM: tegra: create defines for SD-related GPIO names This ensures they're kept in sync between platform_data definitions and the GPIO table initialization. Signed-off-by: Stephen Warren Signed-off-by: Olof Johansson --- arch/arm/mach-tegra/board-harmony-pinmux.c | 12 ++++++------ arch/arm/mach-tegra/board-harmony.c | 12 ++++++------ arch/arm/mach-tegra/board-harmony.h | 7 +++++++ arch/arm/mach-tegra/board-seaboard-pinmux.c | 10 +++++----- arch/arm/mach-tegra/board-seaboard.c | 6 +++--- arch/arm/mach-tegra/board-seaboard.h | 3 +++ 6 files changed, 30 insertions(+), 20 deletions(-) diff --git a/arch/arm/mach-tegra/board-harmony-pinmux.c b/arch/arm/mach-tegra/board-harmony-pinmux.c index 98368d947be31..3ada474fbafbb 100644 --- a/arch/arm/mach-tegra/board-harmony-pinmux.c +++ b/arch/arm/mach-tegra/board-harmony-pinmux.c @@ -141,12 +141,12 @@ static struct tegra_pingroup_config harmony_pinmux[] = { }; static struct tegra_gpio_table gpio_table[] = { - { .gpio = TEGRA_GPIO_PI5, .enable = true }, /* mmc2 cd */ - { .gpio = TEGRA_GPIO_PH1, .enable = true }, /* mmc2 wp */ - { .gpio = TEGRA_GPIO_PT3, .enable = true }, /* mmc2 pwr */ - { .gpio = TEGRA_GPIO_PH2, .enable = true }, /* mmc4 cd */ - { .gpio = TEGRA_GPIO_PH3, .enable = true }, /* mmc4 wp */ - { .gpio = TEGRA_GPIO_PI6, .enable = true }, /* mmc4 pwr */ + { .gpio = TEGRA_GPIO_SD2_CD, .enable = true }, + { .gpio = TEGRA_GPIO_SD2_WP, .enable = true }, + { .gpio = TEGRA_GPIO_SD2_POWER, .enable = true }, + { .gpio = TEGRA_GPIO_SD4_CD, .enable = true }, + { .gpio = TEGRA_GPIO_SD4_WP, .enable = true }, + { .gpio = TEGRA_GPIO_SD4_POWER, .enable = true }, }; void harmony_pinmux_init(void) diff --git a/arch/arm/mach-tegra/board-harmony.c b/arch/arm/mach-tegra/board-harmony.c index 49224e936eb48..2c4a234f8acb8 100644 --- a/arch/arm/mach-tegra/board-harmony.c +++ b/arch/arm/mach-tegra/board-harmony.c @@ -91,15 +91,15 @@ static struct tegra_sdhci_platform_data sdhci_pdata1 = { }; static struct tegra_sdhci_platform_data sdhci_pdata2 = { - .cd_gpio = TEGRA_GPIO_PI5, - .wp_gpio = TEGRA_GPIO_PH1, - .power_gpio = TEGRA_GPIO_PT3, + .cd_gpio = TEGRA_GPIO_SD2_CD, + .wp_gpio = TEGRA_GPIO_SD2_WP, + .power_gpio = TEGRA_GPIO_SD2_POWER, }; static struct tegra_sdhci_platform_data sdhci_pdata4 = { - .cd_gpio = TEGRA_GPIO_PH2, - .wp_gpio = TEGRA_GPIO_PH3, - .power_gpio = TEGRA_GPIO_PI6, + .cd_gpio = TEGRA_GPIO_SD4_CD, + .wp_gpio = TEGRA_GPIO_SD4_WP, + .power_gpio = TEGRA_GPIO_SD4_POWER, .is_8bit = 1, }; diff --git a/arch/arm/mach-tegra/board-harmony.h b/arch/arm/mach-tegra/board-harmony.h index 09ca7755dd555..4fe33b8daa9dd 100644 --- a/arch/arm/mach-tegra/board-harmony.h +++ b/arch/arm/mach-tegra/board-harmony.h @@ -17,6 +17,13 @@ #ifndef _MACH_TEGRA_BOARD_HARMONY_H #define _MACH_TEGRA_BOARD_HARMONY_H +#define TEGRA_GPIO_SD2_CD TEGRA_GPIO_PI5 +#define TEGRA_GPIO_SD2_WP TEGRA_GPIO_PH1 +#define TEGRA_GPIO_SD2_POWER TEGRA_GPIO_PT3 +#define TEGRA_GPIO_SD4_CD TEGRA_GPIO_PH2 +#define TEGRA_GPIO_SD4_WP TEGRA_GPIO_PH3 +#define TEGRA_GPIO_SD4_POWER TEGRA_GPIO_PI6 + void harmony_pinmux_init(void); #endif diff --git a/arch/arm/mach-tegra/board-seaboard-pinmux.c b/arch/arm/mach-tegra/board-seaboard-pinmux.c index 2d6ad83ed4b25..7e96d4918b9eb 100644 --- a/arch/arm/mach-tegra/board-seaboard-pinmux.c +++ b/arch/arm/mach-tegra/board-seaboard-pinmux.c @@ -161,11 +161,11 @@ static __initdata struct tegra_pingroup_config seaboard_pinmux[] = { static struct tegra_gpio_table gpio_table[] = { - { .gpio = TEGRA_GPIO_PI5, .enable = true }, /* mmc2 cd */ - { .gpio = TEGRA_GPIO_PH1, .enable = true }, /* mmc2 wp */ - { .gpio = TEGRA_GPIO_PI6, .enable = true }, /* mmc2 pwr */ - { .gpio = TEGRA_GPIO_LIDSWITCH, .enable = true }, /* lid switch */ - { .gpio = TEGRA_GPIO_POWERKEY, .enable = true }, /* power key */ + { .gpio = TEGRA_GPIO_SD2_CD, .enable = true }, + { .gpio = TEGRA_GPIO_SD2_WP, .enable = true }, + { .gpio = TEGRA_GPIO_SD2_POWER, .enable = true }, + { .gpio = TEGRA_GPIO_LIDSWITCH, .enable = true }, + { .gpio = TEGRA_GPIO_POWERKEY, .enable = true }, }; void __init seaboard_pinmux_init(void) diff --git a/arch/arm/mach-tegra/board-seaboard.c b/arch/arm/mach-tegra/board-seaboard.c index 6ca9e61f6cd09..eb28dbdac007a 100644 --- a/arch/arm/mach-tegra/board-seaboard.c +++ b/arch/arm/mach-tegra/board-seaboard.c @@ -103,9 +103,9 @@ static struct tegra_sdhci_platform_data sdhci_pdata1 = { }; static struct tegra_sdhci_platform_data sdhci_pdata3 = { - .cd_gpio = TEGRA_GPIO_PI5, - .wp_gpio = TEGRA_GPIO_PH1, - .power_gpio = TEGRA_GPIO_PI6, + .cd_gpio = TEGRA_GPIO_SD2_CD, + .wp_gpio = TEGRA_GPIO_SD2_WP, + .power_gpio = TEGRA_GPIO_SD2_POWER, }; static struct tegra_sdhci_platform_data sdhci_pdata4 = { diff --git a/arch/arm/mach-tegra/board-seaboard.h b/arch/arm/mach-tegra/board-seaboard.h index a098e3599731c..d8415e1a8434f 100644 --- a/arch/arm/mach-tegra/board-seaboard.h +++ b/arch/arm/mach-tegra/board-seaboard.h @@ -17,6 +17,9 @@ #ifndef _MACH_TEGRA_BOARD_SEABOARD_H #define _MACH_TEGRA_BOARD_SEABOARD_H +#define TEGRA_GPIO_SD2_CD TEGRA_GPIO_PI5 +#define TEGRA_GPIO_SD2_WP TEGRA_GPIO_PH1 +#define TEGRA_GPIO_SD2_POWER TEGRA_GPIO_PI6 #define TEGRA_GPIO_LIDSWITCH TEGRA_GPIO_PC7 #define TEGRA_GPIO_USB1 TEGRA_GPIO_PD0 #define TEGRA_GPIO_POWERKEY TEGRA_GPIO_PV2 -- GitLab From ef2b1a0f1eb299c2d00addfee3a2631395d9bdb5 Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Fri, 4 Mar 2011 22:44:29 -0700 Subject: [PATCH 0314/2822] ARM: tegra: harmony: Beginnings of audio support This change includes everything required to enable audio on Harmony, except those parts which rely on code not currently in Tegra's for-next branch, i.e. except those parts which rely on merges of the Tegra I2C driver or latest ASoC subsystem. * Define GPIO names for audio-related GPIOs * Set up platform data and platform device for ASoC machine driver * Register audio-related platform devices * Initialize audio-related clocks * Correctly configure pinmux and GPIO enables for audio-related pins Signed-off-by: Stephen Warren Signed-off-by: Olof Johansson --- arch/arm/mach-tegra/board-harmony-pinmux.c | 16 ++++++++----- arch/arm/mach-tegra/board-harmony.c | 26 ++++++++++++++++++++++ arch/arm/mach-tegra/board-harmony.h | 7 ++++++ 3 files changed, 43 insertions(+), 6 deletions(-) diff --git a/arch/arm/mach-tegra/board-harmony-pinmux.c b/arch/arm/mach-tegra/board-harmony-pinmux.c index 3ada474fbafbb..4d63e2e97a8d4 100644 --- a/arch/arm/mach-tegra/board-harmony-pinmux.c +++ b/arch/arm/mach-tegra/board-harmony-pinmux.c @@ -27,11 +27,11 @@ static struct tegra_pingroup_config harmony_pinmux[] = { {TEGRA_PINGROUP_ATC, TEGRA_MUX_NAND, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, {TEGRA_PINGROUP_ATD, TEGRA_MUX_GMI, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, {TEGRA_PINGROUP_ATE, TEGRA_MUX_GMI, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, - {TEGRA_PINGROUP_CDEV1, TEGRA_MUX_OSC, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_TRISTATE}, + {TEGRA_PINGROUP_CDEV1, TEGRA_MUX_PLLA_OUT, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, {TEGRA_PINGROUP_CDEV2, TEGRA_MUX_PLLP_OUT4, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_TRISTATE}, {TEGRA_PINGROUP_CRTP, TEGRA_MUX_CRT, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE}, {TEGRA_PINGROUP_CSUS, TEGRA_MUX_VI_SENSOR_CLK, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_TRISTATE}, - {TEGRA_PINGROUP_DAP1, TEGRA_MUX_DAP1, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE}, + {TEGRA_PINGROUP_DAP1, TEGRA_MUX_DAP1, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, {TEGRA_PINGROUP_DAP2, TEGRA_MUX_DAP2, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE}, {TEGRA_PINGROUP_DAP3, TEGRA_MUX_DAP3, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE}, {TEGRA_PINGROUP_DAP4, TEGRA_MUX_DAP4, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE}, @@ -114,13 +114,13 @@ static struct tegra_pingroup_config harmony_pinmux[] = { {TEGRA_PINGROUP_SLXK, TEGRA_MUX_PCIE, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE}, {TEGRA_PINGROUP_SPDI, TEGRA_MUX_RSVD2, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE}, {TEGRA_PINGROUP_SPDO, TEGRA_MUX_RSVD2, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE}, - {TEGRA_PINGROUP_SPIA, TEGRA_MUX_GMI, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_TRISTATE}, - {TEGRA_PINGROUP_SPIB, TEGRA_MUX_GMI, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_TRISTATE}, - {TEGRA_PINGROUP_SPIC, TEGRA_MUX_GMI, TEGRA_PUPD_PULL_UP, TEGRA_TRI_NORMAL}, + {TEGRA_PINGROUP_SPIA, TEGRA_MUX_GMI, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, + {TEGRA_PINGROUP_SPIB, TEGRA_MUX_GMI, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, + {TEGRA_PINGROUP_SPIC, TEGRA_MUX_GMI, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE}, {TEGRA_PINGROUP_SPID, TEGRA_MUX_SPI1, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_TRISTATE}, {TEGRA_PINGROUP_SPIE, TEGRA_MUX_SPI1, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE}, {TEGRA_PINGROUP_SPIF, TEGRA_MUX_SPI1, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_TRISTATE}, - {TEGRA_PINGROUP_SPIG, TEGRA_MUX_SPI2_ALT, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE}, + {TEGRA_PINGROUP_SPIG, TEGRA_MUX_SPI2_ALT, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE}, {TEGRA_PINGROUP_SPIH, TEGRA_MUX_SPI2_ALT, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE}, {TEGRA_PINGROUP_UAA, TEGRA_MUX_ULPI, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE}, {TEGRA_PINGROUP_UAB, TEGRA_MUX_ULPI, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE}, @@ -147,6 +147,10 @@ static struct tegra_gpio_table gpio_table[] = { { .gpio = TEGRA_GPIO_SD4_CD, .enable = true }, { .gpio = TEGRA_GPIO_SD4_WP, .enable = true }, { .gpio = TEGRA_GPIO_SD4_POWER, .enable = true }, + { .gpio = TEGRA_GPIO_CDC_IRQ, .enable = true }, + { .gpio = TEGRA_GPIO_HP_DET, .enable = true }, + { .gpio = TEGRA_GPIO_INT_MIC_EN, .enable = true }, + { .gpio = TEGRA_GPIO_EXT_MIC_EN, .enable = true }, }; void harmony_pinmux_init(void) diff --git a/arch/arm/mach-tegra/board-harmony.c b/arch/arm/mach-tegra/board-harmony.c index 2c4a234f8acb8..38c2ab864503d 100644 --- a/arch/arm/mach-tegra/board-harmony.c +++ b/arch/arm/mach-tegra/board-harmony.c @@ -2,6 +2,7 @@ * arch/arm/mach-tegra/board-harmony.c * * Copyright (C) 2010 Google, Inc. + * Copyright (C) 2011 NVIDIA, Inc. * * This software is licensed under the terms of the GNU General Public * License version 2, as published by the Free Software Foundation, and @@ -22,12 +23,14 @@ #include #include #include +#include #include #include #include #include +#include #include #include #include @@ -60,11 +63,30 @@ static struct platform_device debug_uart = { }, }; +static struct harmony_audio_platform_data harmony_audio_pdata = { + .gpio_spkr_en = TEGRA_GPIO_SPKR_EN, + .gpio_hp_det = TEGRA_GPIO_HP_DET, + .gpio_int_mic_en = TEGRA_GPIO_INT_MIC_EN, + .gpio_ext_mic_en = TEGRA_GPIO_EXT_MIC_EN, +}; + +static struct platform_device harmony_audio_device = { + .name = "tegra-snd-harmony", + .id = 0, + .dev = { + .platform_data = &harmony_audio_pdata, + }, +}; + static struct platform_device *harmony_devices[] __initdata = { &debug_uart, &tegra_sdhci_device1, &tegra_sdhci_device2, &tegra_sdhci_device4, + &tegra_i2s_device1, + &tegra_das_device, + &tegra_pcm_device, + &harmony_audio_device, }; static void __init tegra_harmony_fixup(struct machine_desc *desc, @@ -80,6 +102,10 @@ static void __init tegra_harmony_fixup(struct machine_desc *desc, static __initdata struct tegra_clk_init_table harmony_clk_init_table[] = { /* name parent rate enabled */ { "uartd", "pll_p", 216000000, true }, + { "pll_a", "pll_p_out1", 56448000, true }, + { "pll_a_out0", "pll_a", 11289600, true }, + { "cdev1", NULL, 0, true }, + { "i2s1", "pll_a_out0", 11289600, false}, { NULL, NULL, 0, 0}, }; diff --git a/arch/arm/mach-tegra/board-harmony.h b/arch/arm/mach-tegra/board-harmony.h index 4fe33b8daa9dd..9243521a1d190 100644 --- a/arch/arm/mach-tegra/board-harmony.h +++ b/arch/arm/mach-tegra/board-harmony.h @@ -17,12 +17,19 @@ #ifndef _MACH_TEGRA_BOARD_HARMONY_H #define _MACH_TEGRA_BOARD_HARMONY_H +#define HARMONY_GPIO_WM8903(_x_) (TEGRA_NR_GPIOS + (_x_)) + #define TEGRA_GPIO_SD2_CD TEGRA_GPIO_PI5 #define TEGRA_GPIO_SD2_WP TEGRA_GPIO_PH1 #define TEGRA_GPIO_SD2_POWER TEGRA_GPIO_PT3 #define TEGRA_GPIO_SD4_CD TEGRA_GPIO_PH2 #define TEGRA_GPIO_SD4_WP TEGRA_GPIO_PH3 #define TEGRA_GPIO_SD4_POWER TEGRA_GPIO_PI6 +#define TEGRA_GPIO_CDC_IRQ TEGRA_GPIO_PX3 +#define TEGRA_GPIO_SPKR_EN HARMONY_GPIO_WM8903(2) +#define TEGRA_GPIO_HP_DET TEGRA_GPIO_PW2 +#define TEGRA_GPIO_INT_MIC_EN TEGRA_GPIO_PX0 +#define TEGRA_GPIO_EXT_MIC_EN TEGRA_GPIO_PX1 void harmony_pinmux_init(void); -- GitLab From f9a795af4d3b886140e790507a9158ebe3bc6a4a Mon Sep 17 00:00:00 2001 From: Olof Johansson Date: Fri, 4 Mar 2011 15:21:53 -0800 Subject: [PATCH 0315/2822] ARM: tegra: seaboard: register i2c devices Register the base i2c devices on seaboard. A few more are pending, but it's a start. Signed-off-by: Olof Johansson Acked-by: Stephen Warren --- arch/arm/mach-tegra/board-seaboard-pinmux.c | 1 + arch/arm/mach-tegra/board-seaboard.c | 62 +++++++++++++++++++-- 2 files changed, 59 insertions(+), 4 deletions(-) diff --git a/arch/arm/mach-tegra/board-seaboard-pinmux.c b/arch/arm/mach-tegra/board-seaboard-pinmux.c index 7e96d4918b9eb..0bda495e97423 100644 --- a/arch/arm/mach-tegra/board-seaboard-pinmux.c +++ b/arch/arm/mach-tegra/board-seaboard-pinmux.c @@ -166,6 +166,7 @@ static struct tegra_gpio_table gpio_table[] = { { .gpio = TEGRA_GPIO_SD2_POWER, .enable = true }, { .gpio = TEGRA_GPIO_LIDSWITCH, .enable = true }, { .gpio = TEGRA_GPIO_POWERKEY, .enable = true }, + { .gpio = TEGRA_GPIO_ISL29018_IRQ, .enable = true }, }; void __init seaboard_pinmux_init(void) diff --git a/arch/arm/mach-tegra/board-seaboard.c b/arch/arm/mach-tegra/board-seaboard.c index eb28dbdac007a..a8d7ace9f958e 100644 --- a/arch/arm/mach-tegra/board-seaboard.c +++ b/arch/arm/mach-tegra/board-seaboard.c @@ -18,9 +18,12 @@ #include #include #include +#include +#include #include #include #include +#include #include #include @@ -63,6 +66,22 @@ static __initdata struct tegra_clk_init_table seaboard_clk_init_table[] = { { NULL, NULL, 0, 0}, }; +static struct tegra_i2c_platform_data seaboard_i2c1_platform_data = { + .bus_clk_rate = 400000. +}; + +static struct tegra_i2c_platform_data seaboard_i2c2_platform_data = { + .bus_clk_rate = 400000, +}; + +static struct tegra_i2c_platform_data seaboard_i2c3_platform_data = { + .bus_clk_rate = 400000, +}; + +static struct tegra_i2c_platform_data seaboard_dvc_platform_data = { + .bus_clk_rate = 400000, +}; + static struct gpio_keys_button seaboard_gpio_keys_buttons[] = { { .code = SW_LID, @@ -124,7 +143,36 @@ static struct platform_device *seaboard_devices[] __initdata = { &seaboard_gpio_keys_device, }; -static void __init __tegra_seaboard_init(void) +static struct i2c_board_info __initdata isl29018_device = { + I2C_BOARD_INFO("isl29018", 0x44), + .irq = TEGRA_GPIO_TO_IRQ(TEGRA_GPIO_ISL29018_IRQ), +}; + +static struct i2c_board_info __initdata adt7461_device = { + I2C_BOARD_INFO("adt7461", 0x4c), +}; + +static void __init seaboard_i2c_init(void) +{ + gpio_request(TEGRA_GPIO_ISL29018_IRQ, "isl29018"); + gpio_direction_input(TEGRA_GPIO_ISL29018_IRQ); + + i2c_register_board_info(0, &isl29018_device, 1); + + i2c_register_board_info(4, &adt7461_device, 1); + + tegra_i2c_device1.dev.platform_data = &seaboard_i2c1_platform_data; + tegra_i2c_device2.dev.platform_data = &seaboard_i2c2_platform_data; + tegra_i2c_device3.dev.platform_data = &seaboard_i2c3_platform_data; + tegra_i2c_device4.dev.platform_data = &seaboard_dvc_platform_data; + + platform_device_register(&tegra_i2c_device1); + platform_device_register(&tegra_i2c_device2); + platform_device_register(&tegra_i2c_device3); + platform_device_register(&tegra_i2c_device4); +} + +static void __init seaboard_common_init(void) { seaboard_pinmux_init(); @@ -144,7 +192,9 @@ static void __init tegra_seaboard_init(void) debug_uart_platform_data[0].mapbase = TEGRA_UARTD_BASE; debug_uart_platform_data[0].irq = INT_UARTD; - __tegra_seaboard_init(); + seaboard_common_init(); + + seaboard_i2c_init(); } static void __init tegra_kaen_init(void) @@ -154,7 +204,9 @@ static void __init tegra_kaen_init(void) debug_uart_platform_data[0].mapbase = TEGRA_UARTB_BASE; debug_uart_platform_data[0].irq = INT_UARTB; - __tegra_seaboard_init(); + seaboard_common_init(); + + seaboard_i2c_init(); } static void __init tegra_wario_init(void) @@ -164,7 +216,9 @@ static void __init tegra_wario_init(void) debug_uart_platform_data[0].mapbase = TEGRA_UARTB_BASE; debug_uart_platform_data[0].irq = INT_UARTB; - __tegra_seaboard_init(); + seaboard_common_init(); + + seaboard_i2c_init(); } -- GitLab From de4855d928409caf9c366a9af643bb855aab6bf6 Mon Sep 17 00:00:00 2001 From: Olof Johansson Date: Fri, 4 Mar 2011 15:26:46 -0800 Subject: [PATCH 0316/2822] ARM: tegra: harmony: register i2c devices Register the base i2c busses on harmony. Devices coming at a later date, but this allows for hand-probing of some of them at least. Signed-off-by: Olof Johansson Acked-by: Stephen Warren --- arch/arm/mach-tegra/board-harmony.c | 32 +++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/arch/arm/mach-tegra/board-harmony.c b/arch/arm/mach-tegra/board-harmony.c index 38c2ab864503d..ea908cd0d550e 100644 --- a/arch/arm/mach-tegra/board-harmony.c +++ b/arch/arm/mach-tegra/board-harmony.c @@ -24,6 +24,8 @@ #include #include #include +#include +#include #include #include @@ -78,6 +80,35 @@ static struct platform_device harmony_audio_device = { }, }; +static struct tegra_i2c_platform_data harmony_i2c1_platform_data = { + .bus_clk_rate = 400000, +}; + +static struct tegra_i2c_platform_data harmony_i2c2_platform_data = { + .bus_clk_rate = 400000, +}; + +static struct tegra_i2c_platform_data harmony_i2c3_platform_data = { + .bus_clk_rate = 400000, +}; + +static struct tegra_i2c_platform_data harmony_dvc_platform_data = { + .bus_clk_rate = 400000, +}; + +static void __init harmony_i2c_init(void) +{ + tegra_i2c_device1.dev.platform_data = &harmony_i2c1_platform_data; + tegra_i2c_device2.dev.platform_data = &harmony_i2c2_platform_data; + tegra_i2c_device3.dev.platform_data = &harmony_i2c3_platform_data; + tegra_i2c_device4.dev.platform_data = &harmony_dvc_platform_data; + + platform_device_register(&tegra_i2c_device1); + platform_device_register(&tegra_i2c_device2); + platform_device_register(&tegra_i2c_device3); + platform_device_register(&tegra_i2c_device4); +} + static struct platform_device *harmony_devices[] __initdata = { &debug_uart, &tegra_sdhci_device1, @@ -140,6 +171,7 @@ static void __init tegra_harmony_init(void) tegra_sdhci_device4.dev.platform_data = &sdhci_pdata4; platform_add_devices(harmony_devices, ARRAY_SIZE(harmony_devices)); + harmony_i2c_init(); } MACHINE_START(HARMONY, "harmony") -- GitLab From fba3b2fc1b427696d004f5b22191620f90fe8412 Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Fri, 4 Mar 2011 22:42:31 -0700 Subject: [PATCH 0317/2822] ARM: tegra: harmony: I2C-related portions of audio support This patch is the portion of the audio-related setup that relies additionally on the latest Tegra I2C driver being merged. * Define platform data for WM8903 audio codec * Register WM8903 as an I2C device Signed-off-by: Stephen Warren Signed-off-by: Olof Johansson --- arch/arm/mach-tegra/board-harmony.c | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/arch/arm/mach-tegra/board-harmony.c b/arch/arm/mach-tegra/board-harmony.c index ea908cd0d550e..82c780345a9f0 100644 --- a/arch/arm/mach-tegra/board-harmony.c +++ b/arch/arm/mach-tegra/board-harmony.c @@ -27,6 +27,8 @@ #include #include +#include + #include #include #include @@ -96,6 +98,25 @@ static struct tegra_i2c_platform_data harmony_dvc_platform_data = { .bus_clk_rate = 400000, }; +static struct wm8903_platform_data harmony_wm8903_pdata = { + .irq_active_low = 0, + .micdet_cfg = 0, + .micdet_delay = 100, + .gpio_cfg = { + WM8903_GPIO_NO_CONFIG, + WM8903_GPIO_NO_CONFIG, + 0, + WM8903_GPIO_NO_CONFIG, + WM8903_GPIO_NO_CONFIG, + }, +}; + +static struct i2c_board_info __initdata wm8903_board_info = { + I2C_BOARD_INFO("wm8903", 0x1a), + .platform_data = &harmony_wm8903_pdata, + .irq = TEGRA_GPIO_TO_IRQ(TEGRA_GPIO_CDC_IRQ), +}; + static void __init harmony_i2c_init(void) { tegra_i2c_device1.dev.platform_data = &harmony_i2c1_platform_data; @@ -107,6 +128,8 @@ static void __init harmony_i2c_init(void) platform_device_register(&tegra_i2c_device2); platform_device_register(&tegra_i2c_device3); platform_device_register(&tegra_i2c_device4); + + i2c_register_board_info(0, &wm8903_board_info, 1); } static struct platform_device *harmony_devices[] __initdata = { -- GitLab From 06fc9a30052b82d87da4a34a9c0bb3bf7338412c Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Fri, 4 Mar 2011 22:42:32 -0700 Subject: [PATCH 0318/2822] ARM: tegra: harmony: Set WM8903 gpio_base This is the final patch to enable audio support on Harmony. It additionally relies on the latest ASoC branch being merged in, which provides the header defining the gpio_base field in the WM8903 platform data. Signed-off-by: Stephen Warren Signed-off-by: Olof Johansson --- arch/arm/mach-tegra/board-harmony.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/mach-tegra/board-harmony.c b/arch/arm/mach-tegra/board-harmony.c index 82c780345a9f0..e7c2fead1e2fb 100644 --- a/arch/arm/mach-tegra/board-harmony.c +++ b/arch/arm/mach-tegra/board-harmony.c @@ -102,6 +102,7 @@ static struct wm8903_platform_data harmony_wm8903_pdata = { .irq_active_low = 0, .micdet_cfg = 0, .micdet_delay = 100, + .gpio_base = HARMONY_GPIO_WM8903(0), .gpio_cfg = { WM8903_GPIO_NO_CONFIG, WM8903_GPIO_NO_CONFIG, -- GitLab From 65b935aa998f8df4d96ea746110af0ad7a6f8e76 Mon Sep 17 00:00:00 2001 From: Marc Dietrich Date: Mon, 7 Mar 2011 21:01:31 +0100 Subject: [PATCH 0319/2822] ARM: tegra: Add Toshiba AC100 support This patch adds the config infrastructure, the pinmux and basic board setup code for PAZ00 (name of board inside the AC100/AZ). Signed-off-by: Marc Dietrich Signed-off-by: Olof Johansson --- arch/arm/mach-tegra/Kconfig | 5 + arch/arm/mach-tegra/Makefile | 3 + arch/arm/mach-tegra/board-paz00-pinmux.c | 157 +++++++++++++++++++++++ arch/arm/mach-tegra/board-paz00.c | 128 ++++++++++++++++++ arch/arm/mach-tegra/board-paz00.h | 29 +++++ 5 files changed, 322 insertions(+) create mode 100644 arch/arm/mach-tegra/board-paz00-pinmux.c create mode 100644 arch/arm/mach-tegra/board-paz00.c create mode 100644 arch/arm/mach-tegra/board-paz00.h diff --git a/arch/arm/mach-tegra/Kconfig b/arch/arm/mach-tegra/Kconfig index b94e52df0d8e0..8df6499bf1dfe 100644 --- a/arch/arm/mach-tegra/Kconfig +++ b/arch/arm/mach-tegra/Kconfig @@ -33,6 +33,11 @@ config MACH_KAEN help Support for the Kaen version of Seaboard +config MACH_PAZ00 + bool "Paz00 board" + help + Support for the Toshiba AC100/Dynabook AZ netbook + config MACH_SEABOARD bool "Seaboard board" help diff --git a/arch/arm/mach-tegra/Makefile b/arch/arm/mach-tegra/Makefile index 9bf39fa34d859..673651f0efb82 100644 --- a/arch/arm/mach-tegra/Makefile +++ b/arch/arm/mach-tegra/Makefile @@ -22,6 +22,9 @@ obj-${CONFIG_MACH_HARMONY} += board-harmony.o obj-${CONFIG_MACH_HARMONY} += board-harmony-pinmux.o obj-${CONFIG_MACH_HARMONY} += board-harmony-pcie.o +obj-${CONFIG_MACH_PAZ00} += board-paz00.o +obj-${CONFIG_MACH_PAZ00} += board-paz00-pinmux.o + obj-${CONFIG_MACH_SEABOARD} += board-seaboard.o obj-${CONFIG_MACH_SEABOARD} += board-seaboard-pinmux.o diff --git a/arch/arm/mach-tegra/board-paz00-pinmux.c b/arch/arm/mach-tegra/board-paz00-pinmux.c new file mode 100644 index 0000000000000..2643d1bd568b5 --- /dev/null +++ b/arch/arm/mach-tegra/board-paz00-pinmux.c @@ -0,0 +1,157 @@ +/* + * arch/arm/mach-tegra/board-paz00-pinmux.c + * + * Copyright (C) 2010 Marc Dietrich + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include +#include +#include + +#include "gpio-names.h" +#include "board-paz00.h" + +static struct tegra_pingroup_config paz00_pinmux[] = { + {TEGRA_PINGROUP_ATA, TEGRA_MUX_GMI, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, + {TEGRA_PINGROUP_ATB, TEGRA_MUX_SDIO4, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, + {TEGRA_PINGROUP_ATC, TEGRA_MUX_GMI, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, + {TEGRA_PINGROUP_ATD, TEGRA_MUX_GMI, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, + {TEGRA_PINGROUP_ATE, TEGRA_MUX_GMI, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, + {TEGRA_PINGROUP_CDEV1, TEGRA_MUX_PLLA_OUT, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_TRISTATE}, + {TEGRA_PINGROUP_CDEV2, TEGRA_MUX_PLLP_OUT4, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL}, + {TEGRA_PINGROUP_CRTP, TEGRA_MUX_CRT, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE}, + {TEGRA_PINGROUP_CSUS, TEGRA_MUX_PLLC_OUT1, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_TRISTATE}, + {TEGRA_PINGROUP_DAP1, TEGRA_MUX_DAP1, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, + {TEGRA_PINGROUP_DAP2, TEGRA_MUX_GMI, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, + {TEGRA_PINGROUP_DAP3, TEGRA_MUX_DAP3, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE}, + {TEGRA_PINGROUP_DAP4, TEGRA_MUX_DAP4, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE}, + {TEGRA_PINGROUP_DDC, TEGRA_MUX_I2C2, TEGRA_PUPD_PULL_UP, TEGRA_TRI_NORMAL}, + {TEGRA_PINGROUP_DTA, TEGRA_MUX_RSVD1, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE}, + {TEGRA_PINGROUP_DTB, TEGRA_MUX_RSVD1, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE}, + {TEGRA_PINGROUP_DTC, TEGRA_MUX_RSVD1, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE}, + {TEGRA_PINGROUP_DTD, TEGRA_MUX_RSVD1, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE}, + {TEGRA_PINGROUP_DTE, TEGRA_MUX_RSVD1, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE}, + {TEGRA_PINGROUP_DTF, TEGRA_MUX_I2C3, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, + {TEGRA_PINGROUP_GMA, TEGRA_MUX_SDIO4, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, + {TEGRA_PINGROUP_GMB, TEGRA_MUX_GMI, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, + {TEGRA_PINGROUP_GMC, TEGRA_MUX_GMI, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, + {TEGRA_PINGROUP_GMD, TEGRA_MUX_GMI, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, + {TEGRA_PINGROUP_GME, TEGRA_MUX_SDIO4, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, + {TEGRA_PINGROUP_GPU, TEGRA_MUX_PWM, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, + {TEGRA_PINGROUP_GPU7, TEGRA_MUX_RTCK, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, + {TEGRA_PINGROUP_GPV, TEGRA_MUX_PCIE, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, + {TEGRA_PINGROUP_HDINT, TEGRA_MUX_HDMI, TEGRA_PUPD_PULL_UP, TEGRA_TRI_NORMAL}, + {TEGRA_PINGROUP_I2CP, TEGRA_MUX_I2C, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, + {TEGRA_PINGROUP_IRRX, TEGRA_MUX_UARTA, TEGRA_PUPD_PULL_UP, TEGRA_TRI_NORMAL}, + {TEGRA_PINGROUP_IRTX, TEGRA_MUX_UARTA, TEGRA_PUPD_PULL_UP, TEGRA_TRI_NORMAL}, + {TEGRA_PINGROUP_KBCA, TEGRA_MUX_KBC, TEGRA_PUPD_PULL_UP, TEGRA_TRI_NORMAL}, + {TEGRA_PINGROUP_KBCB, TEGRA_MUX_SDIO2, TEGRA_PUPD_PULL_UP, TEGRA_TRI_NORMAL}, + {TEGRA_PINGROUP_KBCC, TEGRA_MUX_KBC, TEGRA_PUPD_PULL_UP, TEGRA_TRI_NORMAL}, + {TEGRA_PINGROUP_KBCD, TEGRA_MUX_SDIO2, TEGRA_PUPD_PULL_UP, TEGRA_TRI_NORMAL}, + {TEGRA_PINGROUP_KBCE, TEGRA_MUX_KBC, TEGRA_PUPD_PULL_UP, TEGRA_TRI_NORMAL}, + {TEGRA_PINGROUP_KBCF, TEGRA_MUX_KBC, TEGRA_PUPD_PULL_UP, TEGRA_TRI_NORMAL}, + {TEGRA_PINGROUP_LCSN, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE}, + {TEGRA_PINGROUP_LD0, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL}, + {TEGRA_PINGROUP_LD1, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL}, + {TEGRA_PINGROUP_LD10, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL}, + {TEGRA_PINGROUP_LD11, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL}, + {TEGRA_PINGROUP_LD12, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL}, + {TEGRA_PINGROUP_LD13, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL}, + {TEGRA_PINGROUP_LD14, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL}, + {TEGRA_PINGROUP_LD15, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL}, + {TEGRA_PINGROUP_LD16, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL}, + {TEGRA_PINGROUP_LD17, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL}, + {TEGRA_PINGROUP_LD2, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL}, + {TEGRA_PINGROUP_LD3, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL}, + {TEGRA_PINGROUP_LD4, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL}, + {TEGRA_PINGROUP_LD5, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL}, + {TEGRA_PINGROUP_LD6, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL}, + {TEGRA_PINGROUP_LD7, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL}, + {TEGRA_PINGROUP_LD8, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL}, + {TEGRA_PINGROUP_LD9, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL}, + {TEGRA_PINGROUP_LDC, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_UP, TEGRA_TRI_NORMAL}, + {TEGRA_PINGROUP_LDI, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL}, + {TEGRA_PINGROUP_LHP0, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_TRISTATE}, + {TEGRA_PINGROUP_LHP1, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_TRISTATE}, + {TEGRA_PINGROUP_LHP2, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_TRISTATE}, + {TEGRA_PINGROUP_LHS, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_UP, TEGRA_TRI_NORMAL}, + {TEGRA_PINGROUP_LM0, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE}, + {TEGRA_PINGROUP_LM1, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE}, + {TEGRA_PINGROUP_LPP, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_TRISTATE}, + {TEGRA_PINGROUP_LPW0, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE}, + {TEGRA_PINGROUP_LPW1, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE}, + {TEGRA_PINGROUP_LPW2, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE}, + {TEGRA_PINGROUP_LSC0, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_UP, TEGRA_TRI_NORMAL}, + {TEGRA_PINGROUP_LSC1, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE}, + {TEGRA_PINGROUP_LSCK, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE}, + {TEGRA_PINGROUP_LSDA, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE}, + {TEGRA_PINGROUP_LSDI, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE}, + {TEGRA_PINGROUP_LSPI, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_UP, TEGRA_TRI_NORMAL}, + {TEGRA_PINGROUP_LVP0, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE}, + {TEGRA_PINGROUP_LVP1, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_TRISTATE}, + {TEGRA_PINGROUP_LVS, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_UP, TEGRA_TRI_NORMAL}, + {TEGRA_PINGROUP_OWC, TEGRA_MUX_OWR, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE}, + {TEGRA_PINGROUP_PMC, TEGRA_MUX_PWR_ON, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, + {TEGRA_PINGROUP_PTA, TEGRA_MUX_HDMI, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, + {TEGRA_PINGROUP_RM, TEGRA_MUX_I2C, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, + {TEGRA_PINGROUP_SDB, TEGRA_MUX_PWM, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE}, + {TEGRA_PINGROUP_SDC, TEGRA_MUX_TWC, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE}, + {TEGRA_PINGROUP_SDD, TEGRA_MUX_PWM, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE}, + {TEGRA_PINGROUP_SDIO1, TEGRA_MUX_SDIO1, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, + {TEGRA_PINGROUP_SLXA, TEGRA_MUX_PCIE, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE}, + {TEGRA_PINGROUP_SLXC, TEGRA_MUX_SPI4, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE}, + {TEGRA_PINGROUP_SLXD, TEGRA_MUX_SPI4, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE}, + {TEGRA_PINGROUP_SLXK, TEGRA_MUX_PCIE, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, + {TEGRA_PINGROUP_SPDI, TEGRA_MUX_RSVD2, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE}, + {TEGRA_PINGROUP_SPDO, TEGRA_MUX_RSVD2, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, + {TEGRA_PINGROUP_SPIA, TEGRA_MUX_GMI, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_TRISTATE}, + {TEGRA_PINGROUP_SPIB, TEGRA_MUX_GMI, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_TRISTATE}, + {TEGRA_PINGROUP_SPIC, TEGRA_MUX_GMI, TEGRA_PUPD_PULL_UP, TEGRA_TRI_NORMAL}, + {TEGRA_PINGROUP_SPID, TEGRA_MUX_GMI, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_TRISTATE}, + {TEGRA_PINGROUP_SPIE, TEGRA_MUX_GMI, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE}, + {TEGRA_PINGROUP_SPIF, TEGRA_MUX_RSVD4, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_TRISTATE}, + {TEGRA_PINGROUP_SPIG, TEGRA_MUX_SPI2_ALT, TEGRA_PUPD_PULL_UP, TEGRA_TRI_NORMAL}, + {TEGRA_PINGROUP_SPIH, TEGRA_MUX_SPI2_ALT, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE}, + {TEGRA_PINGROUP_UAA, TEGRA_MUX_ULPI, TEGRA_PUPD_PULL_UP, TEGRA_TRI_NORMAL}, + {TEGRA_PINGROUP_UAB, TEGRA_MUX_ULPI, TEGRA_PUPD_PULL_UP, TEGRA_TRI_NORMAL}, + {TEGRA_PINGROUP_UAC, TEGRA_MUX_RSVD4, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, + {TEGRA_PINGROUP_UAD, TEGRA_MUX_SPDIF, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE}, + {TEGRA_PINGROUP_UCA, TEGRA_MUX_UARTC, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE}, + {TEGRA_PINGROUP_UCB, TEGRA_MUX_UARTC, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE}, + {TEGRA_PINGROUP_UDA, TEGRA_MUX_ULPI, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, + {TEGRA_PINGROUP_CK32, TEGRA_MUX_NONE, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, + {TEGRA_PINGROUP_DDRC, TEGRA_MUX_NONE, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, + {TEGRA_PINGROUP_PMCA, TEGRA_MUX_NONE, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, + {TEGRA_PINGROUP_PMCB, TEGRA_MUX_NONE, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, + {TEGRA_PINGROUP_PMCC, TEGRA_MUX_NONE, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, + {TEGRA_PINGROUP_PMCD, TEGRA_MUX_NONE, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, + {TEGRA_PINGROUP_PMCE, TEGRA_MUX_NONE, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, + {TEGRA_PINGROUP_XM2C, TEGRA_MUX_NONE, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, + {TEGRA_PINGROUP_XM2D, TEGRA_MUX_NONE, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, +}; + +static struct tegra_gpio_table gpio_table[] = { + { .gpio = TEGRA_GPIO_SD1_CD, .enable = true }, + { .gpio = TEGRA_GPIO_SD1_WP, .enable = true }, + { .gpio = TEGRA_GPIO_SD1_POWER, .enable = true }, + { .gpio = TEGRA_GPIO_SD4_CD, .enable = true }, + { .gpio = TEGRA_GPIO_SD4_WP, .enable = true }, + { .gpio = TEGRA_GPIO_SD4_POWER, .enable = true }, +}; + +void paz00_pinmux_init(void) +{ + tegra_pinmux_config_table(paz00_pinmux, ARRAY_SIZE(paz00_pinmux)); + + tegra_gpio_config(gpio_table, ARRAY_SIZE(gpio_table)); +} diff --git a/arch/arm/mach-tegra/board-paz00.c b/arch/arm/mach-tegra/board-paz00.c new file mode 100644 index 0000000000000..57e50a823eeca --- /dev/null +++ b/arch/arm/mach-tegra/board-paz00.c @@ -0,0 +1,128 @@ +/* + * arch/arm/mach-tegra/board-paz00.c + * + * Copyright (C) 2011 Marc Dietrich + * + * Based on board-harmony.c + * Copyright (C) 2010 Google, Inc. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include + +#include "board.h" +#include "board-paz00.h" +#include "clock.h" +#include "devices.h" +#include "gpio-names.h" + +static struct plat_serial8250_port debug_uart_platform_data[] = { + { + .membase = IO_ADDRESS(TEGRA_UARTD_BASE), + .mapbase = TEGRA_UARTD_BASE, + .irq = INT_UARTD, + .flags = UPF_BOOT_AUTOCONF, + .iotype = UPIO_MEM, + .regshift = 2, + .uartclk = 216000000, + }, { + .flags = 0 + } +}; + +static struct platform_device debug_uart = { + .name = "serial8250", + .id = PLAT8250_DEV_PLATFORM, + .dev = { + .platform_data = debug_uart_platform_data, + }, +}; + +static struct platform_device *paz00_devices[] __initdata = { + &debug_uart, + &tegra_sdhci_device1, + &tegra_sdhci_device2, + &tegra_sdhci_device4, +}; + +static void __init tegra_paz00_fixup(struct machine_desc *desc, + struct tag *tags, char **cmdline, struct meminfo *mi) +{ + mi->nr_banks = 1; + mi->bank[0].start = PHYS_OFFSET; + mi->bank[0].size = 448 * SZ_1M; +} + +static __initdata struct tegra_clk_init_table paz00_clk_init_table[] = { + /* name parent rate enabled */ + { "uartd", "pll_p", 216000000, true }, + { NULL, NULL, 0, 0}, +}; + + +static struct tegra_sdhci_platform_data sdhci_pdata1 = { + .cd_gpio = TEGRA_GPIO_SD1_CD, + .wp_gpio = TEGRA_GPIO_SD1_WP, + .power_gpio = TEGRA_GPIO_SD1_POWER, +}; + +static struct tegra_sdhci_platform_data sdhci_pdata2 = { + .cd_gpio = -1, + .wp_gpio = -1, + .power_gpio = -1, +}; + +static struct tegra_sdhci_platform_data sdhci_pdata4 = { + .cd_gpio = TEGRA_GPIO_SD4_CD, + .wp_gpio = TEGRA_GPIO_SD4_WP, + .power_gpio = TEGRA_GPIO_SD4_POWER, + .is_8bit = 1, +}; + +static void __init tegra_paz00_init(void) +{ + tegra_clk_init_from_table(paz00_clk_init_table); + + paz00_pinmux_init(); + + tegra_sdhci_device1.dev.platform_data = &sdhci_pdata1; + tegra_sdhci_device2.dev.platform_data = &sdhci_pdata2; + tegra_sdhci_device4.dev.platform_data = &sdhci_pdata4; + + platform_add_devices(paz00_devices, ARRAY_SIZE(paz00_devices)); +} + +MACHINE_START(PAZ00, "paz00") + .boot_params = 0x00000100, + .fixup = tegra_paz00_fixup, + .map_io = tegra_map_common_io, + .init_early = tegra_init_early, + .init_irq = tegra_init_irq, + .timer = &tegra_timer, + .init_machine = tegra_paz00_init, +MACHINE_END diff --git a/arch/arm/mach-tegra/board-paz00.h b/arch/arm/mach-tegra/board-paz00.h new file mode 100644 index 0000000000000..da193ca76d3b1 --- /dev/null +++ b/arch/arm/mach-tegra/board-paz00.h @@ -0,0 +1,29 @@ +/* + * arch/arm/mach-tegra/board-paz00.h + * + * Copyright (C) 2010 Marc Dietrich + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#ifndef _MACH_TEGRA_BOARD_PAZ00_H +#define _MACH_TEGRA_BOARD_PAZ00_H + +#define TEGRA_GPIO_SD1_CD TEGRA_GPIO_PV5 +#define TEGRA_GPIO_SD1_WP TEGRA_GPIO_PH1 +#define TEGRA_GPIO_SD1_POWER TEGRA_GPIO_PT3 +#define TEGRA_GPIO_SD4_CD TEGRA_GPIO_PH2 +#define TEGRA_GPIO_SD4_WP TEGRA_GPIO_PH3 +#define TEGRA_GPIO_SD4_POWER TEGRA_GPIO_PI6 + +void paz00_pinmux_init(void); + +#endif -- GitLab From c4d9e4a0b9960fbf4d945bdad47ba005abe8813c Mon Sep 17 00:00:00 2001 From: Olof Johansson Date: Fri, 4 Mar 2011 16:11:43 -0800 Subject: [PATCH 0320/2822] ARM: tegra: enable new drivers in defconfig Enable new platforms and tegra drivers in tegra_defconfig. Also enable some of the common devices several platforms, and GUID partition tables to make it possible to boot a tegra_defconfig kernel with a ChromiumOS filesystem. Signed-off-by: Olof Johansson Acked-by: Stephen Warren --- arch/arm/configs/tegra_defconfig | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/arch/arm/configs/tegra_defconfig b/arch/arm/configs/tegra_defconfig index 7a9267e5da553..eb8c31ee4e531 100644 --- a/arch/arm/configs/tegra_defconfig +++ b/arch/arm/configs/tegra_defconfig @@ -21,6 +21,10 @@ CONFIG_MODULE_FORCE_UNLOAD=y # CONFIG_IOSCHED_CFQ is not set CONFIG_ARCH_TEGRA=y CONFIG_MACH_HARMONY=y +CONFIG_MACH_KAEN=y +CONFIG_MACH_PAZ00=y +CONFIG_MACH_TRIMSLICE=y +CONFIG_MACH_WARIO=y CONFIG_TEGRA_DEBUG_UARTD=y CONFIG_ARM_ERRATA_742230=y CONFIG_NO_HZ=y @@ -78,12 +82,21 @@ CONFIG_SERIAL_8250_CONSOLE=y # CONFIG_LEGACY_PTYS is not set # CONFIG_HW_RANDOM is not set CONFIG_I2C=y -# CONFIG_HWMON is not set +# CONFIG_I2C_COMPAT is not set +# CONFIG_I2C_HELPER_AUTO is not set +CONFIG_I2C_TEGRA=y +CONFIG_SENSORS_LM90=y # CONFIG_MFD_SUPPORT is not set # CONFIG_USB_SUPPORT is not set CONFIG_MMC=y CONFIG_MMC_SDHCI=y CONFIG_MMC_SDHCI_PLTFM=y +CONFIG_MMC_SDHCI_TEGRA=y +CONFIG_STAGING=y +# CONFIG_STAGING_EXCLUDE_BUILD is not set +CONFIG_IIO=y +CONFIG_SENSORS_ISL29018=y +CONFIG_SENSORS_AK8975=y CONFIG_EXT2_FS=y CONFIG_EXT2_FS_XATTR=y CONFIG_EXT2_FS_POSIX_ACL=y @@ -95,6 +108,8 @@ CONFIG_EXT3_FS_SECURITY=y # CONFIG_DNOTIFY is not set CONFIG_VFAT_FS=y CONFIG_TMPFS=y +CONFIG_PARTITION_ADVANCED=y +CONFIG_EFI_PARTITION=y CONFIG_NLS_CODEPAGE_437=y CONFIG_NLS_ISO8859_1=y CONFIG_PRINTK_TIME=y -- GitLab From 25b18d39cca207f8559af1aac00313deda2d652e Mon Sep 17 00:00:00 2001 From: Ryusuke Konishi Date: Fri, 11 Feb 2011 15:23:27 +0900 Subject: [PATCH 0321/2822] nilfs2: decrement inodes count only if raw inode was successfully deleted This fixes the issue that inodes count will not add up after removal of raw inodes fails. Hence, this prevents possible under flow of the inodes count. Signed-off-by: Ryusuke Konishi --- fs/nilfs2/inode.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/fs/nilfs2/inode.c b/fs/nilfs2/inode.c index 2fd440d8d6b8d..3a6967d14e1c0 100644 --- a/fs/nilfs2/inode.c +++ b/fs/nilfs2/inode.c @@ -707,6 +707,7 @@ void nilfs_evict_inode(struct inode *inode) struct nilfs_transaction_info ti; struct super_block *sb = inode->i_sb; struct nilfs_inode_info *ii = NILFS_I(inode); + int ret; if (inode->i_nlink || !ii->i_root || unlikely(is_bad_inode(inode))) { if (inode->i_data.nrpages) @@ -725,8 +726,9 @@ void nilfs_evict_inode(struct inode *inode) nilfs_mark_inode_dirty(inode); end_writeback(inode); - nilfs_ifile_delete_inode(ii->i_root->ifile, inode->i_ino); - atomic_dec(&ii->i_root->inodes_count); + ret = nilfs_ifile_delete_inode(ii->i_root->ifile, inode->i_ino); + if (!ret) + atomic_dec(&ii->i_root->inodes_count); nilfs_clear_inode(inode); -- GitLab From 9954e7af14868b8b79e76b7b88daaf0b3866db33 Mon Sep 17 00:00:00 2001 From: Ryusuke Konishi Date: Wed, 23 Feb 2011 02:26:17 +0900 Subject: [PATCH 0322/2822] nilfs2: add free entries count only if clear bit operation succeeded Three functions of the current persistent object allocator, nilfs_palloc_commit_free_entry, nilfs_palloc_abort_alloc_entry, and nilfs_palloc_freev functions unconditionally add a counter after doing clear bit operation on a bitmap block. If the clear bit operation overlapped, the counter will not add up. This fixes the issue by making the counter operations conditional. Signed-off-by: Ryusuke Konishi --- fs/nilfs2/alloc.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/fs/nilfs2/alloc.c b/fs/nilfs2/alloc.c index d7fd696e595cc..0a0a66d98cce8 100644 --- a/fs/nilfs2/alloc.c +++ b/fs/nilfs2/alloc.c @@ -521,8 +521,8 @@ void nilfs_palloc_commit_free_entry(struct inode *inode, group_offset, bitmap)) printk(KERN_WARNING "%s: entry number %llu already freed\n", __func__, (unsigned long long)req->pr_entry_nr); - - nilfs_palloc_group_desc_add_entries(inode, group, desc, 1); + else + nilfs_palloc_group_desc_add_entries(inode, group, desc, 1); kunmap(req->pr_bitmap_bh->b_page); kunmap(req->pr_desc_bh->b_page); @@ -558,8 +558,8 @@ void nilfs_palloc_abort_alloc_entry(struct inode *inode, group_offset, bitmap)) printk(KERN_WARNING "%s: entry number %llu already freed\n", __func__, (unsigned long long)req->pr_entry_nr); - - nilfs_palloc_group_desc_add_entries(inode, group, desc, 1); + else + nilfs_palloc_group_desc_add_entries(inode, group, desc, 1); kunmap(req->pr_bitmap_bh->b_page); kunmap(req->pr_desc_bh->b_page); @@ -665,7 +665,7 @@ int nilfs_palloc_freev(struct inode *inode, __u64 *entry_nrs, size_t nitems) for (j = i, n = 0; (j < nitems) && nilfs_palloc_group_is_in(inode, group, entry_nrs[j]); - j++, n++) { + j++) { nilfs_palloc_group(inode, entry_nrs[j], &group_offset); if (!nilfs_clear_bit_atomic( nilfs_mdt_bgl_lock(inode, group), @@ -674,6 +674,8 @@ int nilfs_palloc_freev(struct inode *inode, __u64 *entry_nrs, size_t nitems) "%s: entry number %llu already freed\n", __func__, (unsigned long long)entry_nrs[j]); + } else { + n++; } } nilfs_palloc_group_desc_add_entries(inode, group, desc, n); -- GitLab From f0c9f242f947a37675a883deca7f722cac935b0e Mon Sep 17 00:00:00 2001 From: Ryusuke Konishi Date: Thu, 20 Jan 2011 02:09:52 +0900 Subject: [PATCH 0323/2822] nilfs2: use common file attribute macros Replaces uses of own inode flags (i.e. NILFS_SECRM_FL, NILFS_UNRM_FL, NILFS_COMPR_FL, and so forth) with common inode flags, and removes the own flag declarations. Signed-off-by: Ryusuke Konishi --- fs/nilfs2/dir.c | 3 --- fs/nilfs2/inode.c | 14 +++++++------- include/linux/nilfs2_fs.h | 20 -------------------- 3 files changed, 7 insertions(+), 30 deletions(-) diff --git a/fs/nilfs2/dir.c b/fs/nilfs2/dir.c index 9d45773b79e63..b72833a2cc1c3 100644 --- a/fs/nilfs2/dir.c +++ b/fs/nilfs2/dir.c @@ -440,7 +440,6 @@ void nilfs_set_link(struct inode *dir, struct nilfs_dir_entry *de, nilfs_commit_chunk(page, mapping, from, to); nilfs_put_page(page); dir->i_mtime = dir->i_ctime = CURRENT_TIME; -/* NILFS_I(dir)->i_flags &= ~NILFS_BTREE_FL; */ } /* @@ -531,7 +530,6 @@ got_it: nilfs_set_de_type(de, inode); nilfs_commit_chunk(page, page->mapping, from, to); dir->i_mtime = dir->i_ctime = CURRENT_TIME; -/* NILFS_I(dir)->i_flags &= ~NILFS_BTREE_FL; */ nilfs_mark_inode_dirty(dir); /* OFFSET_CACHE */ out_put: @@ -579,7 +577,6 @@ int nilfs_delete_entry(struct nilfs_dir_entry *dir, struct page *page) dir->inode = 0; nilfs_commit_chunk(page, mapping, from, to); inode->i_ctime = inode->i_mtime = CURRENT_TIME; -/* NILFS_I(inode)->i_flags &= ~NILFS_BTREE_FL; */ out: nilfs_put_page(page); return err; diff --git a/fs/nilfs2/inode.c b/fs/nilfs2/inode.c index 3a6967d14e1c0..f61f80c7f7ccf 100644 --- a/fs/nilfs2/inode.c +++ b/fs/nilfs2/inode.c @@ -317,9 +317,9 @@ struct inode *nilfs_new_inode(struct inode *dir, int mode) ii->i_flags = NILFS_I(dir)->i_flags; if (S_ISLNK(mode)) - ii->i_flags &= ~(NILFS_IMMUTABLE_FL | NILFS_APPEND_FL); + ii->i_flags &= ~(FS_IMMUTABLE_FL | FS_APPEND_FL); if (!S_ISDIR(mode)) - ii->i_flags &= ~NILFS_DIRSYNC_FL; + ii->i_flags &= ~FS_DIRSYNC_FL; /* ii->i_file_acl = 0; */ /* ii->i_dir_acl = 0; */ @@ -359,17 +359,17 @@ void nilfs_set_inode_flags(struct inode *inode) inode->i_flags &= ~(S_SYNC | S_APPEND | S_IMMUTABLE | S_NOATIME | S_DIRSYNC); - if (flags & NILFS_SYNC_FL) + if (flags & FS_SYNC_FL) inode->i_flags |= S_SYNC; - if (flags & NILFS_APPEND_FL) + if (flags & FS_APPEND_FL) inode->i_flags |= S_APPEND; - if (flags & NILFS_IMMUTABLE_FL) + if (flags & FS_IMMUTABLE_FL) inode->i_flags |= S_IMMUTABLE; #ifndef NILFS_ATIME_DISABLE - if (flags & NILFS_NOATIME_FL) + if (flags & FS_NOATIME_FL) #endif inode->i_flags |= S_NOATIME; - if (flags & NILFS_DIRSYNC_FL) + if (flags & FS_DIRSYNC_FL) inode->i_flags |= S_DIRSYNC; mapping_set_gfp_mask(inode->i_mapping, mapping_gfp_mask(inode->i_mapping) & ~__GFP_FS); diff --git a/include/linux/nilfs2_fs.h b/include/linux/nilfs2_fs.h index 227e49dd5720f..fdcd1bc7f61fe 100644 --- a/include/linux/nilfs2_fs.h +++ b/include/linux/nilfs2_fs.h @@ -41,26 +41,6 @@ #include #include -/* - * Inode flags stored in nilfs_inode and on-memory nilfs inode - * - * We define these flags based on ext2-fs because of the - * compatibility reason; to avoid problems in chattr(1) - */ -#define NILFS_SECRM_FL 0x00000001 /* Secure deletion */ -#define NILFS_UNRM_FL 0x00000002 /* Undelete */ -#define NILFS_SYNC_FL 0x00000008 /* Synchronous updates */ -#define NILFS_IMMUTABLE_FL 0x00000010 /* Immutable file */ -#define NILFS_APPEND_FL 0x00000020 /* writes to file may only append */ -#define NILFS_NODUMP_FL 0x00000040 /* do not dump file */ -#define NILFS_NOATIME_FL 0x00000080 /* do not update atime */ -/* Reserved for compression usage... */ -#define NILFS_NOTAIL_FL 0x00008000 /* file tail should not be merged */ -#define NILFS_DIRSYNC_FL 0x00010000 /* dirsync behaviour */ - -#define NILFS_FL_USER_VISIBLE 0x0003DFFF /* User visible flags */ -#define NILFS_FL_USER_MODIFIABLE 0x000380FF /* User modifiable flags */ - #define NILFS_INODE_BMAP_SIZE 7 /** -- GitLab From 32f4aeb31583a85c1e9a5d6d485055c090cebbfb Mon Sep 17 00:00:00 2001 From: Ryusuke Konishi Date: Thu, 20 Jan 2011 02:09:52 +0900 Subject: [PATCH 0324/2822] nilfs2: mark S_NOATIME on inodes only if NOATIME attribute is set At present, nilfs marks S_NOATIME flag on all inodes. This restricts nilfs_set_inode_flags function so that it marks S_NOATIME only if a given inode has an FS_NOATIME_FL flag. Although nilfs does not support atime yet, touch_atime() still safely returns on IS_NOATIME check since MS_NOATIME is always set on sb. Signed-off-by: Ryusuke Konishi --- fs/nilfs2/inode.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/fs/nilfs2/inode.c b/fs/nilfs2/inode.c index f61f80c7f7ccf..2e6ac8e9203a6 100644 --- a/fs/nilfs2/inode.c +++ b/fs/nilfs2/inode.c @@ -365,9 +365,7 @@ void nilfs_set_inode_flags(struct inode *inode) inode->i_flags |= S_APPEND; if (flags & FS_IMMUTABLE_FL) inode->i_flags |= S_IMMUTABLE; -#ifndef NILFS_ATIME_DISABLE if (flags & FS_NOATIME_FL) -#endif inode->i_flags |= S_NOATIME; if (flags & FS_DIRSYNC_FL) inode->i_flags |= S_DIRSYNC; -- GitLab From b253a3e4f2b8eed69b804952ef926df0ac788595 Mon Sep 17 00:00:00 2001 From: Ryusuke Konishi Date: Thu, 20 Jan 2011 02:09:53 +0900 Subject: [PATCH 0325/2822] nilfs2: tighten restrictions on inode flags Nilfs has few rectrictions on which flags may be set on which inodes like ext2/3/4 filesystems used to be. Specifically DIRSYNC may only be set on directories and IMMUTABLE and APPEND may not be set on links. Tighten that to disallow TOPDIR being set on non-directories and only NODUMP and NOATIME to be set on non-regular file, non-directories. This introduces a flags masking function like those of extN and uses it during inode creation. Signed-off-by: Ryusuke Konishi --- fs/nilfs2/inode.c | 7 ++----- fs/nilfs2/nilfs.h | 17 +++++++++++++++++ 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/fs/nilfs2/inode.c b/fs/nilfs2/inode.c index 2e6ac8e9203a6..2534af8d2b5c4 100644 --- a/fs/nilfs2/inode.c +++ b/fs/nilfs2/inode.c @@ -315,11 +315,8 @@ struct inode *nilfs_new_inode(struct inode *dir, int mode) /* No lock is needed; iget() ensures it. */ } - ii->i_flags = NILFS_I(dir)->i_flags; - if (S_ISLNK(mode)) - ii->i_flags &= ~(FS_IMMUTABLE_FL | FS_APPEND_FL); - if (!S_ISDIR(mode)) - ii->i_flags &= ~FS_DIRSYNC_FL; + ii->i_flags = nilfs_mask_flags( + mode, NILFS_I(dir)->i_flags & NILFS_FL_INHERITED); /* ii->i_file_acl = 0; */ /* ii->i_dir_acl = 0; */ diff --git a/fs/nilfs2/nilfs.h b/fs/nilfs2/nilfs.h index 777e8fd043049..3e3acb1fdd2ff 100644 --- a/fs/nilfs2/nilfs.h +++ b/fs/nilfs2/nilfs.h @@ -212,6 +212,23 @@ static inline int nilfs_init_acl(struct inode *inode, struct inode *dir) #define NILFS_ATIME_DISABLE +/* Flags that should be inherited by new inodes from their parent. */ +#define NILFS_FL_INHERITED \ + (FS_SECRM_FL | FS_UNRM_FL | FS_COMPR_FL | FS_SYNC_FL | \ + FS_IMMUTABLE_FL | FS_APPEND_FL | FS_NODUMP_FL | FS_NOATIME_FL |\ + FS_COMPRBLK_FL | FS_NOCOMP_FL | FS_NOTAIL_FL | FS_DIRSYNC_FL) + +/* Mask out flags that are inappropriate for the given type of inode. */ +static inline __u32 nilfs_mask_flags(umode_t mode, __u32 flags) +{ + if (S_ISDIR(mode)) + return flags; + else if (S_ISREG(mode)) + return flags & ~(FS_DIRSYNC_FL | FS_TOPDIR_FL); + else + return flags & (FS_NODUMP_FL | FS_NOATIME_FL); +} + /* dir.c */ extern int nilfs_add_link(struct dentry *, struct inode *); extern ino_t nilfs_inode_by_name(struct inode *, const struct qstr *); -- GitLab From cde98f0f84ccff78e87235cb7b551747d6ad00de Mon Sep 17 00:00:00 2001 From: Ryusuke Konishi Date: Thu, 20 Jan 2011 02:09:53 +0900 Subject: [PATCH 0326/2822] nilfs2: implement FS_IOC_GETFLAGS/SETFLAGS/GETVERSION Add support for the standard attributes set via chattr and read via lsattr. These attributes are already in the flags value in the nilfs2 inode, but currently we don't have any ioctl commands that expose them to the userland. Collaterally, this adds the FS_IOC_GETVERSION ioctl for getting i_generation, which allows users to list the file's generation number with "lsattr -v". Signed-off-by: Ryusuke Konishi --- fs/nilfs2/ioctl.c | 70 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) diff --git a/fs/nilfs2/ioctl.c b/fs/nilfs2/ioctl.c index 496738963fdbd..3aad6413aba44 100644 --- a/fs/nilfs2/ioctl.c +++ b/fs/nilfs2/ioctl.c @@ -97,6 +97,70 @@ static int nilfs_ioctl_wrap_copy(struct the_nilfs *nilfs, return ret; } +static int nilfs_ioctl_getflags(struct inode *inode, void __user *argp) +{ + unsigned int flags = NILFS_I(inode)->i_flags & FS_FL_USER_VISIBLE; + + return put_user(flags, (int __user *)argp); +} + +static int nilfs_ioctl_setflags(struct inode *inode, struct file *filp, + void __user *argp) +{ + struct nilfs_transaction_info ti; + unsigned int flags, oldflags; + int ret; + + if (!is_owner_or_cap(inode)) + return -EACCES; + + if (get_user(flags, (int __user *)argp)) + return -EFAULT; + + ret = mnt_want_write(filp->f_path.mnt); + if (ret) + return ret; + + flags = nilfs_mask_flags(inode->i_mode, flags); + + mutex_lock(&inode->i_mutex); + + oldflags = NILFS_I(inode)->i_flags; + + /* + * The IMMUTABLE and APPEND_ONLY flags can only be changed by the + * relevant capability. + */ + ret = -EPERM; + if (((flags ^ oldflags) & (FS_APPEND_FL | FS_IMMUTABLE_FL)) && + !capable(CAP_LINUX_IMMUTABLE)) + goto out; + + ret = nilfs_transaction_begin(inode->i_sb, &ti, 0); + if (ret) + goto out; + + NILFS_I(inode)->i_flags = (oldflags & ~FS_FL_USER_MODIFIABLE) | + (flags & FS_FL_USER_MODIFIABLE); + + nilfs_set_inode_flags(inode); + inode->i_ctime = CURRENT_TIME; + if (IS_SYNC(inode)) + nilfs_set_transaction_flag(NILFS_TI_SYNC); + + nilfs_mark_inode_dirty(inode); + ret = nilfs_transaction_commit(inode->i_sb); +out: + mutex_unlock(&inode->i_mutex); + mnt_drop_write(filp->f_path.mnt); + return ret; +} + +static int nilfs_ioctl_getversion(struct inode *inode, void __user *argp) +{ + return put_user(inode->i_generation, (int __user *)argp); +} + static int nilfs_ioctl_change_cpmode(struct inode *inode, struct file *filp, unsigned int cmd, void __user *argp) { @@ -666,6 +730,12 @@ long nilfs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) void __user *argp = (void __user *)arg; switch (cmd) { + case FS_IOC_GETFLAGS: + return nilfs_ioctl_getflags(inode, argp); + case FS_IOC_SETFLAGS: + return nilfs_ioctl_setflags(inode, filp, argp); + case FS_IOC_GETVERSION: + return nilfs_ioctl_getversion(inode, argp); case NILFS_IOCTL_CHANGE_CPMODE: return nilfs_ioctl_change_cpmode(inode, filp, cmd, argp); case NILFS_IOCTL_DELETE_CHECKPOINT: -- GitLab From 828b1c50ae11e6dda68f8dfefe43b74c7182b157 Mon Sep 17 00:00:00 2001 From: Ryusuke Konishi Date: Thu, 3 Feb 2011 21:26:17 +0900 Subject: [PATCH 0327/2822] nilfs2: add compat ioctl The current FS_IOC_GETFLAGS/SETFLAGS/GETVERSION will fail if application is 32 bit and kernel is 64 bit. This issue is avoidable by adding compat_ioctl method. Signed-off-by: Ryusuke Konishi --- fs/nilfs2/dir.c | 2 +- fs/nilfs2/file.c | 2 +- fs/nilfs2/ioctl.c | 21 +++++++++++++++++++++ fs/nilfs2/nilfs.h | 1 + 4 files changed, 24 insertions(+), 2 deletions(-) diff --git a/fs/nilfs2/dir.c b/fs/nilfs2/dir.c index b72833a2cc1c3..3a1923943b14c 100644 --- a/fs/nilfs2/dir.c +++ b/fs/nilfs2/dir.c @@ -681,7 +681,7 @@ const struct file_operations nilfs_dir_operations = { .readdir = nilfs_readdir, .unlocked_ioctl = nilfs_ioctl, #ifdef CONFIG_COMPAT - .compat_ioctl = nilfs_ioctl, + .compat_ioctl = nilfs_compat_ioctl, #endif /* CONFIG_COMPAT */ .fsync = nilfs_sync_file, diff --git a/fs/nilfs2/file.c b/fs/nilfs2/file.c index 2f560c9fb8081..7a5e4ab15c6ee 100644 --- a/fs/nilfs2/file.c +++ b/fs/nilfs2/file.c @@ -142,7 +142,7 @@ const struct file_operations nilfs_file_operations = { .aio_write = generic_file_aio_write, .unlocked_ioctl = nilfs_ioctl, #ifdef CONFIG_COMPAT - .compat_ioctl = nilfs_ioctl, + .compat_ioctl = nilfs_compat_ioctl, #endif /* CONFIG_COMPAT */ .mmap = nilfs_file_mmap, .open = generic_file_open, diff --git a/fs/nilfs2/ioctl.c b/fs/nilfs2/ioctl.c index 3aad6413aba44..d89173edd7fed 100644 --- a/fs/nilfs2/ioctl.c +++ b/fs/nilfs2/ioctl.c @@ -26,6 +26,7 @@ #include /* capable() */ #include /* copy_from_user(), copy_to_user() */ #include +#include /* compat_ptr() */ #include /* mnt_want_write(), mnt_drop_write() */ #include #include "nilfs.h" @@ -766,3 +767,23 @@ long nilfs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) return -ENOTTY; } } + +#ifdef CONFIG_COMPAT +long nilfs_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) +{ + switch (cmd) { + case FS_IOC32_GETFLAGS: + cmd = FS_IOC_GETFLAGS; + break; + case FS_IOC32_SETFLAGS: + cmd = FS_IOC_SETFLAGS; + break; + case FS_IOC32_GETVERSION: + cmd = FS_IOC_GETVERSION; + break; + default: + return -ENOIOCTLCMD; + } + return nilfs_ioctl(filp, cmd, (unsigned long)compat_ptr(arg)); +} +#endif diff --git a/fs/nilfs2/nilfs.h b/fs/nilfs2/nilfs.h index 3e3acb1fdd2ff..45b1fd1d02450 100644 --- a/fs/nilfs2/nilfs.h +++ b/fs/nilfs2/nilfs.h @@ -246,6 +246,7 @@ extern int nilfs_sync_file(struct file *, int); /* ioctl.c */ long nilfs_ioctl(struct file *, unsigned int, unsigned long); +long nilfs_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg); int nilfs_ioctl_prepare_clean_segments(struct the_nilfs *, struct nilfs_argv *, void **); -- GitLab From 4138ec23820012009aecc2b02856c62872dd3c34 Mon Sep 17 00:00:00 2001 From: Ryusuke Konishi Date: Mon, 24 Jan 2011 00:28:22 +0900 Subject: [PATCH 0328/2822] nilfs2: append blocksize info to warnings during loading super blocks At present, the same warning message can be output twice when nilfs detected a problem on super blocks: NILFS warning: broken superblock. using spare superblock. NILFS warning: broken superblock. using spare superblock. ... This is because these super blocks are reloaded with the block size written in a super block if it differs from the first block size, but this repetition looks somewhat confusing. So, we hint at what is going on by appending block size information to those messages. Reported-by: Wakko Warner Signed-off-by: Ryusuke Konishi --- fs/nilfs2/the_nilfs.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/fs/nilfs2/the_nilfs.c b/fs/nilfs2/the_nilfs.c index ad4ac607cf573..9098909d5cef5 100644 --- a/fs/nilfs2/the_nilfs.c +++ b/fs/nilfs2/the_nilfs.c @@ -475,10 +475,13 @@ static int nilfs_load_super_block(struct the_nilfs *nilfs, return -EIO; } printk(KERN_WARNING - "NILFS warning: unable to read primary superblock\n"); - } else if (!sbp[1]) + "NILFS warning: unable to read primary superblock " + "(blocksize = %d)\n", blocksize); + } else if (!sbp[1]) { printk(KERN_WARNING - "NILFS warning: unable to read secondary superblock\n"); + "NILFS warning: unable to read secondary superblock " + "(blocksize = %d)\n", blocksize); + } /* * Compare two super blocks and set 1 in swp if the secondary @@ -505,7 +508,7 @@ static int nilfs_load_super_block(struct the_nilfs *nilfs, if (!valid[!swp]) printk(KERN_WARNING "NILFS warning: broken superblock. " - "using spare superblock.\n"); + "using spare superblock (blocksize = %d).\n", blocksize); if (swp) nilfs_swap_super_block(nilfs); -- GitLab From ae191838b0251d73b9d0a7254c6938406f5f6320 Mon Sep 17 00:00:00 2001 From: Ryusuke Konishi Date: Fri, 4 Feb 2011 01:19:38 +0900 Subject: [PATCH 0329/2822] nilfs2: optimize rec_len functions This is a similar change to those in ext2/ext3 codebase (commit 40a063f6691ce937 and a4ae3094869f18e2, respectively). The addition of 64k block capability in the rec_len_from_disk and rec_len_to_disk functions added a bit of math overhead which slows down file create workloads needlessly when the architecture cannot even support 64k blocks. This will cut the corner. Signed-off-by: Ryusuke Konishi --- fs/nilfs2/ioctl.c | 1 + include/linux/nilfs2_fs.h | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/fs/nilfs2/ioctl.c b/fs/nilfs2/ioctl.c index d89173edd7fed..5471eed5eccb1 100644 --- a/fs/nilfs2/ioctl.c +++ b/fs/nilfs2/ioctl.c @@ -28,6 +28,7 @@ #include #include /* compat_ptr() */ #include /* mnt_want_write(), mnt_drop_write() */ +#include #include #include "nilfs.h" #include "segment.h" diff --git a/include/linux/nilfs2_fs.h b/include/linux/nilfs2_fs.h index fdcd1bc7f61fe..3a65e5aa2d765 100644 --- a/include/linux/nilfs2_fs.h +++ b/include/linux/nilfs2_fs.h @@ -326,17 +326,21 @@ static inline unsigned nilfs_rec_len_from_disk(__le16 dlen) { unsigned len = le16_to_cpu(dlen); +#if !defined(__KERNEL__) || (PAGE_CACHE_SIZE >= 65536) if (len == NILFS_MAX_REC_LEN) return 1 << 16; +#endif return len; } static inline __le16 nilfs_rec_len_to_disk(unsigned len) { +#if !defined(__KERNEL__) || (PAGE_CACHE_SIZE >= 65536) if (len == (1 << 16)) return cpu_to_le16(NILFS_MAX_REC_LEN); else if (len > (1 << 16)) BUG(); +#endif return cpu_to_le16(len); } -- GitLab From be667377a8b8cd73e1b923f33fb5be4034aa4bfa Mon Sep 17 00:00:00 2001 From: Ryusuke Konishi Date: Sat, 5 Mar 2011 00:19:32 +0900 Subject: [PATCH 0330/2822] nilfs2: record used amount of each checkpoint in checkpoint list This records the number of used blocks per checkpoint in each checkpoint entry of cpfile. Even though userland tools can get the block count via nilfs_get_cpinfo ioctl, it was not updated by the nilfs2 kernel code. This fixes the issue and makes it available for userland tools to calculate used amount per checkpoint. Signed-off-by: Ryusuke Konishi Cc: Jiro SEKIBA --- fs/nilfs2/bmap.c | 11 ----------- fs/nilfs2/bmap.h | 3 --- fs/nilfs2/btree.c | 6 +++--- fs/nilfs2/direct.c | 4 ++-- fs/nilfs2/inode.c | 18 ++++++++++++++++++ fs/nilfs2/nilfs.h | 2 ++ include/linux/nilfs2_fs.h | 6 ++++-- 7 files changed, 29 insertions(+), 21 deletions(-) diff --git a/fs/nilfs2/bmap.c b/fs/nilfs2/bmap.c index 3ee67c67cc52e..85447a2fab33e 100644 --- a/fs/nilfs2/bmap.c +++ b/fs/nilfs2/bmap.c @@ -425,17 +425,6 @@ int nilfs_bmap_test_and_clear_dirty(struct nilfs_bmap *bmap) /* * Internal use only */ - -void nilfs_bmap_add_blocks(const struct nilfs_bmap *bmap, int n) -{ - inode_add_bytes(bmap->b_inode, (1 << bmap->b_inode->i_blkbits) * n); -} - -void nilfs_bmap_sub_blocks(const struct nilfs_bmap *bmap, int n) -{ - inode_sub_bytes(bmap->b_inode, (1 << bmap->b_inode->i_blkbits) * n); -} - __u64 nilfs_bmap_data_get_key(const struct nilfs_bmap *bmap, const struct buffer_head *bh) { diff --git a/fs/nilfs2/bmap.h b/fs/nilfs2/bmap.h index bde1c0aa2e15a..40d9f453d31c1 100644 --- a/fs/nilfs2/bmap.h +++ b/fs/nilfs2/bmap.h @@ -240,9 +240,6 @@ __u64 nilfs_bmap_data_get_key(const struct nilfs_bmap *, __u64 nilfs_bmap_find_target_seq(const struct nilfs_bmap *, __u64); __u64 nilfs_bmap_find_target_in_group(const struct nilfs_bmap *); -void nilfs_bmap_add_blocks(const struct nilfs_bmap *, int); -void nilfs_bmap_sub_blocks(const struct nilfs_bmap *, int); - /* Assume that bmap semaphore is locked. */ static inline int nilfs_bmap_dirty(const struct nilfs_bmap *bmap) diff --git a/fs/nilfs2/btree.c b/fs/nilfs2/btree.c index 300c2bc00c3f4..d451ae0e0bf37 100644 --- a/fs/nilfs2/btree.c +++ b/fs/nilfs2/btree.c @@ -1174,7 +1174,7 @@ static int nilfs_btree_insert(struct nilfs_bmap *btree, __u64 key, __u64 ptr) if (ret < 0) goto out; nilfs_btree_commit_insert(btree, path, level, key, ptr); - nilfs_bmap_add_blocks(btree, stats.bs_nblocks); + nilfs_inode_add_blocks(btree->b_inode, stats.bs_nblocks); out: nilfs_btree_free_path(path); @@ -1511,7 +1511,7 @@ static int nilfs_btree_delete(struct nilfs_bmap *btree, __u64 key) if (ret < 0) goto out; nilfs_btree_commit_delete(btree, path, level, dat); - nilfs_bmap_sub_blocks(btree, stats.bs_nblocks); + nilfs_inode_sub_blocks(btree->b_inode, stats.bs_nblocks); out: nilfs_btree_free_path(path); @@ -1776,7 +1776,7 @@ int nilfs_btree_convert_and_insert(struct nilfs_bmap *btree, return ret; nilfs_btree_commit_convert_and_insert(btree, key, ptr, keys, ptrs, n, di, ni, bh); - nilfs_bmap_add_blocks(btree, stats.bs_nblocks); + nilfs_inode_add_blocks(btree->b_inode, stats.bs_nblocks); return 0; } diff --git a/fs/nilfs2/direct.c b/fs/nilfs2/direct.c index 324d80c57518a..82f4865e86dd5 100644 --- a/fs/nilfs2/direct.c +++ b/fs/nilfs2/direct.c @@ -146,7 +146,7 @@ static int nilfs_direct_insert(struct nilfs_bmap *bmap, __u64 key, __u64 ptr) if (NILFS_BMAP_USE_VBN(bmap)) nilfs_bmap_set_target_v(bmap, key, req.bpr_ptr); - nilfs_bmap_add_blocks(bmap, 1); + nilfs_inode_add_blocks(bmap->b_inode, 1); } return ret; } @@ -168,7 +168,7 @@ static int nilfs_direct_delete(struct nilfs_bmap *bmap, __u64 key) if (!ret) { nilfs_bmap_commit_end_ptr(bmap, &req, dat); nilfs_direct_set_ptr(bmap, key, NILFS_BMAP_INVALID_PTR); - nilfs_bmap_sub_blocks(bmap, 1); + nilfs_inode_sub_blocks(bmap->b_inode, 1); } return ret; } diff --git a/fs/nilfs2/inode.c b/fs/nilfs2/inode.c index 2534af8d2b5c4..22a816ba3621c 100644 --- a/fs/nilfs2/inode.c +++ b/fs/nilfs2/inode.c @@ -41,6 +41,24 @@ struct nilfs_iget_args { int for_gc; }; +void nilfs_inode_add_blocks(struct inode *inode, int n) +{ + struct nilfs_root *root = NILFS_I(inode)->i_root; + + inode_add_bytes(inode, (1 << inode->i_blkbits) * n); + if (root) + atomic_add(n, &root->blocks_count); +} + +void nilfs_inode_sub_blocks(struct inode *inode, int n) +{ + struct nilfs_root *root = NILFS_I(inode)->i_root; + + inode_sub_bytes(inode, (1 << inode->i_blkbits) * n); + if (root) + atomic_sub(n, &root->blocks_count); +} + /** * nilfs_get_block() - get a file block on the filesystem (callback function) * @inode - inode struct of the target file diff --git a/fs/nilfs2/nilfs.h b/fs/nilfs2/nilfs.h index 45b1fd1d02450..03ba4d88083f5 100644 --- a/fs/nilfs2/nilfs.h +++ b/fs/nilfs2/nilfs.h @@ -251,6 +251,8 @@ int nilfs_ioctl_prepare_clean_segments(struct the_nilfs *, struct nilfs_argv *, void **); /* inode.c */ +void nilfs_inode_add_blocks(struct inode *inode, int n); +void nilfs_inode_sub_blocks(struct inode *inode, int n); extern struct inode *nilfs_new_inode(struct inode *, int); extern void nilfs_free_inode(struct inode *); extern int nilfs_get_block(struct inode *, sector_t, struct buffer_head *, int); diff --git a/include/linux/nilfs2_fs.h b/include/linux/nilfs2_fs.h index 3a65e5aa2d765..ae33ac2db62df 100644 --- a/include/linux/nilfs2_fs.h +++ b/include/linux/nilfs2_fs.h @@ -216,8 +216,10 @@ struct nilfs_super_block { * If there is a bit set in the incompatible feature set that the kernel * doesn't know about, it should refuse to mount the filesystem. */ +#define NILFS_FEATURE_COMPAT_RO_BLOCK_COUNT 0x00000001ULL + #define NILFS_FEATURE_COMPAT_SUPP 0ULL -#define NILFS_FEATURE_COMPAT_RO_SUPP 0ULL +#define NILFS_FEATURE_COMPAT_RO_SUPP NILFS_FEATURE_COMPAT_RO_BLOCK_COUNT #define NILFS_FEATURE_INCOMPAT_SUPP 0ULL /* @@ -509,7 +511,7 @@ struct nilfs_checkpoint { __le64 cp_create; __le64 cp_nblk_inc; __le64 cp_inodes_count; - __le64 cp_blocks_count; /* Reserved (might be deleted) */ + __le64 cp_blocks_count; /* Do not change the byte offset of ifile inode. To keep the compatibility of the disk format, -- GitLab From df677140281beb608f6748c341af7612f7bfe7a0 Mon Sep 17 00:00:00 2001 From: "Martin K. Petersen" Date: Tue, 8 Mar 2011 08:28:01 +0100 Subject: [PATCH 0331/2822] block: biovec_slab vs. CONFIG_BLK_DEV_INTEGRITY The block integrity subsystem no longer uses the bio_vec slabs so this code can safely be compiled in. Signed-off-by: Martin K. Petersen Signed-off-by: Jens Axboe --- fs/bio.c | 4 +--- include/linux/bio.h | 1 - 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/fs/bio.c b/fs/bio.c index 4bd454fa844e3..5694b756ed019 100644 --- a/fs/bio.c +++ b/fs/bio.c @@ -43,7 +43,7 @@ static mempool_t *bio_split_pool __read_mostly; * unsigned short */ #define BV(x) { .nr_vecs = x, .name = "biovec-"__stringify(x) } -struct biovec_slab bvec_slabs[BIOVEC_NR_POOLS] __read_mostly = { +static struct biovec_slab bvec_slabs[BIOVEC_NR_POOLS] __read_mostly = { BV(1), BV(4), BV(16), BV(64), BV(128), BV(BIO_MAX_PAGES), }; #undef BV @@ -1656,12 +1656,10 @@ static void __init biovec_init_slabs(void) int size; struct biovec_slab *bvs = bvec_slabs + i; -#ifndef CONFIG_BLK_DEV_INTEGRITY if (bvs->nr_vecs <= BIO_INLINE_VECS) { bvs->slab = NULL; continue; } -#endif size = bvs->nr_vecs * sizeof(struct bio_vec); bvs->slab = kmem_cache_create(bvs->name, size, 0, diff --git a/include/linux/bio.h b/include/linux/bio.h index 35dcdb3589bc9..ce33e6868a2f5 100644 --- a/include/linux/bio.h +++ b/include/linux/bio.h @@ -304,7 +304,6 @@ struct biovec_slab { }; extern struct bio_set *fs_bio_set; -extern struct biovec_slab bvec_slabs[BIOVEC_NR_POOLS] __read_mostly; /* * a small number of entries is fine, not going to be performance critical. -- GitLab From f02726a77960194995dac9fd218ec10b4de76cd6 Mon Sep 17 00:00:00 2001 From: Mike Rapoport Date: Mon, 7 Mar 2011 16:29:24 +0200 Subject: [PATCH 0332/2822] ARM: tegra: trimslice: enable MMC/SD slots TrimSlice has MicroSD and standard MMC/SD slots. Register sdhci devices and enable GPIOs for MMC/SD slot. Signed-off-by: Mike Rapoport --- arch/arm/mach-tegra/board-trimslice-pinmux.c | 9 +++++++++ arch/arm/mach-tegra/board-trimslice.c | 19 +++++++++++++++++++ arch/arm/mach-tegra/board-trimslice.h | 3 +++ 3 files changed, 31 insertions(+) diff --git a/arch/arm/mach-tegra/board-trimslice-pinmux.c b/arch/arm/mach-tegra/board-trimslice-pinmux.c index 6d4fc9f7f1fb2..13534fa08abfd 100644 --- a/arch/arm/mach-tegra/board-trimslice-pinmux.c +++ b/arch/arm/mach-tegra/board-trimslice-pinmux.c @@ -16,8 +16,11 @@ #include #include + #include +#include +#include "gpio-names.h" #include "board-trimslice.h" static __initdata struct tegra_pingroup_config trimslice_pinmux[] = { @@ -139,7 +142,13 @@ static __initdata struct tegra_pingroup_config trimslice_pinmux[] = { {TEGRA_PINGROUP_XM2D, TEGRA_MUX_NONE, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, }; +static struct tegra_gpio_table gpio_table[] = { + { .gpio = TRIMSLICE_GPIO_SD4_CD, .enable = true }, /* mmc4 cd */ + { .gpio = TRIMSLICE_GPIO_SD4_WP, .enable = true }, /* mmc4 wp */ +}; + void __init trimslice_pinmux_init(void) { tegra_pinmux_config_table(trimslice_pinmux, ARRAY_SIZE(trimslice_pinmux)); + tegra_gpio_config(gpio_table, ARRAY_SIZE(gpio_table)); } diff --git a/arch/arm/mach-tegra/board-trimslice.c b/arch/arm/mach-tegra/board-trimslice.c index 7be7d4acd02f4..cda4cfd78e841 100644 --- a/arch/arm/mach-tegra/board-trimslice.c +++ b/arch/arm/mach-tegra/board-trimslice.c @@ -29,9 +29,12 @@ #include #include +#include #include "board.h" #include "clock.h" +#include "devices.h" +#include "gpio-names.h" #include "board-trimslice.h" @@ -56,9 +59,22 @@ static struct platform_device debug_uart = { .platform_data = debug_uart_platform_data, }, }; +static struct tegra_sdhci_platform_data sdhci_pdata1 = { + .cd_gpio = -1, + .wp_gpio = -1, + .power_gpio = -1, +}; + +static struct tegra_sdhci_platform_data sdhci_pdata4 = { + .cd_gpio = TRIMSLICE_GPIO_SD4_CD, + .wp_gpio = TRIMSLICE_GPIO_SD4_WP, + .power_gpio = -1, +}; static struct platform_device *trimslice_devices[] __initdata = { &debug_uart, + &tegra_sdhci_device1, + &tegra_sdhci_device4, }; static void __init tegra_trimslice_fixup(struct machine_desc *desc, @@ -92,6 +108,9 @@ static void __init tegra_trimslice_init(void) trimslice_pinmux_init(); + tegra_sdhci_device1.dev.platform_data = &sdhci_pdata1; + tegra_sdhci_device4.dev.platform_data = &sdhci_pdata4; + platform_add_devices(trimslice_devices, ARRAY_SIZE(trimslice_devices)); } diff --git a/arch/arm/mach-tegra/board-trimslice.h b/arch/arm/mach-tegra/board-trimslice.h index 16ec0f0d3bb14..e8ef6291c6f19 100644 --- a/arch/arm/mach-tegra/board-trimslice.h +++ b/arch/arm/mach-tegra/board-trimslice.h @@ -17,6 +17,9 @@ #ifndef _MACH_TEGRA_BOARD_TRIMSLICE_H #define _MACH_TEGRA_BOARD_TRIMSLICE_H +#define TRIMSLICE_GPIO_SD4_CD TEGRA_GPIO_PP1 /* mmc4 cd */ +#define TRIMSLICE_GPIO_SD4_WP TEGRA_GPIO_PP2 /* mmc4 wp */ + void trimslice_pinmux_init(void); #endif -- GitLab From f80802cb1fbd7f441dd1d04db77d314adb7ccb37 Mon Sep 17 00:00:00 2001 From: Steven Rostedt Date: Mon, 7 Mar 2011 13:18:47 -0500 Subject: [PATCH 0333/2822] ktest: Print logfile name on failure If the test fails and a logfile was specified. Print the name to let the user know where to look for more information on the failure. Signed-off-by: Steven Rostedt --- tools/testing/ktest/ktest.pl | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tools/testing/ktest/ktest.pl b/tools/testing/ktest/ktest.pl index e1c62eeb88f5f..3e3615a7d968d 100755 --- a/tools/testing/ktest/ktest.pl +++ b/tools/testing/ktest/ktest.pl @@ -462,6 +462,10 @@ sub dodie { `$power_off`; } + if (defined($opt{"LOG_FILE"})) { + print " See $opt{LOG_FILE} for more info.\n"; + } + die @_, "\n"; } -- GitLab From 10abf118f090b9a70ea05296a981fa27196dc7c6 Mon Sep 17 00:00:00 2001 From: Steven Rostedt Date: Mon, 7 Mar 2011 13:21:00 -0500 Subject: [PATCH 0334/2822] ktest: Start failure timeout on panic too Currently we just look for a Call Trace to start the time out when to reboot the box. But if the kernel panics and does not show a Call Trace, the test will not reboot the box after the specified timeout. Signed-off-by: Steven Rostedt --- tools/testing/ktest/ktest.pl | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/testing/ktest/ktest.pl b/tools/testing/ktest/ktest.pl index 3e3615a7d968d..6620fe4b364f1 100755 --- a/tools/testing/ktest/ktest.pl +++ b/tools/testing/ktest/ktest.pl @@ -820,6 +820,7 @@ sub monitor { } if ($full_line =~ /Kernel panic -/) { + $failure_start = time; $bug = 1; } -- GitLab From 612b9e9bd33af80f525a38c05a1663f7126b3d3c Mon Sep 17 00:00:00 2001 From: Steven Rostedt Date: Mon, 7 Mar 2011 13:27:43 -0500 Subject: [PATCH 0335/2822] ktest: Handle kernels before make oldnoconfig When bisecting, one may come across a kernel that does not have make oldnoconfig. In this case, we need to run the command "yes" into a make oldconfig. This will select defaults instead of 'n' into each command, but it works as a work around. Note, "yes n" will not work because a config may have a value that "n" is not acceptable for. Signed-off-by: Steven Rostedt --- tools/testing/ktest/ktest.pl | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/tools/testing/ktest/ktest.pl b/tools/testing/ktest/ktest.pl index 6620fe4b364f1..c95209bac65a7 100755 --- a/tools/testing/ktest/ktest.pl +++ b/tools/testing/ktest/ktest.pl @@ -930,6 +930,18 @@ sub check_buildlog { return 1; } +sub make_oldconfig { + my ($defconfig) = @_; + + if (!run_command "$defconfig $make oldnoconfig") { + # Perhaps oldnoconfig doesn't exist in this version of the kernel + # try a yes '' | oldconfig + doprint "oldnoconfig failed, trying yes '' | make oldconfig\n"; + run_command "yes '' | $defconfig $make oldconfig" or + dodie "failed make config oldconfig"; + } +} + sub build { my ($type) = @_; my $defconfig = ""; @@ -975,8 +987,12 @@ sub build { $defconfig = "KCONFIG_ALLCONFIG=$minconfig"; } - run_command "$defconfig $make $type" or - dodie "failed make config"; + if ($type eq "oldnoconfig") { + make_oldconfig $defconfig; + } else { + run_command "$defconfig $make $type" or + dodie "failed make config"; + } $redirect = "$buildlog"; if (!run_command "$make $build_options") { @@ -1395,9 +1411,7 @@ sub create_config { close(OUT); # exit; - run_command "$make oldnoconfig" or - dodie "failed make config oldconfig"; - + make_oldconfig ""; } sub compare_configs { @@ -1599,8 +1613,7 @@ sub config_bisect { close(IN); # Now run oldconfig with the minconfig (and addconfigs) - run_command "$defconfig $make oldnoconfig" or - dodie "failed make config oldconfig"; + make_oldconfig $defconfig; # check to see what we lost (or gained) open (IN, $output_config) -- GitLab From c960bb9f59c0ed2aded535222cfe461ec6c22c95 Mon Sep 17 00:00:00 2001 From: Steven Rostedt Date: Tue, 8 Mar 2011 09:22:39 -0500 Subject: [PATCH 0336/2822] ktest: Add manual bisect For both git bisect and config bisect, if BISECT_MANUAL is set to 1, then bisect will stop between iterations and ask the user for the result. The actual result is ignored. This makes it possible to use ktest.pl for bisecting configs and git and let the user examine the results themselves and enter their own results. Signed-off-by: Steven Rostedt --- tools/testing/ktest/ktest.pl | 33 +++++++++++++++++++++++++++++++-- tools/testing/ktest/sample.conf | 16 ++++++++++++++++ 2 files changed, 47 insertions(+), 2 deletions(-) diff --git a/tools/testing/ktest/ktest.pl b/tools/testing/ktest/ktest.pl index c95209bac65a7..e55bd52367a66 100755 --- a/tools/testing/ktest/ktest.pl +++ b/tools/testing/ktest/ktest.pl @@ -37,6 +37,7 @@ $default{"POWEROFF_ON_SUCCESS"} = 0; $default{"BUILD_OPTIONS"} = ""; $default{"BISECT_SLEEP_TIME"} = 60; # sleep time between bisects $default{"CLEAR_LOG"} = 0; +$default{"BISECT_MANUAL"} = 0; $default{"SUCCESS_LINE"} = "login:"; $default{"BOOTED_TIMEOUT"} = 1; $default{"DIE_ON_FAILURE"} = 1; @@ -81,6 +82,7 @@ my $addconfig; my $in_bisect = 0; my $bisect_bad = ""; my $reverse_bisect; +my $bisect_manual; my $in_patchcheck = 0; my $run_test; my $redirect; @@ -1046,6 +1048,21 @@ sub get_version { doprint "$version\n"; } +sub answer_bisect { + for (;;) { + doprint "Pass or fail? [p/f]"; + my $ans = ; + chomp $ans; + if ($ans eq "p" || $ans eq "P") { + return 1; + } elsif ($ans eq "f" || $ans eq "F") { + return 0; + } else { + print "Please answer 'P' or 'F'\n"; + } + } +} + sub child_run_test { my $failed = 0; @@ -1214,6 +1231,9 @@ sub run_bisect { my $ret = run_bisect_test $type, $buildtype; + if ($bisect_manual) { + $ret = answer_bisect; + } # Are we looking for where it worked, not failed? if ($reverse_bisect) { @@ -1524,7 +1544,9 @@ sub run_config_bisect { } $ret = run_config_bisect_test $type; - + if ($bisect_manual) { + $ret = answer_bisect; + } if ($ret) { process_passed %current_config; return 0; @@ -1555,7 +1577,13 @@ sub run_config_bisect { $half = int($#start_list / 2); } while ($half > 0); - # we found a single config, try it again + # we found a single config, try it again unless we are running manually + + if ($bisect_manual) { + process_failed $start_list[0]; + return 1; + } + my @tophalf = @start_list[0 .. 0]; $ret = run_config_bisect_test $type; @@ -1925,6 +1953,7 @@ for (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) { $poweroff_after_halt = set_test_option("POWEROFF_AFTER_HALT", $i); $sleep_time = set_test_option("SLEEP_TIME", $i); $bisect_sleep_time = set_test_option("BISECT_SLEEP_TIME", $i); + $bisect_manual = set_test_option("BISECT_MANUAL", $i); $store_failures = set_test_option("STORE_FAILURES", $i); $timeout = set_test_option("TIMEOUT", $i); $booted_timeout = set_test_option("BOOTED_TIMEOUT", $i); diff --git a/tools/testing/ktest/sample.conf b/tools/testing/ktest/sample.conf index 3408c594b2dec..af82ac2897797 100644 --- a/tools/testing/ktest/sample.conf +++ b/tools/testing/ktest/sample.conf @@ -528,6 +528,15 @@ # With BISECT_REVERSE = 1, The test will consider failures as # good, and success as bad. # +# BISECT_MANUAL = 1 (optional, default 0) +# +# In case there's a problem with automating the bisect for +# whatever reason. (Can't reboot, want to inspect each iteration) +# Doing a BISECT_MANUAL will have the test wait for you to +# tell it if the test passed or failed after each iteration. +# This is basicall the same as running git bisect yourself +# but ktest will rebuild and install the kernel for you. +# # BISECT_CHECK = 1 (optional, default 0) # # Just to be sure the good is good and bad is bad, setting @@ -613,10 +622,17 @@ # # CONFIG_BISECT is the config that failed to boot # +# If BISECT_MANUAL is set, it will pause between iterations. +# This is useful to use just ktest.pl just for the config bisect. +# If you set it to build, it will run the bisect and you can +# control what happens in between iterations. It will ask you if +# the test succeeded or not and continue the config bisect. +# # Example: # TEST_START # TEST_TYPE = config_bisect # CONFIG_BISECT_TYPE = build # CONFIG_BISECT = /home/test/onfig-bad # MIN_CONFIG = /home/test/config-min +# BISECT_MANUAL = 1 # -- GitLab From c23dca7cd28eb1bf90053ce4ba30d65d22d2a81e Mon Sep 17 00:00:00 2001 From: Steven Rostedt Date: Tue, 8 Mar 2011 09:26:31 -0500 Subject: [PATCH 0337/2822] ktest: Add BISECT_SKIP If a during a git bisect, ktest fails on something other than what it is testing (if BISECT_TYPE is test but it fails on build), if BISECT_SKIP is set, then it will do a "git bisect skip" instead of just failing the bisect and letting the user find a good commit to test. Signed-off-by: Steven Rostedt --- tools/testing/ktest/ktest.pl | 36 +++++++++++++++++++++++++-------- tools/testing/ktest/sample.conf | 9 +++++++++ 2 files changed, 37 insertions(+), 8 deletions(-) diff --git a/tools/testing/ktest/ktest.pl b/tools/testing/ktest/ktest.pl index e55bd52367a66..0f62916a43f71 100755 --- a/tools/testing/ktest/ktest.pl +++ b/tools/testing/ktest/ktest.pl @@ -38,6 +38,7 @@ $default{"BUILD_OPTIONS"} = ""; $default{"BISECT_SLEEP_TIME"} = 60; # sleep time between bisects $default{"CLEAR_LOG"} = 0; $default{"BISECT_MANUAL"} = 0; +$default{"BISECT_SKIP"} = 1; $default{"SUCCESS_LINE"} = "login:"; $default{"BOOTED_TIMEOUT"} = 1; $default{"DIE_ON_FAILURE"} = 1; @@ -83,6 +84,7 @@ my $in_bisect = 0; my $bisect_bad = ""; my $reverse_bisect; my $bisect_manual; +my $bisect_skip; my $in_patchcheck = 0; my $run_test; my $redirect; @@ -1169,7 +1171,15 @@ sub run_git_bisect { return 1; } -# returns 1 on success, 0 on failure +sub bisect_reboot { + doprint "Reboot and sleep $bisect_sleep_time seconds\n"; + reboot; + start_monitor; + wait_for_monitor $bisect_sleep_time; + end_monitor; +} + +# returns 1 on success, 0 on failure, -1 on skip sub run_bisect_test { my ($type, $buildtype) = @_; @@ -1183,6 +1193,10 @@ sub run_bisect_test { build $buildtype or $failed = 1; if ($type ne "build") { + if ($failed && $bisect_skip) { + $in_bisect = 0; + return -1; + } dodie "Failed on build" if $failed; # Now boot the box @@ -1194,6 +1208,12 @@ sub run_bisect_test { monitor or $failed = 1; if ($type ne "boot") { + if ($failed && $bisect_skip) { + end_monitor; + bisect_reboot; + $in_bisect = 0; + return -1; + } dodie "Failed on boot" if $failed; do_run_test or $failed = 1; @@ -1206,11 +1226,7 @@ sub run_bisect_test { # reboot the box to a good kernel if ($type ne "build") { - doprint "Reboot and sleep $bisect_sleep_time seconds\n"; - reboot; - start_monitor; - wait_for_monitor $bisect_sleep_time; - end_monitor; + bisect_reboot; } } else { $result = 1; @@ -1240,10 +1256,13 @@ sub run_bisect { $ret = !$ret; } - if ($ret) { + if ($ret > 0) { return "good"; - } else { + } elsif ($ret == 0) { return "bad"; + } elsif ($bisect_skip) { + doprint "HIT A BAD COMMIT ... SKIPPING\n"; + return "skip"; } } @@ -1954,6 +1973,7 @@ for (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) { $sleep_time = set_test_option("SLEEP_TIME", $i); $bisect_sleep_time = set_test_option("BISECT_SLEEP_TIME", $i); $bisect_manual = set_test_option("BISECT_MANUAL", $i); + $bisect_skip = set_test_option("BISECT_SKIP", $i); $store_failures = set_test_option("STORE_FAILURES", $i); $timeout = set_test_option("TIMEOUT", $i); $booted_timeout = set_test_option("BOOTED_TIMEOUT", $i); diff --git a/tools/testing/ktest/sample.conf b/tools/testing/ktest/sample.conf index af82ac2897797..4c46b7ef8e468 100644 --- a/tools/testing/ktest/sample.conf +++ b/tools/testing/ktest/sample.conf @@ -519,6 +519,15 @@ # git bisect good, git bisect bad, and running the git bisect replay # if the BISECT_REPLAY is set. # +# BISECT_SKIP = 1 (optional, default 0) +# +# If BISECT_TYPE is set to test but the build fails, ktest will +# simply fail the test and end their. You could use BISECT_REPLAY +# and BISECT_START to resume after you found a new starting point, +# or you could set BISECT_SKIP to 1. If BISECT_SKIP is set to 1, +# when something other than the BISECT_TYPE fails, ktest.pl will +# run "git bisect skip" and try again. +# # BISECT_REVERSE = 1 (optional, default 0) # # In those strange instances where it was broken forever -- GitLab From 3410f6fd5e3e96de4b557a62b7a2fbf19d74b1cd Mon Sep 17 00:00:00 2001 From: Steven Rostedt Date: Tue, 8 Mar 2011 09:38:12 -0500 Subject: [PATCH 0338/2822] ktest: Add BISECT_FILES to run git bisect on paths Add the config option BISECT_FILES that allows the user to specify what path in the kernel to run the git bisect on. Signed-off-by: Steven Rostedt --- tools/testing/ktest/ktest.pl | 9 ++++++++- tools/testing/ktest/sample.conf | 9 +++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/tools/testing/ktest/ktest.pl b/tools/testing/ktest/ktest.pl index 0f62916a43f71..65c5c5515b478 100755 --- a/tools/testing/ktest/ktest.pl +++ b/tools/testing/ktest/ktest.pl @@ -1280,6 +1280,13 @@ sub bisect { my $type = $opt{"BISECT_TYPE[$i]"}; my $start = $opt{"BISECT_START[$i]"}; my $replay = $opt{"BISECT_REPLAY[$i]"}; + my $start_files = $opt{"BISECT_FILES[$i]"}; + + if (defined($start_files)) { + $start_files = " -- " . $start_files; + } else { + $start_files = ""; + } # convert to true sha1's $good = get_sha1($good); @@ -1333,7 +1340,7 @@ sub bisect { die "Failed to checkout $head"; } - run_command "git bisect start" or + run_command "git bisect start$start_files" or dodie "could not start bisect"; run_command "git bisect good $good" or diff --git a/tools/testing/ktest/sample.conf b/tools/testing/ktest/sample.conf index 4c46b7ef8e468..4c83ae77926c0 100644 --- a/tools/testing/ktest/sample.conf +++ b/tools/testing/ktest/sample.conf @@ -528,6 +528,15 @@ # when something other than the BISECT_TYPE fails, ktest.pl will # run "git bisect skip" and try again. # +# BISECT_FILES = (optional, default undefined) +# +# To just run the git bisect on a specific path, set BISECT_FILES. +# For example: +# +# BISECT_FILES = arch/x86 kernel/time +# +# Will run the bisect with "git bisect start -- arch/x86 kernel/time" +# # BISECT_REVERSE = 1 (optional, default 0) # # In those strange instances where it was broken forever -- GitLab From 4651920e0ac7a596c1123a8efdcc2f6d2249deb3 Mon Sep 17 00:00:00 2001 From: Steven Rostedt Date: Tue, 8 Mar 2011 09:40:31 -0500 Subject: [PATCH 0339/2822] ktest: Fix bug where the test would not end after failure The config STOP_AFTER_FAILURE is the number of seconds to continue the test when a failure is detected. This lets the monitor record more data to the logs and console that may be helpful in solving the bug that was found. But the test had a bug. If the failure caused multiple "Call Trace" stack dumps, the start time to compare the STOP_AFTER_FAILURE would constantly be reset. Only update the start time at the first "Call Trace" instance. Signed-off-by: Steven Rostedt --- tools/testing/ktest/ktest.pl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/testing/ktest/ktest.pl b/tools/testing/ktest/ktest.pl index 65c5c5515b478..125ab94e7294c 100755 --- a/tools/testing/ktest/ktest.pl +++ b/tools/testing/ktest/ktest.pl @@ -804,7 +804,7 @@ sub monitor { } if ($full_line =~ /call trace:/i) { - if (!$skip_call_trace) { + if (!$bug && !$skip_call_trace) { $bug = 1; $failure_start = time; } -- GitLab From 8ea0e063a78df91b1ca4d23ea8d4e2e3047f6950 Mon Sep 17 00:00:00 2001 From: Steven Rostedt Date: Tue, 8 Mar 2011 09:44:35 -0500 Subject: [PATCH 0340/2822] ktest: Monitor kernel while running of user tests Record the console of tests to both the console and the log. Also, record the bug reports afte the test has completed. Currently, if a kernel bug happens while running the userland test, the test stops and will not record the kernel bug. This makes it difficult to solve what happened. Signed-off-by: Steven Rostedt --- tools/testing/ktest/ktest.pl | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/tools/testing/ktest/ktest.pl b/tools/testing/ktest/ktest.pl index 125ab94e7294c..8bbfceedfdb29 100755 --- a/tools/testing/ktest/ktest.pl +++ b/tools/testing/ktest/ktest.pl @@ -1110,6 +1110,7 @@ sub do_run_test { # we are not guaranteed to get a full line $full_line .= $line; + doprint $line; if ($full_line =~ /call trace:/i) { $bug = 1; @@ -1126,6 +1127,19 @@ sub do_run_test { } while (!$child_done && !$bug); if ($bug) { + my $failure_start = time; + my $now; + do { + $line = wait_for_input($monitor_fp, 1); + if (defined($line)) { + doprint $line; + } + $now = time; + if ($now - $failure_start >= $stop_after_failure) { + last; + } + } while (defined($line)); + doprint "Detected kernel crash!\n"; # kill the child with extreme prejudice kill 9, $child_pid; -- GitLab From 2d01b26a1b14ab248f850d858f2ff3de3ead6d33 Mon Sep 17 00:00:00 2001 From: Steven Rostedt Date: Tue, 8 Mar 2011 09:47:54 -0500 Subject: [PATCH 0341/2822] ktest: Add STOP_TEST_AFTER to stop the test after a period of time Currently, if a test causes constant output but never reaches a boot prompt, or crashes, the test will never stop. Add STOP_TEST_AFTER to create a variable that will stop (and fail) the test after it has run for this amount of time. The default is 10 minutes. Setting this variable to -1 will disable it. Signed-off-by: Steven Rostedt --- tools/testing/ktest/ktest.pl | 13 ++++++++++++- tools/testing/ktest/sample.conf | 8 ++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/tools/testing/ktest/ktest.pl b/tools/testing/ktest/ktest.pl index 8bbfceedfdb29..a8b3292d06396 100755 --- a/tools/testing/ktest/ktest.pl +++ b/tools/testing/ktest/ktest.pl @@ -47,6 +47,7 @@ $default{"SCP_TO_TARGET"} = "scp \$SRC_FILE \$SSH_USER\@\$MACHINE:\$DST_FILE"; $default{"REBOOT"} = "ssh \$SSH_USER\@\$MACHINE reboot"; $default{"STOP_AFTER_SUCCESS"} = 10; $default{"STOP_AFTER_FAILURE"} = 60; +$default{"STOP_TEST_AFTER"} = 600; $default{"LOCALVERSION"} = "-test"; my $ktest_config; @@ -102,6 +103,7 @@ my $console; my $success_line; my $stop_after_success; my $stop_after_failure; +my $stop_test_after; my $build_target; my $target_image; my $localversion; @@ -768,8 +770,10 @@ sub monitor { my $success_start; my $failure_start; + my $monitor_start = time; + my $done = 0; - for (;;) { + while (!$done) { if ($booted) { $line = wait_for_input($monitor_fp, $booted_timeout); @@ -831,6 +835,12 @@ sub monitor { if ($line =~ /\n/) { $full_line = ""; } + + if ($stop_test_after > 0 && !$booted && !$bug) { + if (time - $monitor_start > $stop_test_after) { + $done = 1; + } + } } close(DMESG); @@ -2002,6 +2012,7 @@ for (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) { $success_line = set_test_option("SUCCESS_LINE", $i); $stop_after_success = set_test_option("STOP_AFTER_SUCCESS", $i); $stop_after_failure = set_test_option("STOP_AFTER_FAILURE", $i); + $stop_test_after = set_test_option("STOP_TEST_AFTER", $i); $build_target = set_test_option("BUILD_TARGET", $i); $ssh_exec = set_test_option("SSH_EXEC", $i); $scp_to_target = set_test_option("SCP_TO_TARGET", $i); diff --git a/tools/testing/ktest/sample.conf b/tools/testing/ktest/sample.conf index 4c83ae77926c0..4c5d6bd74a020 100644 --- a/tools/testing/ktest/sample.conf +++ b/tools/testing/ktest/sample.conf @@ -306,6 +306,14 @@ # (default 60) #STOP_AFTER_FAILURE = 60 +# In case the console constantly fills the screen, having +# a specified time to stop the test if it never succeeds nor fails +# is recommended. +# Note: this is ignored if a success or failure is detected. +# (in seconds) +# (default 600, -1 is to never stop) +#STOP_TEST_AFTER = 600 + # Stop testing if a build fails. If set, the script will end if # a failure is detected, otherwise it will save off the .config, # dmesg and bootlog in a directory called -- GitLab From d47effe1be0c4fc983306a9c704632e3a087eed8 Mon Sep 17 00:00:00 2001 From: Krishna Kumar Date: Tue, 1 Mar 2011 17:06:37 +0530 Subject: [PATCH 0342/2822] vhost: Cleanup vhost.c and net.c Minor cleanup of vhost.c and net.c to match coding style. Signed-off-by: Krishna Kumar Signed-off-by: Michael S. Tsirkin --- drivers/vhost/net.c | 19 ++++++++++------ drivers/vhost/vhost.c | 53 ++++++++++++++++++++++++++++++------------- 2 files changed, 49 insertions(+), 23 deletions(-) diff --git a/drivers/vhost/net.c b/drivers/vhost/net.c index f616cefc95ba7..59dad9fe52ddc 100644 --- a/drivers/vhost/net.c +++ b/drivers/vhost/net.c @@ -60,6 +60,7 @@ static int move_iovec_hdr(struct iovec *from, struct iovec *to, { int seg = 0; size_t size; + while (len && seg < iov_count) { size = min(from->iov_len, len); to->iov_base = from->iov_base; @@ -79,6 +80,7 @@ static void copy_iovec_hdr(const struct iovec *from, struct iovec *to, { int seg = 0; size_t size; + while (len && seg < iovcount) { size = min(from->iov_len, len); to->iov_base = from->iov_base; @@ -296,17 +298,16 @@ static void handle_rx_big(struct vhost_net *net) .msg_iov = vq->iov, .msg_flags = MSG_DONTWAIT, }; - struct virtio_net_hdr hdr = { .flags = 0, .gso_type = VIRTIO_NET_HDR_GSO_NONE }; - size_t len, total_len = 0; int err; size_t hdr_size; /* TODO: check that we are running from vhost_worker? */ struct socket *sock = rcu_dereference_check(vq->private_data, 1); + if (!sock || skb_queue_empty(&sock->sk->sk_receive_queue)) return; @@ -405,18 +406,17 @@ static void handle_rx_mergeable(struct vhost_net *net) .msg_iov = vq->iov, .msg_flags = MSG_DONTWAIT, }; - struct virtio_net_hdr_mrg_rxbuf hdr = { .hdr.flags = 0, .hdr.gso_type = VIRTIO_NET_HDR_GSO_NONE }; - size_t total_len = 0; int err, headcount; size_t vhost_hlen, sock_hlen; size_t vhost_len, sock_len; /* TODO: check that we are running from vhost_worker? */ struct socket *sock = rcu_dereference_check(vq->private_data, 1); + if (!sock || skb_queue_empty(&sock->sk->sk_receive_queue)) return; @@ -654,6 +654,7 @@ static struct socket *get_raw_socket(int fd) } uaddr; int uaddr_len = sizeof uaddr, r; struct socket *sock = sockfd_lookup(fd, &r); + if (!sock) return ERR_PTR(-ENOTSOCK); @@ -682,6 +683,7 @@ static struct socket *get_tap_socket(int fd) { struct file *file = fget(fd); struct socket *sock; + if (!file) return ERR_PTR(-EBADF); sock = tun_get_socket(file); @@ -696,6 +698,7 @@ static struct socket *get_tap_socket(int fd) static struct socket *get_socket(int fd) { struct socket *sock; + /* special case to disable backend */ if (fd == -1) return NULL; @@ -741,9 +744,9 @@ static long vhost_net_set_backend(struct vhost_net *n, unsigned index, int fd) oldsock = rcu_dereference_protected(vq->private_data, lockdep_is_held(&vq->mutex)); if (sock != oldsock) { - vhost_net_disable_vq(n, vq); - rcu_assign_pointer(vq->private_data, sock); - vhost_net_enable_vq(n, vq); + vhost_net_disable_vq(n, vq); + rcu_assign_pointer(vq->private_data, sock); + vhost_net_enable_vq(n, vq); } mutex_unlock(&vq->mutex); @@ -768,6 +771,7 @@ static long vhost_net_reset_owner(struct vhost_net *n) struct socket *tx_sock = NULL; struct socket *rx_sock = NULL; long err; + mutex_lock(&n->dev.mutex); err = vhost_dev_check_owner(&n->dev); if (err) @@ -829,6 +833,7 @@ static long vhost_net_ioctl(struct file *f, unsigned int ioctl, struct vhost_vring_file backend; u64 features; int r; + switch (ioctl) { case VHOST_NET_SET_BACKEND: if (copy_from_user(&backend, argp, sizeof backend)) diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c index ade0568c07a4e..b0cc7f8ca4dea 100644 --- a/drivers/vhost/vhost.c +++ b/drivers/vhost/vhost.c @@ -41,8 +41,8 @@ static void vhost_poll_func(struct file *file, wait_queue_head_t *wqh, poll_table *pt) { struct vhost_poll *poll; - poll = container_of(pt, struct vhost_poll, table); + poll = container_of(pt, struct vhost_poll, table); poll->wqh = wqh; add_wait_queue(wqh, &poll->wait); } @@ -85,6 +85,7 @@ void vhost_poll_init(struct vhost_poll *poll, vhost_work_fn_t fn, void vhost_poll_start(struct vhost_poll *poll, struct file *file) { unsigned long mask; + mask = file->f_op->poll(file, &poll->table); if (mask) vhost_poll_wakeup(&poll->wait, 0, 0, (void *)mask); @@ -101,6 +102,7 @@ static bool vhost_work_seq_done(struct vhost_dev *dev, struct vhost_work *work, unsigned seq) { int left; + spin_lock_irq(&dev->work_lock); left = seq - work->done_seq; spin_unlock_irq(&dev->work_lock); @@ -222,6 +224,7 @@ static int vhost_worker(void *data) static long vhost_dev_alloc_iovecs(struct vhost_dev *dev) { int i; + for (i = 0; i < dev->nvqs; ++i) { dev->vqs[i].indirect = kmalloc(sizeof *dev->vqs[i].indirect * UIO_MAXIOV, GFP_KERNEL); @@ -235,6 +238,7 @@ static long vhost_dev_alloc_iovecs(struct vhost_dev *dev) goto err_nomem; } return 0; + err_nomem: for (; i >= 0; --i) { kfree(dev->vqs[i].indirect); @@ -247,6 +251,7 @@ err_nomem: static void vhost_dev_free_iovecs(struct vhost_dev *dev) { int i; + for (i = 0; i < dev->nvqs; ++i) { kfree(dev->vqs[i].indirect); dev->vqs[i].indirect = NULL; @@ -296,26 +301,28 @@ long vhost_dev_check_owner(struct vhost_dev *dev) } struct vhost_attach_cgroups_struct { - struct vhost_work work; - struct task_struct *owner; - int ret; + struct vhost_work work; + struct task_struct *owner; + int ret; }; static void vhost_attach_cgroups_work(struct vhost_work *work) { - struct vhost_attach_cgroups_struct *s; - s = container_of(work, struct vhost_attach_cgroups_struct, work); - s->ret = cgroup_attach_task_all(s->owner, current); + struct vhost_attach_cgroups_struct *s; + + s = container_of(work, struct vhost_attach_cgroups_struct, work); + s->ret = cgroup_attach_task_all(s->owner, current); } static int vhost_attach_cgroups(struct vhost_dev *dev) { - struct vhost_attach_cgroups_struct attach; - attach.owner = current; - vhost_work_init(&attach.work, vhost_attach_cgroups_work); - vhost_work_queue(dev, &attach.work); - vhost_work_flush(dev, &attach.work); - return attach.ret; + struct vhost_attach_cgroups_struct attach; + + attach.owner = current; + vhost_work_init(&attach.work, vhost_attach_cgroups_work); + vhost_work_queue(dev, &attach.work); + vhost_work_flush(dev, &attach.work); + return attach.ret; } /* Caller should have device mutex */ @@ -323,11 +330,13 @@ static long vhost_dev_set_owner(struct vhost_dev *dev) { struct task_struct *worker; int err; + /* Is there an owner already? */ if (dev->mm) { err = -EBUSY; goto err_mm; } + /* No owner, become one */ dev->mm = get_task_mm(current); worker = kthread_create(vhost_worker, dev, "vhost-%d", current->pid); @@ -380,6 +389,7 @@ long vhost_dev_reset_owner(struct vhost_dev *dev) void vhost_dev_cleanup(struct vhost_dev *dev) { int i; + for (i = 0; i < dev->nvqs; ++i) { if (dev->vqs[i].kick && dev->vqs[i].handle_kick) { vhost_poll_stop(&dev->vqs[i].poll); @@ -421,6 +431,7 @@ void vhost_dev_cleanup(struct vhost_dev *dev) static int log_access_ok(void __user *log_base, u64 addr, unsigned long sz) { u64 a = addr / VHOST_PAGE_SIZE / 8; + /* Make sure 64 bit math will not overflow. */ if (a > ULONG_MAX - (unsigned long)log_base || a + (unsigned long)log_base > ULONG_MAX) @@ -461,6 +472,7 @@ static int memory_access_ok(struct vhost_dev *d, struct vhost_memory *mem, int log_all) { int i; + for (i = 0; i < d->nvqs; ++i) { int ok; mutex_lock(&d->vqs[i].mutex); @@ -527,6 +539,7 @@ static long vhost_set_memory(struct vhost_dev *d, struct vhost_memory __user *m) { struct vhost_memory mem, *newmem, *oldmem; unsigned long size = offsetof(struct vhost_memory, regions); + if (copy_from_user(&mem, m, size)) return -EFAULT; if (mem.padding) @@ -544,7 +557,8 @@ static long vhost_set_memory(struct vhost_dev *d, struct vhost_memory __user *m) return -EFAULT; } - if (!memory_access_ok(d, newmem, vhost_has_feature(d, VHOST_F_LOG_ALL))) { + if (!memory_access_ok(d, newmem, + vhost_has_feature(d, VHOST_F_LOG_ALL))) { kfree(newmem); return -EFAULT; } @@ -560,6 +574,7 @@ static int init_used(struct vhost_virtqueue *vq, struct vring_used __user *used) { int r = put_user(vq->used_flags, &used->flags); + if (r) return r; return get_user(vq->last_used_idx, &used->idx); @@ -849,6 +864,7 @@ static const struct vhost_memory_region *find_region(struct vhost_memory *mem, { struct vhost_memory_region *reg; int i; + /* linear search is not brilliant, but we really have on the order of 6 * regions in practice */ for (i = 0; i < mem->nregions; ++i) { @@ -871,6 +887,7 @@ static int set_bit_to_user(int nr, void __user *addr) void *base; int bit = nr + (log % PAGE_SIZE) * 8; int r; + r = get_user_pages_fast(log, 1, 1, &page); if (r < 0) return r; @@ -888,6 +905,7 @@ static int log_write(void __user *log_base, { u64 write_page = write_address / VHOST_PAGE_SIZE; int r; + if (!write_length) return 0; write_length += write_address % VHOST_PAGE_SIZE; @@ -1037,8 +1055,8 @@ static int get_indirect(struct vhost_dev *dev, struct vhost_virtqueue *vq, i, count); return -EINVAL; } - if (unlikely(memcpy_fromiovec((unsigned char *)&desc, vq->indirect, - sizeof desc))) { + if (unlikely(memcpy_fromiovec((unsigned char *)&desc, + vq->indirect, sizeof desc))) { vq_err(vq, "Failed indirect descriptor: idx %d, %zx\n", i, (size_t)indirect->addr + i * sizeof desc); return -EINVAL; @@ -1317,6 +1335,7 @@ int vhost_add_used_n(struct vhost_virtqueue *vq, struct vring_used_elem *heads, void vhost_signal(struct vhost_dev *dev, struct vhost_virtqueue *vq) { __u16 flags; + /* Flush out used index updates. This is paired * with the barrier that the Guest executes when enabling * interrupts. */ @@ -1361,6 +1380,7 @@ bool vhost_enable_notify(struct vhost_virtqueue *vq) { u16 avail_idx; int r; + if (!(vq->used_flags & VRING_USED_F_NO_NOTIFY)) return false; vq->used_flags &= ~VRING_USED_F_NO_NOTIFY; @@ -1387,6 +1407,7 @@ bool vhost_enable_notify(struct vhost_virtqueue *vq) void vhost_disable_notify(struct vhost_virtqueue *vq) { int r; + if (vq->used_flags & VRING_USED_F_NO_NOTIFY) return; vq->used_flags |= VRING_USED_F_NO_NOTIFY; -- GitLab From fcc042a2806064ffcaed7a0c5cb710eca0e99108 Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Sun, 6 Mar 2011 13:33:49 +0200 Subject: [PATCH 0343/2822] vhost: copy_from_user -> __copy_from_user copy_from_user is pretty high on perf top profile, replacing it with __copy_from_user helps. It's also safe because we do access_ok checks during setup. Signed-off-by: Michael S. Tsirkin --- drivers/vhost/vhost.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c index b0cc7f8ca4dea..2ab291241635d 100644 --- a/drivers/vhost/vhost.c +++ b/drivers/vhost/vhost.c @@ -1171,7 +1171,7 @@ int vhost_get_vq_desc(struct vhost_dev *dev, struct vhost_virtqueue *vq, i, vq->num, head); return -EINVAL; } - ret = copy_from_user(&desc, vq->desc + i, sizeof desc); + ret = __copy_from_user(&desc, vq->desc + i, sizeof desc); if (unlikely(ret)) { vq_err(vq, "Failed to get descriptor: idx %d addr %p\n", i, vq->desc + i); -- GitLab From 8b3e07ac908d005bb791410f594cce8744f6806a Mon Sep 17 00:00:00 2001 From: "J. Bruce Fields" Date: Mon, 7 Mar 2011 22:50:47 -0500 Subject: [PATCH 0344/2822] svcrpc: fix rare race on unix_domain creation Note that "new" here is not yet fully initialized; auth_domain_put should be called only on auth_domains that have actually been added to the hash. Before this fix, two attempts to add the same domain at once could cause the hlist_del in auth_domain_put to fail. Signed-off-by: J. Bruce Fields --- net/sunrpc/svcauth_unix.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/net/sunrpc/svcauth_unix.c b/net/sunrpc/svcauth_unix.c index 30916b06c12bd..d100bf2b4e817 100644 --- a/net/sunrpc/svcauth_unix.c +++ b/net/sunrpc/svcauth_unix.c @@ -38,6 +38,14 @@ struct unix_domain { extern struct auth_ops svcauth_unix; +static void svcauth_unix_domain_release(struct auth_domain *dom) +{ + struct unix_domain *ud = container_of(dom, struct unix_domain, h); + + kfree(dom->name); + kfree(ud); +} + struct auth_domain *unix_domain_find(char *name) { struct auth_domain *rv; @@ -47,7 +55,7 @@ struct auth_domain *unix_domain_find(char *name) while(1) { if (rv) { if (new && rv != &new->h) - auth_domain_put(&new->h); + svcauth_unix_domain_release(new); if (rv->flavour != &svcauth_unix) { auth_domain_put(rv); @@ -74,14 +82,6 @@ struct auth_domain *unix_domain_find(char *name) } EXPORT_SYMBOL_GPL(unix_domain_find); -static void svcauth_unix_domain_release(struct auth_domain *dom) -{ - struct unix_domain *ud = container_of(dom, struct unix_domain, h); - - kfree(dom->name); - kfree(ud); -} - /************************************************** * cache for IP address to unix_domain -- GitLab From df457f845e5449be2e7d96668791f789b3770ac7 Mon Sep 17 00:00:00 2001 From: Justin TerAvest Date: Tue, 8 Mar 2011 19:45:00 +0100 Subject: [PATCH 0345/2822] blk-cgroup: Lower minimum weight from 100 to 10. We've found that we still get good, useful isolation at weights this low. I'd like to adjust the minimum so that any other changes can take these values into account. Signed-off-by: Justin TerAvest Acked-by: Vivek Goyal Signed-off-by: Jens Axboe --- Documentation/cgroups/blkio-controller.txt | 2 +- block/blk-cgroup.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Documentation/cgroups/blkio-controller.txt b/Documentation/cgroups/blkio-controller.txt index d915c16df42c1..465351d4cf853 100644 --- a/Documentation/cgroups/blkio-controller.txt +++ b/Documentation/cgroups/blkio-controller.txt @@ -140,7 +140,7 @@ Proportional weight policy files - Specifies per cgroup weight. This is default weight of the group on all the devices until and unless overridden by per device rule. (See blkio.weight_device). - Currently allowed range of weights is from 100 to 1000. + Currently allowed range of weights is from 10 to 1000. - blkio.weight_device - One can specify per cgroup per device rules using this interface. diff --git a/block/blk-cgroup.h b/block/blk-cgroup.h index ea4861bdd549a..57e7234c5ae5b 100644 --- a/block/blk-cgroup.h +++ b/block/blk-cgroup.h @@ -240,7 +240,7 @@ static inline char *blkg_path(struct blkio_group *blkg) { return NULL; } #endif -#define BLKIO_WEIGHT_MIN 100 +#define BLKIO_WEIGHT_MIN 10 #define BLKIO_WEIGHT_MAX 1000 #define BLKIO_WEIGHT_DEFAULT 500 -- GitLab From 529d7b2a7fa31e9f7d08bc790d232c3cbe64fa24 Mon Sep 17 00:00:00 2001 From: "J. Bruce Fields" Date: Wed, 2 Mar 2011 23:48:33 -0500 Subject: [PATCH 0346/2822] nfsd4: minor nfs4state.c reshuffling Minor cleanup in preparation for a bugfix--moving some code to avoid forward references, etc. No change in functionality. Cc: stable@kernel.org Signed-off-by: J. Bruce Fields --- fs/nfsd/nfs4state.c | 125 +++++++++++++++++++++----------------------- 1 file changed, 61 insertions(+), 64 deletions(-) diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index c4f2b0f63e46b..84d2dd327b2d8 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c @@ -316,64 +316,6 @@ static struct list_head unconf_id_hashtbl[CLIENT_HASH_SIZE]; static struct list_head client_lru; static struct list_head close_lru; -static void unhash_generic_stateid(struct nfs4_stateid *stp) -{ - list_del(&stp->st_hash); - list_del(&stp->st_perfile); - list_del(&stp->st_perstateowner); -} - -static void free_generic_stateid(struct nfs4_stateid *stp) -{ - put_nfs4_file(stp->st_file); - kmem_cache_free(stateid_slab, stp); -} - -static void release_lock_stateid(struct nfs4_stateid *stp) -{ - struct file *file; - - unhash_generic_stateid(stp); - file = find_any_file(stp->st_file); - if (file) - locks_remove_posix(file, (fl_owner_t)stp->st_stateowner); - free_generic_stateid(stp); -} - -static void unhash_lockowner(struct nfs4_stateowner *sop) -{ - struct nfs4_stateid *stp; - - list_del(&sop->so_idhash); - list_del(&sop->so_strhash); - list_del(&sop->so_perstateid); - while (!list_empty(&sop->so_stateids)) { - stp = list_first_entry(&sop->so_stateids, - struct nfs4_stateid, st_perstateowner); - release_lock_stateid(stp); - } -} - -static void release_lockowner(struct nfs4_stateowner *sop) -{ - unhash_lockowner(sop); - nfs4_put_stateowner(sop); -} - -static void -release_stateid_lockowners(struct nfs4_stateid *open_stp) -{ - struct nfs4_stateowner *lock_sop; - - while (!list_empty(&open_stp->st_lockowners)) { - lock_sop = list_entry(open_stp->st_lockowners.next, - struct nfs4_stateowner, so_perstateid); - /* list_del(&open_stp->st_lockowners); */ - BUG_ON(lock_sop->so_is_open_owner); - release_lockowner(lock_sop); - } -} - /* * We store the NONE, READ, WRITE, and BOTH bits separately in the * st_{access,deny}_bmap field of the stateid, in order to track not @@ -446,6 +388,64 @@ static int nfs4_access_bmap_to_omode(struct nfs4_stateid *stp) return nfs4_access_to_omode(access); } +static void unhash_generic_stateid(struct nfs4_stateid *stp) +{ + list_del(&stp->st_hash); + list_del(&stp->st_perfile); + list_del(&stp->st_perstateowner); +} + +static void free_generic_stateid(struct nfs4_stateid *stp) +{ + put_nfs4_file(stp->st_file); + kmem_cache_free(stateid_slab, stp); +} + +static void release_lock_stateid(struct nfs4_stateid *stp) +{ + struct file *file; + + unhash_generic_stateid(stp); + file = find_any_file(stp->st_file); + if (file) + locks_remove_posix(file, (fl_owner_t)stp->st_stateowner); + free_generic_stateid(stp); +} + +static void unhash_lockowner(struct nfs4_stateowner *sop) +{ + struct nfs4_stateid *stp; + + list_del(&sop->so_idhash); + list_del(&sop->so_strhash); + list_del(&sop->so_perstateid); + while (!list_empty(&sop->so_stateids)) { + stp = list_first_entry(&sop->so_stateids, + struct nfs4_stateid, st_perstateowner); + release_lock_stateid(stp); + } +} + +static void release_lockowner(struct nfs4_stateowner *sop) +{ + unhash_lockowner(sop); + nfs4_put_stateowner(sop); +} + +static void +release_stateid_lockowners(struct nfs4_stateid *open_stp) +{ + struct nfs4_stateowner *lock_sop; + + while (!list_empty(&open_stp->st_lockowners)) { + lock_sop = list_entry(open_stp->st_lockowners.next, + struct nfs4_stateowner, so_perstateid); + /* list_del(&open_stp->st_lockowners); */ + BUG_ON(lock_sop->so_is_open_owner); + release_lockowner(lock_sop); + } +} + static void release_open_stateid(struct nfs4_stateid *stp) { int oflag = nfs4_access_bmap_to_omode(stp); @@ -3764,7 +3764,6 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, struct file_lock conflock; __be32 status = 0; unsigned int strhashval; - unsigned int cmd; int err; dprintk("NFSD: nfsd4_lock: start=%Ld length=%Ld\n", @@ -3851,8 +3850,7 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, filp = find_readable_file(lock_stp->st_file); } file_lock.fl_type = F_RDLCK; - cmd = F_SETLK; - break; + break; case NFS4_WRITE_LT: case NFS4_WRITEW_LT: if (find_writeable_file(lock_stp->st_file)) { @@ -3860,8 +3858,7 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, filp = find_writeable_file(lock_stp->st_file); } file_lock.fl_type = F_WRLCK; - cmd = F_SETLK; - break; + break; default: status = nfserr_inval; goto out; @@ -3885,7 +3882,7 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, * Note: locks.c uses the BKL to protect the inode's lock list. */ - err = vfs_lock_file(filp, cmd, &file_lock, &conflock); + err = vfs_lock_file(filp, F_SETLK, &file_lock, &conflock); switch (-err) { case 0: /* success! */ update_stateid(&lock_stp->st_stateid); -- GitLab From 0997b173609b9229ece28941c118a2a9b278796e Mon Sep 17 00:00:00 2001 From: "J. Bruce Fields" Date: Wed, 2 Mar 2011 18:01:35 -0500 Subject: [PATCH 0347/2822] nfsd4: fix struct file leak MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Make sure we properly reference count the struct files that a lock depends on, and release them when the lock stateid is released. This fixes a major leak of struct files when using locking over nfsv4. Cc: stable@kernel.org Reported-by: Rick Koshi Tested-by: Ivo Přikryl Signed-off-by: J. Bruce Fields --- fs/nfsd/nfs4state.c | 32 +++++++++++++++++++++----------- 1 file changed, 21 insertions(+), 11 deletions(-) diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index 84d2dd327b2d8..c26dc31fb943c 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c @@ -397,6 +397,9 @@ static void unhash_generic_stateid(struct nfs4_stateid *stp) static void free_generic_stateid(struct nfs4_stateid *stp) { + int oflag = nfs4_access_bmap_to_omode(stp); + + nfs4_file_put_access(stp->st_file, oflag); put_nfs4_file(stp->st_file); kmem_cache_free(stateid_slab, stp); } @@ -448,11 +451,8 @@ release_stateid_lockowners(struct nfs4_stateid *open_stp) static void release_open_stateid(struct nfs4_stateid *stp) { - int oflag = nfs4_access_bmap_to_omode(stp); - unhash_generic_stateid(stp); release_stateid_lockowners(stp); - nfs4_file_put_access(stp->st_file, oflag); free_generic_stateid(stp); } @@ -3734,6 +3734,7 @@ alloc_init_lock_stateid(struct nfs4_stateowner *sop, struct nfs4_file *fp, struc stp->st_stateid.si_stateownerid = sop->so_id; stp->st_stateid.si_fileid = fp->fi_id; stp->st_stateid.si_generation = 0; + stp->st_access_bmap = 0; stp->st_deny_bmap = open_stp->st_deny_bmap; stp->st_openstp = open_stp; @@ -3748,6 +3749,17 @@ check_lock_length(u64 offset, u64 length) LOFF_OVERFLOW(offset, length))); } +static void get_lock_access(struct nfs4_stateid *lock_stp, u32 access) +{ + struct nfs4_file *fp = lock_stp->st_file; + int oflag = nfs4_access_to_omode(access); + + if (test_bit(access, &lock_stp->st_access_bmap)) + return; + nfs4_file_get_access(fp, oflag); + __set_bit(access, &lock_stp->st_access_bmap); +} + /* * LOCK operation */ @@ -3845,18 +3857,16 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, switch (lock->lk_type) { case NFS4_READ_LT: case NFS4_READW_LT: - if (find_readable_file(lock_stp->st_file)) { - nfs4_get_vfs_file(rqstp, fp, &cstate->current_fh, NFS4_SHARE_ACCESS_READ); - filp = find_readable_file(lock_stp->st_file); - } + filp = find_readable_file(lock_stp->st_file); + if (filp) + get_lock_access(lock_stp, NFS4_SHARE_ACCESS_READ); file_lock.fl_type = F_RDLCK; break; case NFS4_WRITE_LT: case NFS4_WRITEW_LT: - if (find_writeable_file(lock_stp->st_file)) { - nfs4_get_vfs_file(rqstp, fp, &cstate->current_fh, NFS4_SHARE_ACCESS_WRITE); - filp = find_writeable_file(lock_stp->st_file); - } + filp = find_writeable_file(lock_stp->st_file); + if (filp) + get_lock_access(lock_stp, NFS4_SHARE_ACCESS_WRITE); file_lock.fl_type = F_WRLCK; break; default: -- GitLab From 3b2ce58b0f3c1633750529713be0e467282abd78 Mon Sep 17 00:00:00 2001 From: Ryusuke Konishi Date: Wed, 9 Mar 2011 11:05:07 +0900 Subject: [PATCH 0348/2822] nilfs2: move mount options to nilfs object This moves mount_opt local variable to nilfs object from nilfs_sb_info struct. Signed-off-by: Ryusuke Konishi --- fs/nilfs2/sb.h | 16 ------------- fs/nilfs2/segment.c | 9 +++---- fs/nilfs2/super.c | 56 ++++++++++++++++++++++--------------------- fs/nilfs2/the_nilfs.c | 4 ++-- fs/nilfs2/the_nilfs.h | 18 ++++++++++++++ 5 files changed, 54 insertions(+), 49 deletions(-) diff --git a/fs/nilfs2/sb.h b/fs/nilfs2/sb.h index 7a17715f215f7..d7346c949c816 100644 --- a/fs/nilfs2/sb.h +++ b/fs/nilfs2/sb.h @@ -34,8 +34,6 @@ struct nilfs_sc_info; * NILFS super-block data in memory */ struct nilfs_sb_info { - /* Mount options */ - unsigned long s_mount_opt; uid_t s_resuid; gid_t s_resgid; @@ -68,18 +66,4 @@ static inline struct nilfs_sc_info *NILFS_SC(struct nilfs_sb_info *sbi) return sbi->s_sc_info; } -/* - * Bit operations for the mount option - */ -#define nilfs_clear_opt(sbi, opt) \ - do { (sbi)->s_mount_opt &= ~NILFS_MOUNT_##opt; } while (0) -#define nilfs_set_opt(sbi, opt) \ - do { (sbi)->s_mount_opt |= NILFS_MOUNT_##opt; } while (0) -#define nilfs_test_opt(sbi, opt) ((sbi)->s_mount_opt & NILFS_MOUNT_##opt) -#define nilfs_write_opt(sbi, mask, opt) \ - do { (sbi)->s_mount_opt = \ - (((sbi)->s_mount_opt & ~NILFS_MOUNT_##mask) | \ - NILFS_MOUNT_##opt); \ - } while (0) - #endif /* _NILFS_SB */ diff --git a/fs/nilfs2/segment.c b/fs/nilfs2/segment.c index 2de9f636792a7..851bcd3890c8f 100644 --- a/fs/nilfs2/segment.c +++ b/fs/nilfs2/segment.c @@ -2298,6 +2298,7 @@ int nilfs_construct_dsync_segment(struct super_block *sb, struct inode *inode, loff_t start, loff_t end) { struct nilfs_sb_info *sbi = NILFS_SB(sb); + struct the_nilfs *nilfs = sbi->s_nilfs; struct nilfs_sc_info *sci = NILFS_SC(sbi); struct nilfs_inode_info *ii; struct nilfs_transaction_info ti; @@ -2310,9 +2311,9 @@ int nilfs_construct_dsync_segment(struct super_block *sb, struct inode *inode, ii = NILFS_I(inode); if (test_bit(NILFS_I_INODE_DIRTY, &ii->i_state) || - nilfs_test_opt(sbi, STRICT_ORDER) || + nilfs_test_opt(nilfs, STRICT_ORDER) || test_bit(NILFS_SC_UNCLOSED, &sci->sc_flags) || - nilfs_discontinued(sbi->s_nilfs)) { + nilfs_discontinued(nilfs)) { nilfs_transaction_unlock(sbi); err = nilfs_segctor_sync(sci); return err; @@ -2480,14 +2481,14 @@ int nilfs_clean_segments(struct super_block *sb, struct nilfs_argv *argv, set_current_state(TASK_INTERRUPTIBLE); schedule_timeout(sci->sc_interval); } - if (nilfs_test_opt(sbi, DISCARD)) { + if (nilfs_test_opt(nilfs, DISCARD)) { int ret = nilfs_discard_segments(nilfs, sci->sc_freesegs, sci->sc_nfreesegs); if (ret) { printk(KERN_WARNING "NILFS warning: error %d on discard request, " "turning discards off for the device\n", ret); - nilfs_clear_opt(sbi, DISCARD); + nilfs_clear_opt(nilfs, DISCARD); } } diff --git a/fs/nilfs2/super.c b/fs/nilfs2/super.c index 1673b3d998420..0576cb21d699c 100644 --- a/fs/nilfs2/super.c +++ b/fs/nilfs2/super.c @@ -109,7 +109,7 @@ static void nilfs_set_error(struct nilfs_sb_info *sbi) void nilfs_error(struct super_block *sb, const char *function, const char *fmt, ...) { - struct nilfs_sb_info *sbi = NILFS_SB(sb); + struct the_nilfs *nilfs = sbi->s_nilfs; struct va_format vaf; va_list args; @@ -126,13 +126,13 @@ void nilfs_error(struct super_block *sb, const char *function, if (!(sb->s_flags & MS_RDONLY)) { nilfs_set_error(sbi); - if (nilfs_test_opt(sbi, ERRORS_RO)) { + if (nilfs_test_opt(nilfs, ERRORS_RO)) { printk(KERN_CRIT "Remounting filesystem read-only\n"); sb->s_flags |= MS_RDONLY; } } - if (nilfs_test_opt(sbi, ERRORS_PANIC)) + if (nilfs_test_opt(nilfs, ERRORS_PANIC)) panic("NILFS (device %s): panic forced after error\n", sb->s_id); } @@ -196,7 +196,7 @@ static int nilfs_sync_super(struct nilfs_sb_info *sbi, int flag) retry: set_buffer_dirty(nilfs->ns_sbh[0]); - if (nilfs_test_opt(sbi, BARRIER)) { + if (nilfs_test_opt(nilfs, BARRIER)) { err = __sync_dirty_buffer(nilfs->ns_sbh[0], WRITE_SYNC | WRITE_FLUSH_FUA); } else { @@ -530,22 +530,22 @@ static int nilfs_statfs(struct dentry *dentry, struct kstatfs *buf) static int nilfs_show_options(struct seq_file *seq, struct vfsmount *vfs) { struct super_block *sb = vfs->mnt_sb; - struct nilfs_sb_info *sbi = NILFS_SB(sb); + struct the_nilfs *nilfs = NILFS_SB(sb)->s_nilfs; struct nilfs_root *root = NILFS_I(vfs->mnt_root->d_inode)->i_root; - if (!nilfs_test_opt(sbi, BARRIER)) + if (!nilfs_test_opt(nilfs, BARRIER)) seq_puts(seq, ",nobarrier"); if (root->cno != NILFS_CPTREE_CURRENT_CNO) seq_printf(seq, ",cp=%llu", (unsigned long long)root->cno); - if (nilfs_test_opt(sbi, ERRORS_PANIC)) + if (nilfs_test_opt(nilfs, ERRORS_PANIC)) seq_puts(seq, ",errors=panic"); - if (nilfs_test_opt(sbi, ERRORS_CONT)) + if (nilfs_test_opt(nilfs, ERRORS_CONT)) seq_puts(seq, ",errors=continue"); - if (nilfs_test_opt(sbi, STRICT_ORDER)) + if (nilfs_test_opt(nilfs, STRICT_ORDER)) seq_puts(seq, ",order=strict"); - if (nilfs_test_opt(sbi, NORECOVERY)) + if (nilfs_test_opt(nilfs, NORECOVERY)) seq_puts(seq, ",norecovery"); - if (nilfs_test_opt(sbi, DISCARD)) + if (nilfs_test_opt(nilfs, DISCARD)) seq_puts(seq, ",discard"); return 0; @@ -594,7 +594,7 @@ static match_table_t tokens = { static int parse_options(char *options, struct super_block *sb, int is_remount) { - struct nilfs_sb_info *sbi = NILFS_SB(sb); + struct the_nilfs *nilfs = NILFS_SB(sb)->s_nilfs; char *p; substring_t args[MAX_OPT_ARGS]; @@ -609,29 +609,29 @@ static int parse_options(char *options, struct super_block *sb, int is_remount) token = match_token(p, tokens, args); switch (token) { case Opt_barrier: - nilfs_set_opt(sbi, BARRIER); + nilfs_set_opt(nilfs, BARRIER); break; case Opt_nobarrier: - nilfs_clear_opt(sbi, BARRIER); + nilfs_clear_opt(nilfs, BARRIER); break; case Opt_order: if (strcmp(args[0].from, "relaxed") == 0) /* Ordered data semantics */ - nilfs_clear_opt(sbi, STRICT_ORDER); + nilfs_clear_opt(nilfs, STRICT_ORDER); else if (strcmp(args[0].from, "strict") == 0) /* Strict in-order semantics */ - nilfs_set_opt(sbi, STRICT_ORDER); + nilfs_set_opt(nilfs, STRICT_ORDER); else return 0; break; case Opt_err_panic: - nilfs_write_opt(sbi, ERROR_MODE, ERRORS_PANIC); + nilfs_write_opt(nilfs, ERROR_MODE, ERRORS_PANIC); break; case Opt_err_ro: - nilfs_write_opt(sbi, ERROR_MODE, ERRORS_RO); + nilfs_write_opt(nilfs, ERROR_MODE, ERRORS_RO); break; case Opt_err_cont: - nilfs_write_opt(sbi, ERROR_MODE, ERRORS_CONT); + nilfs_write_opt(nilfs, ERROR_MODE, ERRORS_CONT); break; case Opt_snapshot: if (is_remount) { @@ -642,13 +642,13 @@ static int parse_options(char *options, struct super_block *sb, int is_remount) } break; case Opt_norecovery: - nilfs_set_opt(sbi, NORECOVERY); + nilfs_set_opt(nilfs, NORECOVERY); break; case Opt_discard: - nilfs_set_opt(sbi, DISCARD); + nilfs_set_opt(nilfs, DISCARD); break; case Opt_nodiscard: - nilfs_clear_opt(sbi, DISCARD); + nilfs_clear_opt(nilfs, DISCARD); break; default: printk(KERN_ERR @@ -660,10 +660,12 @@ static int parse_options(char *options, struct super_block *sb, int is_remount) } static inline void -nilfs_set_default_options(struct nilfs_sb_info *sbi, +nilfs_set_default_options(struct super_block *sb, struct nilfs_super_block *sbp) { - sbi->s_mount_opt = + struct the_nilfs *nilfs = NILFS_SB(sb)->s_nilfs; + + nilfs->ns_mount_opt = NILFS_MOUNT_ERRORS_RO | NILFS_MOUNT_BARRIER; } @@ -736,7 +738,7 @@ int nilfs_store_magic_and_option(struct super_block *sb, sb->s_flags |= MS_NOATIME; #endif - nilfs_set_default_options(sbi, sbp); + nilfs_set_default_options(sb, sbp); sbi->s_resuid = le16_to_cpu(sbp->s_def_resuid); sbi->s_resgid = le16_to_cpu(sbp->s_def_resgid); @@ -1023,7 +1025,7 @@ static int nilfs_remount(struct super_block *sb, int *flags, char *data) int err; old_sb_flags = sb->s_flags; - old_mount_opt = sbi->s_mount_opt; + old_mount_opt = nilfs->ns_mount_opt; if (!parse_options(data, sb, 1)) { err = -EINVAL; @@ -1092,7 +1094,7 @@ static int nilfs_remount(struct super_block *sb, int *flags, char *data) restore_opts: sb->s_flags = old_sb_flags; - sbi->s_mount_opt = old_mount_opt; + nilfs->ns_mount_opt = old_mount_opt; return err; } diff --git a/fs/nilfs2/the_nilfs.c b/fs/nilfs2/the_nilfs.c index 9098909d5cef5..d3775336a16c9 100644 --- a/fs/nilfs2/the_nilfs.c +++ b/fs/nilfs2/the_nilfs.c @@ -283,7 +283,7 @@ int load_nilfs(struct the_nilfs *nilfs, struct nilfs_sb_info *sbi) if (s_flags & MS_RDONLY) { __u64 features; - if (nilfs_test_opt(sbi, NORECOVERY)) { + if (nilfs_test_opt(nilfs, NORECOVERY)) { printk(KERN_INFO "NILFS: norecovery option specified. " "skipping roll-forward recovery\n"); goto skip_recovery; @@ -305,7 +305,7 @@ int load_nilfs(struct the_nilfs *nilfs, struct nilfs_sb_info *sbi) goto failed_unload; } sbi->s_super->s_flags &= ~MS_RDONLY; - } else if (nilfs_test_opt(sbi, NORECOVERY)) { + } else if (nilfs_test_opt(nilfs, NORECOVERY)) { printk(KERN_ERR "NILFS: recovery cancelled because norecovery " "option was specified for a read/write mount\n"); err = -EINVAL; diff --git a/fs/nilfs2/the_nilfs.h b/fs/nilfs2/the_nilfs.h index fd85e4c05c6b2..438278041d802 100644 --- a/fs/nilfs2/the_nilfs.h +++ b/fs/nilfs2/the_nilfs.h @@ -72,6 +72,7 @@ enum { * @ns_cptree: rb-tree of all mounted checkpoints (nilfs_root) * @ns_cptree_lock: lock protecting @ns_cptree * @ns_gc_inodes: dummy inodes to keep live blocks + * @ns_mount_opt: mount options * @ns_blocksize_bits: bit length of block size * @ns_blocksize: block size * @ns_nsegments: number of segments in filesystem @@ -148,6 +149,9 @@ struct the_nilfs { /* GC inode list */ struct list_head ns_gc_inodes; + /* Mount options */ + unsigned long ns_mount_opt; + /* Disk layout information (static) */ unsigned int ns_blocksize_bits; unsigned int ns_blocksize; @@ -180,6 +184,20 @@ THE_NILFS_FNS(DISCONTINUED, discontinued) THE_NILFS_FNS(GC_RUNNING, gc_running) THE_NILFS_FNS(SB_DIRTY, sb_dirty) +/* + * Mount option operations + */ +#define nilfs_clear_opt(nilfs, opt) \ + do { (nilfs)->ns_mount_opt &= ~NILFS_MOUNT_##opt; } while (0) +#define nilfs_set_opt(nilfs, opt) \ + do { (nilfs)->ns_mount_opt |= NILFS_MOUNT_##opt; } while (0) +#define nilfs_test_opt(nilfs, opt) ((nilfs)->ns_mount_opt & NILFS_MOUNT_##opt) +#define nilfs_write_opt(nilfs, mask, opt) \ + do { (nilfs)->ns_mount_opt = \ + (((nilfs)->ns_mount_opt & ~NILFS_MOUNT_##mask) | \ + NILFS_MOUNT_##opt); \ + } while (0) + /** * struct nilfs_root - nilfs root object * @cno: checkpoint number -- GitLab From 574e6c3145c5754141361c695b58736c294a8ae1 Mon Sep 17 00:00:00 2001 From: Ryusuke Konishi Date: Wed, 9 Mar 2011 11:05:07 +0900 Subject: [PATCH 0349/2822] nilfs2: move parameters on nilfs_sb_info into nilfs object This moves four parameter variables on nilfs_sb_info s_resuid, s_resgid, s_interval and s_watermark to the nilfs object. Signed-off-by: Ryusuke Konishi --- fs/nilfs2/sb.h | 7 ------- fs/nilfs2/segment.c | 9 +++++---- fs/nilfs2/super.c | 10 +++++----- fs/nilfs2/the_nilfs.h | 9 +++++++++ 4 files changed, 19 insertions(+), 16 deletions(-) diff --git a/fs/nilfs2/sb.h b/fs/nilfs2/sb.h index d7346c949c816..0512521ba8a44 100644 --- a/fs/nilfs2/sb.h +++ b/fs/nilfs2/sb.h @@ -34,13 +34,6 @@ struct nilfs_sc_info; * NILFS super-block data in memory */ struct nilfs_sb_info { - uid_t s_resuid; - gid_t s_resgid; - - unsigned long s_interval; /* construction interval */ - unsigned long s_watermark; /* threshold of data amount - for the segment construction */ - /* Fundamental members */ struct super_block *s_super; /* reverse pointer to super_block */ struct the_nilfs *s_nilfs; diff --git a/fs/nilfs2/segment.c b/fs/nilfs2/segment.c index 851bcd3890c8f..a32d9cb2842a0 100644 --- a/fs/nilfs2/segment.c +++ b/fs/nilfs2/segment.c @@ -2676,6 +2676,7 @@ static void nilfs_segctor_kill_thread(struct nilfs_sc_info *sci) static struct nilfs_sc_info *nilfs_segctor_new(struct nilfs_sb_info *sbi, struct nilfs_root *root) { + struct the_nilfs *nilfs = sbi->s_nilfs; struct nilfs_sc_info *sci; sci = kzalloc(sizeof(*sci), GFP_KERNEL); @@ -2703,10 +2704,10 @@ static struct nilfs_sc_info *nilfs_segctor_new(struct nilfs_sb_info *sbi, sci->sc_mjcp_freq = HZ * NILFS_SC_DEFAULT_SR_FREQ; sci->sc_watermark = NILFS_SC_DEFAULT_WATERMARK; - if (sbi->s_interval) - sci->sc_interval = sbi->s_interval; - if (sbi->s_watermark) - sci->sc_watermark = sbi->s_watermark; + if (nilfs->ns_interval) + sci->sc_interval = nilfs->ns_interval; + if (nilfs->ns_watermark) + sci->sc_watermark = nilfs->ns_watermark; return sci; } diff --git a/fs/nilfs2/super.c b/fs/nilfs2/super.c index 0576cb21d699c..2f17a2f9ef9cc 100644 --- a/fs/nilfs2/super.c +++ b/fs/nilfs2/super.c @@ -729,7 +729,7 @@ int nilfs_store_magic_and_option(struct super_block *sb, struct nilfs_super_block *sbp, char *data) { - struct nilfs_sb_info *sbi = NILFS_SB(sb); + struct the_nilfs *nilfs = NILFS_SB(sb)->s_nilfs; sb->s_magic = le16_to_cpu(sbp->s_magic); @@ -740,10 +740,10 @@ int nilfs_store_magic_and_option(struct super_block *sb, nilfs_set_default_options(sb, sbp); - sbi->s_resuid = le16_to_cpu(sbp->s_def_resuid); - sbi->s_resgid = le16_to_cpu(sbp->s_def_resgid); - sbi->s_interval = le32_to_cpu(sbp->s_c_interval); - sbi->s_watermark = le32_to_cpu(sbp->s_c_block_max); + nilfs->ns_resuid = le16_to_cpu(sbp->s_def_resuid); + nilfs->ns_resgid = le16_to_cpu(sbp->s_def_resgid); + nilfs->ns_interval = le32_to_cpu(sbp->s_c_interval); + nilfs->ns_watermark = le32_to_cpu(sbp->s_c_block_max); return !parse_options(data, sb, 0) ? -EINVAL : 0 ; } diff --git a/fs/nilfs2/the_nilfs.h b/fs/nilfs2/the_nilfs.h index 438278041d802..4a9bf3913c9c6 100644 --- a/fs/nilfs2/the_nilfs.h +++ b/fs/nilfs2/the_nilfs.h @@ -73,6 +73,10 @@ enum { * @ns_cptree_lock: lock protecting @ns_cptree * @ns_gc_inodes: dummy inodes to keep live blocks * @ns_mount_opt: mount options + * @ns_resuid: uid for reserved blocks + * @ns_resgid: gid for reserved blocks + * @ns_interval: checkpoint creation interval + * @ns_watermark: watermark for the number of dirty buffers * @ns_blocksize_bits: bit length of block size * @ns_blocksize: block size * @ns_nsegments: number of segments in filesystem @@ -152,6 +156,11 @@ struct the_nilfs { /* Mount options */ unsigned long ns_mount_opt; + uid_t ns_resuid; + gid_t ns_resgid; + unsigned long ns_interval; + unsigned long ns_watermark; + /* Disk layout information (static) */ unsigned int ns_blocksize_bits; unsigned int ns_blocksize; -- GitLab From 693dd321222f03b17668f88ceb0f7d518900191e Mon Sep 17 00:00:00 2001 From: Ryusuke Konishi Date: Wed, 9 Mar 2011 11:05:07 +0900 Subject: [PATCH 0350/2822] nilfs2: move s_inode_lock and s_dirty_files into nilfs object Moves s_inode_lock spinlock and s_dirty_files list to nilfs object from nilfs_sb_info structure. Signed-off-by: Ryusuke Konishi --- fs/nilfs2/inode.c | 30 ++++++++-------- fs/nilfs2/sb.h | 3 -- fs/nilfs2/segment.c | 80 +++++++++++++++++++++---------------------- fs/nilfs2/super.c | 3 -- fs/nilfs2/the_nilfs.c | 2 ++ fs/nilfs2/the_nilfs.h | 6 ++++ 6 files changed, 63 insertions(+), 61 deletions(-) diff --git a/fs/nilfs2/inode.c b/fs/nilfs2/inode.c index 22a816ba3621c..dd5d6d633ea1c 100644 --- a/fs/nilfs2/inode.c +++ b/fs/nilfs2/inode.c @@ -807,18 +807,18 @@ int nilfs_permission(struct inode *inode, int mask, unsigned int flags) int nilfs_load_inode_block(struct inode *inode, struct buffer_head **pbh) { - struct nilfs_sb_info *sbi = NILFS_SB(inode->i_sb); + struct the_nilfs *nilfs = NILFS_SB(inode->i_sb)->s_nilfs; struct nilfs_inode_info *ii = NILFS_I(inode); int err; - spin_lock(&sbi->s_inode_lock); + spin_lock(&nilfs->ns_inode_lock); if (ii->i_bh == NULL) { - spin_unlock(&sbi->s_inode_lock); + spin_unlock(&nilfs->ns_inode_lock); err = nilfs_ifile_get_inode_block(ii->i_root->ifile, inode->i_ino, pbh); if (unlikely(err)) return err; - spin_lock(&sbi->s_inode_lock); + spin_lock(&nilfs->ns_inode_lock); if (ii->i_bh == NULL) ii->i_bh = *pbh; else { @@ -829,36 +829,36 @@ int nilfs_load_inode_block(struct inode *inode, struct buffer_head **pbh) *pbh = ii->i_bh; get_bh(*pbh); - spin_unlock(&sbi->s_inode_lock); + spin_unlock(&nilfs->ns_inode_lock); return 0; } int nilfs_inode_dirty(struct inode *inode) { struct nilfs_inode_info *ii = NILFS_I(inode); - struct nilfs_sb_info *sbi = NILFS_SB(inode->i_sb); + struct the_nilfs *nilfs = NILFS_SB(inode->i_sb)->s_nilfs; int ret = 0; if (!list_empty(&ii->i_dirty)) { - spin_lock(&sbi->s_inode_lock); + spin_lock(&nilfs->ns_inode_lock); ret = test_bit(NILFS_I_DIRTY, &ii->i_state) || test_bit(NILFS_I_BUSY, &ii->i_state); - spin_unlock(&sbi->s_inode_lock); + spin_unlock(&nilfs->ns_inode_lock); } return ret; } int nilfs_set_file_dirty(struct inode *inode, unsigned nr_dirty) { - struct nilfs_sb_info *sbi = NILFS_SB(inode->i_sb); struct nilfs_inode_info *ii = NILFS_I(inode); + struct the_nilfs *nilfs = NILFS_SB(inode->i_sb)->s_nilfs; - atomic_add(nr_dirty, &sbi->s_nilfs->ns_ndirtyblks); + atomic_add(nr_dirty, &nilfs->ns_ndirtyblks); if (test_and_set_bit(NILFS_I_DIRTY, &ii->i_state)) return 0; - spin_lock(&sbi->s_inode_lock); + spin_lock(&nilfs->ns_inode_lock); if (!test_bit(NILFS_I_QUEUED, &ii->i_state) && !test_bit(NILFS_I_BUSY, &ii->i_state)) { /* Because this routine may race with nilfs_dispose_list(), @@ -866,18 +866,18 @@ int nilfs_set_file_dirty(struct inode *inode, unsigned nr_dirty) if (list_empty(&ii->i_dirty) && igrab(inode) == NULL) { /* This will happen when somebody is freeing this inode. */ - nilfs_warning(sbi->s_super, __func__, + nilfs_warning(inode->i_sb, __func__, "cannot get inode (ino=%lu)\n", inode->i_ino); - spin_unlock(&sbi->s_inode_lock); + spin_unlock(&nilfs->ns_inode_lock); return -EINVAL; /* NILFS_I_DIRTY may remain for freeing inode */ } list_del(&ii->i_dirty); - list_add_tail(&ii->i_dirty, &sbi->s_dirty_files); + list_add_tail(&ii->i_dirty, &nilfs->ns_dirty_files); set_bit(NILFS_I_QUEUED, &ii->i_state); } - spin_unlock(&sbi->s_inode_lock); + spin_unlock(&nilfs->ns_inode_lock); return 0; } diff --git a/fs/nilfs2/sb.h b/fs/nilfs2/sb.h index 0512521ba8a44..3232e75fab751 100644 --- a/fs/nilfs2/sb.h +++ b/fs/nilfs2/sb.h @@ -39,10 +39,7 @@ struct nilfs_sb_info { struct the_nilfs *s_nilfs; /* Segment constructor */ - struct list_head s_dirty_files; /* dirty files list */ struct nilfs_sc_info *s_sc_info; /* segment constructor info */ - spinlock_t s_inode_lock; /* Lock for the nilfs inode. - It covers s_dirty_files list */ /* Inode allocator */ spinlock_t s_next_gen_lock; diff --git a/fs/nilfs2/segment.c b/fs/nilfs2/segment.c index a32d9cb2842a0..6ac50d811841b 100644 --- a/fs/nilfs2/segment.c +++ b/fs/nilfs2/segment.c @@ -104,8 +104,7 @@ struct nilfs_sc_operations { static void nilfs_segctor_start_timer(struct nilfs_sc_info *); static void nilfs_segctor_do_flush(struct nilfs_sc_info *, int); static void nilfs_segctor_do_immediate_flush(struct nilfs_sc_info *); -static void nilfs_dispose_list(struct nilfs_sb_info *, struct list_head *, - int); +static void nilfs_dispose_list(struct the_nilfs *, struct list_head *, int); #define nilfs_cnt32_gt(a, b) \ (typecheck(__u32, a) && typecheck(__u32, b) && \ @@ -325,14 +324,15 @@ static void nilfs_transaction_lock(struct nilfs_sb_info *sbi, static void nilfs_transaction_unlock(struct nilfs_sb_info *sbi) { struct nilfs_transaction_info *ti = current->journal_info; + struct the_nilfs *nilfs = sbi->s_nilfs; BUG_ON(ti == NULL || ti->ti_magic != NILFS_TI_MAGIC); BUG_ON(ti->ti_count > 0); - up_write(&sbi->s_nilfs->ns_segctor_sem); + up_write(&nilfs->ns_segctor_sem); current->journal_info = ti->ti_save; if (!list_empty(&ti->ti_garbage)) - nilfs_dispose_list(sbi, &ti->ti_garbage, 0); + nilfs_dispose_list(nilfs, &ti->ti_garbage, 0); } static void *nilfs_segctor_map_segsum_entry(struct nilfs_sc_info *sci, @@ -714,7 +714,7 @@ static void nilfs_lookup_dirty_node_buffers(struct inode *inode, } } -static void nilfs_dispose_list(struct nilfs_sb_info *sbi, +static void nilfs_dispose_list(struct the_nilfs *nilfs, struct list_head *head, int force) { struct nilfs_inode_info *ii, *n; @@ -722,7 +722,7 @@ static void nilfs_dispose_list(struct nilfs_sb_info *sbi, unsigned nv = 0; while (!list_empty(head)) { - spin_lock(&sbi->s_inode_lock); + spin_lock(&nilfs->ns_inode_lock); list_for_each_entry_safe(ii, n, head, i_dirty) { list_del_init(&ii->i_dirty); if (force) { @@ -733,14 +733,14 @@ static void nilfs_dispose_list(struct nilfs_sb_info *sbi, } else if (test_bit(NILFS_I_DIRTY, &ii->i_state)) { set_bit(NILFS_I_QUEUED, &ii->i_state); list_add_tail(&ii->i_dirty, - &sbi->s_dirty_files); + &nilfs->ns_dirty_files); continue; } ivec[nv++] = ii; if (nv == SC_N_INODEVEC) break; } - spin_unlock(&sbi->s_inode_lock); + spin_unlock(&nilfs->ns_inode_lock); for (pii = ivec; nv > 0; pii++, nv--) iput(&(*pii)->vfs_inode); @@ -773,17 +773,17 @@ static int nilfs_segctor_clean(struct nilfs_sc_info *sci) static int nilfs_segctor_confirm(struct nilfs_sc_info *sci) { - struct nilfs_sb_info *sbi = sci->sc_sbi; + struct the_nilfs *nilfs = sci->sc_sbi->s_nilfs; int ret = 0; - if (nilfs_test_metadata_dirty(sbi->s_nilfs, sci->sc_root)) + if (nilfs_test_metadata_dirty(nilfs, sci->sc_root)) set_bit(NILFS_SC_DIRTY, &sci->sc_flags); - spin_lock(&sbi->s_inode_lock); - if (list_empty(&sbi->s_dirty_files) && nilfs_segctor_clean(sci)) + spin_lock(&nilfs->ns_inode_lock); + if (list_empty(&nilfs->ns_dirty_files) && nilfs_segctor_clean(sci)) ret++; - spin_unlock(&sbi->s_inode_lock); + spin_unlock(&nilfs->ns_inode_lock); return ret; } @@ -1963,30 +1963,30 @@ static int nilfs_segctor_wait(struct nilfs_sc_info *sci) return ret; } -static int nilfs_segctor_check_in_files(struct nilfs_sc_info *sci, - struct nilfs_sb_info *sbi) +static int nilfs_segctor_collect_dirty_files(struct nilfs_sc_info *sci, + struct the_nilfs *nilfs) { struct nilfs_inode_info *ii, *n; struct inode *ifile = sci->sc_root->ifile; - spin_lock(&sbi->s_inode_lock); + spin_lock(&nilfs->ns_inode_lock); retry: - list_for_each_entry_safe(ii, n, &sbi->s_dirty_files, i_dirty) { + list_for_each_entry_safe(ii, n, &nilfs->ns_dirty_files, i_dirty) { if (!ii->i_bh) { struct buffer_head *ibh; int err; - spin_unlock(&sbi->s_inode_lock); + spin_unlock(&nilfs->ns_inode_lock); err = nilfs_ifile_get_inode_block( ifile, ii->vfs_inode.i_ino, &ibh); if (unlikely(err)) { - nilfs_warning(sbi->s_super, __func__, + nilfs_warning(sci->sc_super, __func__, "failed to get inode block.\n"); return err; } nilfs_mdt_mark_buffer_dirty(ibh); nilfs_mdt_mark_dirty(ifile); - spin_lock(&sbi->s_inode_lock); + spin_lock(&nilfs->ns_inode_lock); if (likely(!ii->i_bh)) ii->i_bh = ibh; else @@ -1999,18 +1999,18 @@ static int nilfs_segctor_check_in_files(struct nilfs_sc_info *sci, list_del(&ii->i_dirty); list_add_tail(&ii->i_dirty, &sci->sc_dirty_files); } - spin_unlock(&sbi->s_inode_lock); + spin_unlock(&nilfs->ns_inode_lock); return 0; } -static void nilfs_segctor_check_out_files(struct nilfs_sc_info *sci, - struct nilfs_sb_info *sbi) +static void nilfs_segctor_drop_written_files(struct nilfs_sc_info *sci, + struct the_nilfs *nilfs) { struct nilfs_transaction_info *ti = current->journal_info; struct nilfs_inode_info *ii, *n; - spin_lock(&sbi->s_inode_lock); + spin_lock(&nilfs->ns_inode_lock); list_for_each_entry_safe(ii, n, &sci->sc_dirty_files, i_dirty) { if (!test_and_clear_bit(NILFS_I_UPDATED, &ii->i_state) || test_bit(NILFS_I_DIRTY, &ii->i_state)) @@ -2022,7 +2022,7 @@ static void nilfs_segctor_check_out_files(struct nilfs_sc_info *sci, list_del(&ii->i_dirty); list_add_tail(&ii->i_dirty, &ti->ti_garbage); } - spin_unlock(&sbi->s_inode_lock); + spin_unlock(&nilfs->ns_inode_lock); } /* @@ -2038,7 +2038,7 @@ static int nilfs_segctor_do_construct(struct nilfs_sc_info *sci, int mode) sci->sc_stage.scnt = NILFS_ST_INIT; sci->sc_cno = nilfs->ns_cno; - err = nilfs_segctor_check_in_files(sci, sbi); + err = nilfs_segctor_collect_dirty_files(sci, nilfs); if (unlikely(err)) goto out; @@ -2116,7 +2116,7 @@ static int nilfs_segctor_do_construct(struct nilfs_sc_info *sci, int mode) } while (sci->sc_stage.scnt != NILFS_ST_DONE); out: - nilfs_segctor_check_out_files(sci, sbi); + nilfs_segctor_drop_written_files(sci, nilfs); return err; failed_to_write: @@ -2319,14 +2319,14 @@ int nilfs_construct_dsync_segment(struct super_block *sb, struct inode *inode, return err; } - spin_lock(&sbi->s_inode_lock); + spin_lock(&nilfs->ns_inode_lock); if (!test_bit(NILFS_I_QUEUED, &ii->i_state) && !test_bit(NILFS_I_BUSY, &ii->i_state)) { - spin_unlock(&sbi->s_inode_lock); + spin_unlock(&nilfs->ns_inode_lock); nilfs_transaction_unlock(sbi); return 0; } - spin_unlock(&sbi->s_inode_lock); + spin_unlock(&nilfs->ns_inode_lock); sci->sc_dsync_inode = ii; sci->sc_dsync_start = start; sci->sc_dsync_end = end; @@ -2738,10 +2738,10 @@ static void nilfs_segctor_write_out(struct nilfs_sc_info *sci) */ static void nilfs_segctor_destroy(struct nilfs_sc_info *sci) { - struct nilfs_sb_info *sbi = sci->sc_sbi; + struct the_nilfs *nilfs = sci->sc_sbi->s_nilfs; int flag; - up_write(&sbi->s_nilfs->ns_segctor_sem); + up_write(&nilfs->ns_segctor_sem); spin_lock(&sci->sc_state_lock); nilfs_segctor_kill_thread(sci); @@ -2755,9 +2755,9 @@ static void nilfs_segctor_destroy(struct nilfs_sc_info *sci) WARN_ON(!list_empty(&sci->sc_copied_buffers)); if (!list_empty(&sci->sc_dirty_files)) { - nilfs_warning(sbi->s_super, __func__, + nilfs_warning(sci->sc_super, __func__, "dirty file(s) after the final construction\n"); - nilfs_dispose_list(sbi, &sci->sc_dirty_files, 1); + nilfs_dispose_list(nilfs, &sci->sc_dirty_files, 1); } WARN_ON(!list_empty(&sci->sc_segbufs)); @@ -2765,7 +2765,7 @@ static void nilfs_segctor_destroy(struct nilfs_sc_info *sci) nilfs_put_root(sci->sc_root); - down_write(&sbi->s_nilfs->ns_segctor_sem); + down_write(&nilfs->ns_segctor_sem); del_timer_sync(&sci->sc_timer); kfree(sci); @@ -2829,15 +2829,15 @@ void nilfs_detach_segment_constructor(struct nilfs_sb_info *sbi) } /* Force to free the list of dirty files */ - spin_lock(&sbi->s_inode_lock); - if (!list_empty(&sbi->s_dirty_files)) { - list_splice_init(&sbi->s_dirty_files, &garbage_list); + spin_lock(&nilfs->ns_inode_lock); + if (!list_empty(&nilfs->ns_dirty_files)) { + list_splice_init(&nilfs->ns_dirty_files, &garbage_list); nilfs_warning(sbi->s_super, __func__, "Non empty dirty list after the last " "segment construction\n"); } - spin_unlock(&sbi->s_inode_lock); + spin_unlock(&nilfs->ns_inode_lock); up_write(&nilfs->ns_segctor_sem); - nilfs_dispose_list(sbi, &garbage_list, 1); + nilfs_dispose_list(nilfs, &garbage_list, 1); } diff --git a/fs/nilfs2/super.c b/fs/nilfs2/super.c index 2f17a2f9ef9cc..6dc8b3cad1270 100644 --- a/fs/nilfs2/super.c +++ b/fs/nilfs2/super.c @@ -943,9 +943,6 @@ nilfs_fill_super(struct super_block *sb, void *data, int silent) if (err) goto failed_nilfs; - spin_lock_init(&sbi->s_inode_lock); - INIT_LIST_HEAD(&sbi->s_dirty_files); - /* * Following initialization is overlapped because * nilfs_sb_info structure has been cleared at the beginning. diff --git a/fs/nilfs2/the_nilfs.c b/fs/nilfs2/the_nilfs.c index d3775336a16c9..40239a932dec6 100644 --- a/fs/nilfs2/the_nilfs.c +++ b/fs/nilfs2/the_nilfs.c @@ -75,7 +75,9 @@ struct the_nilfs *alloc_nilfs(struct block_device *bdev) nilfs->ns_bdev = bdev; atomic_set(&nilfs->ns_ndirtyblks, 0); init_rwsem(&nilfs->ns_sem); + INIT_LIST_HEAD(&nilfs->ns_dirty_files); INIT_LIST_HEAD(&nilfs->ns_gc_inodes); + spin_lock_init(&nilfs->ns_inode_lock); spin_lock_init(&nilfs->ns_last_segment_lock); nilfs->ns_cptree = RB_ROOT; spin_lock_init(&nilfs->ns_cptree_lock); diff --git a/fs/nilfs2/the_nilfs.h b/fs/nilfs2/the_nilfs.h index 4a9bf3913c9c6..6106ec5ad89ad 100644 --- a/fs/nilfs2/the_nilfs.h +++ b/fs/nilfs2/the_nilfs.h @@ -71,6 +71,8 @@ enum { * @ns_sufile: segusage file inode * @ns_cptree: rb-tree of all mounted checkpoints (nilfs_root) * @ns_cptree_lock: lock protecting @ns_cptree + * @ns_dirty_files: list of dirty files + * @ns_inode_lock: lock protecting @ns_dirty_files * @ns_gc_inodes: dummy inodes to keep live blocks * @ns_mount_opt: mount options * @ns_resuid: uid for reserved blocks @@ -150,6 +152,10 @@ struct the_nilfs { struct rb_root ns_cptree; spinlock_t ns_cptree_lock; + /* Dirty inode list */ + struct list_head ns_dirty_files; + spinlock_t ns_inode_lock; + /* GC inode list */ struct list_head ns_gc_inodes; -- GitLab From 9b1fc4e4973469dd3fab27ba5d78eca1cd5c13fe Mon Sep 17 00:00:00 2001 From: Ryusuke Konishi Date: Wed, 9 Mar 2011 11:05:08 +0900 Subject: [PATCH 0351/2822] nilfs2: move next generation counter into nilfs object Moves s_next_generation counter and a spinlock protecting it to nilfs object from nilfs_sb_info structure. Signed-off-by: Ryusuke Konishi --- fs/nilfs2/inode.c | 8 ++++---- fs/nilfs2/sb.h | 4 ---- fs/nilfs2/super.c | 11 ----------- fs/nilfs2/the_nilfs.c | 5 +++++ fs/nilfs2/the_nilfs.h | 6 ++++++ 5 files changed, 15 insertions(+), 19 deletions(-) diff --git a/fs/nilfs2/inode.c b/fs/nilfs2/inode.c index dd5d6d633ea1c..7a3dbe4f229ce 100644 --- a/fs/nilfs2/inode.c +++ b/fs/nilfs2/inode.c @@ -295,7 +295,7 @@ const struct address_space_operations nilfs_aops = { struct inode *nilfs_new_inode(struct inode *dir, int mode) { struct super_block *sb = dir->i_sb; - struct nilfs_sb_info *sbi = NILFS_SB(sb); + struct the_nilfs *nilfs = NILFS_SB(sb)->s_nilfs; struct inode *inode; struct nilfs_inode_info *ii; struct nilfs_root *root; @@ -340,9 +340,9 @@ struct inode *nilfs_new_inode(struct inode *dir, int mode) /* ii->i_dir_acl = 0; */ ii->i_dir_start_lookup = 0; nilfs_set_inode_flags(inode); - spin_lock(&sbi->s_next_gen_lock); - inode->i_generation = sbi->s_next_generation++; - spin_unlock(&sbi->s_next_gen_lock); + spin_lock(&nilfs->ns_next_gen_lock); + inode->i_generation = nilfs->ns_next_generation++; + spin_unlock(&nilfs->ns_next_gen_lock); insert_inode_hash(inode); err = nilfs_init_acl(inode, dir); diff --git a/fs/nilfs2/sb.h b/fs/nilfs2/sb.h index 3232e75fab751..6f190dfdc6496 100644 --- a/fs/nilfs2/sb.h +++ b/fs/nilfs2/sb.h @@ -40,10 +40,6 @@ struct nilfs_sb_info { /* Segment constructor */ struct nilfs_sc_info *s_sc_info; /* segment constructor info */ - - /* Inode allocator */ - spinlock_t s_next_gen_lock; - u32 s_next_generation; }; static inline struct nilfs_sb_info *NILFS_SB(struct super_block *sb) diff --git a/fs/nilfs2/super.c b/fs/nilfs2/super.c index 6dc8b3cad1270..1368c4293c7fb 100644 --- a/fs/nilfs2/super.c +++ b/fs/nilfs2/super.c @@ -43,7 +43,6 @@ #include #include #include -#include #include #include #include @@ -943,16 +942,6 @@ nilfs_fill_super(struct super_block *sb, void *data, int silent) if (err) goto failed_nilfs; - /* - * Following initialization is overlapped because - * nilfs_sb_info structure has been cleared at the beginning. - * But we reserve them to keep our interest and make ready - * for the future change. - */ - get_random_bytes(&sbi->s_next_generation, - sizeof(sbi->s_next_generation)); - spin_lock_init(&sbi->s_next_gen_lock); - sb->s_op = &nilfs_sops; sb->s_export_op = &nilfs_export_ops; sb->s_root = NULL; diff --git a/fs/nilfs2/the_nilfs.c b/fs/nilfs2/the_nilfs.c index 40239a932dec6..1bf695e887a70 100644 --- a/fs/nilfs2/the_nilfs.c +++ b/fs/nilfs2/the_nilfs.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include "nilfs.h" #include "segment.h" @@ -78,6 +79,7 @@ struct the_nilfs *alloc_nilfs(struct block_device *bdev) INIT_LIST_HEAD(&nilfs->ns_dirty_files); INIT_LIST_HEAD(&nilfs->ns_gc_inodes); spin_lock_init(&nilfs->ns_inode_lock); + spin_lock_init(&nilfs->ns_next_gen_lock); spin_lock_init(&nilfs->ns_last_segment_lock); nilfs->ns_cptree = RB_ROOT; spin_lock_init(&nilfs->ns_cptree_lock); @@ -593,6 +595,9 @@ int init_nilfs(struct the_nilfs *nilfs, struct nilfs_sb_info *sbi, char *data) nilfs->ns_blocksize_bits = sb->s_blocksize_bits; nilfs->ns_blocksize = blocksize; + get_random_bytes(&nilfs->ns_next_generation, + sizeof(nilfs->ns_next_generation)); + err = nilfs_store_disk_layout(nilfs, sbp); if (err) goto failed_sbh; diff --git a/fs/nilfs2/the_nilfs.h b/fs/nilfs2/the_nilfs.h index 6106ec5ad89ad..3ecc968f21238 100644 --- a/fs/nilfs2/the_nilfs.h +++ b/fs/nilfs2/the_nilfs.h @@ -74,6 +74,8 @@ enum { * @ns_dirty_files: list of dirty files * @ns_inode_lock: lock protecting @ns_dirty_files * @ns_gc_inodes: dummy inodes to keep live blocks + * @ns_next_generation: next generation number for inodes + * @ns_next_gen_lock: lock protecting @ns_next_generation * @ns_mount_opt: mount options * @ns_resuid: uid for reserved blocks * @ns_resgid: gid for reserved blocks @@ -159,6 +161,10 @@ struct the_nilfs { /* GC inode list */ struct list_head ns_gc_inodes; + /* Inode allocator */ + u32 ns_next_generation; + spinlock_t ns_next_gen_lock; + /* Mount options */ unsigned long ns_mount_opt; -- GitLab From 3fd3fe5aeaa171a5638d2bb54a1a170eab7b7cdc Mon Sep 17 00:00:00 2001 From: Ryusuke Konishi Date: Wed, 9 Mar 2011 11:05:08 +0900 Subject: [PATCH 0352/2822] nilfs2: move log writer onto nilfs object Log writer is held by the nilfs_sb_info structure. This moves it into nilfs object and replaces all uses of NILFS_SC() accessor. Signed-off-by: Ryusuke Konishi --- fs/nilfs2/sb.h | 9 ------- fs/nilfs2/segment.c | 58 +++++++++++++++++++++---------------------- fs/nilfs2/the_nilfs.h | 6 ++++- 3 files changed, 34 insertions(+), 39 deletions(-) diff --git a/fs/nilfs2/sb.h b/fs/nilfs2/sb.h index 6f190dfdc6496..44553f42ebac8 100644 --- a/fs/nilfs2/sb.h +++ b/fs/nilfs2/sb.h @@ -28,7 +28,6 @@ #include struct the_nilfs; -struct nilfs_sc_info; /* * NILFS super-block data in memory @@ -37,9 +36,6 @@ struct nilfs_sb_info { /* Fundamental members */ struct super_block *s_super; /* reverse pointer to super_block */ struct the_nilfs *s_nilfs; - - /* Segment constructor */ - struct nilfs_sc_info *s_sc_info; /* segment constructor info */ }; static inline struct nilfs_sb_info *NILFS_SB(struct super_block *sb) @@ -47,9 +43,4 @@ static inline struct nilfs_sb_info *NILFS_SB(struct super_block *sb) return sb->s_fs_info; } -static inline struct nilfs_sc_info *NILFS_SC(struct nilfs_sb_info *sbi) -{ - return sbi->s_sc_info; -} - #endif /* _NILFS_SB */ diff --git a/fs/nilfs2/segment.c b/fs/nilfs2/segment.c index 6ac50d811841b..e3d1785faf1bd 100644 --- a/fs/nilfs2/segment.c +++ b/fs/nilfs2/segment.c @@ -224,8 +224,7 @@ int nilfs_transaction_begin(struct super_block *sb, int nilfs_transaction_commit(struct super_block *sb) { struct nilfs_transaction_info *ti = current->journal_info; - struct nilfs_sb_info *sbi; - struct nilfs_sc_info *sci; + struct the_nilfs *nilfs = NILFS_SB(sb)->s_nilfs; int err = 0; BUG_ON(ti == NULL || ti->ti_magic != NILFS_TI_MAGIC); @@ -234,16 +233,15 @@ int nilfs_transaction_commit(struct super_block *sb) ti->ti_count--; return 0; } - sbi = NILFS_SB(sb); - sci = NILFS_SC(sbi); - if (sci != NULL) { + if (nilfs->ns_writer) { + struct nilfs_sc_info *sci = nilfs->ns_writer; + if (ti->ti_flags & NILFS_TI_COMMIT) nilfs_segctor_start_timer(sci); - if (atomic_read(&sbi->s_nilfs->ns_ndirtyblks) > - sci->sc_watermark) + if (atomic_read(&nilfs->ns_ndirtyblks) > sci->sc_watermark) nilfs_segctor_do_flush(sci, 0); } - up_read(&sbi->s_nilfs->ns_segctor_sem); + up_read(&nilfs->ns_segctor_sem); current->journal_info = ti->ti_save; if (ti->ti_flags & NILFS_TI_SYNC) @@ -271,9 +269,8 @@ void nilfs_transaction_abort(struct super_block *sb) void nilfs_relax_pressure_in_lock(struct super_block *sb) { - struct nilfs_sb_info *sbi = NILFS_SB(sb); - struct nilfs_sc_info *sci = NILFS_SC(sbi); - struct the_nilfs *nilfs = sbi->s_nilfs; + struct the_nilfs *nilfs = NILFS_SB(sb)->s_nilfs; + struct nilfs_sc_info *sci = nilfs->ns_writer; if (!sci || !sci->sc_flush_request) return; @@ -298,6 +295,8 @@ static void nilfs_transaction_lock(struct nilfs_sb_info *sbi, int gcflag) { struct nilfs_transaction_info *cur_ti = current->journal_info; + struct the_nilfs *nilfs = sbi->s_nilfs; + struct nilfs_sc_info *sci = nilfs->ns_writer; WARN_ON(cur_ti); ti->ti_flags = NILFS_TI_WRITER; @@ -308,11 +307,11 @@ static void nilfs_transaction_lock(struct nilfs_sb_info *sbi, current->journal_info = ti; for (;;) { - down_write(&sbi->s_nilfs->ns_segctor_sem); - if (!test_bit(NILFS_SC_PRIOR_FLUSH, &NILFS_SC(sbi)->sc_flags)) + down_write(&nilfs->ns_segctor_sem); + if (!test_bit(NILFS_SC_PRIOR_FLUSH, &sci->sc_flags)) break; - nilfs_segctor_do_immediate_flush(NILFS_SC(sbi)); + nilfs_segctor_do_immediate_flush(sci); up_write(&sbi->s_nilfs->ns_segctor_sem); yield(); @@ -2169,8 +2168,8 @@ static void nilfs_segctor_do_flush(struct nilfs_sc_info *sci, int bn) */ void nilfs_flush_segment(struct super_block *sb, ino_t ino) { - struct nilfs_sb_info *sbi = NILFS_SB(sb); - struct nilfs_sc_info *sci = NILFS_SC(sbi); + struct the_nilfs *nilfs = NILFS_SB(sb)->s_nilfs; + struct nilfs_sc_info *sci = nilfs->ns_writer; if (!sci || nilfs_doing_construction()) return; @@ -2259,8 +2258,8 @@ static void nilfs_segctor_wakeup(struct nilfs_sc_info *sci, int err) */ int nilfs_construct_segment(struct super_block *sb) { - struct nilfs_sb_info *sbi = NILFS_SB(sb); - struct nilfs_sc_info *sci = NILFS_SC(sbi); + struct the_nilfs *nilfs = NILFS_SB(sb)->s_nilfs; + struct nilfs_sc_info *sci = nilfs->ns_writer; struct nilfs_transaction_info *ti; int err; @@ -2299,7 +2298,7 @@ int nilfs_construct_dsync_segment(struct super_block *sb, struct inode *inode, { struct nilfs_sb_info *sbi = NILFS_SB(sb); struct the_nilfs *nilfs = sbi->s_nilfs; - struct nilfs_sc_info *sci = NILFS_SC(sbi); + struct nilfs_sc_info *sci = nilfs->ns_writer; struct nilfs_inode_info *ii; struct nilfs_transaction_info ti; int err = 0; @@ -2445,8 +2444,8 @@ int nilfs_clean_segments(struct super_block *sb, struct nilfs_argv *argv, void **kbufs) { struct nilfs_sb_info *sbi = NILFS_SB(sb); - struct nilfs_sc_info *sci = NILFS_SC(sbi); struct the_nilfs *nilfs = sbi->s_nilfs; + struct nilfs_sc_info *sci = nilfs->ns_writer; struct nilfs_transaction_info ti; int err; @@ -2787,9 +2786,10 @@ static void nilfs_segctor_destroy(struct nilfs_sc_info *sci) int nilfs_attach_segment_constructor(struct nilfs_sb_info *sbi, struct nilfs_root *root) { + struct the_nilfs *nilfs = sbi->s_nilfs; int err; - if (NILFS_SC(sbi)) { + if (nilfs->ns_writer) { /* * This happens if the filesystem was remounted * read/write after nilfs_error degenerated it into a @@ -2798,14 +2798,14 @@ int nilfs_attach_segment_constructor(struct nilfs_sb_info *sbi, nilfs_detach_segment_constructor(sbi); } - sbi->s_sc_info = nilfs_segctor_new(sbi, root); - if (!sbi->s_sc_info) + nilfs->ns_writer = nilfs_segctor_new(sbi, root); + if (!nilfs->ns_writer) return -ENOMEM; - err = nilfs_segctor_start_thread(NILFS_SC(sbi)); + err = nilfs_segctor_start_thread(nilfs->ns_writer); if (err) { - kfree(sbi->s_sc_info); - sbi->s_sc_info = NULL; + kfree(nilfs->ns_writer); + nilfs->ns_writer = NULL; } return err; } @@ -2823,9 +2823,9 @@ void nilfs_detach_segment_constructor(struct nilfs_sb_info *sbi) LIST_HEAD(garbage_list); down_write(&nilfs->ns_segctor_sem); - if (NILFS_SC(sbi)) { - nilfs_segctor_destroy(NILFS_SC(sbi)); - sbi->s_sc_info = NULL; + if (nilfs->ns_writer) { + nilfs_segctor_destroy(nilfs->ns_writer); + nilfs->ns_writer = NULL; } /* Force to free the list of dirty files */ diff --git a/fs/nilfs2/the_nilfs.h b/fs/nilfs2/the_nilfs.h index 3ecc968f21238..10521b97ded60 100644 --- a/fs/nilfs2/the_nilfs.h +++ b/fs/nilfs2/the_nilfs.h @@ -33,6 +33,8 @@ #include #include "sb.h" +struct nilfs_sc_info; + /* the_nilfs struct */ enum { THE_NILFS_INIT = 0, /* Information from super_block is set */ @@ -65,7 +67,8 @@ enum { * @ns_last_cno: checkpoint number of the latest segment * @ns_prot_seq: least sequence number of segments which must not be reclaimed * @ns_prev_seq: base sequence number used to decide if advance log cursor - * @ns_segctor_sem: segment constructor semaphore + * @ns_writer: log writer + * @ns_segctor_sem: semaphore protecting log write * @ns_dat: DAT file inode * @ns_cpfile: checkpoint file inode * @ns_sufile: segusage file inode @@ -140,6 +143,7 @@ struct the_nilfs { u64 ns_prot_seq; u64 ns_prev_seq; + struct nilfs_sc_info *ns_writer; struct rw_semaphore ns_segctor_sem; /* -- GitLab From d96bbfa28aa7a1d5a5bf549026a594d7a273c5d7 Mon Sep 17 00:00:00 2001 From: Ryusuke Konishi Date: Wed, 9 Mar 2011 11:05:08 +0900 Subject: [PATCH 0353/2822] nilfs2: get rid of sc_sbi back pointer Removes sci->sc_sbi which is a back pointer to nilfs_sb_info struct from log writer object (nilfs_sc_info). Signed-off-by: Ryusuke Konishi --- fs/nilfs2/segment.c | 29 ++++++++++++----------------- fs/nilfs2/segment.h | 2 -- 2 files changed, 12 insertions(+), 19 deletions(-) diff --git a/fs/nilfs2/segment.c b/fs/nilfs2/segment.c index e3d1785faf1bd..b14788ec0d158 100644 --- a/fs/nilfs2/segment.c +++ b/fs/nilfs2/segment.c @@ -772,7 +772,7 @@ static int nilfs_segctor_clean(struct nilfs_sc_info *sci) static int nilfs_segctor_confirm(struct nilfs_sc_info *sci) { - struct the_nilfs *nilfs = sci->sc_sbi->s_nilfs; + struct the_nilfs *nilfs = NILFS_SB(sci->sc_super)->s_nilfs; int ret = 0; if (nilfs_test_metadata_dirty(nilfs, sci->sc_root)) @@ -788,8 +788,7 @@ static int nilfs_segctor_confirm(struct nilfs_sc_info *sci) static void nilfs_segctor_clear_metadata_dirty(struct nilfs_sc_info *sci) { - struct nilfs_sb_info *sbi = sci->sc_sbi; - struct the_nilfs *nilfs = sbi->s_nilfs; + struct the_nilfs *nilfs = NILFS_SB(sci->sc_super)->s_nilfs; nilfs_mdt_clear_dirty(sci->sc_root->ifile); nilfs_mdt_clear_dirty(nilfs->ns_cpfile); @@ -799,7 +798,7 @@ static void nilfs_segctor_clear_metadata_dirty(struct nilfs_sc_info *sci) static int nilfs_segctor_create_checkpoint(struct nilfs_sc_info *sci) { - struct the_nilfs *nilfs = sci->sc_sbi->s_nilfs; + struct the_nilfs *nilfs = NILFS_SB(sci->sc_super)->s_nilfs; struct buffer_head *bh_cp; struct nilfs_checkpoint *raw_cp; int err; @@ -823,8 +822,7 @@ static int nilfs_segctor_create_checkpoint(struct nilfs_sc_info *sci) static int nilfs_segctor_fill_in_checkpoint(struct nilfs_sc_info *sci) { - struct nilfs_sb_info *sbi = sci->sc_sbi; - struct the_nilfs *nilfs = sbi->s_nilfs; + struct the_nilfs *nilfs = NILFS_SB(sci->sc_super)->s_nilfs; struct buffer_head *bh_cp; struct nilfs_checkpoint *raw_cp; int err; @@ -1048,8 +1046,7 @@ static int nilfs_segctor_scan_file_dsync(struct nilfs_sc_info *sci, static int nilfs_segctor_collect_blocks(struct nilfs_sc_info *sci, int mode) { - struct nilfs_sb_info *sbi = sci->sc_sbi; - struct the_nilfs *nilfs = sbi->s_nilfs; + struct the_nilfs *nilfs = NILFS_SB(sci->sc_super)->s_nilfs; struct list_head *head; struct nilfs_inode_info *ii; size_t ndone; @@ -1858,7 +1855,7 @@ static void nilfs_segctor_complete_write(struct nilfs_sc_info *sci) { struct nilfs_segment_buffer *segbuf; struct page *bd_page = NULL, *fs_page = NULL; - struct the_nilfs *nilfs = sci->sc_sbi->s_nilfs; + struct the_nilfs *nilfs = NILFS_SB(sci->sc_super)->s_nilfs; int update_sr = false; list_for_each_entry(segbuf, &sci->sc_write_logs, sb_list) { @@ -2029,8 +2026,7 @@ static void nilfs_segctor_drop_written_files(struct nilfs_sc_info *sci, */ static int nilfs_segctor_do_construct(struct nilfs_sc_info *sci, int mode) { - struct nilfs_sb_info *sbi = sci->sc_sbi; - struct the_nilfs *nilfs = sbi->s_nilfs; + struct the_nilfs *nilfs = NILFS_SB(sci->sc_super)->s_nilfs; struct page *failed_page; int err; @@ -2388,7 +2384,7 @@ static void nilfs_segctor_notify(struct nilfs_sc_info *sci, int mode, int err) */ static int nilfs_segctor_construct(struct nilfs_sc_info *sci, int mode) { - struct nilfs_sb_info *sbi = sci->sc_sbi; + struct nilfs_sb_info *sbi = NILFS_SB(sci->sc_super); struct the_nilfs *nilfs = sbi->s_nilfs; struct nilfs_super_block **sbp; int err = 0; @@ -2501,7 +2497,7 @@ int nilfs_clean_segments(struct super_block *sb, struct nilfs_argv *argv, static void nilfs_segctor_thread_construct(struct nilfs_sc_info *sci, int mode) { - struct nilfs_sb_info *sbi = sci->sc_sbi; + struct nilfs_sb_info *sbi = NILFS_SB(sci->sc_super); struct nilfs_transaction_info ti; nilfs_transaction_lock(sbi, &ti, 0); @@ -2561,7 +2557,7 @@ static int nilfs_segctor_flush_mode(struct nilfs_sc_info *sci) static int nilfs_segctor_thread(void *arg) { struct nilfs_sc_info *sci = (struct nilfs_sc_info *)arg; - struct the_nilfs *nilfs = sci->sc_sbi->s_nilfs; + struct the_nilfs *nilfs = NILFS_SB(sci->sc_super)->s_nilfs; int timeout = 0; sci->sc_timer.data = (unsigned long)current; @@ -2682,7 +2678,6 @@ static struct nilfs_sc_info *nilfs_segctor_new(struct nilfs_sb_info *sbi, if (!sci) return NULL; - sci->sc_sbi = sbi; sci->sc_super = sbi->s_super; nilfs_get_root(root); @@ -2717,7 +2712,7 @@ static void nilfs_segctor_write_out(struct nilfs_sc_info *sci) /* The segctord thread was stopped and its timer was removed. But some tasks remain. */ do { - struct nilfs_sb_info *sbi = sci->sc_sbi; + struct nilfs_sb_info *sbi = NILFS_SB(sci->sc_super); struct nilfs_transaction_info ti; nilfs_transaction_lock(sbi, &ti, 0); @@ -2737,7 +2732,7 @@ static void nilfs_segctor_write_out(struct nilfs_sc_info *sci) */ static void nilfs_segctor_destroy(struct nilfs_sc_info *sci) { - struct the_nilfs *nilfs = sci->sc_sbi->s_nilfs; + struct the_nilfs *nilfs = NILFS_SB(sci->sc_super)->s_nilfs; int flag; up_write(&nilfs->ns_segctor_sem); diff --git a/fs/nilfs2/segment.h b/fs/nilfs2/segment.h index cd8056e7cbed0..9544aa97dd49e 100644 --- a/fs/nilfs2/segment.h +++ b/fs/nilfs2/segment.h @@ -88,7 +88,6 @@ struct nilfs_segsum_pointer { /** * struct nilfs_sc_info - Segment constructor information * @sc_super: Back pointer to super_block struct - * @sc_sbi: Back pointer to nilfs_sb_info struct * @sc_root: root object of the current filesystem tree * @sc_nblk_inc: Block count of current generation * @sc_dirty_files: List of files to be written @@ -131,7 +130,6 @@ struct nilfs_segsum_pointer { */ struct nilfs_sc_info { struct super_block *sc_super; - struct nilfs_sb_info *sc_sbi; struct nilfs_root *sc_root; unsigned long sc_nblk_inc; -- GitLab From f7545144c2e3d280139260df934043e0a6ccce6f Mon Sep 17 00:00:00 2001 From: Ryusuke Konishi Date: Wed, 9 Mar 2011 11:05:08 +0900 Subject: [PATCH 0354/2822] nilfs2: use sb instance instead of nilfs_sb_info struct This replaces sbi uses with direct reference to sb instance. Signed-off-by: Ryusuke Konishi --- fs/nilfs2/nilfs.h | 10 ++-- fs/nilfs2/recovery.c | 32 ++++++------- fs/nilfs2/segment.c | 90 +++++++++++++++++------------------- fs/nilfs2/segment.h | 10 ++-- fs/nilfs2/super.c | 105 ++++++++++++++++++++---------------------- fs/nilfs2/the_nilfs.c | 22 ++++----- fs/nilfs2/the_nilfs.h | 5 +- 7 files changed, 129 insertions(+), 145 deletions(-) diff --git a/fs/nilfs2/nilfs.h b/fs/nilfs2/nilfs.h index 03ba4d88083f5..eba1aaa7fb7b6 100644 --- a/fs/nilfs2/nilfs.h +++ b/fs/nilfs2/nilfs.h @@ -295,11 +295,11 @@ extern int nilfs_check_feature_compatibility(struct super_block *, struct nilfs_super_block *); extern void nilfs_set_log_cursor(struct nilfs_super_block *, struct the_nilfs *); -extern struct nilfs_super_block **nilfs_prepare_super(struct nilfs_sb_info *, - int flip); -extern int nilfs_commit_super(struct nilfs_sb_info *, int); -extern int nilfs_cleanup_super(struct nilfs_sb_info *); -int nilfs_attach_checkpoint(struct nilfs_sb_info *sbi, __u64 cno, int curr_mnt, +struct nilfs_super_block **nilfs_prepare_super(struct super_block *sb, + int flip); +int nilfs_commit_super(struct super_block *sb, int flag); +int nilfs_cleanup_super(struct super_block *sb); +int nilfs_attach_checkpoint(struct super_block *sb, __u64 cno, int curr_mnt, struct nilfs_root **root); int nilfs_checkpoint_is_mounted(struct super_block *sb, __u64 cno); diff --git a/fs/nilfs2/recovery.c b/fs/nilfs2/recovery.c index 3dfcd3b7d3891..ba4a64518f389 100644 --- a/fs/nilfs2/recovery.c +++ b/fs/nilfs2/recovery.c @@ -425,7 +425,7 @@ void nilfs_dispose_segment_list(struct list_head *head) } static int nilfs_prepare_segment_for_recovery(struct the_nilfs *nilfs, - struct nilfs_sb_info *sbi, + struct super_block *sb, struct nilfs_recovery_info *ri) { struct list_head *head = &ri->ri_used_segments; @@ -501,7 +501,7 @@ static int nilfs_recovery_copy_block(struct the_nilfs *nilfs, } static int nilfs_recover_dsync_blocks(struct the_nilfs *nilfs, - struct nilfs_sb_info *sbi, + struct super_block *sb, struct nilfs_root *root, struct list_head *head, unsigned long *nr_salvaged_blocks) @@ -514,7 +514,7 @@ static int nilfs_recover_dsync_blocks(struct the_nilfs *nilfs, int err = 0, err2 = 0; list_for_each_entry_safe(rb, n, head, list) { - inode = nilfs_iget(sbi->s_super, root, rb->ino); + inode = nilfs_iget(sb, root, rb->ino); if (IS_ERR(inode)) { err = PTR_ERR(inode); inode = NULL; @@ -572,11 +572,11 @@ static int nilfs_recover_dsync_blocks(struct the_nilfs *nilfs, * nilfs_do_roll_forward - salvage logical segments newer than the latest * checkpoint * @nilfs: nilfs object - * @sbi: nilfs_sb_info + * @sb: super block instance * @ri: pointer to a nilfs_recovery_info */ static int nilfs_do_roll_forward(struct the_nilfs *nilfs, - struct nilfs_sb_info *sbi, + struct super_block *sb, struct nilfs_root *root, struct nilfs_recovery_info *ri) { @@ -648,7 +648,7 @@ static int nilfs_do_roll_forward(struct the_nilfs *nilfs, goto failed; if (flags & NILFS_SS_LOGEND) { err = nilfs_recover_dsync_blocks( - nilfs, sbi, root, &dsync_blocks, + nilfs, sb, root, &dsync_blocks, &nsalvaged_blocks); if (unlikely(err)) goto failed; @@ -681,7 +681,7 @@ static int nilfs_do_roll_forward(struct the_nilfs *nilfs, if (nsalvaged_blocks) { printk(KERN_INFO "NILFS (device %s): salvaged %lu blocks\n", - sbi->s_super->s_id, nsalvaged_blocks); + sb->s_id, nsalvaged_blocks); ri->ri_need_recovery = NILFS_RECOVERY_ROLLFORWARD_DONE; } out: @@ -695,7 +695,7 @@ static int nilfs_do_roll_forward(struct the_nilfs *nilfs, printk(KERN_ERR "NILFS (device %s): Error roll-forwarding " "(err=%d, pseg block=%llu). ", - sbi->s_super->s_id, err, (unsigned long long)pseg_start); + sb->s_id, err, (unsigned long long)pseg_start); goto out; } @@ -724,7 +724,7 @@ static void nilfs_finish_roll_forward(struct the_nilfs *nilfs, /** * nilfs_salvage_orphan_logs - salvage logs written after the latest checkpoint * @nilfs: nilfs object - * @sbi: nilfs_sb_info + * @sb: super block instance * @ri: pointer to a nilfs_recovery_info struct to store search results. * * Return Value: On success, 0 is returned. On error, one of the following @@ -741,7 +741,7 @@ static void nilfs_finish_roll_forward(struct the_nilfs *nilfs, * %-ENOMEM - Insufficient memory available. */ int nilfs_salvage_orphan_logs(struct the_nilfs *nilfs, - struct nilfs_sb_info *sbi, + struct super_block *sb, struct nilfs_recovery_info *ri) { struct nilfs_root *root; @@ -750,32 +750,32 @@ int nilfs_salvage_orphan_logs(struct the_nilfs *nilfs, if (ri->ri_lsegs_start == 0 || ri->ri_lsegs_end == 0) return 0; - err = nilfs_attach_checkpoint(sbi, ri->ri_cno, true, &root); + err = nilfs_attach_checkpoint(sb, ri->ri_cno, true, &root); if (unlikely(err)) { printk(KERN_ERR "NILFS: error loading the latest checkpoint.\n"); return err; } - err = nilfs_do_roll_forward(nilfs, sbi, root, ri); + err = nilfs_do_roll_forward(nilfs, sb, root, ri); if (unlikely(err)) goto failed; if (ri->ri_need_recovery == NILFS_RECOVERY_ROLLFORWARD_DONE) { - err = nilfs_prepare_segment_for_recovery(nilfs, sbi, ri); + err = nilfs_prepare_segment_for_recovery(nilfs, sb, ri); if (unlikely(err)) { printk(KERN_ERR "NILFS: Error preparing segments for " "recovery.\n"); goto failed; } - err = nilfs_attach_segment_constructor(sbi, root); + err = nilfs_attach_log_writer(sb, root); if (unlikely(err)) goto failed; set_nilfs_discontinued(nilfs); - err = nilfs_construct_segment(sbi->s_super); - nilfs_detach_segment_constructor(sbi); + err = nilfs_construct_segment(sb); + nilfs_detach_log_writer(sb); if (unlikely(err)) { printk(KERN_ERR "NILFS: Oops! recovery failed. " diff --git a/fs/nilfs2/segment.c b/fs/nilfs2/segment.c index b14788ec0d158..90e3130303a33 100644 --- a/fs/nilfs2/segment.c +++ b/fs/nilfs2/segment.c @@ -181,7 +181,6 @@ int nilfs_transaction_begin(struct super_block *sb, struct nilfs_transaction_info *ti, int vacancy_check) { - struct nilfs_sb_info *sbi; struct the_nilfs *nilfs; int ret = nilfs_prepare_segment_lock(ti); @@ -192,8 +191,7 @@ int nilfs_transaction_begin(struct super_block *sb, vfs_check_frozen(sb, SB_FREEZE_WRITE); - sbi = NILFS_SB(sb); - nilfs = sbi->s_nilfs; + nilfs = NILFS_SB(sb)->s_nilfs; down_read(&nilfs->ns_segctor_sem); if (vacancy_check && nilfs_near_disk_full(nilfs)) { up_read(&nilfs->ns_segctor_sem); @@ -290,12 +288,12 @@ void nilfs_relax_pressure_in_lock(struct super_block *sb) downgrade_write(&nilfs->ns_segctor_sem); } -static void nilfs_transaction_lock(struct nilfs_sb_info *sbi, +static void nilfs_transaction_lock(struct super_block *sb, struct nilfs_transaction_info *ti, int gcflag) { struct nilfs_transaction_info *cur_ti = current->journal_info; - struct the_nilfs *nilfs = sbi->s_nilfs; + struct the_nilfs *nilfs = NILFS_SB(sb)->s_nilfs; struct nilfs_sc_info *sci = nilfs->ns_writer; WARN_ON(cur_ti); @@ -313,17 +311,17 @@ static void nilfs_transaction_lock(struct nilfs_sb_info *sbi, nilfs_segctor_do_immediate_flush(sci); - up_write(&sbi->s_nilfs->ns_segctor_sem); + up_write(&nilfs->ns_segctor_sem); yield(); } if (gcflag) ti->ti_flags |= NILFS_TI_GC; } -static void nilfs_transaction_unlock(struct nilfs_sb_info *sbi) +static void nilfs_transaction_unlock(struct super_block *sb) { struct nilfs_transaction_info *ti = current->journal_info; - struct the_nilfs *nilfs = sbi->s_nilfs; + struct the_nilfs *nilfs = NILFS_SB(sb)->s_nilfs; BUG_ON(ti == NULL || ti->ti_magic != NILFS_TI_MAGIC); BUG_ON(ti->ti_count > 0); @@ -2292,8 +2290,7 @@ int nilfs_construct_segment(struct super_block *sb) int nilfs_construct_dsync_segment(struct super_block *sb, struct inode *inode, loff_t start, loff_t end) { - struct nilfs_sb_info *sbi = NILFS_SB(sb); - struct the_nilfs *nilfs = sbi->s_nilfs; + struct the_nilfs *nilfs = NILFS_SB(sb)->s_nilfs; struct nilfs_sc_info *sci = nilfs->ns_writer; struct nilfs_inode_info *ii; struct nilfs_transaction_info ti; @@ -2302,14 +2299,14 @@ int nilfs_construct_dsync_segment(struct super_block *sb, struct inode *inode, if (!sci) return -EROFS; - nilfs_transaction_lock(sbi, &ti, 0); + nilfs_transaction_lock(sb, &ti, 0); ii = NILFS_I(inode); if (test_bit(NILFS_I_INODE_DIRTY, &ii->i_state) || nilfs_test_opt(nilfs, STRICT_ORDER) || test_bit(NILFS_SC_UNCLOSED, &sci->sc_flags) || nilfs_discontinued(nilfs)) { - nilfs_transaction_unlock(sbi); + nilfs_transaction_unlock(sb); err = nilfs_segctor_sync(sci); return err; } @@ -2318,7 +2315,7 @@ int nilfs_construct_dsync_segment(struct super_block *sb, struct inode *inode, if (!test_bit(NILFS_I_QUEUED, &ii->i_state) && !test_bit(NILFS_I_BUSY, &ii->i_state)) { spin_unlock(&nilfs->ns_inode_lock); - nilfs_transaction_unlock(sbi); + nilfs_transaction_unlock(sb); return 0; } spin_unlock(&nilfs->ns_inode_lock); @@ -2328,7 +2325,7 @@ int nilfs_construct_dsync_segment(struct super_block *sb, struct inode *inode, err = nilfs_segctor_do_construct(sci, SC_LSEG_DSYNC); - nilfs_transaction_unlock(sbi); + nilfs_transaction_unlock(sb); return err; } @@ -2384,8 +2381,7 @@ static void nilfs_segctor_notify(struct nilfs_sc_info *sci, int mode, int err) */ static int nilfs_segctor_construct(struct nilfs_sc_info *sci, int mode) { - struct nilfs_sb_info *sbi = NILFS_SB(sci->sc_super); - struct the_nilfs *nilfs = sbi->s_nilfs; + struct the_nilfs *nilfs = NILFS_SB(sci->sc_super)->s_nilfs; struct nilfs_super_block **sbp; int err = 0; @@ -2403,11 +2399,12 @@ static int nilfs_segctor_construct(struct nilfs_sc_info *sci, int mode) nilfs_discontinued(nilfs)) { down_write(&nilfs->ns_sem); err = -EIO; - sbp = nilfs_prepare_super(sbi, + sbp = nilfs_prepare_super(sci->sc_super, nilfs_sb_will_flip(nilfs)); if (likely(sbp)) { nilfs_set_log_cursor(sbp[0], nilfs); - err = nilfs_commit_super(sbi, NILFS_SB_COMMIT); + err = nilfs_commit_super(sci->sc_super, + NILFS_SB_COMMIT); } up_write(&nilfs->ns_sem); } @@ -2439,8 +2436,7 @@ nilfs_remove_written_gcinodes(struct the_nilfs *nilfs, struct list_head *head) int nilfs_clean_segments(struct super_block *sb, struct nilfs_argv *argv, void **kbufs) { - struct nilfs_sb_info *sbi = NILFS_SB(sb); - struct the_nilfs *nilfs = sbi->s_nilfs; + struct the_nilfs *nilfs = NILFS_SB(sb)->s_nilfs; struct nilfs_sc_info *sci = nilfs->ns_writer; struct nilfs_transaction_info ti; int err; @@ -2448,7 +2444,7 @@ int nilfs_clean_segments(struct super_block *sb, struct nilfs_argv *argv, if (unlikely(!sci)) return -EROFS; - nilfs_transaction_lock(sbi, &ti, 1); + nilfs_transaction_lock(sb, &ti, 1); err = nilfs_mdt_save_to_shadow_map(nilfs->ns_dat); if (unlikely(err)) @@ -2491,16 +2487,15 @@ int nilfs_clean_segments(struct super_block *sb, struct nilfs_argv *argv, sci->sc_freesegs = NULL; sci->sc_nfreesegs = 0; nilfs_mdt_clear_shadow_map(nilfs->ns_dat); - nilfs_transaction_unlock(sbi); + nilfs_transaction_unlock(sb); return err; } static void nilfs_segctor_thread_construct(struct nilfs_sc_info *sci, int mode) { - struct nilfs_sb_info *sbi = NILFS_SB(sci->sc_super); struct nilfs_transaction_info ti; - nilfs_transaction_lock(sbi, &ti, 0); + nilfs_transaction_lock(sci->sc_super, &ti, 0); nilfs_segctor_construct(sci, mode); /* @@ -2511,7 +2506,7 @@ static void nilfs_segctor_thread_construct(struct nilfs_sc_info *sci, int mode) if (test_bit(NILFS_SC_UNCLOSED, &sci->sc_flags)) nilfs_segctor_start_timer(sci); - nilfs_transaction_unlock(sbi); + nilfs_transaction_unlock(sci->sc_super); } static void nilfs_segctor_do_immediate_flush(struct nilfs_sc_info *sci) @@ -2668,17 +2663,17 @@ static void nilfs_segctor_kill_thread(struct nilfs_sc_info *sci) /* * Setup & clean-up functions */ -static struct nilfs_sc_info *nilfs_segctor_new(struct nilfs_sb_info *sbi, +static struct nilfs_sc_info *nilfs_segctor_new(struct super_block *sb, struct nilfs_root *root) { - struct the_nilfs *nilfs = sbi->s_nilfs; + struct the_nilfs *nilfs = NILFS_SB(sb)->s_nilfs; struct nilfs_sc_info *sci; sci = kzalloc(sizeof(*sci), GFP_KERNEL); if (!sci) return NULL; - sci->sc_super = sbi->s_super; + sci->sc_super = sb; nilfs_get_root(root); sci->sc_root = root; @@ -2712,12 +2707,11 @@ static void nilfs_segctor_write_out(struct nilfs_sc_info *sci) /* The segctord thread was stopped and its timer was removed. But some tasks remain. */ do { - struct nilfs_sb_info *sbi = NILFS_SB(sci->sc_super); struct nilfs_transaction_info ti; - nilfs_transaction_lock(sbi, &ti, 0); + nilfs_transaction_lock(sci->sc_super, &ti, 0); ret = nilfs_segctor_construct(sci, SC_LSEG_SR); - nilfs_transaction_unlock(sbi); + nilfs_transaction_unlock(sci->sc_super); } while (ret && retrycount-- > 0); } @@ -2766,22 +2760,21 @@ static void nilfs_segctor_destroy(struct nilfs_sc_info *sci) } /** - * nilfs_attach_segment_constructor - attach a segment constructor - * @sbi: nilfs_sb_info + * nilfs_attach_log_writer - attach log writer + * @sb: super block instance * @root: root object of the current filesystem tree * - * nilfs_attach_segment_constructor() allocates a struct nilfs_sc_info, - * initializes it, and starts the segment constructor. + * This allocates a log writer object, initializes it, and starts the + * log writer. * * Return Value: On success, 0 is returned. On error, one of the following * negative error code is returned. * * %-ENOMEM - Insufficient memory available. */ -int nilfs_attach_segment_constructor(struct nilfs_sb_info *sbi, - struct nilfs_root *root) +int nilfs_attach_log_writer(struct super_block *sb, struct nilfs_root *root) { - struct the_nilfs *nilfs = sbi->s_nilfs; + struct the_nilfs *nilfs = NILFS_SB(sb)->s_nilfs; int err; if (nilfs->ns_writer) { @@ -2790,10 +2783,10 @@ int nilfs_attach_segment_constructor(struct nilfs_sb_info *sbi, * read/write after nilfs_error degenerated it into a * read-only mount. */ - nilfs_detach_segment_constructor(sbi); + nilfs_detach_log_writer(sb); } - nilfs->ns_writer = nilfs_segctor_new(sbi, root); + nilfs->ns_writer = nilfs_segctor_new(sb, root); if (!nilfs->ns_writer) return -ENOMEM; @@ -2806,15 +2799,15 @@ int nilfs_attach_segment_constructor(struct nilfs_sb_info *sbi, } /** - * nilfs_detach_segment_constructor - destroy the segment constructor - * @sbi: nilfs_sb_info + * nilfs_detach_log_writer - destroy log writer + * @sb: super block instance * - * nilfs_detach_segment_constructor() kills the segment constructor daemon, - * frees the struct nilfs_sc_info, and destroy the dirty file list. + * This kills log writer daemon, frees the log writer object, and + * destroys list of dirty files. */ -void nilfs_detach_segment_constructor(struct nilfs_sb_info *sbi) +void nilfs_detach_log_writer(struct super_block *sb) { - struct the_nilfs *nilfs = sbi->s_nilfs; + struct the_nilfs *nilfs = NILFS_SB(sb)->s_nilfs; LIST_HEAD(garbage_list); down_write(&nilfs->ns_segctor_sem); @@ -2827,9 +2820,8 @@ void nilfs_detach_segment_constructor(struct nilfs_sb_info *sbi) spin_lock(&nilfs->ns_inode_lock); if (!list_empty(&nilfs->ns_dirty_files)) { list_splice_init(&nilfs->ns_dirty_files, &garbage_list); - nilfs_warning(sbi->s_super, __func__, - "Non empty dirty list after the last " - "segment construction\n"); + nilfs_warning(sb, __func__, + "Hit dirty file after stopped log writer\n"); } spin_unlock(&nilfs->ns_inode_lock); up_write(&nilfs->ns_segctor_sem); diff --git a/fs/nilfs2/segment.h b/fs/nilfs2/segment.h index 9544aa97dd49e..e01998e33b316 100644 --- a/fs/nilfs2/segment.h +++ b/fs/nilfs2/segment.h @@ -233,18 +233,16 @@ extern void nilfs_flush_segment(struct super_block *, ino_t); extern int nilfs_clean_segments(struct super_block *, struct nilfs_argv *, void **); -int nilfs_attach_segment_constructor(struct nilfs_sb_info *sbi, - struct nilfs_root *root); -extern void nilfs_detach_segment_constructor(struct nilfs_sb_info *); +int nilfs_attach_log_writer(struct super_block *sb, struct nilfs_root *root); +void nilfs_detach_log_writer(struct super_block *sb); /* recovery.c */ extern int nilfs_read_super_root_block(struct the_nilfs *, sector_t, struct buffer_head **, int); extern int nilfs_search_super_root(struct the_nilfs *, struct nilfs_recovery_info *); -extern int nilfs_salvage_orphan_logs(struct the_nilfs *, - struct nilfs_sb_info *, - struct nilfs_recovery_info *); +int nilfs_salvage_orphan_logs(struct the_nilfs *nilfs, struct super_block *sb, + struct nilfs_recovery_info *ri); extern void nilfs_dispose_segment_list(struct list_head *); #endif /* _NILFS_SEGMENT_H */ diff --git a/fs/nilfs2/super.c b/fs/nilfs2/super.c index 1368c4293c7fb..a8cbd695441e4 100644 --- a/fs/nilfs2/super.c +++ b/fs/nilfs2/super.c @@ -71,23 +71,23 @@ struct kmem_cache *nilfs_transaction_cachep; struct kmem_cache *nilfs_segbuf_cachep; struct kmem_cache *nilfs_btree_path_cache; -static int nilfs_setup_super(struct nilfs_sb_info *sbi, int is_mount); +static int nilfs_setup_super(struct super_block *sb, int is_mount); static int nilfs_remount(struct super_block *sb, int *flags, char *data); -static void nilfs_set_error(struct nilfs_sb_info *sbi) +static void nilfs_set_error(struct super_block *sb) { - struct the_nilfs *nilfs = sbi->s_nilfs; + struct the_nilfs *nilfs = NILFS_SB(sb)->s_nilfs; struct nilfs_super_block **sbp; down_write(&nilfs->ns_sem); if (!(nilfs->ns_mount_state & NILFS_ERROR_FS)) { nilfs->ns_mount_state |= NILFS_ERROR_FS; - sbp = nilfs_prepare_super(sbi, 0); + sbp = nilfs_prepare_super(sb, 0); if (likely(sbp)) { sbp[0]->s_state |= cpu_to_le16(NILFS_ERROR_FS); if (sbp[1]) sbp[1]->s_state |= cpu_to_le16(NILFS_ERROR_FS); - nilfs_commit_super(sbi, NILFS_SB_COMMIT_ALL); + nilfs_commit_super(sb, NILFS_SB_COMMIT_ALL); } } up_write(&nilfs->ns_sem); @@ -108,7 +108,7 @@ static void nilfs_set_error(struct nilfs_sb_info *sbi) void nilfs_error(struct super_block *sb, const char *function, const char *fmt, ...) { - struct the_nilfs *nilfs = sbi->s_nilfs; + struct the_nilfs *nilfs = NILFS_SB(sb)->s_nilfs; struct va_format vaf; va_list args; @@ -123,7 +123,7 @@ void nilfs_error(struct super_block *sb, const char *function, va_end(args); if (!(sb->s_flags & MS_RDONLY)) { - nilfs_set_error(sbi); + nilfs_set_error(sb); if (nilfs_test_opt(nilfs, ERRORS_RO)) { printk(KERN_CRIT "Remounting filesystem read-only\n"); @@ -188,9 +188,9 @@ void nilfs_destroy_inode(struct inode *inode) call_rcu(&inode->i_rcu, nilfs_i_callback); } -static int nilfs_sync_super(struct nilfs_sb_info *sbi, int flag) +static int nilfs_sync_super(struct super_block *sb, int flag) { - struct the_nilfs *nilfs = sbi->s_nilfs; + struct the_nilfs *nilfs = NILFS_SB(sb)->s_nilfs; int err; retry: @@ -262,10 +262,10 @@ void nilfs_set_log_cursor(struct nilfs_super_block *sbp, spin_unlock(&nilfs->ns_last_segment_lock); } -struct nilfs_super_block **nilfs_prepare_super(struct nilfs_sb_info *sbi, +struct nilfs_super_block **nilfs_prepare_super(struct super_block *sb, int flip) { - struct the_nilfs *nilfs = sbi->s_nilfs; + struct the_nilfs *nilfs = NILFS_SB(sb)->s_nilfs; struct nilfs_super_block **sbp = nilfs->ns_sbp; /* nilfs->ns_sem must be locked by the caller. */ @@ -275,7 +275,7 @@ struct nilfs_super_block **nilfs_prepare_super(struct nilfs_sb_info *sbi, memcpy(sbp[0], sbp[1], nilfs->ns_sbsize); } else { printk(KERN_CRIT "NILFS: superblock broke on dev %s\n", - sbi->s_super->s_id); + sb->s_id); return NULL; } } else if (sbp[1] && @@ -289,9 +289,9 @@ struct nilfs_super_block **nilfs_prepare_super(struct nilfs_sb_info *sbi, return sbp; } -int nilfs_commit_super(struct nilfs_sb_info *sbi, int flag) +int nilfs_commit_super(struct super_block *sb, int flag) { - struct the_nilfs *nilfs = sbi->s_nilfs; + struct the_nilfs *nilfs = NILFS_SB(sb)->s_nilfs; struct nilfs_super_block **sbp = nilfs->ns_sbp; time_t t; @@ -311,27 +311,28 @@ int nilfs_commit_super(struct nilfs_sb_info *sbi, int flag) nilfs->ns_sbsize)); } clear_nilfs_sb_dirty(nilfs); - return nilfs_sync_super(sbi, flag); + return nilfs_sync_super(sb, flag); } /** * nilfs_cleanup_super() - write filesystem state for cleanup - * @sbi: nilfs_sb_info to be unmounted or degraded to read-only + * @sb: super block instance to be unmounted or degraded to read-only * * This function restores state flags in the on-disk super block. * This will set "clean" flag (i.e. NILFS_VALID_FS) unless the * filesystem was not clean previously. */ -int nilfs_cleanup_super(struct nilfs_sb_info *sbi) +int nilfs_cleanup_super(struct super_block *sb) { + struct the_nilfs *nilfs = NILFS_SB(sb)->s_nilfs; struct nilfs_super_block **sbp; int flag = NILFS_SB_COMMIT; int ret = -EIO; - sbp = nilfs_prepare_super(sbi, 0); + sbp = nilfs_prepare_super(sb, 0); if (sbp) { - sbp[0]->s_state = cpu_to_le16(sbi->s_nilfs->ns_mount_state); - nilfs_set_log_cursor(sbp[0], sbi->s_nilfs); + sbp[0]->s_state = cpu_to_le16(nilfs->ns_mount_state); + nilfs_set_log_cursor(sbp[0], nilfs); if (sbp[1] && sbp[0]->s_last_cno == sbp[1]->s_last_cno) { /* * make the "clean" flag also to the opposite @@ -341,7 +342,7 @@ int nilfs_cleanup_super(struct nilfs_sb_info *sbi) sbp[1]->s_state = sbp[0]->s_state; flag = NILFS_SB_COMMIT_ALL; } - ret = nilfs_commit_super(sbi, flag); + ret = nilfs_commit_super(sb, flag); } return ret; } @@ -351,11 +352,11 @@ static void nilfs_put_super(struct super_block *sb) struct nilfs_sb_info *sbi = NILFS_SB(sb); struct the_nilfs *nilfs = sbi->s_nilfs; - nilfs_detach_segment_constructor(sbi); + nilfs_detach_log_writer(sb); if (!(sb->s_flags & MS_RDONLY)) { down_write(&nilfs->ns_sem); - nilfs_cleanup_super(sbi); + nilfs_cleanup_super(sb); up_write(&nilfs->ns_sem); } @@ -371,8 +372,7 @@ static void nilfs_put_super(struct super_block *sb) static int nilfs_sync_fs(struct super_block *sb, int wait) { - struct nilfs_sb_info *sbi = NILFS_SB(sb); - struct the_nilfs *nilfs = sbi->s_nilfs; + struct the_nilfs *nilfs = NILFS_SB(sb)->s_nilfs; struct nilfs_super_block **sbp; int err = 0; @@ -382,10 +382,10 @@ static int nilfs_sync_fs(struct super_block *sb, int wait) down_write(&nilfs->ns_sem); if (nilfs_sb_dirty(nilfs)) { - sbp = nilfs_prepare_super(sbi, nilfs_sb_will_flip(nilfs)); + sbp = nilfs_prepare_super(sb, nilfs_sb_will_flip(nilfs)); if (likely(sbp)) { nilfs_set_log_cursor(sbp[0], nilfs); - nilfs_commit_super(sbi, NILFS_SB_COMMIT); + nilfs_commit_super(sb, NILFS_SB_COMMIT); } } up_write(&nilfs->ns_sem); @@ -393,10 +393,10 @@ static int nilfs_sync_fs(struct super_block *sb, int wait) return err; } -int nilfs_attach_checkpoint(struct nilfs_sb_info *sbi, __u64 cno, int curr_mnt, +int nilfs_attach_checkpoint(struct super_block *sb, __u64 cno, int curr_mnt, struct nilfs_root **rootp) { - struct the_nilfs *nilfs = sbi->s_nilfs; + struct the_nilfs *nilfs = NILFS_SB(sb)->s_nilfs; struct nilfs_root *root; struct nilfs_checkpoint *raw_cp; struct buffer_head *bh_cp; @@ -425,7 +425,7 @@ int nilfs_attach_checkpoint(struct nilfs_sb_info *sbi, __u64 cno, int curr_mnt, goto failed; } - err = nilfs_ifile_read(sbi->s_super, root, nilfs->ns_inode_size, + err = nilfs_ifile_read(sb, root, nilfs->ns_inode_size, &raw_cp->cp_ifile_inode, &root->ifile); if (err) goto failed_bh; @@ -449,8 +449,7 @@ int nilfs_attach_checkpoint(struct nilfs_sb_info *sbi, __u64 cno, int curr_mnt, static int nilfs_freeze(struct super_block *sb) { - struct nilfs_sb_info *sbi = NILFS_SB(sb); - struct the_nilfs *nilfs = sbi->s_nilfs; + struct the_nilfs *nilfs = NILFS_SB(sb)->s_nilfs; int err; if (sb->s_flags & MS_RDONLY) @@ -458,21 +457,20 @@ static int nilfs_freeze(struct super_block *sb) /* Mark super block clean */ down_write(&nilfs->ns_sem); - err = nilfs_cleanup_super(sbi); + err = nilfs_cleanup_super(sb); up_write(&nilfs->ns_sem); return err; } static int nilfs_unfreeze(struct super_block *sb) { - struct nilfs_sb_info *sbi = NILFS_SB(sb); - struct the_nilfs *nilfs = sbi->s_nilfs; + struct the_nilfs *nilfs = NILFS_SB(sb)->s_nilfs; if (sb->s_flags & MS_RDONLY) return 0; down_write(&nilfs->ns_sem); - nilfs_setup_super(sbi, false); + nilfs_setup_super(sb, false); up_write(&nilfs->ns_sem); return 0; } @@ -668,15 +666,15 @@ nilfs_set_default_options(struct super_block *sb, NILFS_MOUNT_ERRORS_RO | NILFS_MOUNT_BARRIER; } -static int nilfs_setup_super(struct nilfs_sb_info *sbi, int is_mount) +static int nilfs_setup_super(struct super_block *sb, int is_mount) { - struct the_nilfs *nilfs = sbi->s_nilfs; + struct the_nilfs *nilfs = NILFS_SB(sb)->s_nilfs; struct nilfs_super_block **sbp; int max_mnt_count; int mnt_count; /* nilfs->ns_sem must be locked by the caller. */ - sbp = nilfs_prepare_super(sbi, 0); + sbp = nilfs_prepare_super(sb, 0); if (!sbp) return -EIO; @@ -707,7 +705,7 @@ skip_mount_setup: /* synchronize sbp[1] with sbp[0] */ if (sbp[1]) memcpy(sbp[1], sbp[0], nilfs->ns_sbsize); - return nilfs_commit_super(sbi, NILFS_SB_COMMIT_ALL); + return nilfs_commit_super(sb, NILFS_SB_COMMIT_ALL); } struct nilfs_super_block *nilfs_read_super_block(struct super_block *sb, @@ -841,7 +839,7 @@ static int nilfs_attach_snapshot(struct super_block *s, __u64 cno, goto out; } - ret = nilfs_attach_checkpoint(NILFS_SB(s), cno, false, &root); + ret = nilfs_attach_checkpoint(s, cno, false, &root); if (ret) { printk(KERN_ERR "NILFS: error loading snapshot " "(checkpoint number=%llu).\n", @@ -938,7 +936,7 @@ nilfs_fill_super(struct super_block *sb, void *data, int silent) } sbi->s_nilfs = nilfs; - err = init_nilfs(nilfs, sbi, (char *)data); + err = init_nilfs(nilfs, sb, (char *)data); if (err) goto failed_nilfs; @@ -950,12 +948,12 @@ nilfs_fill_super(struct super_block *sb, void *data, int silent) bdi = sb->s_bdev->bd_inode->i_mapping->backing_dev_info; sb->s_bdi = bdi ? : &default_backing_dev_info; - err = load_nilfs(nilfs, sbi); + err = load_nilfs(nilfs, sb); if (err) goto failed_nilfs; cno = nilfs_last_cno(nilfs); - err = nilfs_attach_checkpoint(sbi, cno, true, &fsroot); + err = nilfs_attach_checkpoint(sb, cno, true, &fsroot); if (err) { printk(KERN_ERR "NILFS: error loading last checkpoint " "(checkpoint number=%llu).\n", (unsigned long long)cno); @@ -963,7 +961,7 @@ nilfs_fill_super(struct super_block *sb, void *data, int silent) } if (!(sb->s_flags & MS_RDONLY)) { - err = nilfs_attach_segment_constructor(sbi, fsroot); + err = nilfs_attach_log_writer(sb, fsroot); if (err) goto failed_checkpoint; } @@ -976,14 +974,14 @@ nilfs_fill_super(struct super_block *sb, void *data, int silent) if (!(sb->s_flags & MS_RDONLY)) { down_write(&nilfs->ns_sem); - nilfs_setup_super(sbi, true); + nilfs_setup_super(sb, true); up_write(&nilfs->ns_sem); } return 0; failed_segctor: - nilfs_detach_segment_constructor(sbi); + nilfs_detach_log_writer(sb); failed_checkpoint: nilfs_put_root(fsroot); @@ -1004,8 +1002,7 @@ nilfs_fill_super(struct super_block *sb, void *data, int silent) static int nilfs_remount(struct super_block *sb, int *flags, char *data) { - struct nilfs_sb_info *sbi = NILFS_SB(sb); - struct the_nilfs *nilfs = sbi->s_nilfs; + struct the_nilfs *nilfs = NILFS_SB(sb)->s_nilfs; unsigned long old_sb_flags; unsigned long old_mount_opt; int err; @@ -1031,8 +1028,8 @@ static int nilfs_remount(struct super_block *sb, int *flags, char *data) if ((*flags & MS_RDONLY) == (sb->s_flags & MS_RDONLY)) goto out; if (*flags & MS_RDONLY) { - /* Shutting down the segment constructor */ - nilfs_detach_segment_constructor(sbi); + /* Shutting down log writer */ + nilfs_detach_log_writer(sb); sb->s_flags |= MS_RDONLY; /* @@ -1040,7 +1037,7 @@ static int nilfs_remount(struct super_block *sb, int *flags, char *data) * the RDONLY flag and then mark the partition as valid again. */ down_write(&nilfs->ns_sem); - nilfs_cleanup_super(sbi); + nilfs_cleanup_super(sb); up_write(&nilfs->ns_sem); } else { __u64 features; @@ -1067,12 +1064,12 @@ static int nilfs_remount(struct super_block *sb, int *flags, char *data) sb->s_flags &= ~MS_RDONLY; root = NILFS_I(sb->s_root->d_inode)->i_root; - err = nilfs_attach_segment_constructor(sbi, root); + err = nilfs_attach_log_writer(sb, root); if (err) goto restore_opts; down_write(&nilfs->ns_sem); - nilfs_setup_super(sbi, true); + nilfs_setup_super(sb, true); up_write(&nilfs->ns_sem); } out: diff --git a/fs/nilfs2/the_nilfs.c b/fs/nilfs2/the_nilfs.c index 1bf695e887a70..d2acd1a651f31 100644 --- a/fs/nilfs2/the_nilfs.c +++ b/fs/nilfs2/the_nilfs.c @@ -201,16 +201,16 @@ static int nilfs_store_log_cursor(struct the_nilfs *nilfs, /** * load_nilfs - load and recover the nilfs * @nilfs: the_nilfs structure to be released - * @sbi: nilfs_sb_info used to recover past segment + * @sb: super block isntance used to recover past segment * * load_nilfs() searches and load the latest super root, * attaches the last segment, and does recovery if needed. * The caller must call this exclusively for simultaneous mounts. */ -int load_nilfs(struct the_nilfs *nilfs, struct nilfs_sb_info *sbi) +int load_nilfs(struct the_nilfs *nilfs, struct super_block *sb) { struct nilfs_recovery_info ri; - unsigned int s_flags = sbi->s_super->s_flags; + unsigned int s_flags = sb->s_flags; int really_read_only = bdev_read_only(nilfs->ns_bdev); int valid_fs = nilfs_valid_fs(nilfs); int err; @@ -275,7 +275,7 @@ int load_nilfs(struct the_nilfs *nilfs, struct nilfs_sb_info *sbi) goto scan_error; } - err = nilfs_load_super_root(nilfs, sbi->s_super, ri.ri_super_root); + err = nilfs_load_super_root(nilfs, sb, ri.ri_super_root); if (unlikely(err)) { printk(KERN_ERR "NILFS: error loading super root.\n"); goto failed; @@ -308,7 +308,7 @@ int load_nilfs(struct the_nilfs *nilfs, struct nilfs_sb_info *sbi) err = -EROFS; goto failed_unload; } - sbi->s_super->s_flags &= ~MS_RDONLY; + sb->s_flags &= ~MS_RDONLY; } else if (nilfs_test_opt(nilfs, NORECOVERY)) { printk(KERN_ERR "NILFS: recovery cancelled because norecovery " "option was specified for a read/write mount\n"); @@ -316,13 +316,13 @@ int load_nilfs(struct the_nilfs *nilfs, struct nilfs_sb_info *sbi) goto failed_unload; } - err = nilfs_salvage_orphan_logs(nilfs, sbi, &ri); + err = nilfs_salvage_orphan_logs(nilfs, sb, &ri); if (err) goto failed_unload; down_write(&nilfs->ns_sem); nilfs->ns_mount_state |= NILFS_VALID_FS; /* set "clean" flag */ - err = nilfs_cleanup_super(sbi); + err = nilfs_cleanup_super(sb); up_write(&nilfs->ns_sem); if (err) { @@ -334,7 +334,7 @@ int load_nilfs(struct the_nilfs *nilfs, struct nilfs_sb_info *sbi) skip_recovery: nilfs_clear_recovery_info(&ri); - sbi->s_super->s_flags = s_flags; + sb->s_flags = s_flags; return 0; scan_error: @@ -348,7 +348,7 @@ int load_nilfs(struct the_nilfs *nilfs, struct nilfs_sb_info *sbi) failed: nilfs_clear_recovery_info(&ri); - sbi->s_super->s_flags = s_flags; + sb->s_flags = s_flags; return err; } @@ -526,7 +526,6 @@ static int nilfs_load_super_block(struct the_nilfs *nilfs, /** * init_nilfs - initialize a NILFS instance. * @nilfs: the_nilfs structure - * @sbi: nilfs_sb_info * @sb: super block * @data: mount options * @@ -537,9 +536,8 @@ static int nilfs_load_super_block(struct the_nilfs *nilfs, * Return Value: On success, 0 is returned. On error, a negative error * code is returned. */ -int init_nilfs(struct the_nilfs *nilfs, struct nilfs_sb_info *sbi, char *data) +int init_nilfs(struct the_nilfs *nilfs, struct super_block *sb, char *data) { - struct super_block *sb = sbi->s_super; struct nilfs_super_block *sbp; int blocksize; int err; diff --git a/fs/nilfs2/the_nilfs.h b/fs/nilfs2/the_nilfs.h index 10521b97ded60..793bd272f9e0b 100644 --- a/fs/nilfs2/the_nilfs.h +++ b/fs/nilfs2/the_nilfs.h @@ -267,15 +267,14 @@ static inline int nilfs_sb_will_flip(struct the_nilfs *nilfs) void nilfs_set_last_segment(struct the_nilfs *, sector_t, u64, __u64); struct the_nilfs *alloc_nilfs(struct block_device *bdev); void destroy_nilfs(struct the_nilfs *nilfs); -int init_nilfs(struct the_nilfs *, struct nilfs_sb_info *, char *); -int load_nilfs(struct the_nilfs *, struct nilfs_sb_info *); +int init_nilfs(struct the_nilfs *nilfs, struct super_block *sb, char *data); +int load_nilfs(struct the_nilfs *nilfs, struct super_block *sb); int nilfs_discard_segments(struct the_nilfs *, __u64 *, size_t); int nilfs_count_free_blocks(struct the_nilfs *, sector_t *); struct nilfs_root *nilfs_lookup_root(struct the_nilfs *nilfs, __u64 cno); struct nilfs_root *nilfs_find_or_create_root(struct the_nilfs *nilfs, __u64 cno); void nilfs_put_root(struct nilfs_root *root); -struct nilfs_sb_info *nilfs_find_sbinfo(struct the_nilfs *, int, __u64); int nilfs_near_disk_full(struct the_nilfs *); void nilfs_fall_back_super_block(struct the_nilfs *); void nilfs_swap_super_block(struct the_nilfs *); -- GitLab From e3154e9748f0f337e9f6ff9dc7d7bf24d426bd1a Mon Sep 17 00:00:00 2001 From: Ryusuke Konishi Date: Wed, 9 Mar 2011 11:05:08 +0900 Subject: [PATCH 0355/2822] nilfs2: get rid of nilfs_sb_info structure This directly uses sb->s_fs_info to keep a nilfs filesystem object and fully removes the intermediate nilfs_sb_info structure. With this change, the hierarchy of on-memory structures of nilfs will be simplified as follows: Before: super_block -> nilfs_sb_info -> the_nilfs -> cptree --+-> nilfs_root (current file system) +-> nilfs_root (snapshot A) +-> nilfs_root (snapshot B) : -> nilfs_sc_info (log writer structure) After: super_block -> the_nilfs -> cptree --+-> nilfs_root (current file system) +-> nilfs_root (snapshot A) +-> nilfs_root (snapshot B) : -> nilfs_sc_info (log writer structure) The reason why we didn't design so from the beginning is because the initial shape also differed from the above. The early hierachy was composed of "per-mount-point" super_block -> nilfs_sb_info pairs and a shared nilfs object. On the kernel 2.6.37, it was changed to the current shape in order to unify super block instances into one per device, and this cleanup became applicable as the result. Signed-off-by: Ryusuke Konishi --- fs/nilfs2/bmap.c | 1 - fs/nilfs2/file.c | 2 +- fs/nilfs2/inode.c | 10 +++---- fs/nilfs2/ioctl.c | 23 ++++++++-------- fs/nilfs2/mdt.h | 2 +- fs/nilfs2/namei.c | 2 +- fs/nilfs2/nilfs.h | 3 +-- fs/nilfs2/sb.h | 46 ------------------------------- fs/nilfs2/segment.c | 47 ++++++++++++++++---------------- fs/nilfs2/segment.h | 2 +- fs/nilfs2/super.c | 63 ++++++++++++++++--------------------------- fs/nilfs2/the_nilfs.h | 1 - 12 files changed, 68 insertions(+), 134 deletions(-) delete mode 100644 fs/nilfs2/sb.h diff --git a/fs/nilfs2/bmap.c b/fs/nilfs2/bmap.c index 85447a2fab33e..4723f04e9b12a 100644 --- a/fs/nilfs2/bmap.c +++ b/fs/nilfs2/bmap.c @@ -25,7 +25,6 @@ #include #include "nilfs.h" #include "bmap.h" -#include "sb.h" #include "btree.h" #include "direct.h" #include "btnode.h" diff --git a/fs/nilfs2/file.c b/fs/nilfs2/file.c index 7a5e4ab15c6ee..93589fccdd974 100644 --- a/fs/nilfs2/file.c +++ b/fs/nilfs2/file.c @@ -59,7 +59,7 @@ static int nilfs_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf) struct nilfs_transaction_info ti; int ret; - if (unlikely(nilfs_near_disk_full(NILFS_SB(inode->i_sb)->s_nilfs))) + if (unlikely(nilfs_near_disk_full(inode->i_sb->s_fs_info))) return VM_FAULT_SIGBUS; /* -ENOSPC */ lock_page(page); diff --git a/fs/nilfs2/inode.c b/fs/nilfs2/inode.c index 7a3dbe4f229ce..d5625be236a8c 100644 --- a/fs/nilfs2/inode.c +++ b/fs/nilfs2/inode.c @@ -295,7 +295,7 @@ const struct address_space_operations nilfs_aops = { struct inode *nilfs_new_inode(struct inode *dir, int mode) { struct super_block *sb = dir->i_sb; - struct the_nilfs *nilfs = NILFS_SB(sb)->s_nilfs; + struct the_nilfs *nilfs = sb->s_fs_info; struct inode *inode; struct nilfs_inode_info *ii; struct nilfs_root *root; @@ -433,7 +433,7 @@ static int __nilfs_read_inode(struct super_block *sb, struct nilfs_root *root, unsigned long ino, struct inode *inode) { - struct the_nilfs *nilfs = NILFS_SB(sb)->s_nilfs; + struct the_nilfs *nilfs = sb->s_fs_info; struct buffer_head *bh; struct nilfs_inode *raw_inode; int err; @@ -807,7 +807,7 @@ int nilfs_permission(struct inode *inode, int mask, unsigned int flags) int nilfs_load_inode_block(struct inode *inode, struct buffer_head **pbh) { - struct the_nilfs *nilfs = NILFS_SB(inode->i_sb)->s_nilfs; + struct the_nilfs *nilfs = inode->i_sb->s_fs_info; struct nilfs_inode_info *ii = NILFS_I(inode); int err; @@ -836,7 +836,7 @@ int nilfs_load_inode_block(struct inode *inode, struct buffer_head **pbh) int nilfs_inode_dirty(struct inode *inode) { struct nilfs_inode_info *ii = NILFS_I(inode); - struct the_nilfs *nilfs = NILFS_SB(inode->i_sb)->s_nilfs; + struct the_nilfs *nilfs = inode->i_sb->s_fs_info; int ret = 0; if (!list_empty(&ii->i_dirty)) { @@ -851,7 +851,7 @@ int nilfs_inode_dirty(struct inode *inode) int nilfs_set_file_dirty(struct inode *inode, unsigned nr_dirty) { struct nilfs_inode_info *ii = NILFS_I(inode); - struct the_nilfs *nilfs = NILFS_SB(inode->i_sb)->s_nilfs; + struct the_nilfs *nilfs = inode->i_sb->s_fs_info; atomic_add(nr_dirty, &nilfs->ns_ndirtyblks); diff --git a/fs/nilfs2/ioctl.c b/fs/nilfs2/ioctl.c index 5471eed5eccb1..95c04c2f2b3e0 100644 --- a/fs/nilfs2/ioctl.c +++ b/fs/nilfs2/ioctl.c @@ -166,8 +166,7 @@ static int nilfs_ioctl_getversion(struct inode *inode, void __user *argp) static int nilfs_ioctl_change_cpmode(struct inode *inode, struct file *filp, unsigned int cmd, void __user *argp) { - struct the_nilfs *nilfs = NILFS_SB(inode->i_sb)->s_nilfs; - struct inode *cpfile = nilfs->ns_cpfile; + struct the_nilfs *nilfs = inode->i_sb->s_fs_info; struct nilfs_transaction_info ti; struct nilfs_cpmode cpmode; int ret; @@ -187,7 +186,7 @@ static int nilfs_ioctl_change_cpmode(struct inode *inode, struct file *filp, nilfs_transaction_begin(inode->i_sb, &ti, 0); ret = nilfs_cpfile_change_cpmode( - cpfile, cpmode.cm_cno, cpmode.cm_mode); + nilfs->ns_cpfile, cpmode.cm_cno, cpmode.cm_mode); if (unlikely(ret < 0)) nilfs_transaction_abort(inode->i_sb); else @@ -203,7 +202,7 @@ static int nilfs_ioctl_delete_checkpoint(struct inode *inode, struct file *filp, unsigned int cmd, void __user *argp) { - struct inode *cpfile = NILFS_SB(inode->i_sb)->s_nilfs->ns_cpfile; + struct the_nilfs *nilfs = inode->i_sb->s_fs_info; struct nilfs_transaction_info ti; __u64 cno; int ret; @@ -220,7 +219,7 @@ nilfs_ioctl_delete_checkpoint(struct inode *inode, struct file *filp, goto out; nilfs_transaction_begin(inode->i_sb, &ti, 0); - ret = nilfs_cpfile_delete_checkpoint(cpfile, cno); + ret = nilfs_cpfile_delete_checkpoint(nilfs->ns_cpfile, cno); if (unlikely(ret < 0)) nilfs_transaction_abort(inode->i_sb); else @@ -246,7 +245,7 @@ nilfs_ioctl_do_get_cpinfo(struct the_nilfs *nilfs, __u64 *posp, int flags, static int nilfs_ioctl_get_cpstat(struct inode *inode, struct file *filp, unsigned int cmd, void __user *argp) { - struct the_nilfs *nilfs = NILFS_SB(inode->i_sb)->s_nilfs; + struct the_nilfs *nilfs = inode->i_sb->s_fs_info; struct nilfs_cpstat cpstat; int ret; @@ -277,7 +276,7 @@ nilfs_ioctl_do_get_suinfo(struct the_nilfs *nilfs, __u64 *posp, int flags, static int nilfs_ioctl_get_sustat(struct inode *inode, struct file *filp, unsigned int cmd, void __user *argp) { - struct the_nilfs *nilfs = NILFS_SB(inode->i_sb)->s_nilfs; + struct the_nilfs *nilfs = inode->i_sb->s_fs_info; struct nilfs_sustat sustat; int ret; @@ -333,7 +332,7 @@ nilfs_ioctl_do_get_bdescs(struct the_nilfs *nilfs, __u64 *posp, int flags, static int nilfs_ioctl_get_bdescs(struct inode *inode, struct file *filp, unsigned int cmd, void __user *argp) { - struct the_nilfs *nilfs = NILFS_SB(inode->i_sb)->s_nilfs; + struct the_nilfs *nilfs = inode->i_sb->s_fs_info; struct nilfs_argv argv; int ret; @@ -402,7 +401,7 @@ static int nilfs_ioctl_move_blocks(struct super_block *sb, struct nilfs_argv *argv, void *buf) { size_t nmembs = argv->v_nmembs; - struct the_nilfs *nilfs = NILFS_SB(sb)->s_nilfs; + struct the_nilfs *nilfs = sb->s_fs_info; struct inode *inode; struct nilfs_vdesc *vdesc; struct buffer_head *bh, *n; @@ -616,7 +615,7 @@ static int nilfs_ioctl_clean_segments(struct inode *inode, struct file *filp, ret = PTR_ERR(kbufs[4]); goto out; } - nilfs = NILFS_SB(inode->i_sb)->s_nilfs; + nilfs = inode->i_sb->s_fs_info; for (n = 0; n < 4; n++) { ret = -EINVAL; @@ -689,7 +688,7 @@ static int nilfs_ioctl_sync(struct inode *inode, struct file *filp, return ret; if (argp != NULL) { - nilfs = NILFS_SB(inode->i_sb)->s_nilfs; + nilfs = inode->i_sb->s_fs_info; down_read(&nilfs->ns_segctor_sem); cno = nilfs->ns_cno - 1; up_read(&nilfs->ns_segctor_sem); @@ -707,7 +706,7 @@ static int nilfs_ioctl_get_info(struct inode *inode, struct file *filp, void *, size_t, size_t)) { - struct the_nilfs *nilfs = NILFS_SB(inode->i_sb)->s_nilfs; + struct the_nilfs *nilfs = inode->i_sb->s_fs_info; struct nilfs_argv argv; int ret; diff --git a/fs/nilfs2/mdt.h b/fs/nilfs2/mdt.h index b13734bf3521d..ed68563ec708b 100644 --- a/fs/nilfs2/mdt.h +++ b/fs/nilfs2/mdt.h @@ -66,7 +66,7 @@ static inline struct nilfs_mdt_info *NILFS_MDT(const struct inode *inode) static inline struct the_nilfs *NILFS_I_NILFS(struct inode *inode) { - return NILFS_SB(inode->i_sb)->s_nilfs; + return inode->i_sb->s_fs_info; } /* Default GFP flags using highmem */ diff --git a/fs/nilfs2/namei.c b/fs/nilfs2/namei.c index 161791d26458b..546849b3e88f1 100644 --- a/fs/nilfs2/namei.c +++ b/fs/nilfs2/namei.c @@ -482,7 +482,7 @@ static struct dentry *nilfs_get_dentry(struct super_block *sb, u64 cno, if (ino < NILFS_FIRST_INO(sb) && ino != NILFS_ROOT_INO) return ERR_PTR(-ESTALE); - root = nilfs_lookup_root(NILFS_SB(sb)->s_nilfs, cno); + root = nilfs_lookup_root(sb->s_fs_info, cno); if (!root) return ERR_PTR(-ESTALE); diff --git a/fs/nilfs2/nilfs.h b/fs/nilfs2/nilfs.h index eba1aaa7fb7b6..856e8e4e0b74d 100644 --- a/fs/nilfs2/nilfs.h +++ b/fs/nilfs2/nilfs.h @@ -30,7 +30,6 @@ #include #include #include "the_nilfs.h" -#include "sb.h" #include "bmap.h" /* @@ -122,7 +121,7 @@ enum { #define NILFS_SYS_INO_BITS \ ((unsigned int)(1 << NILFS_ROOT_INO) | NILFS_MDT_INO_BITS) -#define NILFS_FIRST_INO(sb) (NILFS_SB(sb)->s_nilfs->ns_first_ino) +#define NILFS_FIRST_INO(sb) (((struct the_nilfs *)sb->s_fs_info)->ns_first_ino) #define NILFS_MDT_INODE(sb, ino) \ ((ino) < NILFS_FIRST_INO(sb) && (NILFS_MDT_INO_BITS & (1 << (ino)))) diff --git a/fs/nilfs2/sb.h b/fs/nilfs2/sb.h deleted file mode 100644 index 44553f42ebac8..0000000000000 --- a/fs/nilfs2/sb.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - * sb.h - NILFS on-memory super block structure. - * - * Copyright (C) 2005-2008 Nippon Telegraph and Telephone Corporation. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - * Written by Ryusuke Konishi - * - */ - -#ifndef _NILFS_SB -#define _NILFS_SB - -#include -#include - -struct the_nilfs; - -/* - * NILFS super-block data in memory - */ -struct nilfs_sb_info { - /* Fundamental members */ - struct super_block *s_super; /* reverse pointer to super_block */ - struct the_nilfs *s_nilfs; -}; - -static inline struct nilfs_sb_info *NILFS_SB(struct super_block *sb) -{ - return sb->s_fs_info; -} - -#endif /* _NILFS_SB */ diff --git a/fs/nilfs2/segment.c b/fs/nilfs2/segment.c index 90e3130303a33..afe4f2183454d 100644 --- a/fs/nilfs2/segment.c +++ b/fs/nilfs2/segment.c @@ -191,7 +191,7 @@ int nilfs_transaction_begin(struct super_block *sb, vfs_check_frozen(sb, SB_FREEZE_WRITE); - nilfs = NILFS_SB(sb)->s_nilfs; + nilfs = sb->s_fs_info; down_read(&nilfs->ns_segctor_sem); if (vacancy_check && nilfs_near_disk_full(nilfs)) { up_read(&nilfs->ns_segctor_sem); @@ -222,7 +222,7 @@ int nilfs_transaction_begin(struct super_block *sb, int nilfs_transaction_commit(struct super_block *sb) { struct nilfs_transaction_info *ti = current->journal_info; - struct the_nilfs *nilfs = NILFS_SB(sb)->s_nilfs; + struct the_nilfs *nilfs = sb->s_fs_info; int err = 0; BUG_ON(ti == NULL || ti->ti_magic != NILFS_TI_MAGIC); @@ -252,13 +252,14 @@ int nilfs_transaction_commit(struct super_block *sb) void nilfs_transaction_abort(struct super_block *sb) { struct nilfs_transaction_info *ti = current->journal_info; + struct the_nilfs *nilfs = sb->s_fs_info; BUG_ON(ti == NULL || ti->ti_magic != NILFS_TI_MAGIC); if (ti->ti_count > 0) { ti->ti_count--; return; } - up_read(&NILFS_SB(sb)->s_nilfs->ns_segctor_sem); + up_read(&nilfs->ns_segctor_sem); current->journal_info = ti->ti_save; if (ti->ti_flags & NILFS_TI_DYNAMIC_ALLOC) @@ -267,7 +268,7 @@ void nilfs_transaction_abort(struct super_block *sb) void nilfs_relax_pressure_in_lock(struct super_block *sb) { - struct the_nilfs *nilfs = NILFS_SB(sb)->s_nilfs; + struct the_nilfs *nilfs = sb->s_fs_info; struct nilfs_sc_info *sci = nilfs->ns_writer; if (!sci || !sci->sc_flush_request) @@ -293,7 +294,7 @@ static void nilfs_transaction_lock(struct super_block *sb, int gcflag) { struct nilfs_transaction_info *cur_ti = current->journal_info; - struct the_nilfs *nilfs = NILFS_SB(sb)->s_nilfs; + struct the_nilfs *nilfs = sb->s_fs_info; struct nilfs_sc_info *sci = nilfs->ns_writer; WARN_ON(cur_ti); @@ -321,7 +322,7 @@ static void nilfs_transaction_lock(struct super_block *sb, static void nilfs_transaction_unlock(struct super_block *sb) { struct nilfs_transaction_info *ti = current->journal_info; - struct the_nilfs *nilfs = NILFS_SB(sb)->s_nilfs; + struct the_nilfs *nilfs = sb->s_fs_info; BUG_ON(ti == NULL || ti->ti_magic != NILFS_TI_MAGIC); BUG_ON(ti->ti_count > 0); @@ -770,7 +771,7 @@ static int nilfs_segctor_clean(struct nilfs_sc_info *sci) static int nilfs_segctor_confirm(struct nilfs_sc_info *sci) { - struct the_nilfs *nilfs = NILFS_SB(sci->sc_super)->s_nilfs; + struct the_nilfs *nilfs = sci->sc_super->s_fs_info; int ret = 0; if (nilfs_test_metadata_dirty(nilfs, sci->sc_root)) @@ -786,7 +787,7 @@ static int nilfs_segctor_confirm(struct nilfs_sc_info *sci) static void nilfs_segctor_clear_metadata_dirty(struct nilfs_sc_info *sci) { - struct the_nilfs *nilfs = NILFS_SB(sci->sc_super)->s_nilfs; + struct the_nilfs *nilfs = sci->sc_super->s_fs_info; nilfs_mdt_clear_dirty(sci->sc_root->ifile); nilfs_mdt_clear_dirty(nilfs->ns_cpfile); @@ -796,7 +797,7 @@ static void nilfs_segctor_clear_metadata_dirty(struct nilfs_sc_info *sci) static int nilfs_segctor_create_checkpoint(struct nilfs_sc_info *sci) { - struct the_nilfs *nilfs = NILFS_SB(sci->sc_super)->s_nilfs; + struct the_nilfs *nilfs = sci->sc_super->s_fs_info; struct buffer_head *bh_cp; struct nilfs_checkpoint *raw_cp; int err; @@ -820,7 +821,7 @@ static int nilfs_segctor_create_checkpoint(struct nilfs_sc_info *sci) static int nilfs_segctor_fill_in_checkpoint(struct nilfs_sc_info *sci) { - struct the_nilfs *nilfs = NILFS_SB(sci->sc_super)->s_nilfs; + struct the_nilfs *nilfs = sci->sc_super->s_fs_info; struct buffer_head *bh_cp; struct nilfs_checkpoint *raw_cp; int err; @@ -1044,7 +1045,7 @@ static int nilfs_segctor_scan_file_dsync(struct nilfs_sc_info *sci, static int nilfs_segctor_collect_blocks(struct nilfs_sc_info *sci, int mode) { - struct the_nilfs *nilfs = NILFS_SB(sci->sc_super)->s_nilfs; + struct the_nilfs *nilfs = sci->sc_super->s_fs_info; struct list_head *head; struct nilfs_inode_info *ii; size_t ndone; @@ -1853,7 +1854,7 @@ static void nilfs_segctor_complete_write(struct nilfs_sc_info *sci) { struct nilfs_segment_buffer *segbuf; struct page *bd_page = NULL, *fs_page = NULL; - struct the_nilfs *nilfs = NILFS_SB(sci->sc_super)->s_nilfs; + struct the_nilfs *nilfs = sci->sc_super->s_fs_info; int update_sr = false; list_for_each_entry(segbuf, &sci->sc_write_logs, sb_list) { @@ -2024,7 +2025,7 @@ static void nilfs_segctor_drop_written_files(struct nilfs_sc_info *sci, */ static int nilfs_segctor_do_construct(struct nilfs_sc_info *sci, int mode) { - struct the_nilfs *nilfs = NILFS_SB(sci->sc_super)->s_nilfs; + struct the_nilfs *nilfs = sci->sc_super->s_fs_info; struct page *failed_page; int err; @@ -2162,7 +2163,7 @@ static void nilfs_segctor_do_flush(struct nilfs_sc_info *sci, int bn) */ void nilfs_flush_segment(struct super_block *sb, ino_t ino) { - struct the_nilfs *nilfs = NILFS_SB(sb)->s_nilfs; + struct the_nilfs *nilfs = sb->s_fs_info; struct nilfs_sc_info *sci = nilfs->ns_writer; if (!sci || nilfs_doing_construction()) @@ -2252,7 +2253,7 @@ static void nilfs_segctor_wakeup(struct nilfs_sc_info *sci, int err) */ int nilfs_construct_segment(struct super_block *sb) { - struct the_nilfs *nilfs = NILFS_SB(sb)->s_nilfs; + struct the_nilfs *nilfs = sb->s_fs_info; struct nilfs_sc_info *sci = nilfs->ns_writer; struct nilfs_transaction_info *ti; int err; @@ -2290,7 +2291,7 @@ int nilfs_construct_segment(struct super_block *sb) int nilfs_construct_dsync_segment(struct super_block *sb, struct inode *inode, loff_t start, loff_t end) { - struct the_nilfs *nilfs = NILFS_SB(sb)->s_nilfs; + struct the_nilfs *nilfs = sb->s_fs_info; struct nilfs_sc_info *sci = nilfs->ns_writer; struct nilfs_inode_info *ii; struct nilfs_transaction_info ti; @@ -2381,7 +2382,7 @@ static void nilfs_segctor_notify(struct nilfs_sc_info *sci, int mode, int err) */ static int nilfs_segctor_construct(struct nilfs_sc_info *sci, int mode) { - struct the_nilfs *nilfs = NILFS_SB(sci->sc_super)->s_nilfs; + struct the_nilfs *nilfs = sci->sc_super->s_fs_info; struct nilfs_super_block **sbp; int err = 0; @@ -2436,7 +2437,7 @@ nilfs_remove_written_gcinodes(struct the_nilfs *nilfs, struct list_head *head) int nilfs_clean_segments(struct super_block *sb, struct nilfs_argv *argv, void **kbufs) { - struct the_nilfs *nilfs = NILFS_SB(sb)->s_nilfs; + struct the_nilfs *nilfs = sb->s_fs_info; struct nilfs_sc_info *sci = nilfs->ns_writer; struct nilfs_transaction_info ti; int err; @@ -2552,7 +2553,7 @@ static int nilfs_segctor_flush_mode(struct nilfs_sc_info *sci) static int nilfs_segctor_thread(void *arg) { struct nilfs_sc_info *sci = (struct nilfs_sc_info *)arg; - struct the_nilfs *nilfs = NILFS_SB(sci->sc_super)->s_nilfs; + struct the_nilfs *nilfs = sci->sc_super->s_fs_info; int timeout = 0; sci->sc_timer.data = (unsigned long)current; @@ -2666,7 +2667,7 @@ static void nilfs_segctor_kill_thread(struct nilfs_sc_info *sci) static struct nilfs_sc_info *nilfs_segctor_new(struct super_block *sb, struct nilfs_root *root) { - struct the_nilfs *nilfs = NILFS_SB(sb)->s_nilfs; + struct the_nilfs *nilfs = sb->s_fs_info; struct nilfs_sc_info *sci; sci = kzalloc(sizeof(*sci), GFP_KERNEL); @@ -2726,7 +2727,7 @@ static void nilfs_segctor_write_out(struct nilfs_sc_info *sci) */ static void nilfs_segctor_destroy(struct nilfs_sc_info *sci) { - struct the_nilfs *nilfs = NILFS_SB(sci->sc_super)->s_nilfs; + struct the_nilfs *nilfs = sci->sc_super->s_fs_info; int flag; up_write(&nilfs->ns_segctor_sem); @@ -2774,7 +2775,7 @@ static void nilfs_segctor_destroy(struct nilfs_sc_info *sci) */ int nilfs_attach_log_writer(struct super_block *sb, struct nilfs_root *root) { - struct the_nilfs *nilfs = NILFS_SB(sb)->s_nilfs; + struct the_nilfs *nilfs = sb->s_fs_info; int err; if (nilfs->ns_writer) { @@ -2807,7 +2808,7 @@ int nilfs_attach_log_writer(struct super_block *sb, struct nilfs_root *root) */ void nilfs_detach_log_writer(struct super_block *sb) { - struct the_nilfs *nilfs = NILFS_SB(sb)->s_nilfs; + struct the_nilfs *nilfs = sb->s_fs_info; LIST_HEAD(garbage_list); down_write(&nilfs->ns_segctor_sem); diff --git a/fs/nilfs2/segment.h b/fs/nilfs2/segment.h index e01998e33b316..6c02a86745fb1 100644 --- a/fs/nilfs2/segment.h +++ b/fs/nilfs2/segment.h @@ -27,7 +27,7 @@ #include #include #include -#include "sb.h" +#include "nilfs.h" struct nilfs_root; diff --git a/fs/nilfs2/super.c b/fs/nilfs2/super.c index a8cbd695441e4..062cca065195e 100644 --- a/fs/nilfs2/super.c +++ b/fs/nilfs2/super.c @@ -76,7 +76,7 @@ static int nilfs_remount(struct super_block *sb, int *flags, char *data); static void nilfs_set_error(struct super_block *sb) { - struct the_nilfs *nilfs = NILFS_SB(sb)->s_nilfs; + struct the_nilfs *nilfs = sb->s_fs_info; struct nilfs_super_block **sbp; down_write(&nilfs->ns_sem); @@ -108,7 +108,7 @@ static void nilfs_set_error(struct super_block *sb) void nilfs_error(struct super_block *sb, const char *function, const char *fmt, ...) { - struct the_nilfs *nilfs = NILFS_SB(sb)->s_nilfs; + struct the_nilfs *nilfs = sb->s_fs_info; struct va_format vaf; va_list args; @@ -190,7 +190,7 @@ void nilfs_destroy_inode(struct inode *inode) static int nilfs_sync_super(struct super_block *sb, int flag) { - struct the_nilfs *nilfs = NILFS_SB(sb)->s_nilfs; + struct the_nilfs *nilfs = sb->s_fs_info; int err; retry: @@ -265,7 +265,7 @@ void nilfs_set_log_cursor(struct nilfs_super_block *sbp, struct nilfs_super_block **nilfs_prepare_super(struct super_block *sb, int flip) { - struct the_nilfs *nilfs = NILFS_SB(sb)->s_nilfs; + struct the_nilfs *nilfs = sb->s_fs_info; struct nilfs_super_block **sbp = nilfs->ns_sbp; /* nilfs->ns_sem must be locked by the caller. */ @@ -291,7 +291,7 @@ struct nilfs_super_block **nilfs_prepare_super(struct super_block *sb, int nilfs_commit_super(struct super_block *sb, int flag) { - struct the_nilfs *nilfs = NILFS_SB(sb)->s_nilfs; + struct the_nilfs *nilfs = sb->s_fs_info; struct nilfs_super_block **sbp = nilfs->ns_sbp; time_t t; @@ -324,7 +324,7 @@ int nilfs_commit_super(struct super_block *sb, int flag) */ int nilfs_cleanup_super(struct super_block *sb) { - struct the_nilfs *nilfs = NILFS_SB(sb)->s_nilfs; + struct the_nilfs *nilfs = sb->s_fs_info; struct nilfs_super_block **sbp; int flag = NILFS_SB_COMMIT; int ret = -EIO; @@ -349,8 +349,7 @@ int nilfs_cleanup_super(struct super_block *sb) static void nilfs_put_super(struct super_block *sb) { - struct nilfs_sb_info *sbi = NILFS_SB(sb); - struct the_nilfs *nilfs = sbi->s_nilfs; + struct the_nilfs *nilfs = sb->s_fs_info; nilfs_detach_log_writer(sb); @@ -365,14 +364,12 @@ static void nilfs_put_super(struct super_block *sb) iput(nilfs->ns_dat); destroy_nilfs(nilfs); - sbi->s_super = NULL; sb->s_fs_info = NULL; - kfree(sbi); } static int nilfs_sync_fs(struct super_block *sb, int wait) { - struct the_nilfs *nilfs = NILFS_SB(sb)->s_nilfs; + struct the_nilfs *nilfs = sb->s_fs_info; struct nilfs_super_block **sbp; int err = 0; @@ -396,7 +393,7 @@ static int nilfs_sync_fs(struct super_block *sb, int wait) int nilfs_attach_checkpoint(struct super_block *sb, __u64 cno, int curr_mnt, struct nilfs_root **rootp) { - struct the_nilfs *nilfs = NILFS_SB(sb)->s_nilfs; + struct the_nilfs *nilfs = sb->s_fs_info; struct nilfs_root *root; struct nilfs_checkpoint *raw_cp; struct buffer_head *bh_cp; @@ -449,7 +446,7 @@ int nilfs_attach_checkpoint(struct super_block *sb, __u64 cno, int curr_mnt, static int nilfs_freeze(struct super_block *sb) { - struct the_nilfs *nilfs = NILFS_SB(sb)->s_nilfs; + struct the_nilfs *nilfs = sb->s_fs_info; int err; if (sb->s_flags & MS_RDONLY) @@ -464,7 +461,7 @@ static int nilfs_freeze(struct super_block *sb) static int nilfs_unfreeze(struct super_block *sb) { - struct the_nilfs *nilfs = NILFS_SB(sb)->s_nilfs; + struct the_nilfs *nilfs = sb->s_fs_info; if (sb->s_flags & MS_RDONLY) return 0; @@ -527,7 +524,7 @@ static int nilfs_statfs(struct dentry *dentry, struct kstatfs *buf) static int nilfs_show_options(struct seq_file *seq, struct vfsmount *vfs) { struct super_block *sb = vfs->mnt_sb; - struct the_nilfs *nilfs = NILFS_SB(sb)->s_nilfs; + struct the_nilfs *nilfs = sb->s_fs_info; struct nilfs_root *root = NILFS_I(vfs->mnt_root->d_inode)->i_root; if (!nilfs_test_opt(nilfs, BARRIER)) @@ -591,7 +588,7 @@ static match_table_t tokens = { static int parse_options(char *options, struct super_block *sb, int is_remount) { - struct the_nilfs *nilfs = NILFS_SB(sb)->s_nilfs; + struct the_nilfs *nilfs = sb->s_fs_info; char *p; substring_t args[MAX_OPT_ARGS]; @@ -660,7 +657,7 @@ static inline void nilfs_set_default_options(struct super_block *sb, struct nilfs_super_block *sbp) { - struct the_nilfs *nilfs = NILFS_SB(sb)->s_nilfs; + struct the_nilfs *nilfs = sb->s_fs_info; nilfs->ns_mount_opt = NILFS_MOUNT_ERRORS_RO | NILFS_MOUNT_BARRIER; @@ -668,7 +665,7 @@ nilfs_set_default_options(struct super_block *sb, static int nilfs_setup_super(struct super_block *sb, int is_mount) { - struct the_nilfs *nilfs = NILFS_SB(sb)->s_nilfs; + struct the_nilfs *nilfs = sb->s_fs_info; struct nilfs_super_block **sbp; int max_mnt_count; int mnt_count; @@ -726,7 +723,7 @@ int nilfs_store_magic_and_option(struct super_block *sb, struct nilfs_super_block *sbp, char *data) { - struct the_nilfs *nilfs = NILFS_SB(sb)->s_nilfs; + struct the_nilfs *nilfs = sb->s_fs_info; sb->s_magic = le16_to_cpu(sbp->s_magic); @@ -821,7 +818,7 @@ static int nilfs_get_root_dentry(struct super_block *sb, static int nilfs_attach_snapshot(struct super_block *s, __u64 cno, struct dentry **root_dentry) { - struct the_nilfs *nilfs = NILFS_SB(s)->s_nilfs; + struct the_nilfs *nilfs = s->s_fs_info; struct nilfs_root *root; int ret; @@ -873,7 +870,7 @@ static int nilfs_try_to_shrink_tree(struct dentry *root_dentry) int nilfs_checkpoint_is_mounted(struct super_block *sb, __u64 cno) { - struct the_nilfs *nilfs = NILFS_SB(sb)->s_nilfs; + struct the_nilfs *nilfs = sb->s_fs_info; struct nilfs_root *root; struct inode *inode; struct dentry *dentry; @@ -886,7 +883,7 @@ int nilfs_checkpoint_is_mounted(struct super_block *sb, __u64 cno) return true; /* protect recent checkpoints */ ret = false; - root = nilfs_lookup_root(NILFS_SB(sb)->s_nilfs, cno); + root = nilfs_lookup_root(nilfs, cno); if (root) { inode = nilfs_ilookup(sb, root, NILFS_ROOT_INO); if (inode) { @@ -916,25 +913,16 @@ static int nilfs_fill_super(struct super_block *sb, void *data, int silent) { struct the_nilfs *nilfs; - struct nilfs_sb_info *sbi; struct nilfs_root *fsroot; struct backing_dev_info *bdi; __u64 cno; int err; - sbi = kzalloc(sizeof(*sbi), GFP_KERNEL); - if (!sbi) + nilfs = alloc_nilfs(sb->s_bdev); + if (!nilfs) return -ENOMEM; - sb->s_fs_info = sbi; - sbi->s_super = sb; - - nilfs = alloc_nilfs(sb->s_bdev); - if (!nilfs) { - err = -ENOMEM; - goto failed_sbi; - } - sbi->s_nilfs = nilfs; + sb->s_fs_info = nilfs; err = init_nilfs(nilfs, sb, (char *)data); if (err) @@ -993,16 +981,12 @@ nilfs_fill_super(struct super_block *sb, void *data, int silent) failed_nilfs: destroy_nilfs(nilfs); - - failed_sbi: - sb->s_fs_info = NULL; - kfree(sbi); return err; } static int nilfs_remount(struct super_block *sb, int *flags, char *data) { - struct the_nilfs *nilfs = NILFS_SB(sb)->s_nilfs; + struct the_nilfs *nilfs = sb->s_fs_info; unsigned long old_sb_flags; unsigned long old_mount_opt; int err; @@ -1083,7 +1067,6 @@ static int nilfs_remount(struct super_block *sb, int *flags, char *data) struct nilfs_super_data { struct block_device *bdev; - struct nilfs_sb_info *sbi; __u64 cno; int flags; }; diff --git a/fs/nilfs2/the_nilfs.h b/fs/nilfs2/the_nilfs.h index 793bd272f9e0b..f4968145c2a3e 100644 --- a/fs/nilfs2/the_nilfs.h +++ b/fs/nilfs2/the_nilfs.h @@ -31,7 +31,6 @@ #include #include #include -#include "sb.h" struct nilfs_sc_info; -- GitLab From 86fa8af69d8e90b7b40b8dab84d168527143ae20 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Fri, 4 Mar 2011 12:59:54 +0000 Subject: [PATCH 0356/2822] xfs: clean up the xfs_alloc_compute_aligned calling convention Pass a xfs_alloc_arg structure to xfs_alloc_compute_aligned and derive the alignment and minlen paramters from it. This cleans up the existing callers, and we'll need even more information from the xfs_alloc_arg in subsequent patches. Based on a patch from Dave Chinner. Signed-off-by: Christoph Hellwig Reviewed-by: Dave Chinner Signed-off-by: Alex Elder --- fs/xfs/xfs_alloc.c | 29 +++++++++++++---------------- 1 file changed, 13 insertions(+), 16 deletions(-) diff --git a/fs/xfs/xfs_alloc.c b/fs/xfs/xfs_alloc.c index f3227984a9bf8..b5af10713dca6 100644 --- a/fs/xfs/xfs_alloc.c +++ b/fs/xfs/xfs_alloc.c @@ -147,10 +147,9 @@ xfs_alloc_get_rec( */ STATIC void xfs_alloc_compute_aligned( + xfs_alloc_arg_t *args, /* allocation argument structure */ xfs_agblock_t foundbno, /* starting block in found extent */ xfs_extlen_t foundlen, /* length in found extent */ - xfs_extlen_t alignment, /* alignment for allocation */ - xfs_extlen_t minlen, /* minimum length for allocation */ xfs_agblock_t *resbno, /* result block number */ xfs_extlen_t *reslen) /* result length */ { @@ -158,8 +157,8 @@ xfs_alloc_compute_aligned( xfs_extlen_t diff; xfs_extlen_t len; - if (alignment > 1 && foundlen >= minlen) { - bno = roundup(foundbno, alignment); + if (args->alignment > 1 && foundlen >= args->minlen) { + bno = roundup(foundbno, args->alignment); diff = bno - foundbno; len = diff >= foundlen ? 0 : foundlen - diff; } else { @@ -693,8 +692,7 @@ xfs_alloc_find_best_extent( if (error) goto error0; XFS_WANT_CORRUPTED_GOTO(i == 1, error0); - xfs_alloc_compute_aligned(*sbno, *slen, args->alignment, - args->minlen, &bno, slena); + xfs_alloc_compute_aligned(args, *sbno, *slen, &bno, slena); /* * The good extent is closer than this one. @@ -866,8 +864,8 @@ xfs_alloc_ag_vextent_near( if ((error = xfs_alloc_get_rec(cnt_cur, <bno, <len, &i))) goto error0; XFS_WANT_CORRUPTED_GOTO(i == 1, error0); - xfs_alloc_compute_aligned(ltbno, ltlen, args->alignment, - args->minlen, <bnoa, <lena); + xfs_alloc_compute_aligned(args, ltbno, ltlen, + <bnoa, <lena); if (ltlena < args->minlen) continue; args->len = XFS_EXTLEN_MIN(ltlena, args->maxlen); @@ -987,8 +985,8 @@ xfs_alloc_ag_vextent_near( if ((error = xfs_alloc_get_rec(bno_cur_lt, <bno, <len, &i))) goto error0; XFS_WANT_CORRUPTED_GOTO(i == 1, error0); - xfs_alloc_compute_aligned(ltbno, ltlen, args->alignment, - args->minlen, <bnoa, <lena); + xfs_alloc_compute_aligned(args, ltbno, ltlen, + <bnoa, <lena); if (ltlena >= args->minlen) break; if ((error = xfs_btree_decrement(bno_cur_lt, 0, &i))) @@ -1003,8 +1001,8 @@ xfs_alloc_ag_vextent_near( if ((error = xfs_alloc_get_rec(bno_cur_gt, >bno, >len, &i))) goto error0; XFS_WANT_CORRUPTED_GOTO(i == 1, error0); - xfs_alloc_compute_aligned(gtbno, gtlen, args->alignment, - args->minlen, >bnoa, >lena); + xfs_alloc_compute_aligned(args, gtbno, gtlen, + >bnoa, >lena); if (gtlena >= args->minlen) break; if ((error = xfs_btree_increment(bno_cur_gt, 0, &i))) @@ -1183,8 +1181,7 @@ xfs_alloc_ag_vextent_size( * once aligned; if not, we search left for something better. * This can't happen in the second case above. */ - xfs_alloc_compute_aligned(fbno, flen, args->alignment, args->minlen, - &rbno, &rlen); + xfs_alloc_compute_aligned(args, fbno, flen, &rbno, &rlen); rlen = XFS_EXTLEN_MIN(args->maxlen, rlen); XFS_WANT_CORRUPTED_GOTO(rlen == 0 || (rlen <= flen && rbno + rlen <= fbno + flen), error0); @@ -1209,8 +1206,8 @@ xfs_alloc_ag_vextent_size( XFS_WANT_CORRUPTED_GOTO(i == 1, error0); if (flen < bestrlen) break; - xfs_alloc_compute_aligned(fbno, flen, args->alignment, - args->minlen, &rbno, &rlen); + xfs_alloc_compute_aligned(args, fbno, flen, + &rbno, &rlen); rlen = XFS_EXTLEN_MIN(args->maxlen, rlen); XFS_WANT_CORRUPTED_GOTO(rlen == 0 || (rlen <= flen && rbno + rlen <= fbno + flen), -- GitLab From ecb6928fcf969b302929f109e175981df1dba697 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Fri, 4 Mar 2011 12:59:55 +0000 Subject: [PATCH 0357/2822] xfs: factor agf counter updates into a helper Updating the AGF and transactions counters is duplicated between allocating and freeing extents. Factor the code into a common helper. Signed-off-by: Christoph Hellwig Reviewed-by: Dave Chinner Signed-off-by: Alex Elder --- fs/xfs/xfs_alloc.c | 129 ++++++++++++++++++++++++--------------------- 1 file changed, 68 insertions(+), 61 deletions(-) diff --git a/fs/xfs/xfs_alloc.c b/fs/xfs/xfs_alloc.c index b5af10713dca6..4bc3c649aee4b 100644 --- a/fs/xfs/xfs_alloc.c +++ b/fs/xfs/xfs_alloc.c @@ -463,6 +463,27 @@ xfs_alloc_read_agfl( return 0; } +STATIC int +xfs_alloc_update_counters( + struct xfs_trans *tp, + struct xfs_perag *pag, + struct xfs_buf *agbp, + long len) +{ + struct xfs_agf *agf = XFS_BUF_TO_AGF(agbp); + + pag->pagf_freeblks += len; + be32_add_cpu(&agf->agf_freeblks, len); + + xfs_trans_agblocks_delta(tp, len); + if (unlikely(be32_to_cpu(agf->agf_freeblks) > + be32_to_cpu(agf->agf_length))) + return EFSCORRUPTED; + + xfs_alloc_log_agf(tp, agbp, XFS_AGF_FREEBLKS); + return 0; +} + /* * Allocation group level functions. */ @@ -504,49 +525,44 @@ xfs_alloc_ag_vextent( ASSERT(0); /* NOTREACHED */ } - if (error) + + if (error || args->agbno == NULLAGBLOCK) return error; - /* - * If the allocation worked, need to change the agf structure - * (and log it), and the superblock. - */ - if (args->agbno != NULLAGBLOCK) { - xfs_agf_t *agf; /* allocation group freelist header */ - long slen = (long)args->len; - ASSERT(args->len >= args->minlen && args->len <= args->maxlen); - ASSERT(!(args->wasfromfl) || !args->isfl); - ASSERT(args->agbno % args->alignment == 0); - if (!(args->wasfromfl)) { - - agf = XFS_BUF_TO_AGF(args->agbp); - be32_add_cpu(&agf->agf_freeblks, -(args->len)); - xfs_trans_agblocks_delta(args->tp, - -((long)(args->len))); - args->pag->pagf_freeblks -= args->len; - ASSERT(be32_to_cpu(agf->agf_freeblks) <= - be32_to_cpu(agf->agf_length)); - xfs_alloc_log_agf(args->tp, args->agbp, - XFS_AGF_FREEBLKS); - /* - * Search the busylist for these blocks and mark the - * transaction as synchronous if blocks are found. This - * avoids the need to block due to a synchronous log - * force to ensure correct ordering as the synchronous - * transaction will guarantee that for us. - */ - if (xfs_alloc_busy_search(args->mp, args->agno, - args->agbno, args->len)) - xfs_trans_set_sync(args->tp); - } - if (!args->isfl) - xfs_trans_mod_sb(args->tp, - args->wasdel ? XFS_TRANS_SB_RES_FDBLOCKS : - XFS_TRANS_SB_FDBLOCKS, -slen); - XFS_STATS_INC(xs_allocx); - XFS_STATS_ADD(xs_allocb, args->len); + ASSERT(args->len >= args->minlen); + ASSERT(args->len <= args->maxlen); + ASSERT(!args->wasfromfl || !args->isfl); + ASSERT(args->agbno % args->alignment == 0); + + if (!args->wasfromfl) { + error = xfs_alloc_update_counters(args->tp, args->pag, + args->agbp, + -((long)(args->len))); + if (error) + return error; + + /* + * Search the busylist for these blocks and mark the + * transaction as synchronous if blocks are found. This + * avoids the need to block due to a synchronous log + * force to ensure correct ordering as the synchronous + * transaction will guarantee that for us. + */ + if (xfs_alloc_busy_search(args->mp, args->agno, + args->agbno, args->len)) + xfs_trans_set_sync(args->tp); } - return 0; + + if (!args->isfl) { + xfs_trans_mod_sb(args->tp, args->wasdel ? + XFS_TRANS_SB_RES_FDBLOCKS : + XFS_TRANS_SB_FDBLOCKS, + -((long)(args->len))); + } + + XFS_STATS_INC(xs_allocx); + XFS_STATS_ADD(xs_allocb, args->len); + return error; } /* @@ -1385,6 +1401,7 @@ xfs_free_ag_extent( xfs_mount_t *mp; /* mount point struct for filesystem */ xfs_agblock_t nbno; /* new starting block of freespace */ xfs_extlen_t nlen; /* new length of freespace */ + xfs_perag_t *pag; /* per allocation group data */ mp = tp->t_mountp; /* @@ -1583,30 +1600,20 @@ xfs_free_ag_extent( XFS_WANT_CORRUPTED_GOTO(i == 1, error0); xfs_btree_del_cursor(cnt_cur, XFS_BTREE_NOERROR); cnt_cur = NULL; + /* * Update the freespace totals in the ag and superblock. */ - { - xfs_agf_t *agf; - xfs_perag_t *pag; /* per allocation group data */ - - pag = xfs_perag_get(mp, agno); - pag->pagf_freeblks += len; - xfs_perag_put(pag); - - agf = XFS_BUF_TO_AGF(agbp); - be32_add_cpu(&agf->agf_freeblks, len); - xfs_trans_agblocks_delta(tp, len); - XFS_WANT_CORRUPTED_GOTO( - be32_to_cpu(agf->agf_freeblks) <= - be32_to_cpu(agf->agf_length), - error0); - xfs_alloc_log_agf(tp, agbp, XFS_AGF_FREEBLKS); - if (!isfl) - xfs_trans_mod_sb(tp, XFS_TRANS_SB_FDBLOCKS, (long)len); - XFS_STATS_INC(xs_freex); - XFS_STATS_ADD(xs_freeb, len); - } + pag = xfs_perag_get(mp, agno); + error = xfs_alloc_update_counters(tp, pag, agbp, len); + xfs_perag_put(pag); + if (error) + goto error0; + + if (!isfl) + xfs_trans_mod_sb(tp, XFS_TRANS_SB_FDBLOCKS, (long)len); + XFS_STATS_INC(xs_freex); + XFS_STATS_ADD(xs_freeb, len); trace_xfs_free_extent(mp, agno, bno, len, isfl, haveleft, haveright); -- GitLab From 4a5838ad9d2d4f7354a310982483f4c76aa0abeb Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Tue, 1 Mar 2011 09:35:29 +0100 Subject: [PATCH 0358/2822] kbuild: Add extra gcc checks Add a 'W=1' Makefile switch which adds additional checking per build object. The idea behind this option is targeted at developers who, in the process of writing their code, want to do the occasional make W=1 [target.o] and let gcc do more extensive code checking for them. Then, they could eyeball the output for valid gcc warnings about various bugs/discrepancies which are not reported during the normal build process. For more background information and a use case, read through this thread: http://marc.info/?l=kernel-janitors&m=129802065918147&w=2 Cc: Michal Marek Cc: linux-kbuild@vger.kernel.org Acked-by: Sam Ravnborg Acked-by: Ingo Molnar Signed-off-by: Borislav Petkov Signed-off-by: Michal Marek --- Documentation/kbuild/kbuild.txt | 5 +++++ Makefile | 5 +++++ scripts/Makefile.build | 35 ++++++++++++++++++++++++++++++++- 3 files changed, 44 insertions(+), 1 deletion(-) diff --git a/Documentation/kbuild/kbuild.txt b/Documentation/kbuild/kbuild.txt index 4a990317b84a7..376538c984cef 100644 --- a/Documentation/kbuild/kbuild.txt +++ b/Documentation/kbuild/kbuild.txt @@ -196,3 +196,8 @@ to be included in the databases, separated by blank space. E.g.: To get all available archs you can also specify all. E.g.: $ make ALLSOURCE_ARCHS=all tags + +KBUILD_ENABLE_EXTRA_GCC_CHECKS +-------------------------------------------------- +If enabled over the make command line with "W=1", it turns on additional +gcc -W... options for more extensive build-time checking. diff --git a/Makefile b/Makefile index abb49bf8596ea..2b1e37da2bb59 100644 --- a/Makefile +++ b/Makefile @@ -102,6 +102,10 @@ ifeq ("$(origin O)", "command line") KBUILD_OUTPUT := $(O) endif +ifeq ("$(origin W)", "command line") + export KBUILD_ENABLE_EXTRA_GCC_CHECKS := 1 +endif + # That's our default target when none is given on the command line PHONY := _all _all: @@ -1262,6 +1266,7 @@ help: @echo ' make O=dir [targets] Locate all output files in "dir", including .config' @echo ' make C=1 [targets] Check all c source with $$CHECK (sparse by default)' @echo ' make C=2 [targets] Force check of all c source with $$CHECK' + @echo ' make W=1 [targets] Enable extra gcc checks' @echo '' @echo 'Execute "make" or "make all" to build all targets marked with [*] ' @echo 'For further info see the ./README file' diff --git a/scripts/Makefile.build b/scripts/Makefile.build index 4eb99ab340537..d5f925abe4d29 100644 --- a/scripts/Makefile.build +++ b/scripts/Makefile.build @@ -49,6 +49,40 @@ ifeq ($(KBUILD_NOPEDANTIC),) $(error CFLAGS was changed in "$(kbuild-file)". Fix it to use EXTRA_CFLAGS) endif endif + +# +# make W=1 settings +# +# $(call cc-option... ) handles gcc -W.. options which +# are not supported by all versions of the compiler +ifdef KBUILD_ENABLE_EXTRA_GCC_CHECKS +KBUILD_EXTRA_WARNINGS := -Wextra +KBUILD_EXTRA_WARNINGS += -Wunused -Wno-unused-parameter +KBUILD_EXTRA_WARNINGS += -Waggregate-return +KBUILD_EXTRA_WARNINGS += -Wbad-function-cast +KBUILD_EXTRA_WARNINGS += -Wcast-qual +KBUILD_EXTRA_WARNINGS += -Wcast-align +KBUILD_EXTRA_WARNINGS += -Wconversion +KBUILD_EXTRA_WARNINGS += -Wdisabled-optimization +KBUILD_EXTRA_WARNINGS += -Wlogical-op +KBUILD_EXTRA_WARNINGS += -Wmissing-declarations +KBUILD_EXTRA_WARNINGS += -Wmissing-format-attribute +KBUILD_EXTRA_WARNINGS += $(call cc-option, -Wmissing-include-dirs,) +KBUILD_EXTRA_WARNINGS += -Wmissing-prototypes +KBUILD_EXTRA_WARNINGS += -Wnested-externs +KBUILD_EXTRA_WARNINGS += -Wold-style-definition +KBUILD_EXTRA_WARNINGS += $(call cc-option, -Woverlength-strings,) +KBUILD_EXTRA_WARNINGS += -Wpacked +KBUILD_EXTRA_WARNINGS += -Wpacked-bitfield-compat +KBUILD_EXTRA_WARNINGS += -Wpadded +KBUILD_EXTRA_WARNINGS += -Wpointer-arith +KBUILD_EXTRA_WARNINGS += -Wredundant-decls +KBUILD_EXTRA_WARNINGS += -Wshadow +KBUILD_EXTRA_WARNINGS += -Wswitch-default +KBUILD_EXTRA_WARNINGS += $(call cc-option, -Wvla,) +KBUILD_CFLAGS += $(KBUILD_EXTRA_WARNINGS) +endif + include scripts/Makefile.lib ifdef host-progs @@ -403,7 +437,6 @@ ifneq ($(cmd_files),) include $(cmd_files) endif - # Declare the contents of the .PHONY variable as phony. We keep that # information in a variable se we can use it in if_changed and friends. -- GitLab From 9a17f40048be305749f53278c857bf52939081f3 Mon Sep 17 00:00:00 2001 From: Zdenek Kaspar Date: Sun, 30 Jan 2011 12:18:51 +0100 Subject: [PATCH 0359/2822] kbuild: Add make tarxz-pkg build option Signed-off-by: Zdenek Kaspar Signed-off-by: Michal Marek --- scripts/package/Makefile | 5 ++++- scripts/package/buildtar | 4 ++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/scripts/package/Makefile b/scripts/package/Makefile index d0b931b994fcc..a834b935f5363 100644 --- a/scripts/package/Makefile +++ b/scripts/package/Makefile @@ -127,7 +127,8 @@ rm -r $(perf-tar); \ $(if $(findstring tar-src,$@),, \ $(if $(findstring bz2,$@),bzip2, \ $(if $(findstring gz,$@),gzip, \ -$(error unknown target $@))) \ +$(if $(findstring xz,$@),xz, \ +$(error unknown target $@)))) \ -f -9 $(perf-tar).tar) perf-%pkg: FORCE @@ -142,7 +143,9 @@ help: FORCE @echo ' tar-pkg - Build the kernel as an uncompressed tarball' @echo ' targz-pkg - Build the kernel as a gzip compressed tarball' @echo ' tarbz2-pkg - Build the kernel as a bzip2 compressed tarball' + @echo ' tarxz-pkg - Build the kernel as a xz compressed tarball' @echo ' perf-tar-src-pkg - Build $(perf-tar).tar source tarball' @echo ' perf-targz-src-pkg - Build $(perf-tar).tar.gz source tarball' @echo ' perf-tarbz2-src-pkg - Build $(perf-tar).tar.bz2 source tarball' + @echo ' perf-tarxz-src-pkg - Build $(perf-tar).tar.xz source tarball' diff --git a/scripts/package/buildtar b/scripts/package/buildtar index 51b2aa0acb82d..83c9c04102f2b 100644 --- a/scripts/package/buildtar +++ b/scripts/package/buildtar @@ -35,6 +35,10 @@ case "${1}" in compress="bzip2 -c9" file_ext=".bz2" ;; + tarxz-pkg) + compress="xz -c9" + file_ext=".xz" + ;; *) echo "Unknown tarball target \"${1}\" requested, please add it to ${0}." >&2 exit 1 -- GitLab From facc31ddc3570a3a0d8951c94f16b898e01b464d Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 9 Mar 2011 19:54:27 +0100 Subject: [PATCH 0360/2822] block: Don't implicitly trigger event check on disk_unblock_events() Currently, disk_unblock_events() implicitly kick event check if the block count reaches zero. This behavior is not described in the comment and hinders with future changes. Make the unblocker explicitly check events by calling disk_check_events() as necessary. This patch doesn't cause any behavior difference. Signed-off-by: Tejun Heo Cc: Jens Axboe Cc: Kay Sievers --- block/genhd.c | 2 +- fs/block_dev.c | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/block/genhd.c b/block/genhd.c index 3e2b57b55e384..c91a2dac6b6b2 100644 --- a/block/genhd.c +++ b/block/genhd.c @@ -1494,7 +1494,7 @@ void disk_block_events(struct gendisk *disk) void disk_unblock_events(struct gendisk *disk) { if (disk->ev) - __disk_unblock_events(disk, true); + __disk_unblock_events(disk, false); } /** diff --git a/fs/block_dev.c b/fs/block_dev.c index 889287019599a..fffdf86c17574 100644 --- a/fs/block_dev.c +++ b/fs/block_dev.c @@ -1446,6 +1446,7 @@ int blkdev_put(struct block_device *bdev, fmode_t mode) if (bdev_free) { if (bdev->bd_write_holder) { disk_unblock_events(bdev->bd_disk); + disk_check_events(bdev->bd_disk); bdev->bd_write_holder = false; } else disk_check_events(bdev->bd_disk); -- GitLab From 6936217cc7e58573026bdba25b1bfb778e8f2267 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 9 Mar 2011 19:54:27 +0100 Subject: [PATCH 0361/2822] block: Don't check events on close unless it was blocked The block event mechanism currently always checks events when the device is being closed regardless of the open mode. The intention was to allow detection of EJECT_REQUEST when a device is closed whether disk event polling is enabled or not. This is unnecessary as, for devices of interest, events are checked from either userland or kernel and in the former case ->check_events() is performed on open of each poll attempt anyway. Furthermore, this unconditional event check on close makes the code susceptible to event loop if the block driver doesn't clear reported events correctly - an event triggers userland to open and close the device which in turn causes another event, rinse and repeat. Check events on close only if it was blocked by excl write open. Signed-off-by: Tejun Heo Cc: Jens Axboe Cc: Kay Sievers --- fs/block_dev.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/fs/block_dev.c b/fs/block_dev.c index fffdf86c17574..7dd2c658d429d 100644 --- a/fs/block_dev.c +++ b/fs/block_dev.c @@ -1448,13 +1448,11 @@ int blkdev_put(struct block_device *bdev, fmode_t mode) disk_unblock_events(bdev->bd_disk); disk_check_events(bdev->bd_disk); bdev->bd_write_holder = false; - } else - disk_check_events(bdev->bd_disk); + } } mutex_unlock(&bdev->bd_mutex); - } else - disk_check_events(bdev->bd_disk); + } return __blkdev_put(bdev, mode, 0); } -- GitLab From 69e02c59a7d962dced8047401b81a8d897e1702e Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 9 Mar 2011 19:54:27 +0100 Subject: [PATCH 0362/2822] block: Don't check events while open is in progress Not all block drivers clear events immediately after reporting. Some do so in ->revalidate_disk() or other steps during ->open(). There is a slim chance event poll may happen between the clearing event check from check_disk_change() and the actual clearing of the events which would result in spurious events. Block event checks while block device open is in progress. There is no need to kick explicit event check afterwards as events are always checked during open. -v2: The original patch could have called disk_unblock_events() with an already released or %NULL @disk causing oops. Fixed by making sure references are put after disk_unblock_events() is called. It also makes the error path of __blkdev_get() a bit simpler. This problem was reported by Jens. Signed-off-by: Tejun Heo Cc: Jens Axboe Cc: Kay Sievers --- fs/block_dev.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/fs/block_dev.c b/fs/block_dev.c index 7dd2c658d429d..d42cad2757ae9 100644 --- a/fs/block_dev.c +++ b/fs/block_dev.c @@ -1087,6 +1087,7 @@ static int __blkdev_get(struct block_device *bdev, fmode_t mode, int for_part) if (!disk) goto out; + disk_block_events(disk); mutex_lock_nested(&bdev->bd_mutex, for_part); if (!bdev->bd_openers) { bdev->bd_disk = disk; @@ -1108,10 +1109,11 @@ static int __blkdev_get(struct block_device *bdev, fmode_t mode, int for_part) */ disk_put_part(bdev->bd_part); bdev->bd_part = NULL; - module_put(disk->fops->owner); - put_disk(disk); bdev->bd_disk = NULL; mutex_unlock(&bdev->bd_mutex); + disk_unblock_events(disk); + module_put(disk->fops->owner); + put_disk(disk); goto restart; } if (ret) @@ -1148,9 +1150,6 @@ static int __blkdev_get(struct block_device *bdev, fmode_t mode, int for_part) bd_set_size(bdev, (loff_t)bdev->bd_part->nr_sects << 9); } } else { - module_put(disk->fops->owner); - put_disk(disk); - disk = NULL; if (bdev->bd_contains == bdev) { if (bdev->bd_disk->fops->open) { ret = bdev->bd_disk->fops->open(bdev, mode); @@ -1160,11 +1159,15 @@ static int __blkdev_get(struct block_device *bdev, fmode_t mode, int for_part) if (bdev->bd_invalidated) rescan_partitions(bdev->bd_disk, bdev); } + /* only one opener holds refs to the module and disk */ + module_put(disk->fops->owner); + put_disk(disk); } bdev->bd_openers++; if (for_part) bdev->bd_part_count++; mutex_unlock(&bdev->bd_mutex); + disk_unblock_events(disk); return 0; out_clear: @@ -1177,9 +1180,9 @@ static int __blkdev_get(struct block_device *bdev, fmode_t mode, int for_part) bdev->bd_contains = NULL; out_unlock_bdev: mutex_unlock(&bdev->bd_mutex); + disk_unblock_events(disk); out: - if (disk) - module_put(disk->fops->owner); + module_put(disk->fops->owner); put_disk(disk); bdput(bdev); -- GitLab From 5b03a1b140e13a28ff6be1526892a9dc538ddef6 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 9 Mar 2011 19:54:27 +0100 Subject: [PATCH 0363/2822] ide: Convert to bdops->check_events() Convert ->media_changed() to the new ->check_events() method. The conversion is mostly mechanical. The only notable change is that cdrom now doesn't generate any event if @slot_nr isn't CDSL_CURRENT. It used to return -EINVAL which would be treated as media changed. As media changer isn't supported anyway, this doesn't make any difference. This makes ide emit the standard disk events and allows kernel event polling. Currently, only MEDIA_CHANGE event is implemented. Adding support for EJECT_REQUEST shouldn't be difficult; however, given that ide driver is already deprecated, it probably is best to leave it alone. Signed-off-by: Tejun Heo Acked-by: Jens Axboe Cc: Kay Sievers Cc: "David S. Miller" Cc: linux-ide@vger.kernel.org --- drivers/ide/ide-cd.c | 10 ++++++---- drivers/ide/ide-cd.h | 3 ++- drivers/ide/ide-cd_ioctl.c | 8 ++++---- drivers/ide/ide-gd.c | 14 ++++++++------ 4 files changed, 20 insertions(+), 15 deletions(-) diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c index 0c73fe39a236b..a2e29099ee0c1 100644 --- a/drivers/ide/ide-cd.c +++ b/drivers/ide/ide-cd.c @@ -1177,7 +1177,7 @@ static struct cdrom_device_ops ide_cdrom_dops = { .open = ide_cdrom_open_real, .release = ide_cdrom_release_real, .drive_status = ide_cdrom_drive_status, - .media_changed = ide_cdrom_check_media_change_real, + .check_events = ide_cdrom_check_events_real, .tray_move = ide_cdrom_tray_move, .lock_door = ide_cdrom_lock_door, .select_speed = ide_cdrom_select_speed, @@ -1702,10 +1702,11 @@ static int idecd_ioctl(struct block_device *bdev, fmode_t mode, } -static int idecd_media_changed(struct gendisk *disk) +static unsigned int idecd_check_events(struct gendisk *disk, + unsigned int clearing) { struct cdrom_info *info = ide_drv_g(disk, cdrom_info); - return cdrom_media_changed(&info->devinfo); + return cdrom_check_events(&info->devinfo, clearing); } static int idecd_revalidate_disk(struct gendisk *disk) @@ -1723,7 +1724,7 @@ static const struct block_device_operations idecd_ops = { .open = idecd_open, .release = idecd_release, .ioctl = idecd_ioctl, - .media_changed = idecd_media_changed, + .check_events = idecd_check_events, .revalidate_disk = idecd_revalidate_disk }; @@ -1790,6 +1791,7 @@ static int ide_cd_probe(ide_drive_t *drive) ide_cd_read_toc(drive, &sense); g->fops = &idecd_ops; g->flags |= GENHD_FL_REMOVABLE; + g->events = DISK_EVENT_MEDIA_CHANGE; add_disk(g); return 0; diff --git a/drivers/ide/ide-cd.h b/drivers/ide/ide-cd.h index 93a3cf1b0f3f8..1efc936f5b667 100644 --- a/drivers/ide/ide-cd.h +++ b/drivers/ide/ide-cd.h @@ -111,7 +111,8 @@ int cdrom_check_status(ide_drive_t *, struct request_sense *); int ide_cdrom_open_real(struct cdrom_device_info *, int); void ide_cdrom_release_real(struct cdrom_device_info *); int ide_cdrom_drive_status(struct cdrom_device_info *, int); -int ide_cdrom_check_media_change_real(struct cdrom_device_info *, int); +unsigned int ide_cdrom_check_events_real(struct cdrom_device_info *, + unsigned int clearing, int slot_nr); int ide_cdrom_tray_move(struct cdrom_device_info *, int); int ide_cdrom_lock_door(struct cdrom_device_info *, int); int ide_cdrom_select_speed(struct cdrom_device_info *, int); diff --git a/drivers/ide/ide-cd_ioctl.c b/drivers/ide/ide-cd_ioctl.c index 766b3deeb23c7..2a6bc50e8a41e 100644 --- a/drivers/ide/ide-cd_ioctl.c +++ b/drivers/ide/ide-cd_ioctl.c @@ -79,8 +79,8 @@ int ide_cdrom_drive_status(struct cdrom_device_info *cdi, int slot_nr) return CDS_DRIVE_NOT_READY; } -int ide_cdrom_check_media_change_real(struct cdrom_device_info *cdi, - int slot_nr) +unsigned int ide_cdrom_check_events_real(struct cdrom_device_info *cdi, + unsigned int clearing, int slot_nr) { ide_drive_t *drive = cdi->handle; int retval; @@ -89,9 +89,9 @@ int ide_cdrom_check_media_change_real(struct cdrom_device_info *cdi, (void) cdrom_check_status(drive, NULL); retval = (drive->dev_flags & IDE_DFLAG_MEDIA_CHANGED) ? 1 : 0; drive->dev_flags &= ~IDE_DFLAG_MEDIA_CHANGED; - return retval; + return retval ? DISK_EVENT_MEDIA_CHANGE : 0; } else { - return -EINVAL; + return 0; } } diff --git a/drivers/ide/ide-gd.c b/drivers/ide/ide-gd.c index 35c4b43585e34..c4ffd4888939a 100644 --- a/drivers/ide/ide-gd.c +++ b/drivers/ide/ide-gd.c @@ -285,11 +285,12 @@ static int ide_gd_getgeo(struct block_device *bdev, struct hd_geometry *geo) return 0; } -static int ide_gd_media_changed(struct gendisk *disk) +static unsigned int ide_gd_check_events(struct gendisk *disk, + unsigned int clearing) { struct ide_disk_obj *idkp = ide_drv_g(disk, ide_disk_obj); ide_drive_t *drive = idkp->drive; - int ret; + bool ret; /* do not scan partitions twice if this is a removable device */ if (drive->dev_flags & IDE_DFLAG_ATTACH) { @@ -297,10 +298,10 @@ static int ide_gd_media_changed(struct gendisk *disk) return 0; } - ret = !!(drive->dev_flags & IDE_DFLAG_MEDIA_CHANGED); + ret = drive->dev_flags & IDE_DFLAG_MEDIA_CHANGED; drive->dev_flags &= ~IDE_DFLAG_MEDIA_CHANGED; - return ret; + return ret ? DISK_EVENT_MEDIA_CHANGE : 0; } static void ide_gd_unlock_native_capacity(struct gendisk *disk) @@ -318,7 +319,7 @@ static int ide_gd_revalidate_disk(struct gendisk *disk) struct ide_disk_obj *idkp = ide_drv_g(disk, ide_disk_obj); ide_drive_t *drive = idkp->drive; - if (ide_gd_media_changed(disk)) + if (ide_gd_check_events(disk, 0)) drive->disk_ops->get_capacity(drive); set_capacity(disk, ide_gd_capacity(drive)); @@ -340,7 +341,7 @@ static const struct block_device_operations ide_gd_ops = { .release = ide_gd_release, .ioctl = ide_gd_ioctl, .getgeo = ide_gd_getgeo, - .media_changed = ide_gd_media_changed, + .check_events = ide_gd_check_events, .unlock_native_capacity = ide_gd_unlock_native_capacity, .revalidate_disk = ide_gd_revalidate_disk }; @@ -412,6 +413,7 @@ static int ide_gd_probe(ide_drive_t *drive) if (drive->dev_flags & IDE_DFLAG_REMOVABLE) g->flags = GENHD_FL_REMOVABLE; g->fops = &ide_gd_ops; + g->events = DISK_EVENT_MEDIA_CHANGE; add_disk(g); return 0; -- GitLab From 1a8a74f03fcde1725ff26520220f3d21dbd8faa1 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 9 Mar 2011 19:54:27 +0100 Subject: [PATCH 0364/2822] floppy,{ami|ata}flop: Convert to bdops->check_events() Convert the floppy drivers from ->media_changed() to ->check_events(). Both floppy and ataflop buffer media changed state bit and clear them on revalidation and will behave correctly with kernel event polling. I can't tell how amiflop clears its event and it's possible that it may generate spurious events when polled. Signed-off-by: Tejun Heo Cc: Jens Axboe Cc: Kay Sievers --- drivers/block/amiflop.c | 9 +++++---- drivers/block/ataflop.c | 14 ++++++++------ drivers/block/floppy.c | 10 ++++++---- 3 files changed, 19 insertions(+), 14 deletions(-) diff --git a/drivers/block/amiflop.c b/drivers/block/amiflop.c index 7888501ad9ee1..5e7d3fe2c13bc 100644 --- a/drivers/block/amiflop.c +++ b/drivers/block/amiflop.c @@ -1658,12 +1658,12 @@ static int floppy_release(struct gendisk *disk, fmode_t mode) } /* - * floppy-change is never called from an interrupt, so we can relax a bit + * check_events is never called from an interrupt, so we can relax a bit * here, sleep etc. Note that floppy-on tries to set current_DOR to point * to the desired drive, but it will probably not survive the sleep if * several floppies are used at the same time: thus the loop. */ -static int amiga_floppy_change(struct gendisk *disk) +static unsigned amiga_check_events(struct gendisk *disk, unsigned int clearing) { struct amiga_floppy_struct *p = disk->private_data; int drive = p - unit; @@ -1686,7 +1686,7 @@ static int amiga_floppy_change(struct gendisk *disk) p->dirty = 0; writepending = 0; /* if this was true before, too bad! */ writefromint = 0; - return 1; + return DISK_EVENT_MEDIA_CHANGE; } return 0; } @@ -1697,7 +1697,7 @@ static const struct block_device_operations floppy_fops = { .release = floppy_release, .ioctl = fd_ioctl, .getgeo = fd_getgeo, - .media_changed = amiga_floppy_change, + .check_events = amiga_check_events, }; static int __init fd_probe_drives(void) @@ -1736,6 +1736,7 @@ static int __init fd_probe_drives(void) disk->major = FLOPPY_MAJOR; disk->first_minor = drive; disk->fops = &floppy_fops; + disk->events = DISK_EVENT_MEDIA_CHANGE; sprintf(disk->disk_name, "fd%d", drive); disk->private_data = &unit[drive]; set_capacity(disk, 880*2); diff --git a/drivers/block/ataflop.c b/drivers/block/ataflop.c index 605a67e40bbfc..c871eae141204 100644 --- a/drivers/block/ataflop.c +++ b/drivers/block/ataflop.c @@ -1324,23 +1324,24 @@ static void finish_fdc_done( int dummy ) * due to unrecognised disk changes. */ -static int check_floppy_change(struct gendisk *disk) +static unsigned int floppy_check_events(struct gendisk *disk, + unsigned int clearing) { struct atari_floppy_struct *p = disk->private_data; unsigned int drive = p - unit; if (test_bit (drive, &fake_change)) { /* simulated change (e.g. after formatting) */ - return 1; + return DISK_EVENT_MEDIA_CHANGE; } if (test_bit (drive, &changed_floppies)) { /* surely changed (the WP signal changed at least once) */ - return 1; + return DISK_EVENT_MEDIA_CHANGE; } if (UD.wpstat) { /* WP is on -> could be changed: to be sure, buffers should be * invalidated... */ - return 1; + return DISK_EVENT_MEDIA_CHANGE; } return 0; @@ -1570,7 +1571,7 @@ static int fd_locked_ioctl(struct block_device *bdev, fmode_t mode, * or the next access will revalidate - and clear UDT :-( */ - if (check_floppy_change(disk)) + if (floppy_check_events(disk, 0)) floppy_revalidate(disk); if (UD.flags & FTD_MSG) @@ -1904,7 +1905,7 @@ static const struct block_device_operations floppy_fops = { .open = floppy_unlocked_open, .release = floppy_release, .ioctl = fd_ioctl, - .media_changed = check_floppy_change, + .check_events = floppy_check_events, .revalidate_disk= floppy_revalidate, }; @@ -1963,6 +1964,7 @@ static int __init atari_floppy_init (void) unit[i].disk->first_minor = i; sprintf(unit[i].disk->disk_name, "fd%d", i); unit[i].disk->fops = &floppy_fops; + unit[i].disk->events = DISK_EVENT_MEDIA_CHANGE; unit[i].disk->private_data = &unit[i]; unit[i].disk->queue = blk_init_queue(do_fd_request, &ataflop_lock); diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c index 77fc76f8aea91..3851dbc03e05e 100644 --- a/drivers/block/floppy.c +++ b/drivers/block/floppy.c @@ -3770,13 +3770,14 @@ out2: /* * Check if the disk has been changed or if a change has been faked. */ -static int check_floppy_change(struct gendisk *disk) +static unsigned int floppy_check_events(struct gendisk *disk, + unsigned int clearing) { int drive = (long)disk->private_data; if (test_bit(FD_DISK_CHANGED_BIT, &UDRS->flags) || test_bit(FD_VERIFY_BIT, &UDRS->flags)) - return 1; + return DISK_EVENT_MEDIA_CHANGE; if (time_after(jiffies, UDRS->last_checked + UDP->checkfreq)) { lock_fdc(drive, false); @@ -3788,7 +3789,7 @@ static int check_floppy_change(struct gendisk *disk) test_bit(FD_VERIFY_BIT, &UDRS->flags) || test_bit(drive, &fake_change) || drive_no_geom(drive)) - return 1; + return DISK_EVENT_MEDIA_CHANGE; return 0; } @@ -3898,7 +3899,7 @@ static const struct block_device_operations floppy_fops = { .release = floppy_release, .ioctl = fd_ioctl, .getgeo = fd_getgeo, - .media_changed = check_floppy_change, + .check_events = floppy_check_events, .revalidate_disk = floppy_revalidate, }; @@ -4205,6 +4206,7 @@ static int __init floppy_init(void) disks[dr]->major = FLOPPY_MAJOR; disks[dr]->first_minor = TOMINOR(dr); disks[dr]->fops = &floppy_fops; + disks[dr]->events = DISK_EVENT_MEDIA_CHANGE; sprintf(disks[dr]->disk_name, "fd%d", dr); init_timer(&motor_off_timer[dr]); -- GitLab From 1c27030bd21e7e2c68ef5be9f28c63778cf4b27f Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 9 Mar 2011 19:54:28 +0100 Subject: [PATCH 0365/2822] gdrom,viocd: Convert to bdops->check_events() Convert gdrom and viocd from ->media_changed() to ->check_events(). It's unclear how the conditions are cleared and it's possible that it may generate spurious events when polled. Signed-off-by: Tejun Heo Cc: Jens Axboe Cc: Kay Sievers --- drivers/cdrom/gdrom.c | 16 ++++++++++------ drivers/cdrom/viocd.c | 17 ++++++++++------- 2 files changed, 20 insertions(+), 13 deletions(-) diff --git a/drivers/cdrom/gdrom.c b/drivers/cdrom/gdrom.c index 64a21461c408f..b2b034fea34e6 100644 --- a/drivers/cdrom/gdrom.c +++ b/drivers/cdrom/gdrom.c @@ -395,10 +395,12 @@ static int gdrom_drivestatus(struct cdrom_device_info *cd_info, int ignore) return CDS_NO_INFO; } -static int gdrom_mediachanged(struct cdrom_device_info *cd_info, int ignore) +static unsigned int gdrom_check_events(struct cdrom_device_info *cd_info, + unsigned int clearing, int ignore) { /* check the sense key */ - return (__raw_readb(GDROM_ERROR_REG) & 0xF0) == 0x60; + return (__raw_readb(GDROM_ERROR_REG) & 0xF0) == 0x60 ? + DISK_EVENT_MEDIA_CHANGE : 0; } /* reset the G1 bus */ @@ -483,7 +485,7 @@ static struct cdrom_device_ops gdrom_ops = { .open = gdrom_open, .release = gdrom_release, .drive_status = gdrom_drivestatus, - .media_changed = gdrom_mediachanged, + .check_events = gdrom_check_events, .get_last_session = gdrom_get_last_session, .reset = gdrom_hardreset, .audio_ioctl = gdrom_audio_ioctl, @@ -509,9 +511,10 @@ static int gdrom_bdops_release(struct gendisk *disk, fmode_t mode) return 0; } -static int gdrom_bdops_mediachanged(struct gendisk *disk) +static unsigned int gdrom_bdops_check_events(struct gendisk *disk, + unsigned int clearing) { - return cdrom_media_changed(gd.cd_info); + return cdrom_check_events(gd.cd_info, clearing); } static int gdrom_bdops_ioctl(struct block_device *bdev, fmode_t mode, @@ -530,7 +533,7 @@ static const struct block_device_operations gdrom_bdops = { .owner = THIS_MODULE, .open = gdrom_bdops_open, .release = gdrom_bdops_release, - .media_changed = gdrom_bdops_mediachanged, + .check_events = gdrom_bdops_check_events, .ioctl = gdrom_bdops_ioctl, }; @@ -800,6 +803,7 @@ static int __devinit probe_gdrom(struct platform_device *devptr) goto probe_fail_cdrom_register; } gd.disk->fops = &gdrom_bdops; + gd.disk->events = DISK_EVENT_MEDIA_CHANGE; /* latch on to the interrupt */ err = gdrom_set_interrupt_handlers(); if (err) diff --git a/drivers/cdrom/viocd.c b/drivers/cdrom/viocd.c index be73a9b493a69..4e874c5fa6059 100644 --- a/drivers/cdrom/viocd.c +++ b/drivers/cdrom/viocd.c @@ -186,10 +186,11 @@ static int viocd_blk_ioctl(struct block_device *bdev, fmode_t mode, return ret; } -static int viocd_blk_media_changed(struct gendisk *disk) +static unsigned int viocd_blk_check_events(struct gendisk *disk, + unsigned int clearing) { struct disk_info *di = disk->private_data; - return cdrom_media_changed(&di->viocd_info); + return cdrom_check_events(&di->viocd_info, clearing); } static const struct block_device_operations viocd_fops = { @@ -197,7 +198,7 @@ static const struct block_device_operations viocd_fops = { .open = viocd_blk_open, .release = viocd_blk_release, .ioctl = viocd_blk_ioctl, - .media_changed = viocd_blk_media_changed, + .check_events = viocd_blk_check_events, }; static int viocd_open(struct cdrom_device_info *cdi, int purpose) @@ -320,7 +321,8 @@ static void do_viocd_request(struct request_queue *q) } } -static int viocd_media_changed(struct cdrom_device_info *cdi, int disc_nr) +static unsigned int viocd_check_events(struct cdrom_device_info *cdi, + unsigned int clearing, int disc_nr) { struct viocd_waitevent we; HvLpEvent_Rc hvrc; @@ -340,7 +342,7 @@ static int viocd_media_changed(struct cdrom_device_info *cdi, int disc_nr) if (hvrc != 0) { pr_warning("bad rc on HvCallEvent_signalLpEventFast %d\n", (int)hvrc); - return -EIO; + return 0; } wait_for_completion(&we.com); @@ -354,7 +356,7 @@ static int viocd_media_changed(struct cdrom_device_info *cdi, int disc_nr) return 0; } - return we.changed; + return we.changed ? DISK_EVENT_MEDIA_CHANGE : 0; } static int viocd_lock_door(struct cdrom_device_info *cdi, int locking) @@ -550,7 +552,7 @@ static int viocd_audio_ioctl(struct cdrom_device_info *cdi, unsigned int cmd, static struct cdrom_device_ops viocd_dops = { .open = viocd_open, .release = viocd_release, - .media_changed = viocd_media_changed, + .check_events = viocd_check_events, .lock_door = viocd_lock_door, .generic_packet = viocd_packet, .audio_ioctl = viocd_audio_ioctl, @@ -624,6 +626,7 @@ static int viocd_probe(struct vio_dev *vdev, const struct vio_device_id *id) gendisk->queue = q; gendisk->fops = &viocd_fops; gendisk->flags = GENHD_FL_CD|GENHD_FL_REMOVABLE; + gendisk->events = DISK_EVENT_MEDIA_CHANGE; set_capacity(gendisk, 0); gendisk->private_data = d; d->viocd_disk = gendisk; -- GitLab From b1b56b93f331bd61492fdb99e7986f7a528ca730 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 9 Mar 2011 19:54:28 +0100 Subject: [PATCH 0366/2822] paride: Convert to bdops->check_events() Convert paride drivers from ->media_changed() to ->check_events(). pcd and pd buffer and clear events after reporting; however, pf unconditionally reports MEDIA_CHANGE and will generate spurious events when polled. Signed-off-by: Tejun Heo Cc: Jens Axboe Cc: Kay Sievers Cc: Tim Waugh --- drivers/block/paride/pcd.c | 18 +++++++++++------- drivers/block/paride/pd.c | 7 ++++--- drivers/block/paride/pf.c | 10 ++++++---- 3 files changed, 21 insertions(+), 14 deletions(-) diff --git a/drivers/block/paride/pcd.c b/drivers/block/paride/pcd.c index 62cec6afd7adf..2f2ccf6862519 100644 --- a/drivers/block/paride/pcd.c +++ b/drivers/block/paride/pcd.c @@ -172,7 +172,8 @@ module_param_array(drive3, int, NULL, 0); static int pcd_open(struct cdrom_device_info *cdi, int purpose); static void pcd_release(struct cdrom_device_info *cdi); static int pcd_drive_status(struct cdrom_device_info *cdi, int slot_nr); -static int pcd_media_changed(struct cdrom_device_info *cdi, int slot_nr); +static unsigned int pcd_check_events(struct cdrom_device_info *cdi, + unsigned int clearing, int slot_nr); static int pcd_tray_move(struct cdrom_device_info *cdi, int position); static int pcd_lock_door(struct cdrom_device_info *cdi, int lock); static int pcd_drive_reset(struct cdrom_device_info *cdi); @@ -257,10 +258,11 @@ static int pcd_block_ioctl(struct block_device *bdev, fmode_t mode, return ret; } -static int pcd_block_media_changed(struct gendisk *disk) +static unsigned int pcd_block_check_events(struct gendisk *disk, + unsigned int clearing) { struct pcd_unit *cd = disk->private_data; - return cdrom_media_changed(&cd->info); + return cdrom_check_events(&cd->info, clearing); } static const struct block_device_operations pcd_bdops = { @@ -268,14 +270,14 @@ static const struct block_device_operations pcd_bdops = { .open = pcd_block_open, .release = pcd_block_release, .ioctl = pcd_block_ioctl, - .media_changed = pcd_block_media_changed, + .check_events = pcd_block_check_events, }; static struct cdrom_device_ops pcd_dops = { .open = pcd_open, .release = pcd_release, .drive_status = pcd_drive_status, - .media_changed = pcd_media_changed, + .check_events = pcd_check_events, .tray_move = pcd_tray_move, .lock_door = pcd_lock_door, .get_mcn = pcd_get_mcn, @@ -318,6 +320,7 @@ static void pcd_init_units(void) disk->first_minor = unit; strcpy(disk->disk_name, cd->name); /* umm... */ disk->fops = &pcd_bdops; + disk->events = DISK_EVENT_MEDIA_CHANGE; } } @@ -502,13 +505,14 @@ static int pcd_packet(struct cdrom_device_info *cdi, struct packet_command *cgc) #define DBMSG(msg) ((verbose>1)?(msg):NULL) -static int pcd_media_changed(struct cdrom_device_info *cdi, int slot_nr) +static unsigned int pcd_check_events(struct cdrom_device_info *cdi, + unsigned int clearing, int slot_nr) { struct pcd_unit *cd = cdi->handle; int res = cd->changed; if (res) cd->changed = 0; - return res; + return res ? DISK_EVENT_MEDIA_CHANGE : 0; } static int pcd_lock_door(struct cdrom_device_info *cdi, int lock) diff --git a/drivers/block/paride/pd.c b/drivers/block/paride/pd.c index c0ee1558b9bba..21dfdb7768695 100644 --- a/drivers/block/paride/pd.c +++ b/drivers/block/paride/pd.c @@ -794,7 +794,7 @@ static int pd_release(struct gendisk *p, fmode_t mode) return 0; } -static int pd_check_media(struct gendisk *p) +static unsigned int pd_check_events(struct gendisk *p, unsigned int clearing) { struct pd_unit *disk = p->private_data; int r; @@ -803,7 +803,7 @@ static int pd_check_media(struct gendisk *p) pd_special_command(disk, pd_media_check); r = disk->changed; disk->changed = 0; - return r; + return r ? DISK_EVENT_MEDIA_CHANGE : 0; } static int pd_revalidate(struct gendisk *p) @@ -822,7 +822,7 @@ static const struct block_device_operations pd_fops = { .release = pd_release, .ioctl = pd_ioctl, .getgeo = pd_getgeo, - .media_changed = pd_check_media, + .check_events = pd_check_events, .revalidate_disk= pd_revalidate }; @@ -837,6 +837,7 @@ static void pd_probe_drive(struct pd_unit *disk) p->fops = &pd_fops; p->major = major; p->first_minor = (disk - pd) << PD_BITS; + p->events = DISK_EVENT_MEDIA_CHANGE; disk->gd = p; p->private_data = disk; p->queue = pd_queue; diff --git a/drivers/block/paride/pf.c b/drivers/block/paride/pf.c index 635f25dd9e108..7adeb1edbf43f 100644 --- a/drivers/block/paride/pf.c +++ b/drivers/block/paride/pf.c @@ -243,7 +243,8 @@ static struct pf_unit units[PF_UNITS]; static int pf_identify(struct pf_unit *pf); static void pf_lock(struct pf_unit *pf, int func); static void pf_eject(struct pf_unit *pf); -static int pf_check_media(struct gendisk *disk); +static unsigned int pf_check_events(struct gendisk *disk, + unsigned int clearing); static char pf_scratch[512]; /* scratch block buffer */ @@ -270,7 +271,7 @@ static const struct block_device_operations pf_fops = { .release = pf_release, .ioctl = pf_ioctl, .getgeo = pf_getgeo, - .media_changed = pf_check_media, + .check_events = pf_check_events, }; static void __init pf_init_units(void) @@ -293,6 +294,7 @@ static void __init pf_init_units(void) disk->first_minor = unit; strcpy(disk->disk_name, pf->name); disk->fops = &pf_fops; + disk->events = DISK_EVENT_MEDIA_CHANGE; if (!(*drives[unit])[D_PRT]) pf_drive_count++; } @@ -377,9 +379,9 @@ static int pf_release(struct gendisk *disk, fmode_t mode) } -static int pf_check_media(struct gendisk *disk) +static unsigned int pf_check_events(struct gendisk *disk, unsigned int clearing) { - return 1; + return DISK_EVENT_MEDIA_CHANGE; } static inline int status_reg(struct pf_unit *pf) -- GitLab From 507daea2276677785ba8096d90b9e8049632fc46 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 9 Mar 2011 19:54:28 +0100 Subject: [PATCH 0367/2822] dac960: Convert to bdops->check_events() Convert from ->media_changed() to ->check_events(). DAC960 media change notification seems to be one way (once set, never cleared) and will generate spurious events when polled once the condition triggers. Signed-off-by: Tejun Heo Cc: Jens Axboe Cc: Kay Sievers --- drivers/block/DAC960.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/block/DAC960.c b/drivers/block/DAC960.c index 1f286ab461d3d..79882104e431a 100644 --- a/drivers/block/DAC960.c +++ b/drivers/block/DAC960.c @@ -140,13 +140,14 @@ static int DAC960_getgeo(struct block_device *bdev, struct hd_geometry *geo) return 0; } -static int DAC960_media_changed(struct gendisk *disk) +static unsigned int DAC960_check_events(struct gendisk *disk, + unsigned int clearing) { DAC960_Controller_T *p = disk->queue->queuedata; int drive_nr = (long)disk->private_data; if (!p->LogicalDriveInitiallyAccessible[drive_nr]) - return 1; + return DISK_EVENT_MEDIA_CHANGE; return 0; } @@ -163,7 +164,7 @@ static const struct block_device_operations DAC960_BlockDeviceOperations = { .owner = THIS_MODULE, .open = DAC960_open, .getgeo = DAC960_getgeo, - .media_changed = DAC960_media_changed, + .check_events = DAC960_check_events, .revalidate_disk = DAC960_revalidate_disk, }; @@ -2546,6 +2547,7 @@ static bool DAC960_RegisterBlockDevice(DAC960_Controller_T *Controller) disk->major = MajorNumber; disk->first_minor = n << DAC960_MaxPartitionsBits; disk->fops = &DAC960_BlockDeviceOperations; + disk->events = DISK_EVENT_MEDIA_CHANGE; } /* Indicate the Block Device Registration completed successfully, -- GitLab From 4bbde77787270e17418dd32c7eb32e42ad16cfc7 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 9 Mar 2011 19:54:28 +0100 Subject: [PATCH 0368/2822] swim[3]: Convert to bdops->check_events() Convert from ->media_changed() to ->check_events(). Both swim and swim3 buffer media changed state and clear it on revalidation. They will behave correctly with kernel event polling. Signed-off-by: Tejun Heo Cc: Jens Axboe Cc: Kay Sievers Cc: Laurent Vivier Cc: Benjamin Herrenschmidt --- drivers/block/swim.c | 8 +++++--- drivers/block/swim3.c | 11 +++++++---- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/drivers/block/swim.c b/drivers/block/swim.c index 75333d0a3327d..24a482f2fbd60 100644 --- a/drivers/block/swim.c +++ b/drivers/block/swim.c @@ -741,11 +741,12 @@ static int floppy_getgeo(struct block_device *bdev, struct hd_geometry *geo) return 0; } -static int floppy_check_change(struct gendisk *disk) +static unsigned int floppy_check_events(struct gendisk *disk, + unsigned int clearing) { struct floppy_state *fs = disk->private_data; - return fs->ejected; + return fs->ejected ? DISK_EVENT_MEDIA_CHANGE : 0; } static int floppy_revalidate(struct gendisk *disk) @@ -772,7 +773,7 @@ static const struct block_device_operations floppy_fops = { .release = floppy_release, .ioctl = floppy_ioctl, .getgeo = floppy_getgeo, - .media_changed = floppy_check_change, + .check_events = floppy_check_events, .revalidate_disk = floppy_revalidate, }; @@ -857,6 +858,7 @@ static int __devinit swim_floppy_init(struct swim_priv *swd) swd->unit[drive].disk->first_minor = drive; sprintf(swd->unit[drive].disk->disk_name, "fd%d", drive); swd->unit[drive].disk->fops = &floppy_fops; + swd->unit[drive].disk->events = DISK_EVENT_MEDIA_CHANGE; swd->unit[drive].disk->private_data = &swd->unit[drive]; swd->unit[drive].disk->queue = swd->queue; set_capacity(swd->unit[drive].disk, 2880); diff --git a/drivers/block/swim3.c b/drivers/block/swim3.c index bf3a5b8592990..4c10f56facbff 100644 --- a/drivers/block/swim3.c +++ b/drivers/block/swim3.c @@ -250,7 +250,8 @@ static int floppy_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd, unsigned long param); static int floppy_open(struct block_device *bdev, fmode_t mode); static int floppy_release(struct gendisk *disk, fmode_t mode); -static int floppy_check_change(struct gendisk *disk); +static unsigned int floppy_check_events(struct gendisk *disk, + unsigned int clearing); static int floppy_revalidate(struct gendisk *disk); static bool swim3_end_request(int err, unsigned int nr_bytes) @@ -975,10 +976,11 @@ static int floppy_release(struct gendisk *disk, fmode_t mode) return 0; } -static int floppy_check_change(struct gendisk *disk) +static unsigned int floppy_check_events(struct gendisk *disk, + unsigned int clearing) { struct floppy_state *fs = disk->private_data; - return fs->ejected; + return fs->ejected ? DISK_EVENT_MEDIA_CHANGE : 0; } static int floppy_revalidate(struct gendisk *disk) @@ -1025,7 +1027,7 @@ static const struct block_device_operations floppy_fops = { .open = floppy_unlocked_open, .release = floppy_release, .ioctl = floppy_ioctl, - .media_changed = floppy_check_change, + .check_events = floppy_check_events, .revalidate_disk= floppy_revalidate, }; @@ -1161,6 +1163,7 @@ static int __devinit swim3_attach(struct macio_dev *mdev, const struct of_device disk->major = FLOPPY_MAJOR; disk->first_minor = i; disk->fops = &floppy_fops; + disk->events = DISK_EVENT_MEDIA_CHANGE; disk->private_data = &floppy_states[i]; disk->queue = swim3_queue; disk->flags |= GENHD_FL_REMOVABLE; -- GitLab From aaa7c01546d3dc944f5758f671284177131ccce3 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 9 Mar 2011 19:54:28 +0100 Subject: [PATCH 0369/2822] ub: Convert to bdops->check_events() Convert from ->media_changed() to ->check_events(). ub buffers media changed state and clears it on revalidation. It will behave correctly with kernel event polling. Signed-off-by: Tejun Heo Cc: Jens Axboe Cc: Kay Sievers Cc: Pete Zaitcev --- drivers/block/ub.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/block/ub.c b/drivers/block/ub.c index 9ae3bb713286f..68b9430c7cfe5 100644 --- a/drivers/block/ub.c +++ b/drivers/block/ub.c @@ -1788,7 +1788,8 @@ static int ub_bd_revalidate(struct gendisk *disk) * * The return code is bool! */ -static int ub_bd_media_changed(struct gendisk *disk) +static unsigned int ub_bd_check_events(struct gendisk *disk, + unsigned int clearing) { struct ub_lun *lun = disk->private_data; @@ -1806,10 +1807,10 @@ static int ub_bd_media_changed(struct gendisk *disk) */ if (ub_sync_tur(lun->udev, lun) != 0) { lun->changed = 1; - return 1; + return DISK_EVENT_MEDIA_CHANGE; } - return lun->changed; + return lun->changed ? DISK_EVENT_MEDIA_CHANGE : 0; } static const struct block_device_operations ub_bd_fops = { @@ -1817,7 +1818,7 @@ static const struct block_device_operations ub_bd_fops = { .open = ub_bd_unlocked_open, .release = ub_bd_release, .ioctl = ub_bd_ioctl, - .media_changed = ub_bd_media_changed, + .check_events = ub_bd_check_events, .revalidate_disk = ub_bd_revalidate, }; @@ -2333,6 +2334,7 @@ static int ub_probe_lun(struct ub_dev *sc, int lnum) disk->major = UB_MAJOR; disk->first_minor = lun->id * UB_PARTS_PER_LUN; disk->fops = &ub_bd_fops; + disk->events = DISK_EVENT_MEDIA_CHANGE; disk->private_data = lun; disk->driverfs_dev = &sc->intf->dev; -- GitLab From 3a200911ada2d5b955c2c6daa22364c6de83c52c Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 9 Mar 2011 19:54:28 +0100 Subject: [PATCH 0370/2822] xsysace: Convert to bdops->check_events() Convert from ->media_changed() to ->check_events(). xsysace buffers media changed state and clears it on revalidation. It will behave correctly with kernel event polling. Signed-off-by: Tejun Heo Acked-by: Grant Likely Cc: Jens Axboe Cc: Kay Sievers --- drivers/block/xsysace.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/block/xsysace.c b/drivers/block/xsysace.c index 829161edae530..16a2fa96b810e 100644 --- a/drivers/block/xsysace.c +++ b/drivers/block/xsysace.c @@ -867,12 +867,12 @@ static void ace_request(struct request_queue * q) } } -static int ace_media_changed(struct gendisk *gd) +static unsigned int ace_check_events(struct gendisk *gd, unsigned int clearing) { struct ace_device *ace = gd->private_data; - dev_dbg(ace->dev, "ace_media_changed(): %i\n", ace->media_change); + dev_dbg(ace->dev, "ace_check_events(): %i\n", ace->media_change); - return ace->media_change; + return ace->media_change ? DISK_EVENT_MEDIA_CHANGE : 0; } static int ace_revalidate_disk(struct gendisk *gd) @@ -953,7 +953,7 @@ static const struct block_device_operations ace_fops = { .owner = THIS_MODULE, .open = ace_open, .release = ace_release, - .media_changed = ace_media_changed, + .check_events = ace_check_events, .revalidate_disk = ace_revalidate_disk, .getgeo = ace_getgeo, }; @@ -1005,6 +1005,7 @@ static int __devinit ace_setup(struct ace_device *ace) ace->gd->major = ace_major; ace->gd->first_minor = ace->id * ACE_NUM_MINORS; ace->gd->fops = &ace_fops; + ace->gd->events = DISK_EVENT_MEDIA_CHANGE; ace->gd->queue = ace->queue; ace->gd->private_data = ace; snprintf(ace->gd->disk_name, 32, "xs%c", ace->id + 'a'); -- GitLab From f47350fdecb7ce9fe715e2df4431c4b51c4ef46b Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 9 Mar 2011 19:54:28 +0100 Subject: [PATCH 0371/2822] i2o_block: Convert to bdops->check_events() Convert from ->media_changed() to ->check_events(). i2o_block buffers media changed state and clears it after reporting. It will behave correctly with kernel event polling. Signed-off-by: Tejun Heo Cc: Jens Axboe Cc: Kay Sievers Cc: Markus Lidel --- drivers/message/i2o/i2o_block.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/drivers/message/i2o/i2o_block.c b/drivers/message/i2o/i2o_block.c index ae7cad1858987..f81c25d4a125b 100644 --- a/drivers/message/i2o/i2o_block.c +++ b/drivers/message/i2o/i2o_block.c @@ -695,20 +695,22 @@ static int i2o_block_ioctl(struct block_device *bdev, fmode_t mode, }; /** - * i2o_block_media_changed - Have we seen a media change? + * i2o_block_check_events - Have we seen a media change? * @disk: gendisk which should be verified + * @clearing: events being cleared * * Verifies if the media has changed. * * Returns 1 if the media was changed or 0 otherwise. */ -static int i2o_block_media_changed(struct gendisk *disk) +static unsigned int i2o_block_check_events(struct gendisk *disk, + unsigned int clearing) { struct i2o_block_device *p = disk->private_data; if (p->media_change_flag) { p->media_change_flag = 0; - return 1; + return DISK_EVENT_MEDIA_CHANGE; } return 0; } @@ -950,7 +952,7 @@ static const struct block_device_operations i2o_block_fops = { .ioctl = i2o_block_ioctl, .compat_ioctl = i2o_block_ioctl, .getgeo = i2o_block_getgeo, - .media_changed = i2o_block_media_changed + .check_events = i2o_block_check_events, }; /** @@ -1002,6 +1004,7 @@ static struct i2o_block_device *i2o_block_device_alloc(void) gd->major = I2O_MAJOR; gd->queue = queue; gd->fops = &i2o_block_fops; + gd->events = DISK_EVENT_MEDIA_CHANGE; gd->private_data = dev; dev->gd = gd; -- GitLab From ffe80cea354519d846767b8165598c2903706c2a Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 9 Mar 2011 19:54:28 +0100 Subject: [PATCH 0372/2822] s390/tape_block: Convert to bdops->check_events() Convert from ->media_changed() to ->check_events(). s390/tape_block buffers media changed state and clears it on revalidation. It will behave correctly with kernel event polling. Signed-off-by: Tejun Heo Cc: Jens Axboe Cc: Kay Sievers Cc: Martin Schwidefsky Cc: Heiko Carstens --- drivers/s390/char/tape_block.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/drivers/s390/char/tape_block.c b/drivers/s390/char/tape_block.c index 55d2d0f4eabc9..ad84316360126 100644 --- a/drivers/s390/char/tape_block.c +++ b/drivers/s390/char/tape_block.c @@ -48,14 +48,14 @@ static DEFINE_MUTEX(tape_block_mutex); static int tapeblock_open(struct block_device *, fmode_t); static int tapeblock_release(struct gendisk *, fmode_t); -static int tapeblock_medium_changed(struct gendisk *); +static unsigned int tapeblock_check_events(struct gendisk *, unsigned int); static int tapeblock_revalidate_disk(struct gendisk *); static const struct block_device_operations tapeblock_fops = { .owner = THIS_MODULE, .open = tapeblock_open, .release = tapeblock_release, - .media_changed = tapeblock_medium_changed, + .check_events = tapeblock_check_events, .revalidate_disk = tapeblock_revalidate_disk, }; @@ -237,6 +237,7 @@ tapeblock_setup_device(struct tape_device * device) disk->major = tapeblock_major; disk->first_minor = device->first_minor; disk->fops = &tapeblock_fops; + disk->events = DISK_EVENT_MEDIA_CHANGE; disk->private_data = tape_get_device(device); disk->queue = blkdat->request_queue; set_capacity(disk, 0); @@ -340,8 +341,8 @@ tapeblock_revalidate_disk(struct gendisk *disk) return 0; } -static int -tapeblock_medium_changed(struct gendisk *disk) +static unsigned int +tapeblock_check_events(struct gendisk *disk, unsigned int clearing) { struct tape_device *device; @@ -349,7 +350,7 @@ tapeblock_medium_changed(struct gendisk *disk) DBF_LH(6, "tapeblock_medium_changed(%p) = %d\n", device, device->blk_data.medium_changed); - return device->blk_data.medium_changed; + return device->blk_data.medium_changed ? DISK_EVENT_MEDIA_CHANGE : 0; } /* -- GitLab From 6fac80e3aa9e5bfc6cadb9ea8d0584c557c4b198 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 9 Mar 2011 19:54:28 +0100 Subject: [PATCH 0373/2822] umem: Drop dummy ->media_changed() umem doesn't implement media changed detection and there's no need to implement dummy callback anymore. Remove it. Signed-off-by: Tejun Heo Cc: Jens Axboe Cc: Kay Sievers --- drivers/block/umem.c | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/drivers/block/umem.c b/drivers/block/umem.c index 8be57151f5d65..9b102abe209ce 100644 --- a/drivers/block/umem.c +++ b/drivers/block/umem.c @@ -779,20 +779,10 @@ static int mm_getgeo(struct block_device *bdev, struct hd_geometry *geo) return 0; } -/* - * Future support for removable devices - */ -static int mm_check_change(struct gendisk *disk) -{ -/* struct cardinfo *dev = disk->private_data; */ - return 0; -} - static const struct block_device_operations mm_fops = { .owner = THIS_MODULE, .getgeo = mm_getgeo, .revalidate_disk = mm_revalidate, - .media_changed = mm_check_change, }; static int __devinit mm_pci_probe(struct pci_dev *dev, -- GitLab From 3c0d206092f50be82523dba2b0e0a02de9e6aad3 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 9 Mar 2011 19:54:28 +0100 Subject: [PATCH 0374/2822] pktcdvd: Convert to bdops->check_events() Convert from ->media_changed() to ->check_events(). pktcdvd needs to forward all event related operations to the underlying device. Forward ->check_events() instead of ->media_changed() and inherit disk->[async_]events. Signed-off-by: Tejun Heo Cc: Jens Axboe Cc: Kay Sievers Cc: Peter Osterlund --- drivers/block/pktcdvd.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c index 77d70eebb6b21..a077db27b7c9a 100644 --- a/drivers/block/pktcdvd.c +++ b/drivers/block/pktcdvd.c @@ -2796,7 +2796,8 @@ static int pkt_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd, return ret; } -static int pkt_media_changed(struct gendisk *disk) +static unsigned int pkt_check_events(struct gendisk *disk, + unsigned int clearing) { struct pktcdvd_device *pd = disk->private_data; struct gendisk *attached_disk; @@ -2806,9 +2807,9 @@ static int pkt_media_changed(struct gendisk *disk) if (!pd->bdev) return 0; attached_disk = pd->bdev->bd_disk; - if (!attached_disk) + if (!attached_disk || !attached_disk->fops->check_events) return 0; - return attached_disk->fops->media_changed(attached_disk); + return attached_disk->fops->check_events(attached_disk, clearing); } static const struct block_device_operations pktcdvd_ops = { @@ -2816,7 +2817,7 @@ static const struct block_device_operations pktcdvd_ops = { .open = pkt_open, .release = pkt_close, .ioctl = pkt_ioctl, - .media_changed = pkt_media_changed, + .check_events = pkt_check_events, }; static char *pktcdvd_devnode(struct gendisk *gd, mode_t *mode) @@ -2889,6 +2890,10 @@ static int pkt_setup_dev(dev_t dev, dev_t* pkt_dev) if (ret) goto out_new_dev; + /* inherit events of the host device */ + disk->events = pd->bdev->bd_disk->events; + disk->async_events = pd->bdev->bd_disk->async_events; + add_disk(disk); pkt_sysfs_dev_new(pd); -- GitLab From cafb0bfca1a73efd6d8a4a6a6a716e6134b96c24 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 9 Mar 2011 19:54:29 +0100 Subject: [PATCH 0375/2822] staging: Convert to bdops->check_events() Convert two staging drivers - blkvsc_drv and cyasblkdev_block - from ->media_changed() to ->check_events(). The former always indicated media changed while the latter always indicated media not changed. Not sure what the drivers are trying to achieve but keep the original behavior. Signed-off-by: Tejun Heo Acked-by: Greg Kroah-Hartman Cc: Jens Axboe Cc: Kay Sievers --- drivers/staging/hv/blkvsc_drv.c | 11 +++++++---- .../westbridge/astoria/block/cyasblkdev_block.c | 11 +++++++---- 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/drivers/staging/hv/blkvsc_drv.c b/drivers/staging/hv/blkvsc_drv.c index 4fb809485d9e6..1ecd7e17f5711 100644 --- a/drivers/staging/hv/blkvsc_drv.c +++ b/drivers/staging/hv/blkvsc_drv.c @@ -131,7 +131,8 @@ static void blkvsc_shutdown(struct device *device); static int blkvsc_open(struct block_device *bdev, fmode_t mode); static int blkvsc_release(struct gendisk *disk, fmode_t mode); -static int blkvsc_media_changed(struct gendisk *gd); +static unsigned int blkvsc_check_events(struct gendisk *gd, + unsigned int clearing); static int blkvsc_revalidate_disk(struct gendisk *gd); static int blkvsc_getgeo(struct block_device *bd, struct hd_geometry *hg); static int blkvsc_ioctl(struct block_device *bd, fmode_t mode, @@ -162,7 +163,7 @@ static const struct block_device_operations block_ops = { .owner = THIS_MODULE, .open = blkvsc_open, .release = blkvsc_release, - .media_changed = blkvsc_media_changed, + .check_events = blkvsc_check_events, .revalidate_disk = blkvsc_revalidate_disk, .getgeo = blkvsc_getgeo, .ioctl = blkvsc_ioctl, @@ -367,6 +368,7 @@ static int blkvsc_probe(struct device *device) else blkdev->gd->first_minor = 0; blkdev->gd->fops = &block_ops; + blkdev->gd->events = DISK_EVENT_MEDIA_CHANGE; blkdev->gd->private_data = blkdev; blkdev->gd->driverfs_dev = &(blkdev->device_ctx->device); sprintf(blkdev->gd->disk_name, "hd%c", 'a' + devnum); @@ -1352,10 +1354,11 @@ static int blkvsc_release(struct gendisk *disk, fmode_t mode) return 0; } -static int blkvsc_media_changed(struct gendisk *gd) +static unsigned int blkvsc_check_events(struct gendisk *gd, + unsigned int clearing) { DPRINT_DBG(BLKVSC_DRV, "- enter\n"); - return 1; + return DISK_EVENT_MEDIA_CHANGE; } static int blkvsc_revalidate_disk(struct gendisk *gd) diff --git a/drivers/staging/westbridge/astoria/block/cyasblkdev_block.c b/drivers/staging/westbridge/astoria/block/cyasblkdev_block.c index e1851f00be568..842cd9214a5ec 100644 --- a/drivers/staging/westbridge/astoria/block/cyasblkdev_block.c +++ b/drivers/staging/westbridge/astoria/block/cyasblkdev_block.c @@ -381,10 +381,10 @@ static int cyasblkdev_blk_ioctl( return -ENOTTY; } -/* Media_changed block_device opp +/* check_events block_device opp * this one is called by kernel to confirm if the media really changed * as we indicated by issuing check_disk_change() call */ -int cyasblkdev_media_changed(struct gendisk *gd) +unsigned int cyasblkdev_check_events(struct gendisk *gd, unsigned int clearing) { struct cyasblkdev_blk_data *bd; @@ -402,7 +402,7 @@ int cyasblkdev_media_changed(struct gendisk *gd) #endif } - /* return media change state "1" yes, 0 no */ + /* return media change state - DISK_EVENT_MEDIA_CHANGE yes, 0 no */ return 0; } @@ -432,7 +432,7 @@ static struct block_device_operations cyasblkdev_bdops = { .ioctl = cyasblkdev_blk_ioctl, /* .getgeo = cyasblkdev_blk_getgeo, */ /* added to support media removal( real and simulated) media */ - .media_changed = cyasblkdev_media_changed, + .check_events = cyasblkdev_check_events, /* added to support media removal( real and simulated) media */ .revalidate_disk = cyasblkdev_revalidate_disk, .owner = THIS_MODULE, @@ -1090,6 +1090,7 @@ static int cyasblkdev_add_disks(int bus_num, bd->user_disk_0->first_minor = devidx << CYASBLKDEV_SHIFT; bd->user_disk_0->minors = 8; bd->user_disk_0->fops = &cyasblkdev_bdops; + bd->user_disk_0->events = DISK_EVENT_MEDIA_CHANGE; bd->user_disk_0->private_data = bd; bd->user_disk_0->queue = bd->queue.queue; bd->dbgprn_flags = DBGPRN_RD_RQ; @@ -1190,6 +1191,7 @@ static int cyasblkdev_add_disks(int bus_num, bd->user_disk_1->first_minor = (devidx + 1) << CYASBLKDEV_SHIFT; bd->user_disk_1->minors = 8; bd->user_disk_1->fops = &cyasblkdev_bdops; + bd->user_disk_0->events = DISK_EVENT_MEDIA_CHANGE; bd->user_disk_1->private_data = bd; bd->user_disk_1->queue = bd->queue.queue; bd->dbgprn_flags = DBGPRN_RD_RQ; @@ -1278,6 +1280,7 @@ static int cyasblkdev_add_disks(int bus_num, (devidx + 2) << CYASBLKDEV_SHIFT; bd->system_disk->minors = 8; bd->system_disk->fops = &cyasblkdev_bdops; + bd->system_disk->events = DISK_EVENT_MEDIA_CHANGE; bd->system_disk->private_data = bd; bd->system_disk->queue = bd->queue.queue; /* don't search for vfat -- GitLab From 352b5d13c0684ba8cd103aa20cb74f105334562a Mon Sep 17 00:00:00 2001 From: "J. Bruce Fields" Date: Wed, 9 Mar 2011 22:40:30 -0500 Subject: [PATCH 0376/2822] svcrpc: fix bad argument in unix_domain_find "After merging the nfsd tree, today's linux-next build (powerpc ppc64_defconfig) produced this warning: net/sunrpc/svcauth_unix.c: In function 'unix_domain_find': net/sunrpc/svcauth_unix.c:58: warning: passing argument 1 of +'svcauth_unix_domain_release' from incompatible pointer type net/sunrpc/svcauth_unix.c:41: note: expected 'struct auth_domain *' but argument +is of type 'struct unix_domain *' Introduced by commit 8b3e07ac908d ("svcrpc: fix rare race on unix_domain creation")." Reported-by: Stephen Rothwell Signed-off-by: J. Bruce Fields --- net/sunrpc/svcauth_unix.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/sunrpc/svcauth_unix.c b/net/sunrpc/svcauth_unix.c index d100bf2b4e817..c8e10216c1134 100644 --- a/net/sunrpc/svcauth_unix.c +++ b/net/sunrpc/svcauth_unix.c @@ -55,7 +55,7 @@ struct auth_domain *unix_domain_find(char *name) while(1) { if (rv) { if (new && rv != &new->h) - svcauth_unix_domain_release(new); + svcauth_unix_domain_release(&new->h); if (rv->flavour != &svcauth_unix) { auth_domain_put(rv); -- GitLab From 3cca6dc1c81e2407928dc4c6105252146fd3924f Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Wed, 2 Mar 2011 11:08:00 -0500 Subject: [PATCH 0377/2822] block: add API for delaying work/request_fn a little bit Currently we use plugging for that, but as plugging is going away, we need an alternative mechanism. Signed-off-by: Jens Axboe --- block/blk-core.c | 29 +++++++++++++++++++++++++++++ include/linux/blkdev.h | 6 ++++++ 2 files changed, 35 insertions(+) diff --git a/block/blk-core.c b/block/blk-core.c index 3cc17e6064d68..e958c7a1e462d 100644 --- a/block/blk-core.c +++ b/block/blk-core.c @@ -197,6 +197,32 @@ void blk_dump_rq_flags(struct request *rq, char *msg) } EXPORT_SYMBOL(blk_dump_rq_flags); +static void blk_delay_work(struct work_struct *work) +{ + struct request_queue *q; + + q = container_of(work, struct request_queue, delay_work.work); + spin_lock_irq(q->queue_lock); + q->request_fn(q); + spin_unlock_irq(q->queue_lock); +} + +/** + * blk_delay_queue - restart queueing after defined interval + * @q: The &struct request_queue in question + * @msecs: Delay in msecs + * + * Description: + * Sometimes queueing needs to be postponed for a little while, to allow + * resources to come back. This function will make sure that queueing is + * restarted around the specified time. + */ +void blk_delay_queue(struct request_queue *q, unsigned long msecs) +{ + schedule_delayed_work(&q->delay_work, msecs_to_jiffies(msecs)); +} +EXPORT_SYMBOL(blk_delay_queue); + /* * "plug" the device if there are no outstanding requests: this will * force the transfer to start only after we have put all the requests @@ -363,6 +389,7 @@ EXPORT_SYMBOL(blk_start_queue); void blk_stop_queue(struct request_queue *q) { blk_remove_plug(q); + cancel_delayed_work(&q->delay_work); queue_flag_set(QUEUE_FLAG_STOPPED, q); } EXPORT_SYMBOL(blk_stop_queue); @@ -387,6 +414,7 @@ void blk_sync_queue(struct request_queue *q) del_timer_sync(&q->timeout); cancel_work_sync(&q->unplug_work); throtl_shutdown_timer_wq(q); + cancel_delayed_work_sync(&q->delay_work); } EXPORT_SYMBOL(blk_sync_queue); @@ -534,6 +562,7 @@ struct request_queue *blk_alloc_queue_node(gfp_t gfp_mask, int node_id) INIT_LIST_HEAD(&q->flush_queue[1]); INIT_LIST_HEAD(&q->flush_data_in_flight); INIT_WORK(&q->unplug_work, blk_unplug_work); + INIT_DELAYED_WORK(&q->delay_work, blk_delay_work); kobject_init(&q->kobj, &blk_queue_ktype); diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index e3ee74fc59030..f55b2a8b66104 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -300,6 +300,11 @@ struct request_queue unsigned long unplug_delay; /* After this many jiffies */ struct work_struct unplug_work; + /* + * Delayed queue handling + */ + struct delayed_work delay_work; + struct backing_dev_info backing_dev_info; /* @@ -677,6 +682,7 @@ extern int blk_insert_cloned_request(struct request_queue *q, extern void blk_plug_device(struct request_queue *); extern void blk_plug_device_unlocked(struct request_queue *); extern int blk_remove_plug(struct request_queue *); +extern void blk_delay_queue(struct request_queue *, unsigned long); extern void blk_recount_segments(struct request_queue *, struct bio *); extern int scsi_cmd_ioctl(struct request_queue *, struct gendisk *, fmode_t, unsigned int, void __user *); -- GitLab From 0a41e90bb7c931fd53d73ea770f5b251af6c91ce Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Fri, 16 Apr 2010 21:11:21 +0200 Subject: [PATCH 0378/2822] ide-cd: convert to blk_delay_queue() for a short pause It was always abuse to reuse the plugging infrastructure for this, convert it to the (new) real API for delaying queueing a bit. Signed-off-by: Jens Axboe Acked-by: David S. Miller --- drivers/ide/ide-cd.c | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c index 0c73fe39a236b..7ce9caf4521b7 100644 --- a/drivers/ide/ide-cd.c +++ b/drivers/ide/ide-cd.c @@ -258,17 +258,10 @@ static int ide_cd_breathe(ide_drive_t *drive, struct request *rq) if (time_after(jiffies, info->write_timeout)) return 0; else { - struct request_queue *q = drive->queue; - unsigned long flags; - /* - * take a breather relying on the unplug timer to kick us again + * take a breather */ - - spin_lock_irqsave(q->queue_lock, flags); - blk_plug_device(q); - spin_unlock_irqrestore(q->queue_lock, flags); - + blk_delay_queue(drive->queue, 1); return 1; } } @@ -1514,8 +1507,6 @@ static int ide_cdrom_setup(ide_drive_t *drive) blk_queue_dma_alignment(q, 31); blk_queue_update_dma_pad(q, 15); - q->unplug_delay = max((1 * HZ) / 1000, 1); - drive->dev_flags |= IDE_DFLAG_MEDIA_CHANGED; drive->atapi_flags = IDE_AFLAG_NO_EJECT | ide_cd_flags(id); -- GitLab From a488e74976bf0a9bccecdd094378394942dacef1 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Fri, 16 Apr 2010 21:13:15 +0200 Subject: [PATCH 0379/2822] scsi: convert to blk_delay_queue() It was always abuse to reuse the plugging infrastructure for this, convert it to the (new) real API for delaying queueing a bit. A default delay of 3 msec is defined, to match the previous behaviour. Signed-off-by: Jens Axboe --- drivers/scsi/scsi_lib.c | 44 ++++++++++++++++++----------------------- 1 file changed, 19 insertions(+), 25 deletions(-) diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 9045c52abd257..5a0ae7a944cef 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -67,6 +67,13 @@ static struct scsi_host_sg_pool scsi_sg_pools[] = { struct kmem_cache *scsi_sdb_cache; +/* + * When to reinvoke queueing after a resource shortage. It's 3 msecs to + * not change behaviour from the previous unplug mechanism, experimentation + * may prove this needs changing. + */ +#define SCSI_QUEUE_DELAY 3 + static void scsi_run_queue(struct request_queue *q); /* @@ -149,14 +156,7 @@ static int __scsi_queue_insert(struct scsi_cmnd *cmd, int reason, int unbusy) /* * Requeue this command. It will go before all other commands * that are already in the queue. - * - * NOTE: there is magic here about the way the queue is plugged if - * we have no outstanding commands. - * - * Although we *don't* plug the queue, we call the request - * function. The SCSI request function detects the blocked condition - * and plugs the queue appropriately. - */ + */ spin_lock_irqsave(q->queue_lock, flags); blk_requeue_request(q, cmd->request); spin_unlock_irqrestore(q->queue_lock, flags); @@ -1194,11 +1194,11 @@ int scsi_prep_return(struct request_queue *q, struct request *req, int ret) case BLKPREP_DEFER: /* * If we defer, the blk_peek_request() returns NULL, but the - * queue must be restarted, so we plug here if no returning - * command will automatically do that. + * queue must be restarted, so we schedule a callback to happen + * shortly. */ if (sdev->device_busy == 0) - blk_plug_device(q); + blk_delay_queue(q, SCSI_QUEUE_DELAY); break; default: req->cmd_flags |= REQ_DONTPREP; @@ -1237,7 +1237,7 @@ static inline int scsi_dev_queue_ready(struct request_queue *q, sdev_printk(KERN_INFO, sdev, "unblocking device at zero depth\n")); } else { - blk_plug_device(q); + blk_delay_queue(q, SCSI_QUEUE_DELAY); return 0; } } @@ -1467,7 +1467,7 @@ static void scsi_request_fn(struct request_queue *q) * the host is no longer able to accept any more requests. */ shost = sdev->host; - while (!blk_queue_plugged(q)) { + for (;;) { int rtn; /* * get next queueable request. We do this early to make sure @@ -1546,15 +1546,8 @@ static void scsi_request_fn(struct request_queue *q) */ rtn = scsi_dispatch_cmd(cmd); spin_lock_irq(q->queue_lock); - if(rtn) { - /* we're refusing the command; because of - * the way locks get dropped, we need to - * check here if plugging is required */ - if(sdev->device_busy == 0) - blk_plug_device(q); - - break; - } + if (rtn) + goto out_delay; } goto out; @@ -1573,9 +1566,10 @@ static void scsi_request_fn(struct request_queue *q) spin_lock_irq(q->queue_lock); blk_requeue_request(q, req); sdev->device_busy--; - if(sdev->device_busy == 0) - blk_plug_device(q); - out: +out_delay: + if (sdev->device_busy == 0) + blk_delay_queue(q, SCSI_QUEUE_DELAY); +out: /* must be careful here...if we trigger the ->remove() function * we cannot be holding the q lock */ spin_unlock_irq(q->queue_lock); -- GitLab From 73c101011926c5832e6e141682180c4debe2cf45 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Tue, 8 Mar 2011 13:19:51 +0100 Subject: [PATCH 0380/2822] block: initial patch for on-stack per-task plugging This patch adds support for creating a queuing context outside of the queue itself. This enables us to batch up pieces of IO before grabbing the block device queue lock and submitting them to the IO scheduler. The context is created on the stack of the process and assigned in the task structure, so that we can auto-unplug it if we hit a schedule event. The current queue plugging happens implicitly if IO is submitted to an empty device, yet callers have to remember to unplug that IO when they are going to wait for it. This is an ugly API and has caused bugs in the past. Additionally, it requires hacks in the vm (->sync_page() callback) to handle that logic. By switching to an explicit plugging scheme we make the API a lot nicer and can get rid of the ->sync_page() hack in the vm. Signed-off-by: Jens Axboe --- block/blk-core.c | 369 ++++++++++++++++++++++++++++---------- block/blk-flush.c | 3 +- block/elevator.c | 6 +- include/linux/blk_types.h | 2 + include/linux/blkdev.h | 42 +++++ include/linux/elevator.h | 1 + include/linux/sched.h | 6 + kernel/exit.c | 1 + kernel/fork.c | 3 + kernel/sched.c | 12 ++ 10 files changed, 344 insertions(+), 101 deletions(-) diff --git a/block/blk-core.c b/block/blk-core.c index e958c7a1e462d..6efb55cc5af06 100644 --- a/block/blk-core.c +++ b/block/blk-core.c @@ -27,6 +27,7 @@ #include #include #include +#include #define CREATE_TRACE_POINTS #include @@ -203,7 +204,7 @@ static void blk_delay_work(struct work_struct *work) q = container_of(work, struct request_queue, delay_work.work); spin_lock_irq(q->queue_lock); - q->request_fn(q); + __blk_run_queue(q); spin_unlock_irq(q->queue_lock); } @@ -686,6 +687,8 @@ int blk_get_queue(struct request_queue *q) static inline void blk_free_request(struct request_queue *q, struct request *rq) { + BUG_ON(rq->cmd_flags & REQ_ON_PLUG); + if (rq->cmd_flags & REQ_ELVPRIV) elv_put_request(q, rq); mempool_free(rq, q->rq.rq_pool); @@ -1051,6 +1054,13 @@ void blk_requeue_request(struct request_queue *q, struct request *rq) } EXPORT_SYMBOL(blk_requeue_request); +static void add_acct_request(struct request_queue *q, struct request *rq, + int where) +{ + drive_stat_acct(rq, 1); + __elv_add_request(q, rq, where, 0); +} + /** * blk_insert_request - insert a special request into a request queue * @q: request queue where request should be inserted @@ -1093,8 +1103,7 @@ void blk_insert_request(struct request_queue *q, struct request *rq, if (blk_rq_tagged(rq)) blk_queue_end_tag(q, rq); - drive_stat_acct(rq, 1); - __elv_add_request(q, rq, where, 0); + add_acct_request(q, rq, where); __blk_run_queue(q); spin_unlock_irqrestore(q->queue_lock, flags); } @@ -1215,6 +1224,113 @@ void blk_add_request_payload(struct request *rq, struct page *page, } EXPORT_SYMBOL_GPL(blk_add_request_payload); +static bool bio_attempt_back_merge(struct request_queue *q, struct request *req, + struct bio *bio) +{ + const int ff = bio->bi_rw & REQ_FAILFAST_MASK; + + /* + * Debug stuff, kill later + */ + if (!rq_mergeable(req)) { + blk_dump_rq_flags(req, "back"); + return false; + } + + if (!ll_back_merge_fn(q, req, bio)) + return false; + + trace_block_bio_backmerge(q, bio); + + if ((req->cmd_flags & REQ_FAILFAST_MASK) != ff) + blk_rq_set_mixed_merge(req); + + req->biotail->bi_next = bio; + req->biotail = bio; + req->__data_len += bio->bi_size; + req->ioprio = ioprio_best(req->ioprio, bio_prio(bio)); + + drive_stat_acct(req, 0); + return true; +} + +static bool bio_attempt_front_merge(struct request_queue *q, + struct request *req, struct bio *bio) +{ + const int ff = bio->bi_rw & REQ_FAILFAST_MASK; + sector_t sector; + + /* + * Debug stuff, kill later + */ + if (!rq_mergeable(req)) { + blk_dump_rq_flags(req, "front"); + return false; + } + + if (!ll_front_merge_fn(q, req, bio)) + return false; + + trace_block_bio_frontmerge(q, bio); + + if ((req->cmd_flags & REQ_FAILFAST_MASK) != ff) + blk_rq_set_mixed_merge(req); + + sector = bio->bi_sector; + + bio->bi_next = req->bio; + req->bio = bio; + + /* + * may not be valid. if the low level driver said + * it didn't need a bounce buffer then it better + * not touch req->buffer either... + */ + req->buffer = bio_data(bio); + req->__sector = bio->bi_sector; + req->__data_len += bio->bi_size; + req->ioprio = ioprio_best(req->ioprio, bio_prio(bio)); + + drive_stat_acct(req, 0); + return true; +} + +/* + * Attempts to merge with the plugged list in the current process. Returns + * true if merge was succesful, otherwise false. + */ +static bool attempt_plug_merge(struct task_struct *tsk, struct request_queue *q, + struct bio *bio) +{ + struct blk_plug *plug; + struct request *rq; + bool ret = false; + + plug = tsk->plug; + if (!plug) + goto out; + + list_for_each_entry_reverse(rq, &plug->list, queuelist) { + int el_ret; + + if (rq->q != q) + continue; + + el_ret = elv_try_merge(rq, bio); + if (el_ret == ELEVATOR_BACK_MERGE) { + ret = bio_attempt_back_merge(q, rq, bio); + if (ret) + break; + } else if (el_ret == ELEVATOR_FRONT_MERGE) { + ret = bio_attempt_front_merge(q, rq, bio); + if (ret) + break; + } + } +out: + return ret; +} + void init_request_from_bio(struct request *req, struct bio *bio) { req->cpu = bio->bi_comp_cpu; @@ -1230,26 +1346,12 @@ void init_request_from_bio(struct request *req, struct bio *bio) blk_rq_bio_prep(req->q, req, bio); } -/* - * Only disabling plugging for non-rotational devices if it does tagging - * as well, otherwise we do need the proper merging - */ -static inline bool queue_should_plug(struct request_queue *q) -{ - return !(blk_queue_nonrot(q) && blk_queue_tagged(q)); -} - static int __make_request(struct request_queue *q, struct bio *bio) { - struct request *req; - int el_ret; - unsigned int bytes = bio->bi_size; - const unsigned short prio = bio_prio(bio); const bool sync = !!(bio->bi_rw & REQ_SYNC); - const bool unplug = !!(bio->bi_rw & REQ_UNPLUG); - const unsigned long ff = bio->bi_rw & REQ_FAILFAST_MASK; - int where = ELEVATOR_INSERT_SORT; - int rw_flags; + struct blk_plug *plug; + int el_ret, rw_flags, where = ELEVATOR_INSERT_SORT; + struct request *req; /* * low level driver can indicate that it wants pages above a @@ -1258,78 +1360,36 @@ static int __make_request(struct request_queue *q, struct bio *bio) */ blk_queue_bounce(q, &bio); - spin_lock_irq(q->queue_lock); - if (bio->bi_rw & (REQ_FLUSH | REQ_FUA)) { + spin_lock_irq(q->queue_lock); where = ELEVATOR_INSERT_FLUSH; goto get_rq; } - if (elv_queue_empty(q)) - goto get_rq; - - el_ret = elv_merge(q, &req, bio); - switch (el_ret) { - case ELEVATOR_BACK_MERGE: - BUG_ON(!rq_mergeable(req)); - - if (!ll_back_merge_fn(q, req, bio)) - break; - - trace_block_bio_backmerge(q, bio); - - if ((req->cmd_flags & REQ_FAILFAST_MASK) != ff) - blk_rq_set_mixed_merge(req); - - req->biotail->bi_next = bio; - req->biotail = bio; - req->__data_len += bytes; - req->ioprio = ioprio_best(req->ioprio, prio); - if (!blk_rq_cpu_valid(req)) - req->cpu = bio->bi_comp_cpu; - drive_stat_acct(req, 0); - elv_bio_merged(q, req, bio); - if (!attempt_back_merge(q, req)) - elv_merged_request(q, req, el_ret); + /* + * Check if we can merge with the plugged list before grabbing + * any locks. + */ + if (attempt_plug_merge(current, q, bio)) goto out; - case ELEVATOR_FRONT_MERGE: - BUG_ON(!rq_mergeable(req)); - - if (!ll_front_merge_fn(q, req, bio)) - break; - - trace_block_bio_frontmerge(q, bio); + spin_lock_irq(q->queue_lock); - if ((req->cmd_flags & REQ_FAILFAST_MASK) != ff) { - blk_rq_set_mixed_merge(req); - req->cmd_flags &= ~REQ_FAILFAST_MASK; - req->cmd_flags |= ff; + el_ret = elv_merge(q, &req, bio); + if (el_ret == ELEVATOR_BACK_MERGE) { + BUG_ON(req->cmd_flags & REQ_ON_PLUG); + if (bio_attempt_back_merge(q, req, bio)) { + if (!attempt_back_merge(q, req)) + elv_merged_request(q, req, el_ret); + goto out_unlock; + } + } else if (el_ret == ELEVATOR_FRONT_MERGE) { + BUG_ON(req->cmd_flags & REQ_ON_PLUG); + if (bio_attempt_front_merge(q, req, bio)) { + if (!attempt_front_merge(q, req)) + elv_merged_request(q, req, el_ret); + goto out_unlock; } - - bio->bi_next = req->bio; - req->bio = bio; - - /* - * may not be valid. if the low level driver said - * it didn't need a bounce buffer then it better - * not touch req->buffer either... - */ - req->buffer = bio_data(bio); - req->__sector = bio->bi_sector; - req->__data_len += bytes; - req->ioprio = ioprio_best(req->ioprio, prio); - if (!blk_rq_cpu_valid(req)) - req->cpu = bio->bi_comp_cpu; - drive_stat_acct(req, 0); - elv_bio_merged(q, req, bio); - if (!attempt_front_merge(q, req)) - elv_merged_request(q, req, el_ret); - goto out; - - /* ELV_NO_MERGE: elevator says don't/can't merge. */ - default: - ; } get_rq: @@ -1356,20 +1416,35 @@ get_rq: */ init_request_from_bio(req, bio); - spin_lock_irq(q->queue_lock); if (test_bit(QUEUE_FLAG_SAME_COMP, &q->queue_flags) || - bio_flagged(bio, BIO_CPU_AFFINE)) - req->cpu = blk_cpu_to_group(smp_processor_id()); - if (queue_should_plug(q) && elv_queue_empty(q)) - blk_plug_device(q); - - /* insert the request into the elevator */ - drive_stat_acct(req, 1); - __elv_add_request(q, req, where, 0); + bio_flagged(bio, BIO_CPU_AFFINE)) { + req->cpu = blk_cpu_to_group(get_cpu()); + put_cpu(); + } + + plug = current->plug; + if (plug && !sync) { + if (!plug->should_sort && !list_empty(&plug->list)) { + struct request *__rq; + + __rq = list_entry_rq(plug->list.prev); + if (__rq->q != q) + plug->should_sort = 1; + } + /* + * Debug flag, kill later + */ + req->cmd_flags |= REQ_ON_PLUG; + list_add_tail(&req->queuelist, &plug->list); + drive_stat_acct(req, 1); + } else { + spin_lock_irq(q->queue_lock); + add_acct_request(q, req, where); + __blk_run_queue(q); +out_unlock: + spin_unlock_irq(q->queue_lock); + } out: - if (unplug || !queue_should_plug(q)) - __generic_unplug_device(q); - spin_unlock_irq(q->queue_lock); return 0; } @@ -1772,9 +1847,7 @@ int blk_insert_cloned_request(struct request_queue *q, struct request *rq) */ BUG_ON(blk_queued_rq(rq)); - drive_stat_acct(rq, 1); - __elv_add_request(q, rq, ELEVATOR_INSERT_BACK, 0); - + add_acct_request(q, rq, ELEVATOR_INSERT_BACK); spin_unlock_irqrestore(q->queue_lock, flags); return 0; @@ -2659,6 +2732,106 @@ int kblockd_schedule_delayed_work(struct request_queue *q, } EXPORT_SYMBOL(kblockd_schedule_delayed_work); +#define PLUG_MAGIC 0x91827364 + +void blk_start_plug(struct blk_plug *plug) +{ + struct task_struct *tsk = current; + + plug->magic = PLUG_MAGIC; + INIT_LIST_HEAD(&plug->list); + plug->should_sort = 0; + + /* + * If this is a nested plug, don't actually assign it. It will be + * flushed on its own. + */ + if (!tsk->plug) { + /* + * Store ordering should not be needed here, since a potential + * preempt will imply a full memory barrier + */ + tsk->plug = plug; + } +} +EXPORT_SYMBOL(blk_start_plug); + +static int plug_rq_cmp(void *priv, struct list_head *a, struct list_head *b) +{ + struct request *rqa = container_of(a, struct request, queuelist); + struct request *rqb = container_of(b, struct request, queuelist); + + return !(rqa->q == rqb->q); +} + +static void flush_plug_list(struct blk_plug *plug) +{ + struct request_queue *q; + unsigned long flags; + struct request *rq; + + BUG_ON(plug->magic != PLUG_MAGIC); + + if (list_empty(&plug->list)) + return; + + if (plug->should_sort) + list_sort(NULL, &plug->list, plug_rq_cmp); + + q = NULL; + local_irq_save(flags); + while (!list_empty(&plug->list)) { + rq = list_entry_rq(plug->list.next); + list_del_init(&rq->queuelist); + BUG_ON(!(rq->cmd_flags & REQ_ON_PLUG)); + BUG_ON(!rq->q); + if (rq->q != q) { + if (q) { + __blk_run_queue(q); + spin_unlock(q->queue_lock); + } + q = rq->q; + spin_lock(q->queue_lock); + } + rq->cmd_flags &= ~REQ_ON_PLUG; + + /* + * rq is already accounted, so use raw insert + */ + __elv_add_request(q, rq, ELEVATOR_INSERT_SORT, 0); + } + + if (q) { + __blk_run_queue(q); + spin_unlock(q->queue_lock); + } + + BUG_ON(!list_empty(&plug->list)); + local_irq_restore(flags); +} + +static void __blk_finish_plug(struct task_struct *tsk, struct blk_plug *plug) +{ + flush_plug_list(plug); + + if (plug == tsk->plug) + tsk->plug = NULL; +} + +void blk_finish_plug(struct blk_plug *plug) +{ + if (plug) + __blk_finish_plug(current, plug); +} +EXPORT_SYMBOL(blk_finish_plug); + +void __blk_flush_plug(struct task_struct *tsk, struct blk_plug *plug) +{ + __blk_finish_plug(tsk, plug); + tsk->plug = plug; +} +EXPORT_SYMBOL(__blk_flush_plug); + int __init blk_dev_init(void) { BUILD_BUG_ON(__REQ_NR_BITS > 8 * diff --git a/block/blk-flush.c b/block/blk-flush.c index a867e3f524f33..1e2aa8a8908c3 100644 --- a/block/blk-flush.c +++ b/block/blk-flush.c @@ -264,10 +264,9 @@ static bool blk_kick_flush(struct request_queue *q) static void flush_data_end_io(struct request *rq, int error) { struct request_queue *q = rq->q; - bool was_empty = elv_queue_empty(q); /* after populating an empty queue, kick it to avoid stall */ - if (blk_flush_complete_seq(rq, REQ_FSEQ_DATA, error) && was_empty) + if (blk_flush_complete_seq(rq, REQ_FSEQ_DATA, error)) __blk_run_queue(q); } diff --git a/block/elevator.c b/block/elevator.c index f98e92edc9378..25713927c0d36 100644 --- a/block/elevator.c +++ b/block/elevator.c @@ -113,7 +113,7 @@ int elv_rq_merge_ok(struct request *rq, struct bio *bio) } EXPORT_SYMBOL(elv_rq_merge_ok); -static inline int elv_try_merge(struct request *__rq, struct bio *bio) +int elv_try_merge(struct request *__rq, struct bio *bio) { int ret = ELEVATOR_NO_MERGE; @@ -421,6 +421,8 @@ void elv_dispatch_sort(struct request_queue *q, struct request *rq) struct list_head *entry; int stop_flags; + BUG_ON(rq->cmd_flags & REQ_ON_PLUG); + if (q->last_merge == rq) q->last_merge = NULL; @@ -696,6 +698,8 @@ void elv_insert(struct request_queue *q, struct request *rq, int where) void __elv_add_request(struct request_queue *q, struct request *rq, int where, int plug) { + BUG_ON(rq->cmd_flags & REQ_ON_PLUG); + if (rq->cmd_flags & REQ_SOFTBARRIER) { /* barriers are scheduling boundary, update end_sector */ if (rq->cmd_type == REQ_TYPE_FS || diff --git a/include/linux/blk_types.h b/include/linux/blk_types.h index dddedfc0af811..16b286473042d 100644 --- a/include/linux/blk_types.h +++ b/include/linux/blk_types.h @@ -152,6 +152,7 @@ enum rq_flag_bits { __REQ_IO_STAT, /* account I/O stat */ __REQ_MIXED_MERGE, /* merge of different types, fail separately */ __REQ_SECURE, /* secure discard (used with __REQ_DISCARD) */ + __REQ_ON_PLUG, /* on plug list */ __REQ_NR_BITS, /* stops here */ }; @@ -193,5 +194,6 @@ enum rq_flag_bits { #define REQ_IO_STAT (1 << __REQ_IO_STAT) #define REQ_MIXED_MERGE (1 << __REQ_MIXED_MERGE) #define REQ_SECURE (1 << __REQ_SECURE) +#define REQ_ON_PLUG (1 << __REQ_ON_PLUG) #endif /* __LINUX_BLK_TYPES_H */ diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index f55b2a8b66104..5873037eeb915 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -871,6 +871,31 @@ struct request_queue *blk_alloc_queue(gfp_t); struct request_queue *blk_alloc_queue_node(gfp_t, int); extern void blk_put_queue(struct request_queue *); +struct blk_plug { + unsigned long magic; + struct list_head list; + unsigned int should_sort; +}; + +extern void blk_start_plug(struct blk_plug *); +extern void blk_finish_plug(struct blk_plug *); +extern void __blk_flush_plug(struct task_struct *, struct blk_plug *); + +static inline void blk_flush_plug(struct task_struct *tsk) +{ + struct blk_plug *plug = tsk->plug; + + if (unlikely(plug)) + __blk_flush_plug(tsk, plug); +} + +static inline bool blk_needs_flush_plug(struct task_struct *tsk) +{ + struct blk_plug *plug = tsk->plug; + + return plug && !list_empty(&plug->list); +} + /* * tag stuff */ @@ -1294,6 +1319,23 @@ static inline long nr_blockdev_pages(void) return 0; } +static inline void blk_start_plug(struct list_head *list) +{ +} + +static inline void blk_finish_plug(struct list_head *list) +{ +} + +static inline void blk_flush_plug(struct task_struct *tsk) +{ +} + +static inline bool blk_needs_flush_plug(struct task_struct *tsk) +{ + return false; +} + #endif /* CONFIG_BLOCK */ #endif diff --git a/include/linux/elevator.h b/include/linux/elevator.h index 39b68edb388d3..8857cf9adbb71 100644 --- a/include/linux/elevator.h +++ b/include/linux/elevator.h @@ -105,6 +105,7 @@ extern void elv_add_request(struct request_queue *, struct request *, int, int); extern void __elv_add_request(struct request_queue *, struct request *, int, int); extern void elv_insert(struct request_queue *, struct request *, int); extern int elv_merge(struct request_queue *, struct request **, struct bio *); +extern int elv_try_merge(struct request *, struct bio *); extern void elv_merge_requests(struct request_queue *, struct request *, struct request *); extern void elv_merged_request(struct request_queue *, struct request *, int); diff --git a/include/linux/sched.h b/include/linux/sched.h index 777d8a5ed06be..96ac226437420 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -99,6 +99,7 @@ struct robust_list_head; struct bio_list; struct fs_struct; struct perf_event_context; +struct blk_plug; /* * List of flags we want to share for kernel threads, @@ -1429,6 +1430,11 @@ struct task_struct { /* stacked block device info */ struct bio_list *bio_list; +#ifdef CONFIG_BLOCK +/* stack plugging */ + struct blk_plug *plug; +#endif + /* VM state */ struct reclaim_state *reclaim_state; diff --git a/kernel/exit.c b/kernel/exit.c index f9a45ebcc7b17..6a488ad2dce5b 100644 --- a/kernel/exit.c +++ b/kernel/exit.c @@ -908,6 +908,7 @@ NORET_TYPE void do_exit(long code) profile_task_exit(tsk); WARN_ON(atomic_read(&tsk->fs_excl)); + WARN_ON(blk_needs_flush_plug(tsk)); if (unlikely(in_interrupt())) panic("Aiee, killing interrupt handler!"); diff --git a/kernel/fork.c b/kernel/fork.c index 25e429152ddc8..027c80e5162fa 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -1204,6 +1204,9 @@ static struct task_struct *copy_process(unsigned long clone_flags, * Clear TID on mm_release()? */ p->clear_child_tid = (clone_flags & CLONE_CHILD_CLEARTID) ? child_tidptr: NULL; +#ifdef CONFIG_BLOCK + p->plug = NULL; +#endif #ifdef CONFIG_FUTEX p->robust_list = NULL; #ifdef CONFIG_COMPAT diff --git a/kernel/sched.c b/kernel/sched.c index 18d38e4ec7ba2..ca098bf4cc65b 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -3978,6 +3978,16 @@ need_resched_nonpreemptible: switch_count = &prev->nvcsw; } + /* + * If we are going to sleep and we have plugged IO queued, make + * sure to submit it to avoid deadlocks. + */ + if (prev->state != TASK_RUNNING && blk_needs_flush_plug(prev)) { + raw_spin_unlock(&rq->lock); + blk_flush_plug(prev); + raw_spin_lock(&rq->lock); + } + pre_schedule(rq, prev); if (unlikely(!rq->nr_running)) @@ -5333,6 +5343,7 @@ void __sched io_schedule(void) delayacct_blkio_start(); atomic_inc(&rq->nr_iowait); + blk_flush_plug(current); current->in_iowait = 1; schedule(); current->in_iowait = 0; @@ -5348,6 +5359,7 @@ long __sched io_schedule_timeout(long timeout) delayacct_blkio_start(); atomic_inc(&rq->nr_iowait); + blk_flush_plug(current); current->in_iowait = 1; ret = schedule_timeout(timeout); current->in_iowait = 0; -- GitLab From 7eaceaccab5f40bbfda044629a6298616aeaed50 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Thu, 10 Mar 2011 08:52:07 +0100 Subject: [PATCH 0381/2822] block: remove per-queue plugging Code has been converted over to the new explicit on-stack plugging, and delay users have been converted to use the new API for that. So lets kill off the old plugging along with aops->sync_page(). Signed-off-by: Jens Axboe --- Documentation/block/biodoc.txt | 5 - block/blk-core.c | 173 ++++------------------------ block/blk-exec.c | 4 +- block/blk-flush.c | 3 +- block/blk-settings.c | 8 -- block/blk-throttle.c | 1 - block/blk.h | 2 - block/cfq-iosched.c | 8 -- block/deadline-iosched.c | 9 -- block/elevator.c | 43 +------ block/noop-iosched.c | 8 -- drivers/block/cciss.c | 6 - drivers/block/cpqarray.c | 3 - drivers/block/drbd/drbd_actlog.c | 2 - drivers/block/drbd/drbd_bitmap.c | 1 - drivers/block/drbd/drbd_int.h | 14 --- drivers/block/drbd/drbd_main.c | 33 +----- drivers/block/drbd/drbd_receiver.c | 20 +--- drivers/block/drbd/drbd_req.c | 4 - drivers/block/drbd/drbd_worker.c | 1 - drivers/block/drbd/drbd_wrappers.h | 18 --- drivers/block/floppy.c | 1 - drivers/block/loop.c | 13 --- drivers/block/pktcdvd.c | 2 - drivers/block/umem.c | 16 +-- drivers/ide/ide-atapi.c | 3 +- drivers/ide/ide-io.c | 4 - drivers/ide/ide-park.c | 2 +- drivers/md/bitmap.c | 3 +- drivers/md/dm-crypt.c | 9 +- drivers/md/dm-kcopyd.c | 52 +-------- drivers/md/dm-raid.c | 2 +- drivers/md/dm-raid1.c | 2 - drivers/md/dm-table.c | 24 ---- drivers/md/dm.c | 33 +----- drivers/md/linear.c | 17 --- drivers/md/md.c | 7 -- drivers/md/multipath.c | 31 ----- drivers/md/raid0.c | 16 --- drivers/md/raid1.c | 83 +++---------- drivers/md/raid10.c | 87 +++----------- drivers/md/raid5.c | 62 ++-------- drivers/md/raid5.h | 2 +- drivers/message/i2o/i2o_block.c | 6 +- drivers/mmc/card/queue.c | 3 +- drivers/s390/block/dasd.c | 2 +- drivers/s390/char/tape_block.c | 1 - drivers/scsi/scsi_transport_fc.c | 2 +- drivers/scsi/scsi_transport_sas.c | 6 +- drivers/target/target_core_iblock.c | 7 +- fs/adfs/inode.c | 1 - fs/affs/file.c | 2 - fs/aio.c | 4 +- fs/befs/linuxvfs.c | 1 - fs/bfs/file.c | 1 - fs/block_dev.c | 1 - fs/btrfs/disk-io.c | 79 ------------- fs/btrfs/inode.c | 1 - fs/btrfs/volumes.c | 91 ++------------- fs/buffer.c | 31 +---- fs/cifs/file.c | 30 ----- fs/direct-io.c | 5 +- fs/efs/inode.c | 1 - fs/exofs/inode.c | 1 - fs/ext2/inode.c | 2 - fs/ext3/inode.c | 3 - fs/ext4/inode.c | 4 - fs/fat/inode.c | 1 - fs/freevxfs/vxfs_subr.c | 1 - fs/fuse/inode.c | 1 - fs/gfs2/aops.c | 3 - fs/gfs2/meta_io.c | 1 - fs/hfs/inode.c | 2 - fs/hfsplus/inode.c | 2 - fs/hpfs/file.c | 1 - fs/isofs/inode.c | 1 - fs/jfs/inode.c | 1 - fs/jfs/jfs_metapage.c | 1 - fs/logfs/dev_bdev.c | 2 - fs/minix/inode.c | 1 - fs/nilfs2/btnode.c | 6 +- fs/nilfs2/gcinode.c | 1 - fs/nilfs2/inode.c | 1 - fs/nilfs2/mdt.c | 9 +- fs/nilfs2/page.c | 5 +- fs/nilfs2/page.h | 3 +- fs/ntfs/aops.c | 4 - fs/ntfs/compress.c | 3 +- fs/ocfs2/aops.c | 1 - fs/ocfs2/cluster/heartbeat.c | 4 - fs/omfs/file.c | 1 - fs/qnx4/inode.c | 1 - fs/reiserfs/inode.c | 1 - fs/sysv/itree.c | 1 - fs/ubifs/super.c | 1 - fs/udf/file.c | 1 - fs/udf/inode.c | 1 - fs/ufs/inode.c | 1 - fs/ufs/truncate.c | 2 +- fs/xfs/linux-2.6/xfs_aops.c | 1 - fs/xfs/linux-2.6/xfs_buf.c | 13 +-- include/linux/backing-dev.h | 16 --- include/linux/blkdev.h | 31 ++--- include/linux/buffer_head.h | 1 - include/linux/device-mapper.h | 5 - include/linux/elevator.h | 7 +- include/linux/fs.h | 1 - include/linux/pagemap.h | 12 -- include/linux/swap.h | 2 - mm/backing-dev.c | 6 - mm/filemap.c | 67 +---------- mm/memory-failure.c | 8 +- mm/nommu.c | 4 - mm/page-writeback.c | 2 +- mm/readahead.c | 12 -- mm/shmem.c | 1 - mm/swap_state.c | 5 +- mm/swapfile.c | 37 ------ mm/vmscan.c | 2 +- 119 files changed, 151 insertions(+), 1269 deletions(-) diff --git a/Documentation/block/biodoc.txt b/Documentation/block/biodoc.txt index b9a83dd247324..2a7b38c832c72 100644 --- a/Documentation/block/biodoc.txt +++ b/Documentation/block/biodoc.txt @@ -963,11 +963,6 @@ elevator_dispatch_fn* fills the dispatch queue with ready requests. elevator_add_req_fn* called to add a new request into the scheduler -elevator_queue_empty_fn returns true if the merge queue is empty. - Drivers shouldn't use this, but rather check - if elv_next_request is NULL (without losing the - request if one exists!) - elevator_former_req_fn elevator_latter_req_fn These return the request before or after the one specified in disk sort order. Used by the diff --git a/block/blk-core.c b/block/blk-core.c index 6efb55cc5af06..82a45898ba76f 100644 --- a/block/blk-core.c +++ b/block/blk-core.c @@ -198,6 +198,19 @@ void blk_dump_rq_flags(struct request *rq, char *msg) } EXPORT_SYMBOL(blk_dump_rq_flags); +/* + * Make sure that plugs that were pending when this function was entered, + * are now complete and requests pushed to the queue. +*/ +static inline void queue_sync_plugs(struct request_queue *q) +{ + /* + * If the current process is plugged and has barriers submitted, + * we will livelock if we don't unplug first. + */ + blk_flush_plug(current); +} + static void blk_delay_work(struct work_struct *work) { struct request_queue *q; @@ -224,137 +237,6 @@ void blk_delay_queue(struct request_queue *q, unsigned long msecs) } EXPORT_SYMBOL(blk_delay_queue); -/* - * "plug" the device if there are no outstanding requests: this will - * force the transfer to start only after we have put all the requests - * on the list. - * - * This is called with interrupts off and no requests on the queue and - * with the queue lock held. - */ -void blk_plug_device(struct request_queue *q) -{ - WARN_ON(!irqs_disabled()); - - /* - * don't plug a stopped queue, it must be paired with blk_start_queue() - * which will restart the queueing - */ - if (blk_queue_stopped(q)) - return; - - if (!queue_flag_test_and_set(QUEUE_FLAG_PLUGGED, q)) { - mod_timer(&q->unplug_timer, jiffies + q->unplug_delay); - trace_block_plug(q); - } -} -EXPORT_SYMBOL(blk_plug_device); - -/** - * blk_plug_device_unlocked - plug a device without queue lock held - * @q: The &struct request_queue to plug - * - * Description: - * Like @blk_plug_device(), but grabs the queue lock and disables - * interrupts. - **/ -void blk_plug_device_unlocked(struct request_queue *q) -{ - unsigned long flags; - - spin_lock_irqsave(q->queue_lock, flags); - blk_plug_device(q); - spin_unlock_irqrestore(q->queue_lock, flags); -} -EXPORT_SYMBOL(blk_plug_device_unlocked); - -/* - * remove the queue from the plugged list, if present. called with - * queue lock held and interrupts disabled. - */ -int blk_remove_plug(struct request_queue *q) -{ - WARN_ON(!irqs_disabled()); - - if (!queue_flag_test_and_clear(QUEUE_FLAG_PLUGGED, q)) - return 0; - - del_timer(&q->unplug_timer); - return 1; -} -EXPORT_SYMBOL(blk_remove_plug); - -/* - * remove the plug and let it rip.. - */ -void __generic_unplug_device(struct request_queue *q) -{ - if (unlikely(blk_queue_stopped(q))) - return; - if (!blk_remove_plug(q) && !blk_queue_nonrot(q)) - return; - - q->request_fn(q); -} - -/** - * generic_unplug_device - fire a request queue - * @q: The &struct request_queue in question - * - * Description: - * Linux uses plugging to build bigger requests queues before letting - * the device have at them. If a queue is plugged, the I/O scheduler - * is still adding and merging requests on the queue. Once the queue - * gets unplugged, the request_fn defined for the queue is invoked and - * transfers started. - **/ -void generic_unplug_device(struct request_queue *q) -{ - if (blk_queue_plugged(q)) { - spin_lock_irq(q->queue_lock); - __generic_unplug_device(q); - spin_unlock_irq(q->queue_lock); - } -} -EXPORT_SYMBOL(generic_unplug_device); - -static void blk_backing_dev_unplug(struct backing_dev_info *bdi, - struct page *page) -{ - struct request_queue *q = bdi->unplug_io_data; - - blk_unplug(q); -} - -void blk_unplug_work(struct work_struct *work) -{ - struct request_queue *q = - container_of(work, struct request_queue, unplug_work); - - trace_block_unplug_io(q); - q->unplug_fn(q); -} - -void blk_unplug_timeout(unsigned long data) -{ - struct request_queue *q = (struct request_queue *)data; - - trace_block_unplug_timer(q); - kblockd_schedule_work(q, &q->unplug_work); -} - -void blk_unplug(struct request_queue *q) -{ - /* - * devices don't necessarily have an ->unplug_fn defined - */ - if (q->unplug_fn) { - trace_block_unplug_io(q); - q->unplug_fn(q); - } -} -EXPORT_SYMBOL(blk_unplug); - /** * blk_start_queue - restart a previously stopped queue * @q: The &struct request_queue in question @@ -389,7 +271,6 @@ EXPORT_SYMBOL(blk_start_queue); **/ void blk_stop_queue(struct request_queue *q) { - blk_remove_plug(q); cancel_delayed_work(&q->delay_work); queue_flag_set(QUEUE_FLAG_STOPPED, q); } @@ -411,11 +292,10 @@ EXPORT_SYMBOL(blk_stop_queue); */ void blk_sync_queue(struct request_queue *q) { - del_timer_sync(&q->unplug_timer); del_timer_sync(&q->timeout); - cancel_work_sync(&q->unplug_work); throtl_shutdown_timer_wq(q); cancel_delayed_work_sync(&q->delay_work); + queue_sync_plugs(q); } EXPORT_SYMBOL(blk_sync_queue); @@ -430,14 +310,9 @@ EXPORT_SYMBOL(blk_sync_queue); */ void __blk_run_queue(struct request_queue *q) { - blk_remove_plug(q); - if (unlikely(blk_queue_stopped(q))) return; - if (elv_queue_empty(q)) - return; - /* * Only recurse once to avoid overrunning the stack, let the unplug * handling reinvoke the handler shortly if we already got there. @@ -445,10 +320,8 @@ void __blk_run_queue(struct request_queue *q) if (!queue_flag_test_and_set(QUEUE_FLAG_REENTER, q)) { q->request_fn(q); queue_flag_clear(QUEUE_FLAG_REENTER, q); - } else { - queue_flag_set(QUEUE_FLAG_PLUGGED, q); - kblockd_schedule_work(q, &q->unplug_work); - } + } else + queue_delayed_work(kblockd_workqueue, &q->delay_work, 0); } EXPORT_SYMBOL(__blk_run_queue); @@ -535,8 +408,6 @@ struct request_queue *blk_alloc_queue_node(gfp_t gfp_mask, int node_id) if (!q) return NULL; - q->backing_dev_info.unplug_io_fn = blk_backing_dev_unplug; - q->backing_dev_info.unplug_io_data = q; q->backing_dev_info.ra_pages = (VM_MAX_READAHEAD * 1024) / PAGE_CACHE_SIZE; q->backing_dev_info.state = 0; @@ -556,13 +427,11 @@ struct request_queue *blk_alloc_queue_node(gfp_t gfp_mask, int node_id) setup_timer(&q->backing_dev_info.laptop_mode_wb_timer, laptop_mode_timer_fn, (unsigned long) q); - init_timer(&q->unplug_timer); setup_timer(&q->timeout, blk_rq_timed_out_timer, (unsigned long) q); INIT_LIST_HEAD(&q->timeout_list); INIT_LIST_HEAD(&q->flush_queue[0]); INIT_LIST_HEAD(&q->flush_queue[1]); INIT_LIST_HEAD(&q->flush_data_in_flight); - INIT_WORK(&q->unplug_work, blk_unplug_work); INIT_DELAYED_WORK(&q->delay_work, blk_delay_work); kobject_init(&q->kobj, &blk_queue_ktype); @@ -652,7 +521,6 @@ blk_init_allocated_queue_node(struct request_queue *q, request_fn_proc *rfn, q->request_fn = rfn; q->prep_rq_fn = NULL; q->unprep_rq_fn = NULL; - q->unplug_fn = generic_unplug_device; q->queue_flags = QUEUE_FLAG_DEFAULT; q->queue_lock = lock; @@ -910,8 +778,8 @@ out: } /* - * No available requests for this queue, unplug the device and wait for some - * requests to become available. + * No available requests for this queue, wait for some requests to become + * available. * * Called with q->queue_lock held, and returns with it unlocked. */ @@ -932,7 +800,6 @@ static struct request *get_request_wait(struct request_queue *q, int rw_flags, trace_block_sleeprq(q, bio, rw_flags & 1); - __generic_unplug_device(q); spin_unlock_irq(q->queue_lock); io_schedule(); @@ -1058,7 +925,7 @@ static void add_acct_request(struct request_queue *q, struct request *rq, int where) { drive_stat_acct(rq, 1); - __elv_add_request(q, rq, where, 0); + __elv_add_request(q, rq, where); } /** @@ -2798,7 +2665,7 @@ static void flush_plug_list(struct blk_plug *plug) /* * rq is already accounted, so use raw insert */ - __elv_add_request(q, rq, ELEVATOR_INSERT_SORT, 0); + __elv_add_request(q, rq, ELEVATOR_INSERT_SORT); } if (q) { diff --git a/block/blk-exec.c b/block/blk-exec.c index cf1456a02acdf..81e31819a597b 100644 --- a/block/blk-exec.c +++ b/block/blk-exec.c @@ -54,8 +54,8 @@ void blk_execute_rq_nowait(struct request_queue *q, struct gendisk *bd_disk, rq->end_io = done; WARN_ON(irqs_disabled()); spin_lock_irq(q->queue_lock); - __elv_add_request(q, rq, where, 1); - __generic_unplug_device(q); + __elv_add_request(q, rq, where); + __blk_run_queue(q); /* the queue is stopped so it won't be plugged+unplugged */ if (rq->cmd_type == REQ_TYPE_PM_RESUME) q->request_fn(q); diff --git a/block/blk-flush.c b/block/blk-flush.c index 1e2aa8a8908c3..671fa9da75600 100644 --- a/block/blk-flush.c +++ b/block/blk-flush.c @@ -194,7 +194,6 @@ static void flush_end_io(struct request *flush_rq, int error) { struct request_queue *q = flush_rq->q; struct list_head *running = &q->flush_queue[q->flush_running_idx]; - bool was_empty = elv_queue_empty(q); bool queued = false; struct request *rq, *n; @@ -213,7 +212,7 @@ static void flush_end_io(struct request *flush_rq, int error) } /* after populating an empty queue, kick it to avoid stall */ - if (queued && was_empty) + if (queued) __blk_run_queue(q); } diff --git a/block/blk-settings.c b/block/blk-settings.c index 36c8c1f2af180..c8d68921dddb2 100644 --- a/block/blk-settings.c +++ b/block/blk-settings.c @@ -164,14 +164,6 @@ void blk_queue_make_request(struct request_queue *q, make_request_fn *mfn) blk_queue_congestion_threshold(q); q->nr_batching = BLK_BATCH_REQ; - q->unplug_thresh = 4; /* hmm */ - q->unplug_delay = msecs_to_jiffies(3); /* 3 milliseconds */ - if (q->unplug_delay == 0) - q->unplug_delay = 1; - - q->unplug_timer.function = blk_unplug_timeout; - q->unplug_timer.data = (unsigned long)q; - blk_set_default_limits(&q->limits); blk_queue_max_hw_sectors(q, BLK_SAFE_MAX_SECTORS); diff --git a/block/blk-throttle.c b/block/blk-throttle.c index a89043a3caa41..b8dcdc2663a11 100644 --- a/block/blk-throttle.c +++ b/block/blk-throttle.c @@ -800,7 +800,6 @@ out: if (nr_disp) { while((bio = bio_list_pop(&bio_list_on_stack))) generic_make_request(bio); - blk_unplug(q); } return nr_disp; } diff --git a/block/blk.h b/block/blk.h index 284b500852bd5..49d21af81d07f 100644 --- a/block/blk.h +++ b/block/blk.h @@ -18,8 +18,6 @@ int blk_rq_append_bio(struct request_queue *q, struct request *rq, void blk_dequeue_request(struct request *rq); void __blk_queue_free_tags(struct request_queue *q); -void blk_unplug_work(struct work_struct *work); -void blk_unplug_timeout(unsigned long data); void blk_rq_timed_out_timer(unsigned long data); void blk_delete_timer(struct request *); void blk_add_timer(struct request *); diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c index 3202c7e87fb3d..ef631539dd2ac 100644 --- a/block/cfq-iosched.c +++ b/block/cfq-iosched.c @@ -499,13 +499,6 @@ static inline void cfq_schedule_dispatch(struct cfq_data *cfqd) } } -static int cfq_queue_empty(struct request_queue *q) -{ - struct cfq_data *cfqd = q->elevator->elevator_data; - - return !cfqd->rq_queued; -} - /* * Scale schedule slice based on io priority. Use the sync time slice only * if a queue is marked sync and has sync io queued. A sync queue with async @@ -4061,7 +4054,6 @@ static struct elevator_type iosched_cfq = { .elevator_add_req_fn = cfq_insert_request, .elevator_activate_req_fn = cfq_activate_request, .elevator_deactivate_req_fn = cfq_deactivate_request, - .elevator_queue_empty_fn = cfq_queue_empty, .elevator_completed_req_fn = cfq_completed_request, .elevator_former_req_fn = elv_rb_former_request, .elevator_latter_req_fn = elv_rb_latter_request, diff --git a/block/deadline-iosched.c b/block/deadline-iosched.c index b547cbca7b23a..5139c0ea1864a 100644 --- a/block/deadline-iosched.c +++ b/block/deadline-iosched.c @@ -326,14 +326,6 @@ dispatch_request: return 1; } -static int deadline_queue_empty(struct request_queue *q) -{ - struct deadline_data *dd = q->elevator->elevator_data; - - return list_empty(&dd->fifo_list[WRITE]) - && list_empty(&dd->fifo_list[READ]); -} - static void deadline_exit_queue(struct elevator_queue *e) { struct deadline_data *dd = e->elevator_data; @@ -445,7 +437,6 @@ static struct elevator_type iosched_deadline = { .elevator_merge_req_fn = deadline_merged_requests, .elevator_dispatch_fn = deadline_dispatch_requests, .elevator_add_req_fn = deadline_add_request, - .elevator_queue_empty_fn = deadline_queue_empty, .elevator_former_req_fn = elv_rb_former_request, .elevator_latter_req_fn = elv_rb_latter_request, .elevator_init_fn = deadline_init_queue, diff --git a/block/elevator.c b/block/elevator.c index 25713927c0d36..3ea208256e783 100644 --- a/block/elevator.c +++ b/block/elevator.c @@ -619,21 +619,12 @@ void elv_quiesce_end(struct request_queue *q) void elv_insert(struct request_queue *q, struct request *rq, int where) { - int unplug_it = 1; - trace_block_rq_insert(q, rq); rq->q = q; switch (where) { case ELEVATOR_INSERT_REQUEUE: - /* - * Most requeues happen because of a busy condition, - * don't force unplug of the queue for that case. - * Clear unplug_it and fall through. - */ - unplug_it = 0; - case ELEVATOR_INSERT_FRONT: rq->cmd_flags |= REQ_SOFTBARRIER; list_add(&rq->queuelist, &q->queue_head); @@ -679,24 +670,14 @@ void elv_insert(struct request_queue *q, struct request *rq, int where) rq->cmd_flags |= REQ_SOFTBARRIER; blk_insert_flush(rq); break; - default: printk(KERN_ERR "%s: bad insertion point %d\n", __func__, where); BUG(); } - - if (unplug_it && blk_queue_plugged(q)) { - int nrq = q->rq.count[BLK_RW_SYNC] + q->rq.count[BLK_RW_ASYNC] - - queue_in_flight(q); - - if (nrq >= q->unplug_thresh) - __generic_unplug_device(q); - } } -void __elv_add_request(struct request_queue *q, struct request *rq, int where, - int plug) +void __elv_add_request(struct request_queue *q, struct request *rq, int where) { BUG_ON(rq->cmd_flags & REQ_ON_PLUG); @@ -711,38 +692,20 @@ void __elv_add_request(struct request_queue *q, struct request *rq, int where, where == ELEVATOR_INSERT_SORT) where = ELEVATOR_INSERT_BACK; - if (plug) - blk_plug_device(q); - elv_insert(q, rq, where); } EXPORT_SYMBOL(__elv_add_request); -void elv_add_request(struct request_queue *q, struct request *rq, int where, - int plug) +void elv_add_request(struct request_queue *q, struct request *rq, int where) { unsigned long flags; spin_lock_irqsave(q->queue_lock, flags); - __elv_add_request(q, rq, where, plug); + __elv_add_request(q, rq, where); spin_unlock_irqrestore(q->queue_lock, flags); } EXPORT_SYMBOL(elv_add_request); -int elv_queue_empty(struct request_queue *q) -{ - struct elevator_queue *e = q->elevator; - - if (!list_empty(&q->queue_head)) - return 0; - - if (e->ops->elevator_queue_empty_fn) - return e->ops->elevator_queue_empty_fn(q); - - return 1; -} -EXPORT_SYMBOL(elv_queue_empty); - struct request *elv_latter_request(struct request_queue *q, struct request *rq) { struct elevator_queue *e = q->elevator; diff --git a/block/noop-iosched.c b/block/noop-iosched.c index 232c4b38cd376..06389e9ef96d5 100644 --- a/block/noop-iosched.c +++ b/block/noop-iosched.c @@ -39,13 +39,6 @@ static void noop_add_request(struct request_queue *q, struct request *rq) list_add_tail(&rq->queuelist, &nd->queue); } -static int noop_queue_empty(struct request_queue *q) -{ - struct noop_data *nd = q->elevator->elevator_data; - - return list_empty(&nd->queue); -} - static struct request * noop_former_request(struct request_queue *q, struct request *rq) { @@ -90,7 +83,6 @@ static struct elevator_type elevator_noop = { .elevator_merge_req_fn = noop_merged_requests, .elevator_dispatch_fn = noop_dispatch, .elevator_add_req_fn = noop_add_request, - .elevator_queue_empty_fn = noop_queue_empty, .elevator_former_req_fn = noop_former_request, .elevator_latter_req_fn = noop_latter_request, .elevator_init_fn = noop_init_queue, diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c index 9279272b37327..35658f445fca4 100644 --- a/drivers/block/cciss.c +++ b/drivers/block/cciss.c @@ -3170,12 +3170,6 @@ static void do_cciss_request(struct request_queue *q) int sg_index = 0; int chained = 0; - /* We call start_io here in case there is a command waiting on the - * queue that has not been sent. - */ - if (blk_queue_plugged(q)) - goto startio; - queue: creq = blk_peek_request(q); if (!creq) diff --git a/drivers/block/cpqarray.c b/drivers/block/cpqarray.c index 946dad4caef37..b2fceb53e8092 100644 --- a/drivers/block/cpqarray.c +++ b/drivers/block/cpqarray.c @@ -911,9 +911,6 @@ static void do_ida_request(struct request_queue *q) struct scatterlist tmp_sg[SG_MAX]; int i, dir, seg; - if (blk_queue_plugged(q)) - goto startio; - queue_next: creq = blk_peek_request(q); if (!creq) diff --git a/drivers/block/drbd/drbd_actlog.c b/drivers/block/drbd/drbd_actlog.c index ba95cba192be8..2096628d6e655 100644 --- a/drivers/block/drbd/drbd_actlog.c +++ b/drivers/block/drbd/drbd_actlog.c @@ -689,8 +689,6 @@ void drbd_al_to_on_disk_bm(struct drbd_conf *mdev) } } - drbd_blk_run_queue(bdev_get_queue(mdev->ldev->md_bdev)); - /* always (try to) flush bitmap to stable storage */ drbd_md_flush(mdev); diff --git a/drivers/block/drbd/drbd_bitmap.c b/drivers/block/drbd/drbd_bitmap.c index fd42832f785b8..0645ca829a941 100644 --- a/drivers/block/drbd/drbd_bitmap.c +++ b/drivers/block/drbd/drbd_bitmap.c @@ -840,7 +840,6 @@ static int bm_rw(struct drbd_conf *mdev, int rw) __must_hold(local) for (i = 0; i < num_pages; i++) bm_page_io_async(mdev, b, i, rw); - drbd_blk_run_queue(bdev_get_queue(mdev->ldev->md_bdev)); wait_event(b->bm_io_wait, atomic_read(&b->bm_async_io) == 0); if (test_bit(BM_MD_IO_ERROR, &b->bm_flags)) { diff --git a/drivers/block/drbd/drbd_int.h b/drivers/block/drbd/drbd_int.h index 3803a03489372..0b5718e19586d 100644 --- a/drivers/block/drbd/drbd_int.h +++ b/drivers/block/drbd/drbd_int.h @@ -2382,20 +2382,6 @@ static inline int drbd_queue_order_type(struct drbd_conf *mdev) return QUEUE_ORDERED_NONE; } -static inline void drbd_blk_run_queue(struct request_queue *q) -{ - if (q && q->unplug_fn) - q->unplug_fn(q); -} - -static inline void drbd_kick_lo(struct drbd_conf *mdev) -{ - if (get_ldev(mdev)) { - drbd_blk_run_queue(bdev_get_queue(mdev->ldev->backing_bdev)); - put_ldev(mdev); - } -} - static inline void drbd_md_flush(struct drbd_conf *mdev) { int r; diff --git a/drivers/block/drbd/drbd_main.c b/drivers/block/drbd/drbd_main.c index 29cd0dc9fe4f8..6049cb85310dc 100644 --- a/drivers/block/drbd/drbd_main.c +++ b/drivers/block/drbd/drbd_main.c @@ -2719,35 +2719,6 @@ static int drbd_release(struct gendisk *gd, fmode_t mode) return 0; } -static void drbd_unplug_fn(struct request_queue *q) -{ - struct drbd_conf *mdev = q->queuedata; - - /* unplug FIRST */ - spin_lock_irq(q->queue_lock); - blk_remove_plug(q); - spin_unlock_irq(q->queue_lock); - - /* only if connected */ - spin_lock_irq(&mdev->req_lock); - if (mdev->state.pdsk >= D_INCONSISTENT && mdev->state.conn >= C_CONNECTED) { - D_ASSERT(mdev->state.role == R_PRIMARY); - if (test_and_clear_bit(UNPLUG_REMOTE, &mdev->flags)) { - /* add to the data.work queue, - * unless already queued. - * XXX this might be a good addition to drbd_queue_work - * anyways, to detect "double queuing" ... */ - if (list_empty(&mdev->unplug_work.list)) - drbd_queue_work(&mdev->data.work, - &mdev->unplug_work); - } - } - spin_unlock_irq(&mdev->req_lock); - - if (mdev->state.disk >= D_INCONSISTENT) - drbd_kick_lo(mdev); -} - static void drbd_set_defaults(struct drbd_conf *mdev) { /* This way we get a compile error when sync_conf grows, @@ -3222,9 +3193,7 @@ struct drbd_conf *drbd_new_device(unsigned int minor) blk_queue_max_segment_size(q, DRBD_MAX_SEGMENT_SIZE); blk_queue_bounce_limit(q, BLK_BOUNCE_ANY); blk_queue_merge_bvec(q, drbd_merge_bvec); - q->queue_lock = &mdev->req_lock; /* needed since we use */ - /* plugging on a queue, that actually has no requests! */ - q->unplug_fn = drbd_unplug_fn; + q->queue_lock = &mdev->req_lock; mdev->md_io_page = alloc_page(GFP_KERNEL); if (!mdev->md_io_page) diff --git a/drivers/block/drbd/drbd_receiver.c b/drivers/block/drbd/drbd_receiver.c index 24487d4fb2029..84132f8bf8a41 100644 --- a/drivers/block/drbd/drbd_receiver.c +++ b/drivers/block/drbd/drbd_receiver.c @@ -187,15 +187,6 @@ static struct page *drbd_pp_first_pages_or_try_alloc(struct drbd_conf *mdev, int return NULL; } -/* kick lower level device, if we have more than (arbitrary number) - * reference counts on it, which typically are locally submitted io - * requests. don't use unacked_cnt, so we speed up proto A and B, too. */ -static void maybe_kick_lo(struct drbd_conf *mdev) -{ - if (atomic_read(&mdev->local_cnt) >= mdev->net_conf->unplug_watermark) - drbd_kick_lo(mdev); -} - static void reclaim_net_ee(struct drbd_conf *mdev, struct list_head *to_be_freed) { struct drbd_epoch_entry *e; @@ -219,7 +210,6 @@ static void drbd_kick_lo_and_reclaim_net(struct drbd_conf *mdev) LIST_HEAD(reclaimed); struct drbd_epoch_entry *e, *t; - maybe_kick_lo(mdev); spin_lock_irq(&mdev->req_lock); reclaim_net_ee(mdev, &reclaimed); spin_unlock_irq(&mdev->req_lock); @@ -436,8 +426,7 @@ void _drbd_wait_ee_list_empty(struct drbd_conf *mdev, struct list_head *head) while (!list_empty(head)) { prepare_to_wait(&mdev->ee_wait, &wait, TASK_UNINTERRUPTIBLE); spin_unlock_irq(&mdev->req_lock); - drbd_kick_lo(mdev); - schedule(); + io_schedule(); finish_wait(&mdev->ee_wait, &wait); spin_lock_irq(&mdev->req_lock); } @@ -1147,7 +1136,6 @@ next_bio: drbd_generic_make_request(mdev, fault_type, bio); } while (bios); - maybe_kick_lo(mdev); return 0; fail: @@ -1167,9 +1155,6 @@ static int receive_Barrier(struct drbd_conf *mdev, enum drbd_packets cmd, unsign inc_unacked(mdev); - if (mdev->net_conf->wire_protocol != DRBD_PROT_C) - drbd_kick_lo(mdev); - mdev->current_epoch->barrier_nr = p->barrier; rv = drbd_may_finish_epoch(mdev, mdev->current_epoch, EV_GOT_BARRIER_NR); @@ -3556,9 +3541,6 @@ static int receive_skip(struct drbd_conf *mdev, enum drbd_packets cmd, unsigned static int receive_UnplugRemote(struct drbd_conf *mdev, enum drbd_packets cmd, unsigned int data_size) { - if (mdev->state.disk >= D_INCONSISTENT) - drbd_kick_lo(mdev); - /* Make sure we've acked all the TCP data associated * with the data requests being unplugged */ drbd_tcp_quickack(mdev->data.socket); diff --git a/drivers/block/drbd/drbd_req.c b/drivers/block/drbd/drbd_req.c index 11a75d32a2e27..ad3fc6228f279 100644 --- a/drivers/block/drbd/drbd_req.c +++ b/drivers/block/drbd/drbd_req.c @@ -960,10 +960,6 @@ allocate_barrier: bio_endio(req->private_bio, -EIO); } - /* we need to plug ALWAYS since we possibly need to kick lo_dev. - * we plug after submit, so we won't miss an unplug event */ - drbd_plug_device(mdev); - return 0; fail_conflicting: diff --git a/drivers/block/drbd/drbd_worker.c b/drivers/block/drbd/drbd_worker.c index 34f224b018b37..e027446590d37 100644 --- a/drivers/block/drbd/drbd_worker.c +++ b/drivers/block/drbd/drbd_worker.c @@ -792,7 +792,6 @@ int drbd_resync_finished(struct drbd_conf *mdev) * queue (or even the read operations for those packets * is not finished by now). Retry in 100ms. */ - drbd_kick_lo(mdev); __set_current_state(TASK_INTERRUPTIBLE); schedule_timeout(HZ / 10); w = kmalloc(sizeof(struct drbd_work), GFP_ATOMIC); diff --git a/drivers/block/drbd/drbd_wrappers.h b/drivers/block/drbd/drbd_wrappers.h index defdb5013ea34..53586fa5ae1b0 100644 --- a/drivers/block/drbd/drbd_wrappers.h +++ b/drivers/block/drbd/drbd_wrappers.h @@ -45,24 +45,6 @@ static inline void drbd_generic_make_request(struct drbd_conf *mdev, generic_make_request(bio); } -static inline void drbd_plug_device(struct drbd_conf *mdev) -{ - struct request_queue *q; - q = bdev_get_queue(mdev->this_bdev); - - spin_lock_irq(q->queue_lock); - -/* XXX the check on !blk_queue_plugged is redundant, - * implicitly checked in blk_plug_device */ - - if (!blk_queue_plugged(q)) { - blk_plug_device(q); - del_timer(&q->unplug_timer); - /* unplugging should not happen automatically... */ - } - spin_unlock_irq(q->queue_lock); -} - static inline int drbd_crypto_is_hash(struct crypto_tfm *tfm) { return (crypto_tfm_alg_type(tfm) & CRYPTO_ALG_TYPE_HASH_MASK) diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c index b9ba04fc2b34e..271142b9e2cd6 100644 --- a/drivers/block/floppy.c +++ b/drivers/block/floppy.c @@ -3837,7 +3837,6 @@ static int __floppy_read_block_0(struct block_device *bdev) bio.bi_end_io = floppy_rb0_complete; submit_bio(READ, &bio); - generic_unplug_device(bdev_get_queue(bdev)); process_fd_request(); wait_for_completion(&complete); diff --git a/drivers/block/loop.c b/drivers/block/loop.c index 49e6a545eb63f..01b8e4a87c9f0 100644 --- a/drivers/block/loop.c +++ b/drivers/block/loop.c @@ -541,17 +541,6 @@ out: return 0; } -/* - * kick off io on the underlying address space - */ -static void loop_unplug(struct request_queue *q) -{ - struct loop_device *lo = q->queuedata; - - queue_flag_clear_unlocked(QUEUE_FLAG_PLUGGED, q); - blk_run_address_space(lo->lo_backing_file->f_mapping); -} - struct switch_request { struct file *file; struct completion wait; @@ -918,7 +907,6 @@ static int loop_set_fd(struct loop_device *lo, fmode_t mode, */ blk_queue_make_request(lo->lo_queue, loop_make_request); lo->lo_queue->queuedata = lo; - lo->lo_queue->unplug_fn = loop_unplug; if (!(lo_flags & LO_FLAGS_READ_ONLY) && file->f_op->fsync) blk_queue_flush(lo->lo_queue, REQ_FLUSH); @@ -1020,7 +1008,6 @@ static int loop_clr_fd(struct loop_device *lo, struct block_device *bdev) kthread_stop(lo->lo_thread); - lo->lo_queue->unplug_fn = NULL; lo->lo_backing_file = NULL; loop_release_xfer(lo); diff --git a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c index 77d70eebb6b21..d20e13f800017 100644 --- a/drivers/block/pktcdvd.c +++ b/drivers/block/pktcdvd.c @@ -1606,8 +1606,6 @@ static int kcdrwd(void *foobar) min_sleep_time = pkt->sleep_time; } - generic_unplug_device(bdev_get_queue(pd->bdev)); - VPRINTK("kcdrwd: sleeping\n"); residue = schedule_timeout(min_sleep_time); VPRINTK("kcdrwd: wake up\n"); diff --git a/drivers/block/umem.c b/drivers/block/umem.c index 8be57151f5d65..653439faa7293 100644 --- a/drivers/block/umem.c +++ b/drivers/block/umem.c @@ -241,8 +241,7 @@ static void dump_dmastat(struct cardinfo *card, unsigned int dmastat) * * Whenever IO on the active page completes, the Ready page is activated * and the ex-Active page is clean out and made Ready. - * Otherwise the Ready page is only activated when it becomes full, or - * when mm_unplug_device is called via the unplug_io_fn. + * Otherwise the Ready page is only activated when it becomes full. * * If a request arrives while both pages a full, it is queued, and b_rdev is * overloaded to record whether it was a read or a write. @@ -333,17 +332,6 @@ static inline void reset_page(struct mm_page *page) page->biotail = &page->bio; } -static void mm_unplug_device(struct request_queue *q) -{ - struct cardinfo *card = q->queuedata; - unsigned long flags; - - spin_lock_irqsave(&card->lock, flags); - if (blk_remove_plug(q)) - activate(card); - spin_unlock_irqrestore(&card->lock, flags); -} - /* * If there is room on Ready page, take * one bh off list and add it. @@ -535,7 +523,6 @@ static int mm_make_request(struct request_queue *q, struct bio *bio) *card->biotail = bio; bio->bi_next = NULL; card->biotail = &bio->bi_next; - blk_plug_device(q); spin_unlock_irq(&card->lock); return 0; @@ -907,7 +894,6 @@ static int __devinit mm_pci_probe(struct pci_dev *dev, blk_queue_make_request(card->queue, mm_make_request); card->queue->queue_lock = &card->lock; card->queue->queuedata = card; - card->queue->unplug_fn = mm_unplug_device; tasklet_init(&card->tasklet, process_page, (unsigned long)card); diff --git a/drivers/ide/ide-atapi.c b/drivers/ide/ide-atapi.c index e88a2cf177110..6f218e014e994 100644 --- a/drivers/ide/ide-atapi.c +++ b/drivers/ide/ide-atapi.c @@ -233,8 +233,7 @@ int ide_queue_sense_rq(ide_drive_t *drive, void *special) drive->hwif->rq = NULL; - elv_add_request(drive->queue, &drive->sense_rq, - ELEVATOR_INSERT_FRONT, 0); + elv_add_request(drive->queue, &drive->sense_rq, ELEVATOR_INSERT_FRONT); return 0; } EXPORT_SYMBOL_GPL(ide_queue_sense_rq); diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c index 999dac054bccc..f4077840d3abd 100644 --- a/drivers/ide/ide-io.c +++ b/drivers/ide/ide-io.c @@ -549,8 +549,6 @@ plug_device_2: if (rq) blk_requeue_request(q, rq); - if (!elv_queue_empty(q)) - blk_plug_device(q); } void ide_requeue_and_plug(ide_drive_t *drive, struct request *rq) @@ -562,8 +560,6 @@ void ide_requeue_and_plug(ide_drive_t *drive, struct request *rq) if (rq) blk_requeue_request(q, rq); - if (!elv_queue_empty(q)) - blk_plug_device(q); spin_unlock_irqrestore(q->queue_lock, flags); } diff --git a/drivers/ide/ide-park.c b/drivers/ide/ide-park.c index 88a380c5a4708..6ab9ab2a5081e 100644 --- a/drivers/ide/ide-park.c +++ b/drivers/ide/ide-park.c @@ -52,7 +52,7 @@ static void issue_park_cmd(ide_drive_t *drive, unsigned long timeout) rq->cmd[0] = REQ_UNPARK_HEADS; rq->cmd_len = 1; rq->cmd_type = REQ_TYPE_SPECIAL; - elv_add_request(q, rq, ELEVATOR_INSERT_FRONT, 1); + elv_add_request(q, rq, ELEVATOR_INSERT_FRONT); out: return; diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c index 9a35320fb59f7..54bfc274b39ab 100644 --- a/drivers/md/bitmap.c +++ b/drivers/md/bitmap.c @@ -1339,8 +1339,7 @@ int bitmap_startwrite(struct bitmap *bitmap, sector_t offset, unsigned long sect prepare_to_wait(&bitmap->overflow_wait, &__wait, TASK_UNINTERRUPTIBLE); spin_unlock_irq(&bitmap->lock); - md_unplug(bitmap->mddev); - schedule(); + io_schedule(); finish_wait(&bitmap->overflow_wait, &__wait); continue; } diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c index 4e054bd91664a..2c62c1169f78a 100644 --- a/drivers/md/dm-crypt.c +++ b/drivers/md/dm-crypt.c @@ -991,11 +991,6 @@ static void clone_init(struct dm_crypt_io *io, struct bio *clone) clone->bi_destructor = dm_crypt_bio_destructor; } -static void kcryptd_unplug(struct crypt_config *cc) -{ - blk_unplug(bdev_get_queue(cc->dev->bdev)); -} - static int kcryptd_io_read(struct dm_crypt_io *io, gfp_t gfp) { struct crypt_config *cc = io->target->private; @@ -1008,10 +1003,8 @@ static int kcryptd_io_read(struct dm_crypt_io *io, gfp_t gfp) * one in order to decrypt the whole bio data *afterwards*. */ clone = bio_alloc_bioset(gfp, bio_segments(base_bio), cc->bs); - if (!clone) { - kcryptd_unplug(cc); + if (!clone) return 1; - } crypt_inc_pending(io); diff --git a/drivers/md/dm-kcopyd.c b/drivers/md/dm-kcopyd.c index 924f5f0084c27..400cf35094a4e 100644 --- a/drivers/md/dm-kcopyd.c +++ b/drivers/md/dm-kcopyd.c @@ -37,13 +37,6 @@ struct dm_kcopyd_client { unsigned int nr_pages; unsigned int nr_free_pages; - /* - * Block devices to unplug. - * Non-NULL pointer means that a block device has some pending requests - * and needs to be unplugged. - */ - struct block_device *unplug[2]; - struct dm_io_client *io_client; wait_queue_head_t destroyq; @@ -315,31 +308,6 @@ static int run_complete_job(struct kcopyd_job *job) return 0; } -/* - * Unplug the block device at the specified index. - */ -static void unplug(struct dm_kcopyd_client *kc, int rw) -{ - if (kc->unplug[rw] != NULL) { - blk_unplug(bdev_get_queue(kc->unplug[rw])); - kc->unplug[rw] = NULL; - } -} - -/* - * Prepare block device unplug. If there's another device - * to be unplugged at the same array index, we unplug that - * device first. - */ -static void prepare_unplug(struct dm_kcopyd_client *kc, int rw, - struct block_device *bdev) -{ - if (likely(kc->unplug[rw] == bdev)) - return; - unplug(kc, rw); - kc->unplug[rw] = bdev; -} - static void complete_io(unsigned long error, void *context) { struct kcopyd_job *job = (struct kcopyd_job *) context; @@ -386,15 +354,12 @@ static int run_io_job(struct kcopyd_job *job) .client = job->kc->io_client, }; - if (job->rw == READ) { + if (job->rw == READ) r = dm_io(&io_req, 1, &job->source, NULL); - prepare_unplug(job->kc, READ, job->source.bdev); - } else { + else { if (job->num_dests > 1) io_req.bi_rw |= REQ_UNPLUG; r = dm_io(&io_req, job->num_dests, job->dests, NULL); - if (!(io_req.bi_rw & REQ_UNPLUG)) - prepare_unplug(job->kc, WRITE, job->dests[0].bdev); } return r; @@ -466,6 +431,7 @@ static void do_work(struct work_struct *work) { struct dm_kcopyd_client *kc = container_of(work, struct dm_kcopyd_client, kcopyd_work); + struct blk_plug plug; /* * The order that these are called is *very* important. @@ -473,18 +439,12 @@ static void do_work(struct work_struct *work) * Pages jobs when successful will jump onto the io jobs * list. io jobs call wake when they complete and it all * starts again. - * - * Note that io_jobs add block devices to the unplug array, - * this array is cleared with "unplug" calls. It is thus - * forbidden to run complete_jobs after io_jobs and before - * unplug because the block device could be destroyed in - * job completion callback. */ + blk_start_plug(&plug); process_jobs(&kc->complete_jobs, kc, run_complete_job); process_jobs(&kc->pages_jobs, kc, run_pages_job); process_jobs(&kc->io_jobs, kc, run_io_job); - unplug(kc, READ); - unplug(kc, WRITE); + blk_finish_plug(&plug); } /* @@ -665,8 +625,6 @@ int dm_kcopyd_client_create(unsigned int nr_pages, INIT_LIST_HEAD(&kc->io_jobs); INIT_LIST_HEAD(&kc->pages_jobs); - memset(kc->unplug, 0, sizeof(kc->unplug)); - kc->job_pool = mempool_create_slab_pool(MIN_JOBS, _job_cache); if (!kc->job_pool) goto bad_slab; diff --git a/drivers/md/dm-raid.c b/drivers/md/dm-raid.c index b9e1e15ef11cb..5ef136cdba91d 100644 --- a/drivers/md/dm-raid.c +++ b/drivers/md/dm-raid.c @@ -394,7 +394,7 @@ static void raid_unplug(struct dm_target_callbacks *cb) { struct raid_set *rs = container_of(cb, struct raid_set, callbacks); - md_raid5_unplug_device(rs->md.private); + md_raid5_kick_device(rs->md.private); } /* diff --git a/drivers/md/dm-raid1.c b/drivers/md/dm-raid1.c index dee326775c606..976ad4688afc2 100644 --- a/drivers/md/dm-raid1.c +++ b/drivers/md/dm-raid1.c @@ -842,8 +842,6 @@ static void do_mirror(struct work_struct *work) do_reads(ms, &reads); do_writes(ms, &writes); do_failures(ms, &failures); - - dm_table_unplug_all(ms->ti->table); } /*----------------------------------------------------------------- diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c index 38e4eb1bb9656..f50a7b9522579 100644 --- a/drivers/md/dm-table.c +++ b/drivers/md/dm-table.c @@ -1275,29 +1275,6 @@ int dm_table_any_busy_target(struct dm_table *t) return 0; } -void dm_table_unplug_all(struct dm_table *t) -{ - struct dm_dev_internal *dd; - struct list_head *devices = dm_table_get_devices(t); - struct dm_target_callbacks *cb; - - list_for_each_entry(dd, devices, list) { - struct request_queue *q = bdev_get_queue(dd->dm_dev.bdev); - char b[BDEVNAME_SIZE]; - - if (likely(q)) - blk_unplug(q); - else - DMWARN_LIMIT("%s: Cannot unplug nonexistent device %s", - dm_device_name(t->md), - bdevname(dd->dm_dev.bdev, b)); - } - - list_for_each_entry(cb, &t->target_callbacks, list) - if (cb->unplug_fn) - cb->unplug_fn(cb); -} - struct mapped_device *dm_table_get_md(struct dm_table *t) { return t->md; @@ -1345,4 +1322,3 @@ EXPORT_SYMBOL(dm_table_get_mode); EXPORT_SYMBOL(dm_table_get_md); EXPORT_SYMBOL(dm_table_put); EXPORT_SYMBOL(dm_table_get); -EXPORT_SYMBOL(dm_table_unplug_all); diff --git a/drivers/md/dm.c b/drivers/md/dm.c index eaa3af0e0632a..d22b9905c1682 100644 --- a/drivers/md/dm.c +++ b/drivers/md/dm.c @@ -807,8 +807,6 @@ void dm_requeue_unmapped_request(struct request *clone) dm_unprep_request(rq); spin_lock_irqsave(q->queue_lock, flags); - if (elv_queue_empty(q)) - blk_plug_device(q); blk_requeue_request(q, rq); spin_unlock_irqrestore(q->queue_lock, flags); @@ -1613,10 +1611,10 @@ static void dm_request_fn(struct request_queue *q) * number of in-flight I/Os after the queue is stopped in * dm_suspend(). */ - while (!blk_queue_plugged(q) && !blk_queue_stopped(q)) { + while (!blk_queue_stopped(q)) { rq = blk_peek_request(q); if (!rq) - goto plug_and_out; + goto delay_and_out; /* always use block 0 to find the target for flushes for now */ pos = 0; @@ -1627,7 +1625,7 @@ static void dm_request_fn(struct request_queue *q) BUG_ON(!dm_target_is_valid(ti)); if (ti->type->busy && ti->type->busy(ti)) - goto plug_and_out; + goto delay_and_out; blk_start_request(rq); clone = rq->special; @@ -1647,11 +1645,8 @@ requeued: BUG_ON(!irqs_disabled()); spin_lock(q->queue_lock); -plug_and_out: - if (!elv_queue_empty(q)) - /* Some requests still remain, retry later */ - blk_plug_device(q); - +delay_and_out: + blk_delay_queue(q, HZ / 10); out: dm_table_put(map); @@ -1680,20 +1675,6 @@ static int dm_lld_busy(struct request_queue *q) return r; } -static void dm_unplug_all(struct request_queue *q) -{ - struct mapped_device *md = q->queuedata; - struct dm_table *map = dm_get_live_table(md); - - if (map) { - if (dm_request_based(md)) - generic_unplug_device(q); - - dm_table_unplug_all(map); - dm_table_put(map); - } -} - static int dm_any_congested(void *congested_data, int bdi_bits) { int r = bdi_bits; @@ -1817,7 +1798,6 @@ static void dm_init_md_queue(struct mapped_device *md) md->queue->backing_dev_info.congested_data = md; blk_queue_make_request(md->queue, dm_request); blk_queue_bounce_limit(md->queue, BLK_BOUNCE_ANY); - md->queue->unplug_fn = dm_unplug_all; blk_queue_merge_bvec(md->queue, dm_merge_bvec); blk_queue_flush(md->queue, REQ_FLUSH | REQ_FUA); } @@ -2263,8 +2243,6 @@ static int dm_wait_for_completion(struct mapped_device *md, int interruptible) int r = 0; DECLARE_WAITQUEUE(wait, current); - dm_unplug_all(md->queue); - add_wait_queue(&md->wait, &wait); while (1) { @@ -2539,7 +2517,6 @@ int dm_resume(struct mapped_device *md) clear_bit(DMF_SUSPENDED, &md->flags); - dm_table_unplug_all(map); r = 0; out: dm_table_put(map); diff --git a/drivers/md/linear.c b/drivers/md/linear.c index 8a2f767f26d80..38861b5b9d90e 100644 --- a/drivers/md/linear.c +++ b/drivers/md/linear.c @@ -87,22 +87,6 @@ static int linear_mergeable_bvec(struct request_queue *q, return maxsectors << 9; } -static void linear_unplug(struct request_queue *q) -{ - mddev_t *mddev = q->queuedata; - linear_conf_t *conf; - int i; - - rcu_read_lock(); - conf = rcu_dereference(mddev->private); - - for (i=0; i < mddev->raid_disks; i++) { - struct request_queue *r_queue = bdev_get_queue(conf->disks[i].rdev->bdev); - blk_unplug(r_queue); - } - rcu_read_unlock(); -} - static int linear_congested(void *data, int bits) { mddev_t *mddev = data; @@ -225,7 +209,6 @@ static int linear_run (mddev_t *mddev) md_set_array_sectors(mddev, linear_size(mddev, 0, 0)); blk_queue_merge_bvec(mddev->queue, linear_mergeable_bvec); - mddev->queue->unplug_fn = linear_unplug; mddev->queue->backing_dev_info.congested_fn = linear_congested; mddev->queue->backing_dev_info.congested_data = mddev; md_integrity_register(mddev); diff --git a/drivers/md/md.c b/drivers/md/md.c index 0cc30ecda4c12..ca0d79c264b98 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -4812,7 +4812,6 @@ static int do_md_stop(mddev_t * mddev, int mode, int is_open) __md_stop_writes(mddev); md_stop(mddev); mddev->queue->merge_bvec_fn = NULL; - mddev->queue->unplug_fn = NULL; mddev->queue->backing_dev_info.congested_fn = NULL; /* tell userspace to handle 'inactive' */ @@ -6669,8 +6668,6 @@ EXPORT_SYMBOL_GPL(md_allow_write); void md_unplug(mddev_t *mddev) { - if (mddev->queue) - blk_unplug(mddev->queue); if (mddev->plug) mddev->plug->unplug_fn(mddev->plug); } @@ -6853,7 +6850,6 @@ void md_do_sync(mddev_t *mddev) >= mddev->resync_max - mddev->curr_resync_completed )) { /* time to update curr_resync_completed */ - md_unplug(mddev); wait_event(mddev->recovery_wait, atomic_read(&mddev->recovery_active) == 0); mddev->curr_resync_completed = j; @@ -6929,7 +6925,6 @@ void md_do_sync(mddev_t *mddev) * about not overloading the IO subsystem. (things like an * e2fsck being done on the RAID array should execute fast) */ - md_unplug(mddev); cond_resched(); currspeed = ((unsigned long)(io_sectors-mddev->resync_mark_cnt))/2 @@ -6948,8 +6943,6 @@ void md_do_sync(mddev_t *mddev) * this also signals 'finished resyncing' to md_stop */ out: - md_unplug(mddev); - wait_event(mddev->recovery_wait, !atomic_read(&mddev->recovery_active)); /* tell personality that we are finished */ diff --git a/drivers/md/multipath.c b/drivers/md/multipath.c index 6d7ddf32ef2ec..1cc8ed44e4ad0 100644 --- a/drivers/md/multipath.c +++ b/drivers/md/multipath.c @@ -106,36 +106,6 @@ static void multipath_end_request(struct bio *bio, int error) rdev_dec_pending(rdev, conf->mddev); } -static void unplug_slaves(mddev_t *mddev) -{ - multipath_conf_t *conf = mddev->private; - int i; - - rcu_read_lock(); - for (i=0; iraid_disks; i++) { - mdk_rdev_t *rdev = rcu_dereference(conf->multipaths[i].rdev); - if (rdev && !test_bit(Faulty, &rdev->flags) - && atomic_read(&rdev->nr_pending)) { - struct request_queue *r_queue = bdev_get_queue(rdev->bdev); - - atomic_inc(&rdev->nr_pending); - rcu_read_unlock(); - - blk_unplug(r_queue); - - rdev_dec_pending(rdev, mddev); - rcu_read_lock(); - } - } - rcu_read_unlock(); -} - -static void multipath_unplug(struct request_queue *q) -{ - unplug_slaves(q->queuedata); -} - - static int multipath_make_request(mddev_t *mddev, struct bio * bio) { multipath_conf_t *conf = mddev->private; @@ -518,7 +488,6 @@ static int multipath_run (mddev_t *mddev) */ md_set_array_sectors(mddev, multipath_size(mddev, 0, 0)); - mddev->queue->unplug_fn = multipath_unplug; mddev->queue->backing_dev_info.congested_fn = multipath_congested; mddev->queue->backing_dev_info.congested_data = mddev; md_integrity_register(mddev); diff --git a/drivers/md/raid0.c b/drivers/md/raid0.c index 637a96855edb2..6338c0fe6208f 100644 --- a/drivers/md/raid0.c +++ b/drivers/md/raid0.c @@ -25,21 +25,6 @@ #include "raid0.h" #include "raid5.h" -static void raid0_unplug(struct request_queue *q) -{ - mddev_t *mddev = q->queuedata; - raid0_conf_t *conf = mddev->private; - mdk_rdev_t **devlist = conf->devlist; - int raid_disks = conf->strip_zone[0].nb_dev; - int i; - - for (i=0; i < raid_disks; i++) { - struct request_queue *r_queue = bdev_get_queue(devlist[i]->bdev); - - blk_unplug(r_queue); - } -} - static int raid0_congested(void *data, int bits) { mddev_t *mddev = data; @@ -272,7 +257,6 @@ static int create_strip_zones(mddev_t *mddev, raid0_conf_t **private_conf) mdname(mddev), (unsigned long long)smallest->sectors); } - mddev->queue->unplug_fn = raid0_unplug; mddev->queue->backing_dev_info.congested_fn = raid0_congested; mddev->queue->backing_dev_info.congested_data = mddev; diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c index a23ffa397ba91..b67d822d57ae2 100644 --- a/drivers/md/raid1.c +++ b/drivers/md/raid1.c @@ -52,23 +52,16 @@ #define NR_RAID1_BIOS 256 -static void unplug_slaves(mddev_t *mddev); - static void allow_barrier(conf_t *conf); static void lower_barrier(conf_t *conf); static void * r1bio_pool_alloc(gfp_t gfp_flags, void *data) { struct pool_info *pi = data; - r1bio_t *r1_bio; int size = offsetof(r1bio_t, bios[pi->raid_disks]); /* allocate a r1bio with room for raid_disks entries in the bios array */ - r1_bio = kzalloc(size, gfp_flags); - if (!r1_bio && pi->mddev) - unplug_slaves(pi->mddev); - - return r1_bio; + return kzalloc(size, gfp_flags); } static void r1bio_pool_free(void *r1_bio, void *data) @@ -91,10 +84,8 @@ static void * r1buf_pool_alloc(gfp_t gfp_flags, void *data) int i, j; r1_bio = r1bio_pool_alloc(gfp_flags, pi); - if (!r1_bio) { - unplug_slaves(pi->mddev); + if (!r1_bio) return NULL; - } /* * Allocate bios : 1 for reading, n-1 for writing @@ -520,37 +511,6 @@ static int read_balance(conf_t *conf, r1bio_t *r1_bio) return new_disk; } -static void unplug_slaves(mddev_t *mddev) -{ - conf_t *conf = mddev->private; - int i; - - rcu_read_lock(); - for (i=0; iraid_disks; i++) { - mdk_rdev_t *rdev = rcu_dereference(conf->mirrors[i].rdev); - if (rdev && !test_bit(Faulty, &rdev->flags) && atomic_read(&rdev->nr_pending)) { - struct request_queue *r_queue = bdev_get_queue(rdev->bdev); - - atomic_inc(&rdev->nr_pending); - rcu_read_unlock(); - - blk_unplug(r_queue); - - rdev_dec_pending(rdev, mddev); - rcu_read_lock(); - } - } - rcu_read_unlock(); -} - -static void raid1_unplug(struct request_queue *q) -{ - mddev_t *mddev = q->queuedata; - - unplug_slaves(mddev); - md_wakeup_thread(mddev->thread); -} - static int raid1_congested(void *data, int bits) { mddev_t *mddev = data; @@ -580,20 +540,16 @@ static int raid1_congested(void *data, int bits) } -static int flush_pending_writes(conf_t *conf) +static void flush_pending_writes(conf_t *conf) { /* Any writes that have been queued but are awaiting * bitmap updates get flushed here. - * We return 1 if any requests were actually submitted. */ - int rv = 0; - spin_lock_irq(&conf->device_lock); if (conf->pending_bio_list.head) { struct bio *bio; bio = bio_list_get(&conf->pending_bio_list); - blk_remove_plug(conf->mddev->queue); spin_unlock_irq(&conf->device_lock); /* flush any pending bitmap writes to * disk before proceeding w/ I/O */ @@ -605,10 +561,14 @@ static int flush_pending_writes(conf_t *conf) generic_make_request(bio); bio = next; } - rv = 1; } else spin_unlock_irq(&conf->device_lock); - return rv; +} + +static void md_kick_device(mddev_t *mddev) +{ + blk_flush_plug(current); + md_wakeup_thread(mddev->thread); } /* Barriers.... @@ -640,8 +600,7 @@ static void raise_barrier(conf_t *conf) /* Wait until no block IO is waiting */ wait_event_lock_irq(conf->wait_barrier, !conf->nr_waiting, - conf->resync_lock, - raid1_unplug(conf->mddev->queue)); + conf->resync_lock, md_kick_device(conf->mddev)); /* block any new IO from starting */ conf->barrier++; @@ -649,8 +608,7 @@ static void raise_barrier(conf_t *conf) /* Now wait for all pending IO to complete */ wait_event_lock_irq(conf->wait_barrier, !conf->nr_pending && conf->barrier < RESYNC_DEPTH, - conf->resync_lock, - raid1_unplug(conf->mddev->queue)); + conf->resync_lock, md_kick_device(conf->mddev)); spin_unlock_irq(&conf->resync_lock); } @@ -672,7 +630,7 @@ static void wait_barrier(conf_t *conf) conf->nr_waiting++; wait_event_lock_irq(conf->wait_barrier, !conf->barrier, conf->resync_lock, - raid1_unplug(conf->mddev->queue)); + md_kick_device(conf->mddev)); conf->nr_waiting--; } conf->nr_pending++; @@ -709,7 +667,7 @@ static void freeze_array(conf_t *conf) conf->nr_pending == conf->nr_queued+1, conf->resync_lock, ({ flush_pending_writes(conf); - raid1_unplug(conf->mddev->queue); })); + md_kick_device(conf->mddev); })); spin_unlock_irq(&conf->resync_lock); } static void unfreeze_array(conf_t *conf) @@ -959,7 +917,6 @@ static int make_request(mddev_t *mddev, struct bio * bio) atomic_inc(&r1_bio->remaining); spin_lock_irqsave(&conf->device_lock, flags); bio_list_add(&conf->pending_bio_list, mbio); - blk_plug_device(mddev->queue); spin_unlock_irqrestore(&conf->device_lock, flags); } r1_bio_write_done(r1_bio, bio->bi_vcnt, behind_pages, behind_pages != NULL); @@ -968,7 +925,7 @@ static int make_request(mddev_t *mddev, struct bio * bio) /* In case raid1d snuck in to freeze_array */ wake_up(&conf->wait_barrier); - if (do_sync) + if (do_sync || !bitmap) md_wakeup_thread(mddev->thread); return 0; @@ -1558,7 +1515,6 @@ static void raid1d(mddev_t *mddev) unsigned long flags; conf_t *conf = mddev->private; struct list_head *head = &conf->retry_list; - int unplug=0; mdk_rdev_t *rdev; md_check_recovery(mddev); @@ -1566,7 +1522,7 @@ static void raid1d(mddev_t *mddev) for (;;) { char b[BDEVNAME_SIZE]; - unplug += flush_pending_writes(conf); + flush_pending_writes(conf); spin_lock_irqsave(&conf->device_lock, flags); if (list_empty(head)) { @@ -1580,10 +1536,9 @@ static void raid1d(mddev_t *mddev) mddev = r1_bio->mddev; conf = mddev->private; - if (test_bit(R1BIO_IsSync, &r1_bio->state)) { + if (test_bit(R1BIO_IsSync, &r1_bio->state)) sync_request_write(mddev, r1_bio); - unplug = 1; - } else { + else { int disk; /* we got a read error. Maybe the drive is bad. Maybe just @@ -1633,14 +1588,11 @@ static void raid1d(mddev_t *mddev) bio->bi_end_io = raid1_end_read_request; bio->bi_rw = READ | do_sync; bio->bi_private = r1_bio; - unplug = 1; generic_make_request(bio); } } cond_resched(); } - if (unplug) - unplug_slaves(mddev); } @@ -2064,7 +2016,6 @@ static int run(mddev_t *mddev) md_set_array_sectors(mddev, raid1_size(mddev, 0, 0)); - mddev->queue->unplug_fn = raid1_unplug; mddev->queue->backing_dev_info.congested_fn = raid1_congested; mddev->queue->backing_dev_info.congested_data = mddev; md_integrity_register(mddev); diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c index 3b607b28741b8..e79f1c5bf71b5 100644 --- a/drivers/md/raid10.c +++ b/drivers/md/raid10.c @@ -57,23 +57,16 @@ */ #define NR_RAID10_BIOS 256 -static void unplug_slaves(mddev_t *mddev); - static void allow_barrier(conf_t *conf); static void lower_barrier(conf_t *conf); static void * r10bio_pool_alloc(gfp_t gfp_flags, void *data) { conf_t *conf = data; - r10bio_t *r10_bio; int size = offsetof(struct r10bio_s, devs[conf->copies]); /* allocate a r10bio with room for raid_disks entries in the bios array */ - r10_bio = kzalloc(size, gfp_flags); - if (!r10_bio && conf->mddev) - unplug_slaves(conf->mddev); - - return r10_bio; + return kzalloc(size, gfp_flags); } static void r10bio_pool_free(void *r10_bio, void *data) @@ -106,10 +99,8 @@ static void * r10buf_pool_alloc(gfp_t gfp_flags, void *data) int nalloc; r10_bio = r10bio_pool_alloc(gfp_flags, conf); - if (!r10_bio) { - unplug_slaves(conf->mddev); + if (!r10_bio) return NULL; - } if (test_bit(MD_RECOVERY_SYNC, &conf->mddev->recovery)) nalloc = conf->copies; /* resync */ @@ -597,37 +588,6 @@ rb_out: return disk; } -static void unplug_slaves(mddev_t *mddev) -{ - conf_t *conf = mddev->private; - int i; - - rcu_read_lock(); - for (i=0; i < conf->raid_disks; i++) { - mdk_rdev_t *rdev = rcu_dereference(conf->mirrors[i].rdev); - if (rdev && !test_bit(Faulty, &rdev->flags) && atomic_read(&rdev->nr_pending)) { - struct request_queue *r_queue = bdev_get_queue(rdev->bdev); - - atomic_inc(&rdev->nr_pending); - rcu_read_unlock(); - - blk_unplug(r_queue); - - rdev_dec_pending(rdev, mddev); - rcu_read_lock(); - } - } - rcu_read_unlock(); -} - -static void raid10_unplug(struct request_queue *q) -{ - mddev_t *mddev = q->queuedata; - - unplug_slaves(q->queuedata); - md_wakeup_thread(mddev->thread); -} - static int raid10_congested(void *data, int bits) { mddev_t *mddev = data; @@ -649,20 +609,16 @@ static int raid10_congested(void *data, int bits) return ret; } -static int flush_pending_writes(conf_t *conf) +static void flush_pending_writes(conf_t *conf) { /* Any writes that have been queued but are awaiting * bitmap updates get flushed here. - * We return 1 if any requests were actually submitted. */ - int rv = 0; - spin_lock_irq(&conf->device_lock); if (conf->pending_bio_list.head) { struct bio *bio; bio = bio_list_get(&conf->pending_bio_list); - blk_remove_plug(conf->mddev->queue); spin_unlock_irq(&conf->device_lock); /* flush any pending bitmap writes to disk * before proceeding w/ I/O */ @@ -674,11 +630,16 @@ static int flush_pending_writes(conf_t *conf) generic_make_request(bio); bio = next; } - rv = 1; } else spin_unlock_irq(&conf->device_lock); - return rv; } + +static void md_kick_device(mddev_t *mddev) +{ + blk_flush_plug(current); + md_wakeup_thread(mddev->thread); +} + /* Barriers.... * Sometimes we need to suspend IO while we do something else, * either some resync/recovery, or reconfigure the array. @@ -708,8 +669,7 @@ static void raise_barrier(conf_t *conf, int force) /* Wait until no block IO is waiting (unless 'force') */ wait_event_lock_irq(conf->wait_barrier, force || !conf->nr_waiting, - conf->resync_lock, - raid10_unplug(conf->mddev->queue)); + conf->resync_lock, md_kick_device(conf->mddev)); /* block any new IO from starting */ conf->barrier++; @@ -717,8 +677,7 @@ static void raise_barrier(conf_t *conf, int force) /* No wait for all pending IO to complete */ wait_event_lock_irq(conf->wait_barrier, !conf->nr_pending && conf->barrier < RESYNC_DEPTH, - conf->resync_lock, - raid10_unplug(conf->mddev->queue)); + conf->resync_lock, md_kick_device(conf->mddev)); spin_unlock_irq(&conf->resync_lock); } @@ -739,7 +698,7 @@ static void wait_barrier(conf_t *conf) conf->nr_waiting++; wait_event_lock_irq(conf->wait_barrier, !conf->barrier, conf->resync_lock, - raid10_unplug(conf->mddev->queue)); + md_kick_device(conf->mddev)); conf->nr_waiting--; } conf->nr_pending++; @@ -776,7 +735,7 @@ static void freeze_array(conf_t *conf) conf->nr_pending == conf->nr_queued+1, conf->resync_lock, ({ flush_pending_writes(conf); - raid10_unplug(conf->mddev->queue); })); + md_kick_device(conf->mddev); })); spin_unlock_irq(&conf->resync_lock); } @@ -971,7 +930,6 @@ static int make_request(mddev_t *mddev, struct bio * bio) atomic_inc(&r10_bio->remaining); spin_lock_irqsave(&conf->device_lock, flags); bio_list_add(&conf->pending_bio_list, mbio); - blk_plug_device(mddev->queue); spin_unlock_irqrestore(&conf->device_lock, flags); } @@ -988,7 +946,7 @@ static int make_request(mddev_t *mddev, struct bio * bio) /* In case raid10d snuck in to freeze_array */ wake_up(&conf->wait_barrier); - if (do_sync) + if (do_sync || !mddev->bitmap) md_wakeup_thread(mddev->thread); return 0; @@ -1681,7 +1639,6 @@ static void raid10d(mddev_t *mddev) unsigned long flags; conf_t *conf = mddev->private; struct list_head *head = &conf->retry_list; - int unplug=0; mdk_rdev_t *rdev; md_check_recovery(mddev); @@ -1689,7 +1646,7 @@ static void raid10d(mddev_t *mddev) for (;;) { char b[BDEVNAME_SIZE]; - unplug += flush_pending_writes(conf); + flush_pending_writes(conf); spin_lock_irqsave(&conf->device_lock, flags); if (list_empty(head)) { @@ -1703,13 +1660,11 @@ static void raid10d(mddev_t *mddev) mddev = r10_bio->mddev; conf = mddev->private; - if (test_bit(R10BIO_IsSync, &r10_bio->state)) { + if (test_bit(R10BIO_IsSync, &r10_bio->state)) sync_request_write(mddev, r10_bio); - unplug = 1; - } else if (test_bit(R10BIO_IsRecover, &r10_bio->state)) { + else if (test_bit(R10BIO_IsRecover, &r10_bio->state)) recovery_request_write(mddev, r10_bio); - unplug = 1; - } else { + else { int mirror; /* we got a read error. Maybe the drive is bad. Maybe just * the block and we can fix it. @@ -1756,14 +1711,11 @@ static void raid10d(mddev_t *mddev) bio->bi_rw = READ | do_sync; bio->bi_private = r10_bio; bio->bi_end_io = raid10_end_read_request; - unplug = 1; generic_make_request(bio); } } cond_resched(); } - if (unplug) - unplug_slaves(mddev); } @@ -2376,7 +2328,6 @@ static int run(mddev_t *mddev) md_set_array_sectors(mddev, size); mddev->resync_max_sectors = size; - mddev->queue->unplug_fn = raid10_unplug; mddev->queue->backing_dev_info.congested_fn = raid10_congested; mddev->queue->backing_dev_info.congested_data = mddev; diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index 702812824195a..e867ee42b1523 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c @@ -433,8 +433,6 @@ static int has_failed(raid5_conf_t *conf) return 0; } -static void unplug_slaves(mddev_t *mddev); - static struct stripe_head * get_active_stripe(raid5_conf_t *conf, sector_t sector, int previous, int noblock, int noquiesce) @@ -463,8 +461,7 @@ get_active_stripe(raid5_conf_t *conf, sector_t sector, < (conf->max_nr_stripes *3/4) || !conf->inactive_blocked), conf->device_lock, - md_raid5_unplug_device(conf) - ); + md_raid5_kick_device(conf)); conf->inactive_blocked = 0; } else init_stripe(sh, sector, previous); @@ -1473,8 +1470,7 @@ static int resize_stripes(raid5_conf_t *conf, int newsize) wait_event_lock_irq(conf->wait_for_stripe, !list_empty(&conf->inactive_list), conf->device_lock, - unplug_slaves(conf->mddev) - ); + blk_flush_plug(current)); osh = get_free_stripe(conf); spin_unlock_irq(&conf->device_lock); atomic_set(&nsh->count, 1); @@ -3645,58 +3641,19 @@ static void activate_bit_delay(raid5_conf_t *conf) } } -static void unplug_slaves(mddev_t *mddev) +void md_raid5_kick_device(raid5_conf_t *conf) { - raid5_conf_t *conf = mddev->private; - int i; - int devs = max(conf->raid_disks, conf->previous_raid_disks); - - rcu_read_lock(); - for (i = 0; i < devs; i++) { - mdk_rdev_t *rdev = rcu_dereference(conf->disks[i].rdev); - if (rdev && !test_bit(Faulty, &rdev->flags) && atomic_read(&rdev->nr_pending)) { - struct request_queue *r_queue = bdev_get_queue(rdev->bdev); - - atomic_inc(&rdev->nr_pending); - rcu_read_unlock(); - - blk_unplug(r_queue); - - rdev_dec_pending(rdev, mddev); - rcu_read_lock(); - } - } - rcu_read_unlock(); -} - -void md_raid5_unplug_device(raid5_conf_t *conf) -{ - unsigned long flags; - - spin_lock_irqsave(&conf->device_lock, flags); - - if (plugger_remove_plug(&conf->plug)) { - conf->seq_flush++; - raid5_activate_delayed(conf); - } + blk_flush_plug(current); + raid5_activate_delayed(conf); md_wakeup_thread(conf->mddev->thread); - - spin_unlock_irqrestore(&conf->device_lock, flags); - - unplug_slaves(conf->mddev); } -EXPORT_SYMBOL_GPL(md_raid5_unplug_device); +EXPORT_SYMBOL_GPL(md_raid5_kick_device); static void raid5_unplug(struct plug_handle *plug) { raid5_conf_t *conf = container_of(plug, raid5_conf_t, plug); - md_raid5_unplug_device(conf); -} -static void raid5_unplug_queue(struct request_queue *q) -{ - mddev_t *mddev = q->queuedata; - md_raid5_unplug_device(mddev->private); + md_raid5_kick_device(conf); } int md_raid5_congested(mddev_t *mddev, int bits) @@ -4100,7 +4057,7 @@ static int make_request(mddev_t *mddev, struct bio * bi) * add failed due to overlap. Flush everything * and wait a while */ - md_raid5_unplug_device(conf); + md_raid5_kick_device(conf); release_stripe(sh); schedule(); goto retry; @@ -4365,7 +4322,6 @@ static inline sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *ski if (sector_nr >= max_sector) { /* just being told to finish up .. nothing much to do */ - unplug_slaves(mddev); if (test_bit(MD_RECOVERY_RESHAPE, &mddev->recovery)) { end_reshape(conf); @@ -4569,7 +4525,6 @@ static void raid5d(mddev_t *mddev) spin_unlock_irq(&conf->device_lock); async_tx_issue_pending_all(); - unplug_slaves(mddev); pr_debug("--- raid5d inactive\n"); } @@ -5205,7 +5160,6 @@ static int run(mddev_t *mddev) mddev->queue->backing_dev_info.congested_data = mddev; mddev->queue->backing_dev_info.congested_fn = raid5_congested; mddev->queue->queue_lock = &conf->device_lock; - mddev->queue->unplug_fn = raid5_unplug_queue; chunk_size = mddev->chunk_sectors << 9; blk_queue_io_min(mddev->queue, chunk_size); diff --git a/drivers/md/raid5.h b/drivers/md/raid5.h index 2ace0582b4098..8d563a4f022a7 100644 --- a/drivers/md/raid5.h +++ b/drivers/md/raid5.h @@ -503,6 +503,6 @@ static inline int algorithm_is_DDF(int layout) } extern int md_raid5_congested(mddev_t *mddev, int bits); -extern void md_raid5_unplug_device(raid5_conf_t *conf); +extern void md_raid5_kick_device(raid5_conf_t *conf); extern int raid5_set_cache_size(mddev_t *mddev, int size); #endif diff --git a/drivers/message/i2o/i2o_block.c b/drivers/message/i2o/i2o_block.c index ae7cad1858987..b29eb4eaa86e1 100644 --- a/drivers/message/i2o/i2o_block.c +++ b/drivers/message/i2o/i2o_block.c @@ -895,11 +895,7 @@ static void i2o_block_request_fn(struct request_queue *q) { struct request *req; - while (!blk_queue_plugged(q)) { - req = blk_peek_request(q); - if (!req) - break; - + while ((req = blk_peek_request(q)) != NULL) { if (req->cmd_type == REQ_TYPE_FS) { struct i2o_block_delayed_request *dreq; struct i2o_block_request *ireq = req->special; diff --git a/drivers/mmc/card/queue.c b/drivers/mmc/card/queue.c index 4e42d030e0972..2ae727568df92 100644 --- a/drivers/mmc/card/queue.c +++ b/drivers/mmc/card/queue.c @@ -55,8 +55,7 @@ static int mmc_queue_thread(void *d) spin_lock_irq(q->queue_lock); set_current_state(TASK_INTERRUPTIBLE); - if (!blk_queue_plugged(q)) - req = blk_fetch_request(q); + req = blk_fetch_request(q); mq->req = req; spin_unlock_irq(q->queue_lock); diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c index 794bfd962266f..4d2df2f76ea0d 100644 --- a/drivers/s390/block/dasd.c +++ b/drivers/s390/block/dasd.c @@ -1917,7 +1917,7 @@ static void __dasd_process_request_queue(struct dasd_block *block) return; } /* Now we try to fetch requests from the request queue */ - while (!blk_queue_plugged(queue) && (req = blk_peek_request(queue))) { + while ((req = blk_peek_request(queue))) { if (basedev->features & DASD_FEATURE_READONLY && rq_data_dir(req) == WRITE) { DBF_DEV_EVENT(DBF_ERR, basedev, diff --git a/drivers/s390/char/tape_block.c b/drivers/s390/char/tape_block.c index 55d2d0f4eabc9..f061b2527b441 100644 --- a/drivers/s390/char/tape_block.c +++ b/drivers/s390/char/tape_block.c @@ -161,7 +161,6 @@ tapeblock_requeue(struct work_struct *work) { spin_lock_irq(&device->blk_data.request_queue_lock); while ( - !blk_queue_plugged(queue) && blk_peek_request(queue) && nr_queued < TAPEBLOCK_MIN_REQUEUE ) { diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c index 998c01be3234f..2cefabd5bdb58 100644 --- a/drivers/scsi/scsi_transport_fc.c +++ b/drivers/scsi/scsi_transport_fc.c @@ -3913,7 +3913,7 @@ fc_bsg_request_handler(struct request_queue *q, struct Scsi_Host *shost, if (!get_device(dev)) return; - while (!blk_queue_plugged(q)) { + while (1) { if (rport && (rport->port_state == FC_PORTSTATE_BLOCKED) && !(rport->flags & FC_RPORT_FAST_FAIL_TIMEDOUT)) break; diff --git a/drivers/scsi/scsi_transport_sas.c b/drivers/scsi/scsi_transport_sas.c index 927e99cb72250..c6fcf76cade54 100644 --- a/drivers/scsi/scsi_transport_sas.c +++ b/drivers/scsi/scsi_transport_sas.c @@ -173,11 +173,7 @@ static void sas_smp_request(struct request_queue *q, struct Scsi_Host *shost, int ret; int (*handler)(struct Scsi_Host *, struct sas_rphy *, struct request *); - while (!blk_queue_plugged(q)) { - req = blk_fetch_request(q); - if (!req) - break; - + while ((req = blk_fetch_request(q)) != NULL) { spin_unlock_irq(q->queue_lock); handler = to_sas_internal(shost->transportt)->f->smp_handler; diff --git a/drivers/target/target_core_iblock.c b/drivers/target/target_core_iblock.c index 67f0c09983c87..c1b539d7b0d37 100644 --- a/drivers/target/target_core_iblock.c +++ b/drivers/target/target_core_iblock.c @@ -392,9 +392,8 @@ static int iblock_do_task(struct se_task *task) { struct se_device *dev = task->task_se_cmd->se_dev; struct iblock_req *req = IBLOCK_REQ(task); - struct iblock_dev *ibd = (struct iblock_dev *)req->ib_dev; - struct request_queue *q = bdev_get_queue(ibd->ibd_bd); struct bio *bio = req->ib_bio, *nbio = NULL; + struct blk_plug plug; int rw; if (task->task_data_direction == DMA_TO_DEVICE) { @@ -412,6 +411,7 @@ static int iblock_do_task(struct se_task *task) rw = READ; } + blk_start_plug(&plug); while (bio) { nbio = bio->bi_next; bio->bi_next = NULL; @@ -421,9 +421,8 @@ static int iblock_do_task(struct se_task *task) submit_bio(rw, bio); bio = nbio; } + blk_finish_plug(&plug); - if (q->unplug_fn) - q->unplug_fn(q); return PYX_TRANSPORT_SENT_TO_TRANSPORT; } diff --git a/fs/adfs/inode.c b/fs/adfs/inode.c index 65794b8fe79eb..1cc84b2761312 100644 --- a/fs/adfs/inode.c +++ b/fs/adfs/inode.c @@ -73,7 +73,6 @@ static sector_t _adfs_bmap(struct address_space *mapping, sector_t block) static const struct address_space_operations adfs_aops = { .readpage = adfs_readpage, .writepage = adfs_writepage, - .sync_page = block_sync_page, .write_begin = adfs_write_begin, .write_end = generic_write_end, .bmap = _adfs_bmap diff --git a/fs/affs/file.c b/fs/affs/file.c index 0a90dcd46de28..acf321b70fcd1 100644 --- a/fs/affs/file.c +++ b/fs/affs/file.c @@ -429,7 +429,6 @@ static sector_t _affs_bmap(struct address_space *mapping, sector_t block) const struct address_space_operations affs_aops = { .readpage = affs_readpage, .writepage = affs_writepage, - .sync_page = block_sync_page, .write_begin = affs_write_begin, .write_end = generic_write_end, .bmap = _affs_bmap @@ -786,7 +785,6 @@ out: const struct address_space_operations affs_aops_ofs = { .readpage = affs_readpage_ofs, //.writepage = affs_writepage_ofs, - //.sync_page = affs_sync_page_ofs, .write_begin = affs_write_begin_ofs, .write_end = affs_write_end_ofs }; diff --git a/fs/aio.c b/fs/aio.c index fc557a3be0a9a..c5ea494ea9e24 100644 --- a/fs/aio.c +++ b/fs/aio.c @@ -1550,9 +1550,11 @@ static void aio_batch_free(struct hlist_head *batch_hash) struct hlist_node *pos, *n; int i; + /* + * TODO: kill this + */ for (i = 0; i < AIO_BATCH_HASH_SIZE; i++) { hlist_for_each_entry_safe(abe, pos, n, &batch_hash[i], list) { - blk_run_address_space(abe->mapping); iput(abe->mapping->host); hlist_del(&abe->list); mempool_free(abe, abe_pool); diff --git a/fs/befs/linuxvfs.c b/fs/befs/linuxvfs.c index b1d0c794747b7..06457ed8f3e7c 100644 --- a/fs/befs/linuxvfs.c +++ b/fs/befs/linuxvfs.c @@ -75,7 +75,6 @@ static const struct inode_operations befs_dir_inode_operations = { static const struct address_space_operations befs_aops = { .readpage = befs_readpage, - .sync_page = block_sync_page, .bmap = befs_bmap, }; diff --git a/fs/bfs/file.c b/fs/bfs/file.c index eb67edd0f8ea3..f20e8a71062f4 100644 --- a/fs/bfs/file.c +++ b/fs/bfs/file.c @@ -186,7 +186,6 @@ static sector_t bfs_bmap(struct address_space *mapping, sector_t block) const struct address_space_operations bfs_aops = { .readpage = bfs_readpage, .writepage = bfs_writepage, - .sync_page = block_sync_page, .write_begin = bfs_write_begin, .write_end = generic_write_end, .bmap = bfs_bmap, diff --git a/fs/block_dev.c b/fs/block_dev.c index 4fb8a34315310..fffc2c6723964 100644 --- a/fs/block_dev.c +++ b/fs/block_dev.c @@ -1520,7 +1520,6 @@ static int blkdev_releasepage(struct page *page, gfp_t wait) static const struct address_space_operations def_blk_aops = { .readpage = blkdev_readpage, .writepage = blkdev_writepage, - .sync_page = block_sync_page, .write_begin = blkdev_write_begin, .write_end = blkdev_write_end, .writepages = generic_writepages, diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index e1aa8d607bc7d..ada1f6bd0a571 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c @@ -847,7 +847,6 @@ static const struct address_space_operations btree_aops = { .writepages = btree_writepages, .releasepage = btree_releasepage, .invalidatepage = btree_invalidatepage, - .sync_page = block_sync_page, #ifdef CONFIG_MIGRATION .migratepage = btree_migratepage, #endif @@ -1330,82 +1329,6 @@ static int btrfs_congested_fn(void *congested_data, int bdi_bits) return ret; } -/* - * this unplugs every device on the box, and it is only used when page - * is null - */ -static void __unplug_io_fn(struct backing_dev_info *bdi, struct page *page) -{ - struct btrfs_device *device; - struct btrfs_fs_info *info; - - info = (struct btrfs_fs_info *)bdi->unplug_io_data; - list_for_each_entry(device, &info->fs_devices->devices, dev_list) { - if (!device->bdev) - continue; - - bdi = blk_get_backing_dev_info(device->bdev); - if (bdi->unplug_io_fn) - bdi->unplug_io_fn(bdi, page); - } -} - -static void btrfs_unplug_io_fn(struct backing_dev_info *bdi, struct page *page) -{ - struct inode *inode; - struct extent_map_tree *em_tree; - struct extent_map *em; - struct address_space *mapping; - u64 offset; - - /* the generic O_DIRECT read code does this */ - if (1 || !page) { - __unplug_io_fn(bdi, page); - return; - } - - /* - * page->mapping may change at any time. Get a consistent copy - * and use that for everything below - */ - smp_mb(); - mapping = page->mapping; - if (!mapping) - return; - - inode = mapping->host; - - /* - * don't do the expensive searching for a small number of - * devices - */ - if (BTRFS_I(inode)->root->fs_info->fs_devices->open_devices <= 2) { - __unplug_io_fn(bdi, page); - return; - } - - offset = page_offset(page); - - em_tree = &BTRFS_I(inode)->extent_tree; - read_lock(&em_tree->lock); - em = lookup_extent_mapping(em_tree, offset, PAGE_CACHE_SIZE); - read_unlock(&em_tree->lock); - if (!em) { - __unplug_io_fn(bdi, page); - return; - } - - if (em->block_start >= EXTENT_MAP_LAST_BYTE) { - free_extent_map(em); - __unplug_io_fn(bdi, page); - return; - } - offset = offset - em->start; - btrfs_unplug_page(&BTRFS_I(inode)->root->fs_info->mapping_tree, - em->block_start + offset, page); - free_extent_map(em); -} - /* * If this fails, caller must call bdi_destroy() to get rid of the * bdi again. @@ -1420,8 +1343,6 @@ static int setup_bdi(struct btrfs_fs_info *info, struct backing_dev_info *bdi) return err; bdi->ra_pages = default_backing_dev_info.ra_pages; - bdi->unplug_io_fn = btrfs_unplug_io_fn; - bdi->unplug_io_data = info; bdi->congested_fn = btrfs_congested_fn; bdi->congested_data = info; return 0; diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index fb9bd7832b6db..462e08e724b08 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -7218,7 +7218,6 @@ static const struct address_space_operations btrfs_aops = { .writepage = btrfs_writepage, .writepages = btrfs_writepages, .readpages = btrfs_readpages, - .sync_page = block_sync_page, .direct_IO = btrfs_direct_IO, .invalidatepage = btrfs_invalidatepage, .releasepage = btrfs_releasepage, diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index af7dbca152762..6e0e82a1b188a 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c @@ -162,7 +162,6 @@ static noinline int run_scheduled_bios(struct btrfs_device *device) struct bio *cur; int again = 0; unsigned long num_run; - unsigned long num_sync_run; unsigned long batch_run = 0; unsigned long limit; unsigned long last_waited = 0; @@ -173,11 +172,6 @@ static noinline int run_scheduled_bios(struct btrfs_device *device) limit = btrfs_async_submit_limit(fs_info); limit = limit * 2 / 3; - /* we want to make sure that every time we switch from the sync - * list to the normal list, we unplug - */ - num_sync_run = 0; - loop: spin_lock(&device->io_lock); @@ -223,15 +217,6 @@ loop_lock: spin_unlock(&device->io_lock); - /* - * if we're doing the regular priority list, make sure we unplug - * for any high prio bios we've sent down - */ - if (pending_bios == &device->pending_bios && num_sync_run > 0) { - num_sync_run = 0; - blk_run_backing_dev(bdi, NULL); - } - while (pending) { rmb(); @@ -259,19 +244,11 @@ loop_lock: BUG_ON(atomic_read(&cur->bi_cnt) == 0); - if (cur->bi_rw & REQ_SYNC) - num_sync_run++; - submit_bio(cur->bi_rw, cur); num_run++; batch_run++; - if (need_resched()) { - if (num_sync_run) { - blk_run_backing_dev(bdi, NULL); - num_sync_run = 0; - } + if (need_resched()) cond_resched(); - } /* * we made progress, there is more work to do and the bdi @@ -304,13 +281,8 @@ loop_lock: * against it before looping */ last_waited = ioc->last_waited; - if (need_resched()) { - if (num_sync_run) { - blk_run_backing_dev(bdi, NULL); - num_sync_run = 0; - } + if (need_resched()) cond_resched(); - } continue; } spin_lock(&device->io_lock); @@ -323,22 +295,6 @@ loop_lock: } } - if (num_sync_run) { - num_sync_run = 0; - blk_run_backing_dev(bdi, NULL); - } - /* - * IO has already been through a long path to get here. Checksumming, - * async helper threads, perhaps compression. We've done a pretty - * good job of collecting a batch of IO and should just unplug - * the device right away. - * - * This will help anyone who is waiting on the IO, they might have - * already unplugged, but managed to do so before the bio they - * cared about found its way down here. - */ - blk_run_backing_dev(bdi, NULL); - cond_resched(); if (again) goto loop; @@ -2948,7 +2904,7 @@ static int find_live_mirror(struct map_lookup *map, int first, int num, static int __btrfs_map_block(struct btrfs_mapping_tree *map_tree, int rw, u64 logical, u64 *length, struct btrfs_multi_bio **multi_ret, - int mirror_num, struct page *unplug_page) + int mirror_num) { struct extent_map *em; struct map_lookup *map; @@ -2980,11 +2936,6 @@ again: em = lookup_extent_mapping(em_tree, logical, *length); read_unlock(&em_tree->lock); - if (!em && unplug_page) { - kfree(multi); - return 0; - } - if (!em) { printk(KERN_CRIT "unable to find logical %llu len %llu\n", (unsigned long long)logical, @@ -3040,13 +2991,13 @@ again: *length = em->len - offset; } - if (!multi_ret && !unplug_page) + if (!multi_ret) goto out; num_stripes = 1; stripe_index = 0; if (map->type & BTRFS_BLOCK_GROUP_RAID1) { - if (unplug_page || (rw & REQ_WRITE)) + if (rw & REQ_WRITE) num_stripes = map->num_stripes; else if (mirror_num) stripe_index = mirror_num - 1; @@ -3068,7 +3019,7 @@ again: stripe_index = do_div(stripe_nr, factor); stripe_index *= map->sub_stripes; - if (unplug_page || (rw & REQ_WRITE)) + if (rw & REQ_WRITE) num_stripes = map->sub_stripes; else if (mirror_num) stripe_index += mirror_num - 1; @@ -3088,22 +3039,10 @@ again: BUG_ON(stripe_index >= map->num_stripes); for (i = 0; i < num_stripes; i++) { - if (unplug_page) { - struct btrfs_device *device; - struct backing_dev_info *bdi; - - device = map->stripes[stripe_index].dev; - if (device->bdev) { - bdi = blk_get_backing_dev_info(device->bdev); - if (bdi->unplug_io_fn) - bdi->unplug_io_fn(bdi, unplug_page); - } - } else { - multi->stripes[i].physical = - map->stripes[stripe_index].physical + - stripe_offset + stripe_nr * map->stripe_len; - multi->stripes[i].dev = map->stripes[stripe_index].dev; - } + multi->stripes[i].physical = + map->stripes[stripe_index].physical + + stripe_offset + stripe_nr * map->stripe_len; + multi->stripes[i].dev = map->stripes[stripe_index].dev; stripe_index++; } if (multi_ret) { @@ -3121,7 +3060,7 @@ int btrfs_map_block(struct btrfs_mapping_tree *map_tree, int rw, struct btrfs_multi_bio **multi_ret, int mirror_num) { return __btrfs_map_block(map_tree, rw, logical, length, multi_ret, - mirror_num, NULL); + mirror_num); } int btrfs_rmap_block(struct btrfs_mapping_tree *map_tree, @@ -3189,14 +3128,6 @@ int btrfs_rmap_block(struct btrfs_mapping_tree *map_tree, return 0; } -int btrfs_unplug_page(struct btrfs_mapping_tree *map_tree, - u64 logical, struct page *page) -{ - u64 length = PAGE_CACHE_SIZE; - return __btrfs_map_block(map_tree, READ, logical, &length, - NULL, 0, page); -} - static void end_bio_multi_stripe(struct bio *bio, int err) { struct btrfs_multi_bio *multi = bio->bi_private; diff --git a/fs/buffer.c b/fs/buffer.c index 2219a76e2caf0..f903f2e5b4fe6 100644 --- a/fs/buffer.c +++ b/fs/buffer.c @@ -54,23 +54,15 @@ init_buffer(struct buffer_head *bh, bh_end_io_t *handler, void *private) } EXPORT_SYMBOL(init_buffer); -static int sync_buffer(void *word) +static int sleep_on_buffer(void *word) { - struct block_device *bd; - struct buffer_head *bh - = container_of(word, struct buffer_head, b_state); - - smp_mb(); - bd = bh->b_bdev; - if (bd) - blk_run_address_space(bd->bd_inode->i_mapping); io_schedule(); return 0; } void __lock_buffer(struct buffer_head *bh) { - wait_on_bit_lock(&bh->b_state, BH_Lock, sync_buffer, + wait_on_bit_lock(&bh->b_state, BH_Lock, sleep_on_buffer, TASK_UNINTERRUPTIBLE); } EXPORT_SYMBOL(__lock_buffer); @@ -90,7 +82,7 @@ EXPORT_SYMBOL(unlock_buffer); */ void __wait_on_buffer(struct buffer_head * bh) { - wait_on_bit(&bh->b_state, BH_Lock, sync_buffer, TASK_UNINTERRUPTIBLE); + wait_on_bit(&bh->b_state, BH_Lock, sleep_on_buffer, TASK_UNINTERRUPTIBLE); } EXPORT_SYMBOL(__wait_on_buffer); @@ -749,7 +741,7 @@ static int fsync_buffers_list(spinlock_t *lock, struct list_head *list) { struct buffer_head *bh; struct list_head tmp; - struct address_space *mapping, *prev_mapping = NULL; + struct address_space *mapping; int err = 0, err2; INIT_LIST_HEAD(&tmp); @@ -783,10 +775,6 @@ static int fsync_buffers_list(spinlock_t *lock, struct list_head *list) * wait_on_buffer() will do that for us * through sync_buffer(). */ - if (prev_mapping && prev_mapping != mapping) - blk_run_address_space(prev_mapping); - prev_mapping = mapping; - brelse(bh); spin_lock(lock); } @@ -3138,17 +3126,6 @@ out: } EXPORT_SYMBOL(try_to_free_buffers); -void block_sync_page(struct page *page) -{ - struct address_space *mapping; - - smp_mb(); - mapping = page_mapping(page); - if (mapping) - blk_run_backing_dev(mapping->backing_dev_info, page); -} -EXPORT_SYMBOL(block_sync_page); - /* * There are no bdflush tunables left. But distributions are * still running obsolete flush daemons, so we terminate them here. diff --git a/fs/cifs/file.c b/fs/cifs/file.c index e964b1cd5dd09..c27d236738fc0 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c @@ -1569,34 +1569,6 @@ int cifs_fsync(struct file *file, int datasync) return rc; } -/* static void cifs_sync_page(struct page *page) -{ - struct address_space *mapping; - struct inode *inode; - unsigned long index = page->index; - unsigned int rpages = 0; - int rc = 0; - - cFYI(1, "sync page %p", page); - mapping = page->mapping; - if (!mapping) - return 0; - inode = mapping->host; - if (!inode) - return; */ - -/* fill in rpages then - result = cifs_pagein_inode(inode, index, rpages); */ /* BB finish */ - -/* cFYI(1, "rpages is %d for sync page of Index %ld", rpages, index); - -#if 0 - if (rc < 0) - return rc; - return 0; -#endif -} */ - /* * As file closes, flush all cached write data for this inode checking * for write behind errors. @@ -2510,7 +2482,6 @@ const struct address_space_operations cifs_addr_ops = { .set_page_dirty = __set_page_dirty_nobuffers, .releasepage = cifs_release_page, .invalidatepage = cifs_invalidate_page, - /* .sync_page = cifs_sync_page, */ /* .direct_IO = */ }; @@ -2528,6 +2499,5 @@ const struct address_space_operations cifs_addr_ops_smallbuf = { .set_page_dirty = __set_page_dirty_nobuffers, .releasepage = cifs_release_page, .invalidatepage = cifs_invalidate_page, - /* .sync_page = cifs_sync_page, */ /* .direct_IO = */ }; diff --git a/fs/direct-io.c b/fs/direct-io.c index b044705eedd4f..df709b3b860a4 100644 --- a/fs/direct-io.c +++ b/fs/direct-io.c @@ -1110,11 +1110,8 @@ direct_io_worker(int rw, struct kiocb *iocb, struct inode *inode, ((rw & READ) || (dio->result == dio->size))) ret = -EIOCBQUEUED; - if (ret != -EIOCBQUEUED) { - /* All IO is now issued, send it on its way */ - blk_run_address_space(inode->i_mapping); + if (ret != -EIOCBQUEUED) dio_await_completion(dio); - } /* * Sync will always be dropping the final ref and completing the diff --git a/fs/efs/inode.c b/fs/efs/inode.c index a8e7797b94779..9c13412e6c99c 100644 --- a/fs/efs/inode.c +++ b/fs/efs/inode.c @@ -23,7 +23,6 @@ static sector_t _efs_bmap(struct address_space *mapping, sector_t block) } static const struct address_space_operations efs_aops = { .readpage = efs_readpage, - .sync_page = block_sync_page, .bmap = _efs_bmap }; diff --git a/fs/exofs/inode.c b/fs/exofs/inode.c index a7555238c41aa..82b94c8f5d220 100644 --- a/fs/exofs/inode.c +++ b/fs/exofs/inode.c @@ -795,7 +795,6 @@ const struct address_space_operations exofs_aops = { .direct_IO = NULL, /* TODO: Should be trivial to do */ /* With these NULL has special meaning or default is not exported */ - .sync_page = NULL, .get_xip_mem = NULL, .migratepage = NULL, .launder_page = NULL, diff --git a/fs/ext2/inode.c b/fs/ext2/inode.c index 40ad210a5049a..c47f706878b5f 100644 --- a/fs/ext2/inode.c +++ b/fs/ext2/inode.c @@ -860,7 +860,6 @@ const struct address_space_operations ext2_aops = { .readpage = ext2_readpage, .readpages = ext2_readpages, .writepage = ext2_writepage, - .sync_page = block_sync_page, .write_begin = ext2_write_begin, .write_end = ext2_write_end, .bmap = ext2_bmap, @@ -880,7 +879,6 @@ const struct address_space_operations ext2_nobh_aops = { .readpage = ext2_readpage, .readpages = ext2_readpages, .writepage = ext2_nobh_writepage, - .sync_page = block_sync_page, .write_begin = ext2_nobh_write_begin, .write_end = nobh_write_end, .bmap = ext2_bmap, diff --git a/fs/ext3/inode.c b/fs/ext3/inode.c index ae94f6d949f52..fe2541d250e44 100644 --- a/fs/ext3/inode.c +++ b/fs/ext3/inode.c @@ -1894,7 +1894,6 @@ static const struct address_space_operations ext3_ordered_aops = { .readpage = ext3_readpage, .readpages = ext3_readpages, .writepage = ext3_ordered_writepage, - .sync_page = block_sync_page, .write_begin = ext3_write_begin, .write_end = ext3_ordered_write_end, .bmap = ext3_bmap, @@ -1910,7 +1909,6 @@ static const struct address_space_operations ext3_writeback_aops = { .readpage = ext3_readpage, .readpages = ext3_readpages, .writepage = ext3_writeback_writepage, - .sync_page = block_sync_page, .write_begin = ext3_write_begin, .write_end = ext3_writeback_write_end, .bmap = ext3_bmap, @@ -1926,7 +1924,6 @@ static const struct address_space_operations ext3_journalled_aops = { .readpage = ext3_readpage, .readpages = ext3_readpages, .writepage = ext3_journalled_writepage, - .sync_page = block_sync_page, .write_begin = ext3_write_begin, .write_end = ext3_journalled_write_end, .set_page_dirty = ext3_journalled_set_page_dirty, diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index 9f7f9e49914fa..9297ad46c4658 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -3903,7 +3903,6 @@ static const struct address_space_operations ext4_ordered_aops = { .readpage = ext4_readpage, .readpages = ext4_readpages, .writepage = ext4_writepage, - .sync_page = block_sync_page, .write_begin = ext4_write_begin, .write_end = ext4_ordered_write_end, .bmap = ext4_bmap, @@ -3919,7 +3918,6 @@ static const struct address_space_operations ext4_writeback_aops = { .readpage = ext4_readpage, .readpages = ext4_readpages, .writepage = ext4_writepage, - .sync_page = block_sync_page, .write_begin = ext4_write_begin, .write_end = ext4_writeback_write_end, .bmap = ext4_bmap, @@ -3935,7 +3933,6 @@ static const struct address_space_operations ext4_journalled_aops = { .readpage = ext4_readpage, .readpages = ext4_readpages, .writepage = ext4_writepage, - .sync_page = block_sync_page, .write_begin = ext4_write_begin, .write_end = ext4_journalled_write_end, .set_page_dirty = ext4_journalled_set_page_dirty, @@ -3951,7 +3948,6 @@ static const struct address_space_operations ext4_da_aops = { .readpages = ext4_readpages, .writepage = ext4_writepage, .writepages = ext4_da_writepages, - .sync_page = block_sync_page, .write_begin = ext4_da_write_begin, .write_end = ext4_da_write_end, .bmap = ext4_bmap, diff --git a/fs/fat/inode.c b/fs/fat/inode.c index 86753fe10bd1d..f4ff09fb79b1a 100644 --- a/fs/fat/inode.c +++ b/fs/fat/inode.c @@ -236,7 +236,6 @@ static const struct address_space_operations fat_aops = { .readpages = fat_readpages, .writepage = fat_writepage, .writepages = fat_writepages, - .sync_page = block_sync_page, .write_begin = fat_write_begin, .write_end = fat_write_end, .direct_IO = fat_direct_IO, diff --git a/fs/freevxfs/vxfs_subr.c b/fs/freevxfs/vxfs_subr.c index 1429f3ae1e868..5d318c44f8554 100644 --- a/fs/freevxfs/vxfs_subr.c +++ b/fs/freevxfs/vxfs_subr.c @@ -44,7 +44,6 @@ static sector_t vxfs_bmap(struct address_space *, sector_t); const struct address_space_operations vxfs_aops = { .readpage = vxfs_readpage, .bmap = vxfs_bmap, - .sync_page = block_sync_page, }; inline void diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c index 9e3f68cc1bd13..09e8d51eeb64f 100644 --- a/fs/fuse/inode.c +++ b/fs/fuse/inode.c @@ -868,7 +868,6 @@ static int fuse_bdi_init(struct fuse_conn *fc, struct super_block *sb) fc->bdi.name = "fuse"; fc->bdi.ra_pages = (VM_MAX_READAHEAD * 1024) / PAGE_CACHE_SIZE; - fc->bdi.unplug_io_fn = default_unplug_io_fn; /* fuse does it's own writeback accounting */ fc->bdi.capabilities = BDI_CAP_NO_ACCT_WB; diff --git a/fs/gfs2/aops.c b/fs/gfs2/aops.c index 4f36f8832b9b1..2f87ad27efd0f 100644 --- a/fs/gfs2/aops.c +++ b/fs/gfs2/aops.c @@ -1116,7 +1116,6 @@ static const struct address_space_operations gfs2_writeback_aops = { .writepages = gfs2_writeback_writepages, .readpage = gfs2_readpage, .readpages = gfs2_readpages, - .sync_page = block_sync_page, .write_begin = gfs2_write_begin, .write_end = gfs2_write_end, .bmap = gfs2_bmap, @@ -1132,7 +1131,6 @@ static const struct address_space_operations gfs2_ordered_aops = { .writepage = gfs2_ordered_writepage, .readpage = gfs2_readpage, .readpages = gfs2_readpages, - .sync_page = block_sync_page, .write_begin = gfs2_write_begin, .write_end = gfs2_write_end, .set_page_dirty = gfs2_set_page_dirty, @@ -1150,7 +1148,6 @@ static const struct address_space_operations gfs2_jdata_aops = { .writepages = gfs2_jdata_writepages, .readpage = gfs2_readpage, .readpages = gfs2_readpages, - .sync_page = block_sync_page, .write_begin = gfs2_write_begin, .write_end = gfs2_write_end, .set_page_dirty = gfs2_set_page_dirty, diff --git a/fs/gfs2/meta_io.c b/fs/gfs2/meta_io.c index 939739c7b3f9d..a566331db4e1a 100644 --- a/fs/gfs2/meta_io.c +++ b/fs/gfs2/meta_io.c @@ -94,7 +94,6 @@ static int gfs2_aspace_writepage(struct page *page, struct writeback_control *wb const struct address_space_operations gfs2_meta_aops = { .writepage = gfs2_aspace_writepage, .releasepage = gfs2_releasepage, - .sync_page = block_sync_page, }; /** diff --git a/fs/hfs/inode.c b/fs/hfs/inode.c index dffb4e9966435..fff16c968e677 100644 --- a/fs/hfs/inode.c +++ b/fs/hfs/inode.c @@ -150,7 +150,6 @@ static int hfs_writepages(struct address_space *mapping, const struct address_space_operations hfs_btree_aops = { .readpage = hfs_readpage, .writepage = hfs_writepage, - .sync_page = block_sync_page, .write_begin = hfs_write_begin, .write_end = generic_write_end, .bmap = hfs_bmap, @@ -160,7 +159,6 @@ const struct address_space_operations hfs_btree_aops = { const struct address_space_operations hfs_aops = { .readpage = hfs_readpage, .writepage = hfs_writepage, - .sync_page = block_sync_page, .write_begin = hfs_write_begin, .write_end = generic_write_end, .bmap = hfs_bmap, diff --git a/fs/hfsplus/inode.c b/fs/hfsplus/inode.c index a8df651747f0e..b248a6cfcad93 100644 --- a/fs/hfsplus/inode.c +++ b/fs/hfsplus/inode.c @@ -146,7 +146,6 @@ static int hfsplus_writepages(struct address_space *mapping, const struct address_space_operations hfsplus_btree_aops = { .readpage = hfsplus_readpage, .writepage = hfsplus_writepage, - .sync_page = block_sync_page, .write_begin = hfsplus_write_begin, .write_end = generic_write_end, .bmap = hfsplus_bmap, @@ -156,7 +155,6 @@ const struct address_space_operations hfsplus_btree_aops = { const struct address_space_operations hfsplus_aops = { .readpage = hfsplus_readpage, .writepage = hfsplus_writepage, - .sync_page = block_sync_page, .write_begin = hfsplus_write_begin, .write_end = generic_write_end, .bmap = hfsplus_bmap, diff --git a/fs/hpfs/file.c b/fs/hpfs/file.c index c0340887c7ea6..9e84257b3ad5e 100644 --- a/fs/hpfs/file.c +++ b/fs/hpfs/file.c @@ -120,7 +120,6 @@ static sector_t _hpfs_bmap(struct address_space *mapping, sector_t block) const struct address_space_operations hpfs_aops = { .readpage = hpfs_readpage, .writepage = hpfs_writepage, - .sync_page = block_sync_page, .write_begin = hpfs_write_begin, .write_end = generic_write_end, .bmap = _hpfs_bmap diff --git a/fs/isofs/inode.c b/fs/isofs/inode.c index a0f3833c0dbf5..3db5ba4568fc8 100644 --- a/fs/isofs/inode.c +++ b/fs/isofs/inode.c @@ -1158,7 +1158,6 @@ static sector_t _isofs_bmap(struct address_space *mapping, sector_t block) static const struct address_space_operations isofs_aops = { .readpage = isofs_readpage, - .sync_page = block_sync_page, .bmap = _isofs_bmap }; diff --git a/fs/jfs/inode.c b/fs/jfs/inode.c index 9978803ceedc5..eddbb373209e9 100644 --- a/fs/jfs/inode.c +++ b/fs/jfs/inode.c @@ -352,7 +352,6 @@ const struct address_space_operations jfs_aops = { .readpages = jfs_readpages, .writepage = jfs_writepage, .writepages = jfs_writepages, - .sync_page = block_sync_page, .write_begin = jfs_write_begin, .write_end = nobh_write_end, .bmap = jfs_bmap, diff --git a/fs/jfs/jfs_metapage.c b/fs/jfs/jfs_metapage.c index 48b44bd8267b9..6740d34cd82b8 100644 --- a/fs/jfs/jfs_metapage.c +++ b/fs/jfs/jfs_metapage.c @@ -583,7 +583,6 @@ static void metapage_invalidatepage(struct page *page, unsigned long offset) const struct address_space_operations jfs_metapage_aops = { .readpage = metapage_readpage, .writepage = metapage_writepage, - .sync_page = block_sync_page, .releasepage = metapage_releasepage, .invalidatepage = metapage_invalidatepage, .set_page_dirty = __set_page_dirty_nobuffers, diff --git a/fs/logfs/dev_bdev.c b/fs/logfs/dev_bdev.c index 723bc5bca09ae..1adc8d455f0ea 100644 --- a/fs/logfs/dev_bdev.c +++ b/fs/logfs/dev_bdev.c @@ -39,7 +39,6 @@ static int sync_request(struct page *page, struct block_device *bdev, int rw) bio.bi_end_io = request_complete; submit_bio(rw, &bio); - generic_unplug_device(bdev_get_queue(bdev)); wait_for_completion(&complete); return test_bit(BIO_UPTODATE, &bio.bi_flags) ? 0 : -EIO; } @@ -168,7 +167,6 @@ static void bdev_writeseg(struct super_block *sb, u64 ofs, size_t len) } len = PAGE_ALIGN(len); __bdev_writeseg(sb, ofs, ofs >> PAGE_SHIFT, len >> PAGE_SHIFT); - generic_unplug_device(bdev_get_queue(logfs_super(sb)->s_bdev)); } diff --git a/fs/minix/inode.c b/fs/minix/inode.c index ae0b83f476a63..adcdc0a4e1826 100644 --- a/fs/minix/inode.c +++ b/fs/minix/inode.c @@ -399,7 +399,6 @@ static sector_t minix_bmap(struct address_space *mapping, sector_t block) static const struct address_space_operations minix_aops = { .readpage = minix_readpage, .writepage = minix_writepage, - .sync_page = block_sync_page, .write_begin = minix_write_begin, .write_end = generic_write_end, .bmap = minix_bmap diff --git a/fs/nilfs2/btnode.c b/fs/nilfs2/btnode.c index 388e9e8f5286f..f4f1c08807edd 100644 --- a/fs/nilfs2/btnode.c +++ b/fs/nilfs2/btnode.c @@ -40,14 +40,10 @@ void nilfs_btnode_cache_init_once(struct address_space *btnc) nilfs_mapping_init_once(btnc); } -static const struct address_space_operations def_btnode_aops = { - .sync_page = block_sync_page, -}; - void nilfs_btnode_cache_init(struct address_space *btnc, struct backing_dev_info *bdi) { - nilfs_mapping_init(btnc, bdi, &def_btnode_aops); + nilfs_mapping_init(btnc, bdi); } void nilfs_btnode_cache_clear(struct address_space *btnc) diff --git a/fs/nilfs2/gcinode.c b/fs/nilfs2/gcinode.c index caf9a6a3fb54f..1c2a3e23f8b2d 100644 --- a/fs/nilfs2/gcinode.c +++ b/fs/nilfs2/gcinode.c @@ -49,7 +49,6 @@ #include "ifile.h" static const struct address_space_operations def_gcinode_aops = { - .sync_page = block_sync_page, }; /* diff --git a/fs/nilfs2/inode.c b/fs/nilfs2/inode.c index 2fd440d8d6b8d..c89d5d1ea7c7a 100644 --- a/fs/nilfs2/inode.c +++ b/fs/nilfs2/inode.c @@ -262,7 +262,6 @@ nilfs_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov, const struct address_space_operations nilfs_aops = { .writepage = nilfs_writepage, .readpage = nilfs_readpage, - .sync_page = block_sync_page, .writepages = nilfs_writepages, .set_page_dirty = nilfs_set_page_dirty, .readpages = nilfs_readpages, diff --git a/fs/nilfs2/mdt.c b/fs/nilfs2/mdt.c index 6a0e2a189f606..3fdb61d79c9a4 100644 --- a/fs/nilfs2/mdt.c +++ b/fs/nilfs2/mdt.c @@ -399,7 +399,6 @@ nilfs_mdt_write_page(struct page *page, struct writeback_control *wbc) static const struct address_space_operations def_mdt_aops = { .writepage = nilfs_mdt_write_page, - .sync_page = block_sync_page, }; static const struct inode_operations def_mdt_iops; @@ -438,10 +437,6 @@ void nilfs_mdt_set_entry_size(struct inode *inode, unsigned entry_size, mi->mi_first_entry_offset = DIV_ROUND_UP(header_size, entry_size); } -static const struct address_space_operations shadow_map_aops = { - .sync_page = block_sync_page, -}; - /** * nilfs_mdt_setup_shadow_map - setup shadow map and bind it to metadata file * @inode: inode of the metadata file @@ -455,9 +450,9 @@ int nilfs_mdt_setup_shadow_map(struct inode *inode, INIT_LIST_HEAD(&shadow->frozen_buffers); nilfs_mapping_init_once(&shadow->frozen_data); - nilfs_mapping_init(&shadow->frozen_data, bdi, &shadow_map_aops); + nilfs_mapping_init(&shadow->frozen_data, bdi); nilfs_mapping_init_once(&shadow->frozen_btnodes); - nilfs_mapping_init(&shadow->frozen_btnodes, bdi, &shadow_map_aops); + nilfs_mapping_init(&shadow->frozen_btnodes, bdi); mi->mi_shadow = shadow; return 0; } diff --git a/fs/nilfs2/page.c b/fs/nilfs2/page.c index 0c432416cfefc..3da37cc5de347 100644 --- a/fs/nilfs2/page.c +++ b/fs/nilfs2/page.c @@ -506,15 +506,14 @@ void nilfs_mapping_init_once(struct address_space *mapping) } void nilfs_mapping_init(struct address_space *mapping, - struct backing_dev_info *bdi, - const struct address_space_operations *aops) + struct backing_dev_info *bdi) { mapping->host = NULL; mapping->flags = 0; mapping_set_gfp_mask(mapping, GFP_NOFS); mapping->assoc_mapping = NULL; mapping->backing_dev_info = bdi; - mapping->a_ops = aops; + mapping->a_ops = NULL; } /* diff --git a/fs/nilfs2/page.h b/fs/nilfs2/page.h index 622df27cd8915..ba4d6fd40b04d 100644 --- a/fs/nilfs2/page.h +++ b/fs/nilfs2/page.h @@ -63,8 +63,7 @@ void nilfs_copy_back_pages(struct address_space *, struct address_space *); void nilfs_clear_dirty_pages(struct address_space *); void nilfs_mapping_init_once(struct address_space *mapping); void nilfs_mapping_init(struct address_space *mapping, - struct backing_dev_info *bdi, - const struct address_space_operations *aops); + struct backing_dev_info *bdi); unsigned nilfs_page_count_clean_buffers(struct page *, unsigned, unsigned); unsigned long nilfs_find_uncommitted_extent(struct inode *inode, sector_t start_blk, diff --git a/fs/ntfs/aops.c b/fs/ntfs/aops.c index c3c2c7ac90204..0b1e885b8cf8f 100644 --- a/fs/ntfs/aops.c +++ b/fs/ntfs/aops.c @@ -1543,8 +1543,6 @@ err_out: */ const struct address_space_operations ntfs_aops = { .readpage = ntfs_readpage, /* Fill page with data. */ - .sync_page = block_sync_page, /* Currently, just unplugs the - disk request queue. */ #ifdef NTFS_RW .writepage = ntfs_writepage, /* Write dirty page to disk. */ #endif /* NTFS_RW */ @@ -1560,8 +1558,6 @@ const struct address_space_operations ntfs_aops = { */ const struct address_space_operations ntfs_mst_aops = { .readpage = ntfs_readpage, /* Fill page with data. */ - .sync_page = block_sync_page, /* Currently, just unplugs the - disk request queue. */ #ifdef NTFS_RW .writepage = ntfs_writepage, /* Write dirty page to disk. */ .set_page_dirty = __set_page_dirty_nobuffers, /* Set the page dirty diff --git a/fs/ntfs/compress.c b/fs/ntfs/compress.c index 6551c7cbad929..ef9ed854255c8 100644 --- a/fs/ntfs/compress.c +++ b/fs/ntfs/compress.c @@ -698,8 +698,7 @@ lock_retry_remap: "uptodate! Unplugging the disk queue " "and rescheduling."); get_bh(tbh); - blk_run_address_space(mapping); - schedule(); + io_schedule(); put_bh(tbh); if (unlikely(!buffer_uptodate(tbh))) goto read_err; diff --git a/fs/ocfs2/aops.c b/fs/ocfs2/aops.c index 1fbb0e20131bf..daea0359e9740 100644 --- a/fs/ocfs2/aops.c +++ b/fs/ocfs2/aops.c @@ -2043,7 +2043,6 @@ const struct address_space_operations ocfs2_aops = { .write_begin = ocfs2_write_begin, .write_end = ocfs2_write_end, .bmap = ocfs2_bmap, - .sync_page = block_sync_page, .direct_IO = ocfs2_direct_IO, .invalidatepage = ocfs2_invalidatepage, .releasepage = ocfs2_releasepage, diff --git a/fs/ocfs2/cluster/heartbeat.c b/fs/ocfs2/cluster/heartbeat.c index b108e863d8f65..1adab287bd24c 100644 --- a/fs/ocfs2/cluster/heartbeat.c +++ b/fs/ocfs2/cluster/heartbeat.c @@ -367,11 +367,7 @@ static inline void o2hb_bio_wait_dec(struct o2hb_bio_wait_ctxt *wc, static void o2hb_wait_on_io(struct o2hb_region *reg, struct o2hb_bio_wait_ctxt *wc) { - struct address_space *mapping = reg->hr_bdev->bd_inode->i_mapping; - - blk_run_address_space(mapping); o2hb_bio_wait_dec(wc, 1); - wait_for_completion(&wc->wc_io_complete); } diff --git a/fs/omfs/file.c b/fs/omfs/file.c index 8a6d34fa668a0..d738a7e493ddc 100644 --- a/fs/omfs/file.c +++ b/fs/omfs/file.c @@ -372,7 +372,6 @@ const struct address_space_operations omfs_aops = { .readpages = omfs_readpages, .writepage = omfs_writepage, .writepages = omfs_writepages, - .sync_page = block_sync_page, .write_begin = omfs_write_begin, .write_end = generic_write_end, .bmap = omfs_bmap, diff --git a/fs/qnx4/inode.c b/fs/qnx4/inode.c index e63b4171d583b..2b0646613f5a1 100644 --- a/fs/qnx4/inode.c +++ b/fs/qnx4/inode.c @@ -335,7 +335,6 @@ static sector_t qnx4_bmap(struct address_space *mapping, sector_t block) static const struct address_space_operations qnx4_aops = { .readpage = qnx4_readpage, .writepage = qnx4_writepage, - .sync_page = block_sync_page, .write_begin = qnx4_write_begin, .write_end = generic_write_end, .bmap = qnx4_bmap diff --git a/fs/reiserfs/inode.c b/fs/reiserfs/inode.c index 0bae036831e2c..03674675f886a 100644 --- a/fs/reiserfs/inode.c +++ b/fs/reiserfs/inode.c @@ -3212,7 +3212,6 @@ const struct address_space_operations reiserfs_address_space_operations = { .readpages = reiserfs_readpages, .releasepage = reiserfs_releasepage, .invalidatepage = reiserfs_invalidatepage, - .sync_page = block_sync_page, .write_begin = reiserfs_write_begin, .write_end = reiserfs_write_end, .bmap = reiserfs_aop_bmap, diff --git a/fs/sysv/itree.c b/fs/sysv/itree.c index 9ca66276315e0..fa8d43c92bb81 100644 --- a/fs/sysv/itree.c +++ b/fs/sysv/itree.c @@ -488,7 +488,6 @@ static sector_t sysv_bmap(struct address_space *mapping, sector_t block) const struct address_space_operations sysv_aops = { .readpage = sysv_readpage, .writepage = sysv_writepage, - .sync_page = block_sync_page, .write_begin = sysv_write_begin, .write_end = generic_write_end, .bmap = sysv_bmap diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c index 6e11c2975dcf5..81368d4d4a2c4 100644 --- a/fs/ubifs/super.c +++ b/fs/ubifs/super.c @@ -1979,7 +1979,6 @@ static int ubifs_fill_super(struct super_block *sb, void *data, int silent) */ c->bdi.name = "ubifs", c->bdi.capabilities = BDI_CAP_MAP_COPY; - c->bdi.unplug_io_fn = default_unplug_io_fn; err = bdi_init(&c->bdi); if (err) goto out_close; diff --git a/fs/udf/file.c b/fs/udf/file.c index 89c78486cbbe5..94e4553491c90 100644 --- a/fs/udf/file.c +++ b/fs/udf/file.c @@ -98,7 +98,6 @@ static int udf_adinicb_write_end(struct file *file, const struct address_space_operations udf_adinicb_aops = { .readpage = udf_adinicb_readpage, .writepage = udf_adinicb_writepage, - .sync_page = block_sync_page, .write_begin = simple_write_begin, .write_end = udf_adinicb_write_end, }; diff --git a/fs/udf/inode.c b/fs/udf/inode.c index c6a2e782b97b1..fa96fc0fe12b4 100644 --- a/fs/udf/inode.c +++ b/fs/udf/inode.c @@ -133,7 +133,6 @@ static sector_t udf_bmap(struct address_space *mapping, sector_t block) const struct address_space_operations udf_aops = { .readpage = udf_readpage, .writepage = udf_writepage, - .sync_page = block_sync_page, .write_begin = udf_write_begin, .write_end = generic_write_end, .bmap = udf_bmap, diff --git a/fs/ufs/inode.c b/fs/ufs/inode.c index 2b251f2093afc..83b28444eb17c 100644 --- a/fs/ufs/inode.c +++ b/fs/ufs/inode.c @@ -588,7 +588,6 @@ static sector_t ufs_bmap(struct address_space *mapping, sector_t block) const struct address_space_operations ufs_aops = { .readpage = ufs_readpage, .writepage = ufs_writepage, - .sync_page = block_sync_page, .write_begin = ufs_write_begin, .write_end = generic_write_end, .bmap = ufs_bmap diff --git a/fs/ufs/truncate.c b/fs/ufs/truncate.c index a58f9155fc9a7..ff0e79276f2dd 100644 --- a/fs/ufs/truncate.c +++ b/fs/ufs/truncate.c @@ -481,7 +481,7 @@ int ufs_truncate(struct inode *inode, loff_t old_i_size) break; if (IS_SYNC(inode) && (inode->i_state & I_DIRTY)) ufs_sync_inode (inode); - blk_run_address_space(inode->i_mapping); + blk_flush_plug(current); yield(); } diff --git a/fs/xfs/linux-2.6/xfs_aops.c b/fs/xfs/linux-2.6/xfs_aops.c index ec7bbb5645b63..83c1c20d145ad 100644 --- a/fs/xfs/linux-2.6/xfs_aops.c +++ b/fs/xfs/linux-2.6/xfs_aops.c @@ -1495,7 +1495,6 @@ const struct address_space_operations xfs_address_space_operations = { .readpages = xfs_vm_readpages, .writepage = xfs_vm_writepage, .writepages = xfs_vm_writepages, - .sync_page = block_sync_page, .releasepage = xfs_vm_releasepage, .invalidatepage = xfs_vm_invalidatepage, .write_begin = xfs_vm_write_begin, diff --git a/fs/xfs/linux-2.6/xfs_buf.c b/fs/xfs/linux-2.6/xfs_buf.c index ac1c7e8378ddd..4f8f53c4d42cd 100644 --- a/fs/xfs/linux-2.6/xfs_buf.c +++ b/fs/xfs/linux-2.6/xfs_buf.c @@ -991,7 +991,7 @@ xfs_buf_lock( if (atomic_read(&bp->b_pin_count) && (bp->b_flags & XBF_STALE)) xfs_log_force(bp->b_target->bt_mount, 0); if (atomic_read(&bp->b_io_remaining)) - blk_run_address_space(bp->b_target->bt_mapping); + blk_flush_plug(current); down(&bp->b_sema); XB_SET_OWNER(bp); @@ -1035,9 +1035,7 @@ xfs_buf_wait_unpin( set_current_state(TASK_UNINTERRUPTIBLE); if (atomic_read(&bp->b_pin_count) == 0) break; - if (atomic_read(&bp->b_io_remaining)) - blk_run_address_space(bp->b_target->bt_mapping); - schedule(); + io_schedule(); } remove_wait_queue(&bp->b_waiters, &wait); set_current_state(TASK_RUNNING); @@ -1443,7 +1441,7 @@ xfs_buf_iowait( trace_xfs_buf_iowait(bp, _RET_IP_); if (atomic_read(&bp->b_io_remaining)) - blk_run_address_space(bp->b_target->bt_mapping); + blk_flush_plug(current); wait_for_completion(&bp->b_iowait); trace_xfs_buf_iowait_done(bp, _RET_IP_); @@ -1667,7 +1665,6 @@ xfs_mapping_buftarg( struct inode *inode; struct address_space *mapping; static const struct address_space_operations mapping_aops = { - .sync_page = block_sync_page, .migratepage = fail_migrate_page, }; @@ -1948,7 +1945,7 @@ xfsbufd( count++; } if (count) - blk_run_address_space(target->bt_mapping); + blk_flush_plug(current); } while (!kthread_should_stop()); @@ -1996,7 +1993,7 @@ xfs_flush_buftarg( if (wait) { /* Expedite and wait for IO to complete. */ - blk_run_address_space(target->bt_mapping); + blk_flush_plug(current); while (!list_empty(&wait_list)) { bp = list_first_entry(&wait_list, struct xfs_buf, b_list); diff --git a/include/linux/backing-dev.h b/include/linux/backing-dev.h index 4ce34fa937d49..96f4094b706d9 100644 --- a/include/linux/backing-dev.h +++ b/include/linux/backing-dev.h @@ -66,8 +66,6 @@ struct backing_dev_info { unsigned int capabilities; /* Device capabilities */ congested_fn *congested_fn; /* Function pointer if device is md/dm */ void *congested_data; /* Pointer to aux data for congested func */ - void (*unplug_io_fn)(struct backing_dev_info *, struct page *); - void *unplug_io_data; char *name; @@ -251,7 +249,6 @@ int bdi_set_max_ratio(struct backing_dev_info *bdi, unsigned int max_ratio); extern struct backing_dev_info default_backing_dev_info; extern struct backing_dev_info noop_backing_dev_info; -void default_unplug_io_fn(struct backing_dev_info *bdi, struct page *page); int writeback_in_progress(struct backing_dev_info *bdi); @@ -336,17 +333,4 @@ static inline int bdi_sched_wait(void *word) return 0; } -static inline void blk_run_backing_dev(struct backing_dev_info *bdi, - struct page *page) -{ - if (bdi && bdi->unplug_io_fn) - bdi->unplug_io_fn(bdi, page); -} - -static inline void blk_run_address_space(struct address_space *mapping) -{ - if (mapping) - blk_run_backing_dev(mapping->backing_dev_info, NULL); -} - #endif /* _LINUX_BACKING_DEV_H */ diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index 5873037eeb915..64ab2a1bb1679 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -196,7 +196,6 @@ typedef void (request_fn_proc) (struct request_queue *q); typedef int (make_request_fn) (struct request_queue *q, struct bio *bio); typedef int (prep_rq_fn) (struct request_queue *, struct request *); typedef void (unprep_rq_fn) (struct request_queue *, struct request *); -typedef void (unplug_fn) (struct request_queue *); struct bio_vec; struct bvec_merge_data { @@ -279,7 +278,6 @@ struct request_queue make_request_fn *make_request_fn; prep_rq_fn *prep_rq_fn; unprep_rq_fn *unprep_rq_fn; - unplug_fn *unplug_fn; merge_bvec_fn *merge_bvec_fn; softirq_done_fn *softirq_done_fn; rq_timed_out_fn *rq_timed_out_fn; @@ -292,14 +290,6 @@ struct request_queue sector_t end_sector; struct request *boundary_rq; - /* - * Auto-unplugging state - */ - struct timer_list unplug_timer; - int unplug_thresh; /* After this many requests */ - unsigned long unplug_delay; /* After this many jiffies */ - struct work_struct unplug_work; - /* * Delayed queue handling */ @@ -399,14 +389,13 @@ struct request_queue #define QUEUE_FLAG_ASYNCFULL 4 /* write queue has been filled */ #define QUEUE_FLAG_DEAD 5 /* queue being torn down */ #define QUEUE_FLAG_REENTER 6 /* Re-entrancy avoidance */ -#define QUEUE_FLAG_PLUGGED 7 /* queue is plugged */ -#define QUEUE_FLAG_ELVSWITCH 8 /* don't use elevator, just do FIFO */ -#define QUEUE_FLAG_BIDI 9 /* queue supports bidi requests */ -#define QUEUE_FLAG_NOMERGES 10 /* disable merge attempts */ -#define QUEUE_FLAG_SAME_COMP 11 /* force complete on same CPU */ -#define QUEUE_FLAG_FAIL_IO 12 /* fake timeout */ -#define QUEUE_FLAG_STACKABLE 13 /* supports request stacking */ -#define QUEUE_FLAG_NONROT 14 /* non-rotational device (SSD) */ +#define QUEUE_FLAG_ELVSWITCH 7 /* don't use elevator, just do FIFO */ +#define QUEUE_FLAG_BIDI 8 /* queue supports bidi requests */ +#define QUEUE_FLAG_NOMERGES 9 /* disable merge attempts */ +#define QUEUE_FLAG_SAME_COMP 10 /* force complete on same CPU */ +#define QUEUE_FLAG_FAIL_IO 11 /* fake timeout */ +#define QUEUE_FLAG_STACKABLE 12 /* supports request stacking */ +#define QUEUE_FLAG_NONROT 13 /* non-rotational device (SSD) */ #define QUEUE_FLAG_VIRT QUEUE_FLAG_NONROT /* paravirt device */ #define QUEUE_FLAG_IO_STAT 15 /* do IO stats */ #define QUEUE_FLAG_DISCARD 16 /* supports DISCARD */ @@ -484,7 +473,6 @@ static inline void queue_flag_clear(unsigned int flag, struct request_queue *q) __clear_bit(flag, &q->queue_flags); } -#define blk_queue_plugged(q) test_bit(QUEUE_FLAG_PLUGGED, &(q)->queue_flags) #define blk_queue_tagged(q) test_bit(QUEUE_FLAG_QUEUED, &(q)->queue_flags) #define blk_queue_stopped(q) test_bit(QUEUE_FLAG_STOPPED, &(q)->queue_flags) #define blk_queue_nomerges(q) test_bit(QUEUE_FLAG_NOMERGES, &(q)->queue_flags) @@ -679,9 +667,6 @@ extern int blk_rq_prep_clone(struct request *rq, struct request *rq_src, extern void blk_rq_unprep_clone(struct request *rq); extern int blk_insert_cloned_request(struct request_queue *q, struct request *rq); -extern void blk_plug_device(struct request_queue *); -extern void blk_plug_device_unlocked(struct request_queue *); -extern int blk_remove_plug(struct request_queue *); extern void blk_delay_queue(struct request_queue *, unsigned long); extern void blk_recount_segments(struct request_queue *, struct bio *); extern int scsi_cmd_ioctl(struct request_queue *, struct gendisk *, fmode_t, @@ -726,7 +711,6 @@ extern int blk_execute_rq(struct request_queue *, struct gendisk *, struct request *, int); extern void blk_execute_rq_nowait(struct request_queue *, struct gendisk *, struct request *, int, rq_end_io_fn *); -extern void blk_unplug(struct request_queue *q); static inline struct request_queue *bdev_get_queue(struct block_device *bdev) { @@ -863,7 +847,6 @@ extern struct backing_dev_info *blk_get_backing_dev_info(struct block_device *bd extern int blk_rq_map_sg(struct request_queue *, struct request *, struct scatterlist *); extern void blk_dump_rq_flags(struct request *, char *); -extern void generic_unplug_device(struct request_queue *); extern long nr_blockdev_pages(void); int blk_get_queue(struct request_queue *); diff --git a/include/linux/buffer_head.h b/include/linux/buffer_head.h index 68d1fe7b877c8..f5df23561b96d 100644 --- a/include/linux/buffer_head.h +++ b/include/linux/buffer_head.h @@ -219,7 +219,6 @@ int generic_cont_expand_simple(struct inode *inode, loff_t size); int block_commit_write(struct page *page, unsigned from, unsigned to); int block_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf, get_block_t get_block); -void block_sync_page(struct page *); sector_t generic_block_bmap(struct address_space *, sector_t, get_block_t *); int block_truncate_page(struct address_space *, loff_t, get_block_t *); int nobh_write_begin(struct address_space *, loff_t, unsigned, unsigned, diff --git a/include/linux/device-mapper.h b/include/linux/device-mapper.h index 272496d1fae41..e2768834f3977 100644 --- a/include/linux/device-mapper.h +++ b/include/linux/device-mapper.h @@ -285,11 +285,6 @@ void dm_table_add_target_callbacks(struct dm_table *t, struct dm_target_callback */ int dm_table_complete(struct dm_table *t); -/* - * Unplug all devices in a table. - */ -void dm_table_unplug_all(struct dm_table *t); - /* * Table reference counting. */ diff --git a/include/linux/elevator.h b/include/linux/elevator.h index 8857cf9adbb71..ec6f72b844774 100644 --- a/include/linux/elevator.h +++ b/include/linux/elevator.h @@ -20,7 +20,6 @@ typedef void (elevator_bio_merged_fn) (struct request_queue *, typedef int (elevator_dispatch_fn) (struct request_queue *, int); typedef void (elevator_add_req_fn) (struct request_queue *, struct request *); -typedef int (elevator_queue_empty_fn) (struct request_queue *); typedef struct request *(elevator_request_list_fn) (struct request_queue *, struct request *); typedef void (elevator_completed_req_fn) (struct request_queue *, struct request *); typedef int (elevator_may_queue_fn) (struct request_queue *, int); @@ -46,7 +45,6 @@ struct elevator_ops elevator_activate_req_fn *elevator_activate_req_fn; elevator_deactivate_req_fn *elevator_deactivate_req_fn; - elevator_queue_empty_fn *elevator_queue_empty_fn; elevator_completed_req_fn *elevator_completed_req_fn; elevator_request_list_fn *elevator_former_req_fn; @@ -101,8 +99,8 @@ struct elevator_queue */ extern void elv_dispatch_sort(struct request_queue *, struct request *); extern void elv_dispatch_add_tail(struct request_queue *, struct request *); -extern void elv_add_request(struct request_queue *, struct request *, int, int); -extern void __elv_add_request(struct request_queue *, struct request *, int, int); +extern void elv_add_request(struct request_queue *, struct request *, int); +extern void __elv_add_request(struct request_queue *, struct request *, int); extern void elv_insert(struct request_queue *, struct request *, int); extern int elv_merge(struct request_queue *, struct request **, struct bio *); extern int elv_try_merge(struct request *, struct bio *); @@ -112,7 +110,6 @@ extern void elv_merged_request(struct request_queue *, struct request *, int); extern void elv_bio_merged(struct request_queue *q, struct request *, struct bio *); extern void elv_requeue_request(struct request_queue *, struct request *); -extern int elv_queue_empty(struct request_queue *); extern struct request *elv_former_request(struct request_queue *, struct request *); extern struct request *elv_latter_request(struct request_queue *, struct request *); extern int elv_register_queue(struct request_queue *q); diff --git a/include/linux/fs.h b/include/linux/fs.h index bd3215940c374..9f2cf69911b81 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -583,7 +583,6 @@ typedef int (*read_actor_t)(read_descriptor_t *, struct page *, struct address_space_operations { int (*writepage)(struct page *page, struct writeback_control *wbc); int (*readpage)(struct file *, struct page *); - void (*sync_page)(struct page *); /* Write back some dirty pages from this mapping. */ int (*writepages)(struct address_space *, struct writeback_control *); diff --git a/include/linux/pagemap.h b/include/linux/pagemap.h index 9c66e994540f6..e112b8db2f3c0 100644 --- a/include/linux/pagemap.h +++ b/include/linux/pagemap.h @@ -298,7 +298,6 @@ static inline pgoff_t linear_page_index(struct vm_area_struct *vma, extern void __lock_page(struct page *page); extern int __lock_page_killable(struct page *page); -extern void __lock_page_nosync(struct page *page); extern int __lock_page_or_retry(struct page *page, struct mm_struct *mm, unsigned int flags); extern void unlock_page(struct page *page); @@ -341,17 +340,6 @@ static inline int lock_page_killable(struct page *page) return 0; } -/* - * lock_page_nosync should only be used if we can't pin the page's inode. - * Doesn't play quite so well with block device plugging. - */ -static inline void lock_page_nosync(struct page *page) -{ - might_sleep(); - if (!trylock_page(page)) - __lock_page_nosync(page); -} - /* * lock_page_or_retry - Lock the page, unless this would block and the * caller indicated that it can handle a retry. diff --git a/include/linux/swap.h b/include/linux/swap.h index 4d559325d919f..9ee321833b21d 100644 --- a/include/linux/swap.h +++ b/include/linux/swap.h @@ -299,8 +299,6 @@ extern void mem_cgroup_get_shmem_target(struct inode *inode, pgoff_t pgoff, struct page **pagep, swp_entry_t *ent); #endif -extern void swap_unplug_io_fn(struct backing_dev_info *, struct page *); - #ifdef CONFIG_SWAP /* linux/mm/page_io.c */ extern int swap_readpage(struct page *); diff --git a/mm/backing-dev.c b/mm/backing-dev.c index 027100d30227f..c91e139a652e7 100644 --- a/mm/backing-dev.c +++ b/mm/backing-dev.c @@ -14,17 +14,11 @@ static atomic_long_t bdi_seq = ATOMIC_LONG_INIT(0); -void default_unplug_io_fn(struct backing_dev_info *bdi, struct page *page) -{ -} -EXPORT_SYMBOL(default_unplug_io_fn); - struct backing_dev_info default_backing_dev_info = { .name = "default", .ra_pages = VM_MAX_READAHEAD * 1024 / PAGE_CACHE_SIZE, .state = 0, .capabilities = BDI_CAP_MAP_COPY, - .unplug_io_fn = default_unplug_io_fn, }; EXPORT_SYMBOL_GPL(default_backing_dev_info); diff --git a/mm/filemap.c b/mm/filemap.c index 83a45d35468b9..380776c2a9acc 100644 --- a/mm/filemap.c +++ b/mm/filemap.c @@ -155,45 +155,15 @@ void remove_from_page_cache(struct page *page) } EXPORT_SYMBOL(remove_from_page_cache); -static int sync_page(void *word) +static int sleep_on_page(void *word) { - struct address_space *mapping; - struct page *page; - - page = container_of((unsigned long *)word, struct page, flags); - - /* - * page_mapping() is being called without PG_locked held. - * Some knowledge of the state and use of the page is used to - * reduce the requirements down to a memory barrier. - * The danger here is of a stale page_mapping() return value - * indicating a struct address_space different from the one it's - * associated with when it is associated with one. - * After smp_mb(), it's either the correct page_mapping() for - * the page, or an old page_mapping() and the page's own - * page_mapping() has gone NULL. - * The ->sync_page() address_space operation must tolerate - * page_mapping() going NULL. By an amazing coincidence, - * this comes about because none of the users of the page - * in the ->sync_page() methods make essential use of the - * page_mapping(), merely passing the page down to the backing - * device's unplug functions when it's non-NULL, which in turn - * ignore it for all cases but swap, where only page_private(page) is - * of interest. When page_mapping() does go NULL, the entire - * call stack gracefully ignores the page and returns. - * -- wli - */ - smp_mb(); - mapping = page_mapping(page); - if (mapping && mapping->a_ops && mapping->a_ops->sync_page) - mapping->a_ops->sync_page(page); io_schedule(); return 0; } -static int sync_page_killable(void *word) +static int sleep_on_page_killable(void *word) { - sync_page(word); + sleep_on_page(word); return fatal_signal_pending(current) ? -EINTR : 0; } @@ -479,12 +449,6 @@ struct page *__page_cache_alloc(gfp_t gfp) EXPORT_SYMBOL(__page_cache_alloc); #endif -static int __sleep_on_page_lock(void *word) -{ - io_schedule(); - return 0; -} - /* * In order to wait for pages to become available there must be * waitqueues associated with pages. By using a hash table of @@ -512,7 +476,7 @@ void wait_on_page_bit(struct page *page, int bit_nr) DEFINE_WAIT_BIT(wait, &page->flags, bit_nr); if (test_bit(bit_nr, &page->flags)) - __wait_on_bit(page_waitqueue(page), &wait, sync_page, + __wait_on_bit(page_waitqueue(page), &wait, sleep_on_page, TASK_UNINTERRUPTIBLE); } EXPORT_SYMBOL(wait_on_page_bit); @@ -576,17 +540,12 @@ EXPORT_SYMBOL(end_page_writeback); /** * __lock_page - get a lock on the page, assuming we need to sleep to get it * @page: the page to lock - * - * Ugly. Running sync_page() in state TASK_UNINTERRUPTIBLE is scary. If some - * random driver's requestfn sets TASK_RUNNING, we could busywait. However - * chances are that on the second loop, the block layer's plug list is empty, - * so sync_page() will then return in state TASK_UNINTERRUPTIBLE. */ void __lock_page(struct page *page) { DEFINE_WAIT_BIT(wait, &page->flags, PG_locked); - __wait_on_bit_lock(page_waitqueue(page), &wait, sync_page, + __wait_on_bit_lock(page_waitqueue(page), &wait, sleep_on_page, TASK_UNINTERRUPTIBLE); } EXPORT_SYMBOL(__lock_page); @@ -596,24 +555,10 @@ int __lock_page_killable(struct page *page) DEFINE_WAIT_BIT(wait, &page->flags, PG_locked); return __wait_on_bit_lock(page_waitqueue(page), &wait, - sync_page_killable, TASK_KILLABLE); + sleep_on_page_killable, TASK_KILLABLE); } EXPORT_SYMBOL_GPL(__lock_page_killable); -/** - * __lock_page_nosync - get a lock on the page, without calling sync_page() - * @page: the page to lock - * - * Variant of lock_page that does not require the caller to hold a reference - * on the page's mapping. - */ -void __lock_page_nosync(struct page *page) -{ - DEFINE_WAIT_BIT(wait, &page->flags, PG_locked); - __wait_on_bit_lock(page_waitqueue(page), &wait, __sleep_on_page_lock, - TASK_UNINTERRUPTIBLE); -} - int __lock_page_or_retry(struct page *page, struct mm_struct *mm, unsigned int flags) { diff --git a/mm/memory-failure.c b/mm/memory-failure.c index 0207c2f6f8bd7..bfba796d374d4 100644 --- a/mm/memory-failure.c +++ b/mm/memory-failure.c @@ -945,7 +945,7 @@ static int hwpoison_user_mappings(struct page *p, unsigned long pfn, collect_procs(ppage, &tokill); if (hpage != ppage) - lock_page_nosync(ppage); + lock_page(ppage); ret = try_to_unmap(ppage, ttu); if (ret != SWAP_SUCCESS) @@ -1038,7 +1038,7 @@ int __memory_failure(unsigned long pfn, int trapno, int flags) * Check "just unpoisoned", "filter hit", and * "race with other subpage." */ - lock_page_nosync(hpage); + lock_page(hpage); if (!PageHWPoison(hpage) || (hwpoison_filter(p) && TestClearPageHWPoison(p)) || (p != hpage && TestSetPageHWPoison(hpage))) { @@ -1088,7 +1088,7 @@ int __memory_failure(unsigned long pfn, int trapno, int flags) * It's very difficult to mess with pages currently under IO * and in many cases impossible, so we just avoid it here. */ - lock_page_nosync(hpage); + lock_page(hpage); /* * unpoison always clear PG_hwpoison inside page lock @@ -1231,7 +1231,7 @@ int unpoison_memory(unsigned long pfn) return 0; } - lock_page_nosync(page); + lock_page(page); /* * This test is racy because PG_hwpoison is set outside of page lock. * That's acceptable because that won't trigger kernel panic. Instead, diff --git a/mm/nommu.c b/mm/nommu.c index f59e1424d3db6..fb6cbd6abe168 100644 --- a/mm/nommu.c +++ b/mm/nommu.c @@ -1842,10 +1842,6 @@ int remap_vmalloc_range(struct vm_area_struct *vma, void *addr, } EXPORT_SYMBOL(remap_vmalloc_range); -void swap_unplug_io_fn(struct backing_dev_info *bdi, struct page *page) -{ -} - unsigned long arch_get_unmapped_area(struct file *file, unsigned long addr, unsigned long len, unsigned long pgoff, unsigned long flags) { diff --git a/mm/page-writeback.c b/mm/page-writeback.c index 2cb01f6ec5d01..cc0ede169e41d 100644 --- a/mm/page-writeback.c +++ b/mm/page-writeback.c @@ -1239,7 +1239,7 @@ int set_page_dirty_lock(struct page *page) { int ret; - lock_page_nosync(page); + lock_page(page); ret = set_page_dirty(page); unlock_page(page); return ret; diff --git a/mm/readahead.c b/mm/readahead.c index 77506a291a2d4..cbddc3e172467 100644 --- a/mm/readahead.c +++ b/mm/readahead.c @@ -554,17 +554,5 @@ page_cache_async_readahead(struct address_space *mapping, /* do read-ahead */ ondemand_readahead(mapping, ra, filp, true, offset, req_size); - -#ifdef CONFIG_BLOCK - /* - * Normally the current page is !uptodate and lock_page() will be - * immediately called to implicitly unplug the device. However this - * is not always true for RAID conifgurations, where data arrives - * not strictly in their submission order. In this case we need to - * explicitly kick off the IO. - */ - if (PageUptodate(page)) - blk_run_backing_dev(mapping->backing_dev_info, NULL); -#endif } EXPORT_SYMBOL_GPL(page_cache_async_readahead); diff --git a/mm/shmem.c b/mm/shmem.c index 5ee67c9906022..24d23f5bedf14 100644 --- a/mm/shmem.c +++ b/mm/shmem.c @@ -224,7 +224,6 @@ static const struct vm_operations_struct shmem_vm_ops; static struct backing_dev_info shmem_backing_dev_info __read_mostly = { .ra_pages = 0, /* No readahead */ .capabilities = BDI_CAP_NO_ACCT_AND_WRITEBACK | BDI_CAP_SWAP_BACKED, - .unplug_io_fn = default_unplug_io_fn, }; static LIST_HEAD(shmem_swaplist); diff --git a/mm/swap_state.c b/mm/swap_state.c index 5c8cfabbc9bc3..46680461785be 100644 --- a/mm/swap_state.c +++ b/mm/swap_state.c @@ -24,12 +24,10 @@ /* * swapper_space is a fiction, retained to simplify the path through - * vmscan's shrink_page_list, to make sync_page look nicer, and to allow - * future use of radix_tree tags in the swap cache. + * vmscan's shrink_page_list. */ static const struct address_space_operations swap_aops = { .writepage = swap_writepage, - .sync_page = block_sync_page, .set_page_dirty = __set_page_dirty_nobuffers, .migratepage = migrate_page, }; @@ -37,7 +35,6 @@ static const struct address_space_operations swap_aops = { static struct backing_dev_info swap_backing_dev_info = { .name = "swap", .capabilities = BDI_CAP_NO_ACCT_AND_WRITEBACK | BDI_CAP_SWAP_BACKED, - .unplug_io_fn = swap_unplug_io_fn, }; struct address_space swapper_space = { diff --git a/mm/swapfile.c b/mm/swapfile.c index 07a458d72fa88..7ceea78ceb200 100644 --- a/mm/swapfile.c +++ b/mm/swapfile.c @@ -94,39 +94,6 @@ __try_to_reclaim_swap(struct swap_info_struct *si, unsigned long offset) return ret; } -/* - * We need this because the bdev->unplug_fn can sleep and we cannot - * hold swap_lock while calling the unplug_fn. And swap_lock - * cannot be turned into a mutex. - */ -static DECLARE_RWSEM(swap_unplug_sem); - -void swap_unplug_io_fn(struct backing_dev_info *unused_bdi, struct page *page) -{ - swp_entry_t entry; - - down_read(&swap_unplug_sem); - entry.val = page_private(page); - if (PageSwapCache(page)) { - struct block_device *bdev = swap_info[swp_type(entry)]->bdev; - struct backing_dev_info *bdi; - - /* - * If the page is removed from swapcache from under us (with a - * racy try_to_unuse/swapoff) we need an additional reference - * count to avoid reading garbage from page_private(page) above. - * If the WARN_ON triggers during a swapoff it maybe the race - * condition and it's harmless. However if it triggers without - * swapoff it signals a problem. - */ - WARN_ON(page_count(page) <= 1); - - bdi = bdev->bd_inode->i_mapping->backing_dev_info; - blk_run_backing_dev(bdi, page); - } - up_read(&swap_unplug_sem); -} - /* * swapon tell device that all the old swap contents can be discarded, * to allow the swap device to optimize its wear-levelling. @@ -1643,10 +1610,6 @@ SYSCALL_DEFINE1(swapoff, const char __user *, specialfile) goto out_dput; } - /* wait for any unplug function to finish */ - down_write(&swap_unplug_sem); - up_write(&swap_unplug_sem); - destroy_swap_extents(p); if (p->flags & SWP_CONTINUED) free_swap_count_continuations(p); diff --git a/mm/vmscan.c b/mm/vmscan.c index 17497d0cd8b9e..251bed73ac034 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -358,7 +358,7 @@ static int may_write_to_queue(struct backing_dev_info *bdi, static void handle_write_error(struct address_space *mapping, struct page *page, int error) { - lock_page_nosync(page); + lock_page(page); if (page_mapping(page) == mapping) mapping_set_error(mapping, error); unlock_page(page); -- GitLab From 55602dd66f5353981b53f734e26c307f310ced37 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Thu, 24 Jun 2010 15:05:37 +0200 Subject: [PATCH 0382/2822] fs: make generic file read/write functions plug Signed-off-by: Jens Axboe --- mm/filemap.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/mm/filemap.c b/mm/filemap.c index 380776c2a9acc..f9a29c87a2cf0 100644 --- a/mm/filemap.c +++ b/mm/filemap.c @@ -1243,12 +1243,15 @@ generic_file_aio_read(struct kiocb *iocb, const struct iovec *iov, unsigned long seg = 0; size_t count; loff_t *ppos = &iocb->ki_pos; + struct blk_plug plug; count = 0; retval = generic_segment_checks(iov, &nr_segs, &count, VERIFY_WRITE); if (retval) return retval; + blk_start_plug(&plug); + /* coalesce the iovecs and go direct-to-BIO for O_DIRECT */ if (filp->f_flags & O_DIRECT) { loff_t size; @@ -1321,6 +1324,7 @@ generic_file_aio_read(struct kiocb *iocb, const struct iovec *iov, break; } out: + blk_finish_plug(&plug); return retval; } EXPORT_SYMBOL(generic_file_aio_read); @@ -2432,11 +2436,13 @@ ssize_t generic_file_aio_write(struct kiocb *iocb, const struct iovec *iov, { struct file *file = iocb->ki_filp; struct inode *inode = file->f_mapping->host; + struct blk_plug plug; ssize_t ret; BUG_ON(iocb->ki_pos != pos); mutex_lock(&inode->i_mutex); + blk_start_plug(&plug); ret = __generic_file_aio_write(iocb, iov, nr_segs, &iocb->ki_pos); mutex_unlock(&inode->i_mutex); @@ -2447,6 +2453,7 @@ ssize_t generic_file_aio_write(struct kiocb *iocb, const struct iovec *iov, if (err < 0 && ret > 0) ret = err; } + blk_finish_plug(&plug); return ret; } EXPORT_SYMBOL(generic_file_aio_write); -- GitLab From 5b417b1873694ece3291d7f64a943304559a817b Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Mon, 19 Apr 2010 10:04:38 +0200 Subject: [PATCH 0383/2822] read-ahead: use plugging Signed-off-by: Jens Axboe --- mm/readahead.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/mm/readahead.c b/mm/readahead.c index cbddc3e172467..2c0cc489e2880 100644 --- a/mm/readahead.c +++ b/mm/readahead.c @@ -109,9 +109,12 @@ EXPORT_SYMBOL(read_cache_pages); static int read_pages(struct address_space *mapping, struct file *filp, struct list_head *pages, unsigned nr_pages) { + struct blk_plug plug; unsigned page_idx; int ret; + blk_start_plug(&plug); + if (mapping->a_ops->readpages) { ret = mapping->a_ops->readpages(filp, mapping, pages, nr_pages); /* Clean up the remaining pages */ @@ -129,7 +132,10 @@ static int read_pages(struct address_space *mapping, struct file *filp, page_cache_release(page); } ret = 0; + out: + blk_finish_plug(&plug); + return ret; } -- GitLab From 2ed1a6bcf97a7ed787e6799bf2e80b9e6f51dca7 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Tue, 22 Jun 2010 12:52:14 +0200 Subject: [PATCH 0384/2822] fs: make mpage read/write_pages() plug Signed-off-by: Jens Axboe --- fs/mpage.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/fs/mpage.c b/fs/mpage.c index d78455a81ec97..0afc809e46e09 100644 --- a/fs/mpage.c +++ b/fs/mpage.c @@ -364,6 +364,9 @@ mpage_readpages(struct address_space *mapping, struct list_head *pages, sector_t last_block_in_bio = 0; struct buffer_head map_bh; unsigned long first_logical_block = 0; + struct blk_plug plug; + + blk_start_plug(&plug); map_bh.b_state = 0; map_bh.b_size = 0; @@ -385,6 +388,7 @@ mpage_readpages(struct address_space *mapping, struct list_head *pages, BUG_ON(!list_empty(pages)); if (bio) mpage_bio_submit(READ, bio); + blk_finish_plug(&plug); return 0; } EXPORT_SYMBOL(mpage_readpages); @@ -666,8 +670,11 @@ int mpage_writepages(struct address_space *mapping, struct writeback_control *wbc, get_block_t get_block) { + struct blk_plug plug; int ret; + blk_start_plug(&plug); + if (!get_block) ret = generic_writepages(mapping, wbc); else { @@ -682,6 +689,7 @@ mpage_writepages(struct address_space *mapping, if (mpd.bio) mpage_bio_submit(WRITE, mpd.bio); } + blk_finish_plug(&plug); return ret; } EXPORT_SYMBOL(mpage_writepages); -- GitLab From 9f5b9425468c85a901d863d241ba5c5dff9b23b8 Mon Sep 17 00:00:00 2001 From: Shaohua Li Date: Thu, 1 Jul 2010 07:55:01 +0200 Subject: [PATCH 0385/2822] fs: make aio plug Signed-off-by: Shaohua Li Signed-off-by: Jens Axboe --- fs/aio.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/fs/aio.c b/fs/aio.c index c5ea494ea9e24..1476bed1c5fbd 100644 --- a/fs/aio.c +++ b/fs/aio.c @@ -1660,6 +1660,7 @@ long do_io_submit(aio_context_t ctx_id, long nr, long ret = 0; int i; struct hlist_head batch_hash[AIO_BATCH_HASH_SIZE] = { { 0, }, }; + struct blk_plug plug; if (unlikely(nr < 0)) return -EINVAL; @@ -1676,6 +1677,8 @@ long do_io_submit(aio_context_t ctx_id, long nr, return -EINVAL; } + blk_start_plug(&plug); + /* * AKPM: should this return a partial result if some of the IOs were * successfully submitted? @@ -1698,6 +1701,7 @@ long do_io_submit(aio_context_t ctx_id, long nr, if (ret) break; } + blk_finish_plug(&plug); aio_batch_free(batch_hash); put_ioctx(ctx); -- GitLab From cf15900e1209d5b46ec2d24643adbf561830935f Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Wed, 2 Mar 2011 20:12:18 -0500 Subject: [PATCH 0386/2822] aio: remove request submission batching This should be useless now that we have on-stack plugging. So lets just kill it. Signed-off-by: Jens Axboe --- fs/aio.c | 75 +++----------------------------------------------------- 1 file changed, 3 insertions(+), 72 deletions(-) diff --git a/fs/aio.c b/fs/aio.c index 1476bed1c5fbd..020de5cb4a67f 100644 --- a/fs/aio.c +++ b/fs/aio.c @@ -34,8 +34,6 @@ #include #include #include -#include -#include #include #include @@ -65,14 +63,6 @@ static DECLARE_WORK(fput_work, aio_fput_routine); static DEFINE_SPINLOCK(fput_lock); static LIST_HEAD(fput_head); -#define AIO_BATCH_HASH_BITS 3 /* allocated on-stack, so don't go crazy */ -#define AIO_BATCH_HASH_SIZE (1 << AIO_BATCH_HASH_BITS) -struct aio_batch_entry { - struct hlist_node list; - struct address_space *mapping; -}; -mempool_t *abe_pool; - static void aio_kick_handler(struct work_struct *); static void aio_queue_work(struct kioctx *); @@ -86,8 +76,7 @@ static int __init aio_setup(void) kioctx_cachep = KMEM_CACHE(kioctx,SLAB_HWCACHE_ALIGN|SLAB_PANIC); aio_wq = create_workqueue("aio"); - abe_pool = mempool_create_kmalloc_pool(1, sizeof(struct aio_batch_entry)); - BUG_ON(!aio_wq || !abe_pool); + BUG_ON(!aio_wq); pr_debug("aio_setup: sizeof(struct page) = %d\n", (int)sizeof(struct page)); @@ -1512,59 +1501,8 @@ static ssize_t aio_setup_iocb(struct kiocb *kiocb, bool compat) return 0; } -static void aio_batch_add(struct address_space *mapping, - struct hlist_head *batch_hash) -{ - struct aio_batch_entry *abe; - struct hlist_node *pos; - unsigned bucket; - - bucket = hash_ptr(mapping, AIO_BATCH_HASH_BITS); - hlist_for_each_entry(abe, pos, &batch_hash[bucket], list) { - if (abe->mapping == mapping) - return; - } - - abe = mempool_alloc(abe_pool, GFP_KERNEL); - - /* - * we should be using igrab here, but - * we don't want to hammer on the global - * inode spinlock just to take an extra - * reference on a file that we must already - * have a reference to. - * - * When we're called, we always have a reference - * on the file, so we must always have a reference - * on the inode, so ihold() is safe here. - */ - ihold(mapping->host); - abe->mapping = mapping; - hlist_add_head(&abe->list, &batch_hash[bucket]); - return; -} - -static void aio_batch_free(struct hlist_head *batch_hash) -{ - struct aio_batch_entry *abe; - struct hlist_node *pos, *n; - int i; - - /* - * TODO: kill this - */ - for (i = 0; i < AIO_BATCH_HASH_SIZE; i++) { - hlist_for_each_entry_safe(abe, pos, n, &batch_hash[i], list) { - iput(abe->mapping->host); - hlist_del(&abe->list); - mempool_free(abe, abe_pool); - } - } -} - static int io_submit_one(struct kioctx *ctx, struct iocb __user *user_iocb, - struct iocb *iocb, struct hlist_head *batch_hash, - bool compat) + struct iocb *iocb, bool compat) { struct kiocb *req; struct file *file; @@ -1638,11 +1576,6 @@ static int io_submit_one(struct kioctx *ctx, struct iocb __user *user_iocb, ; } spin_unlock_irq(&ctx->ctx_lock); - if (req->ki_opcode == IOCB_CMD_PREAD || - req->ki_opcode == IOCB_CMD_PREADV || - req->ki_opcode == IOCB_CMD_PWRITE || - req->ki_opcode == IOCB_CMD_PWRITEV) - aio_batch_add(file->f_mapping, batch_hash); aio_put_req(req); /* drop extra ref to req */ return 0; @@ -1659,7 +1592,6 @@ long do_io_submit(aio_context_t ctx_id, long nr, struct kioctx *ctx; long ret = 0; int i; - struct hlist_head batch_hash[AIO_BATCH_HASH_SIZE] = { { 0, }, }; struct blk_plug plug; if (unlikely(nr < 0)) @@ -1697,12 +1629,11 @@ long do_io_submit(aio_context_t ctx_id, long nr, break; } - ret = io_submit_one(ctx, user_iocb, &tmp, batch_hash, compat); + ret = io_submit_one(ctx, user_iocb, &tmp, compat); if (ret) break; } blk_finish_plug(&plug); - aio_batch_free(batch_hash); put_ioctx(ctx); return i ? i : ret; -- GitLab From 721a9602e6607417c6bc15b18e97a2f35266c690 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Wed, 9 Mar 2011 11:56:30 +0100 Subject: [PATCH 0387/2822] block: kill off REQ_UNPLUG With the plugging now being explicitly controlled by the submitter, callers need not pass down unplugging hints to the block layer. If they want to unplug, it's because they manually plugged on their own - in which case, they should just unplug at will. Signed-off-by: Jens Axboe --- block/blk-core.c | 2 +- drivers/block/drbd/drbd_actlog.c | 2 +- drivers/block/drbd/drbd_int.h | 2 +- drivers/block/drbd/drbd_main.c | 3 +-- drivers/block/drbd/drbd_receiver.c | 9 +-------- drivers/md/bitmap.c | 2 +- drivers/md/dm-io.c | 2 +- drivers/md/dm-kcopyd.c | 5 +---- drivers/md/md.c | 5 ++--- fs/btrfs/extent_io.c | 2 +- fs/buffer.c | 14 ++++---------- fs/direct-io.c | 2 +- fs/ext4/page-io.c | 3 +-- fs/gfs2/log.c | 4 ++-- fs/gfs2/lops.c | 12 ++++++------ fs/gfs2/meta_io.c | 2 +- fs/jbd/commit.c | 2 +- fs/jbd2/commit.c | 6 +++--- fs/nilfs2/segbuf.c | 2 +- fs/xfs/linux-2.6/xfs_aops.c | 3 +-- include/linux/blk_types.h | 2 -- include/linux/fs.h | 28 +++++++++------------------- kernel/power/block_io.c | 2 +- mm/page_io.c | 2 +- 24 files changed, 43 insertions(+), 75 deletions(-) diff --git a/block/blk-core.c b/block/blk-core.c index 82a45898ba76f..7e9715ae18c80 100644 --- a/block/blk-core.c +++ b/block/blk-core.c @@ -1290,7 +1290,7 @@ get_rq: } plug = current->plug; - if (plug && !sync) { + if (plug) { if (!plug->should_sort && !list_empty(&plug->list)) { struct request *__rq; diff --git a/drivers/block/drbd/drbd_actlog.c b/drivers/block/drbd/drbd_actlog.c index 2096628d6e655..aca302492ff20 100644 --- a/drivers/block/drbd/drbd_actlog.c +++ b/drivers/block/drbd/drbd_actlog.c @@ -80,7 +80,7 @@ static int _drbd_md_sync_page_io(struct drbd_conf *mdev, if ((rw & WRITE) && !test_bit(MD_NO_FUA, &mdev->flags)) rw |= REQ_FUA; - rw |= REQ_UNPLUG | REQ_SYNC; + rw |= REQ_SYNC; bio = bio_alloc(GFP_NOIO, 1); bio->bi_bdev = bdev->md_bdev; diff --git a/drivers/block/drbd/drbd_int.h b/drivers/block/drbd/drbd_int.h index 0b5718e19586d..b0bd27dfc1e8a 100644 --- a/drivers/block/drbd/drbd_int.h +++ b/drivers/block/drbd/drbd_int.h @@ -377,7 +377,7 @@ union p_header { #define DP_HARDBARRIER 1 /* depricated */ #define DP_RW_SYNC 2 /* equals REQ_SYNC */ #define DP_MAY_SET_IN_SYNC 4 -#define DP_UNPLUG 8 /* equals REQ_UNPLUG */ +#define DP_UNPLUG 8 /* not used anymore */ #define DP_FUA 16 /* equals REQ_FUA */ #define DP_FLUSH 32 /* equals REQ_FLUSH */ #define DP_DISCARD 64 /* equals REQ_DISCARD */ diff --git a/drivers/block/drbd/drbd_main.c b/drivers/block/drbd/drbd_main.c index 6049cb85310dc..8a43ce0edeed1 100644 --- a/drivers/block/drbd/drbd_main.c +++ b/drivers/block/drbd/drbd_main.c @@ -2477,12 +2477,11 @@ static u32 bio_flags_to_wire(struct drbd_conf *mdev, unsigned long bi_rw) { if (mdev->agreed_pro_version >= 95) return (bi_rw & REQ_SYNC ? DP_RW_SYNC : 0) | - (bi_rw & REQ_UNPLUG ? DP_UNPLUG : 0) | (bi_rw & REQ_FUA ? DP_FUA : 0) | (bi_rw & REQ_FLUSH ? DP_FLUSH : 0) | (bi_rw & REQ_DISCARD ? DP_DISCARD : 0); else - return bi_rw & (REQ_SYNC | REQ_UNPLUG) ? DP_RW_SYNC : 0; + return bi_rw & REQ_SYNC ? DP_RW_SYNC : 0; } /* Used to send write requests diff --git a/drivers/block/drbd/drbd_receiver.c b/drivers/block/drbd/drbd_receiver.c index 84132f8bf8a41..8e68be939debe 100644 --- a/drivers/block/drbd/drbd_receiver.c +++ b/drivers/block/drbd/drbd_receiver.c @@ -1100,8 +1100,6 @@ next_bio: /* > e->sector, unless this is the first bio */ bio->bi_sector = sector; bio->bi_bdev = mdev->ldev->backing_bdev; - /* we special case some flags in the multi-bio case, see below - * (REQ_UNPLUG) */ bio->bi_rw = rw; bio->bi_private = e; bio->bi_end_io = drbd_endio_sec; @@ -1130,10 +1128,6 @@ next_bio: bios = bios->bi_next; bio->bi_next = NULL; - /* strip off REQ_UNPLUG unless it is the last bio */ - if (bios) - bio->bi_rw &= ~REQ_UNPLUG; - drbd_generic_make_request(mdev, fault_type, bio); } while (bios); return 0; @@ -1621,12 +1615,11 @@ static unsigned long write_flags_to_bio(struct drbd_conf *mdev, u32 dpf) { if (mdev->agreed_pro_version >= 95) return (dpf & DP_RW_SYNC ? REQ_SYNC : 0) | - (dpf & DP_UNPLUG ? REQ_UNPLUG : 0) | (dpf & DP_FUA ? REQ_FUA : 0) | (dpf & DP_FLUSH ? REQ_FUA : 0) | (dpf & DP_DISCARD ? REQ_DISCARD : 0); else - return dpf & DP_RW_SYNC ? (REQ_SYNC | REQ_UNPLUG) : 0; + return dpf & DP_RW_SYNC ? REQ_SYNC : 0; } /* mirrored write */ diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c index 54bfc274b39ab..ca203cb23f3c0 100644 --- a/drivers/md/bitmap.c +++ b/drivers/md/bitmap.c @@ -347,7 +347,7 @@ static void write_page(struct bitmap *bitmap, struct page *page, int wait) atomic_inc(&bitmap->pending_writes); set_buffer_locked(bh); set_buffer_mapped(bh); - submit_bh(WRITE | REQ_UNPLUG | REQ_SYNC, bh); + submit_bh(WRITE | REQ_SYNC, bh); bh = bh->b_this_page; } diff --git a/drivers/md/dm-io.c b/drivers/md/dm-io.c index 136d4f71a1162..76a5af00a26b5 100644 --- a/drivers/md/dm-io.c +++ b/drivers/md/dm-io.c @@ -352,7 +352,7 @@ static void dispatch_io(int rw, unsigned int num_regions, BUG_ON(num_regions > DM_IO_MAX_REGIONS); if (sync) - rw |= REQ_SYNC | REQ_UNPLUG; + rw |= REQ_SYNC; /* * For multiple regions we need to be careful to rewind diff --git a/drivers/md/dm-kcopyd.c b/drivers/md/dm-kcopyd.c index 400cf35094a4e..1bb73a13ca400 100644 --- a/drivers/md/dm-kcopyd.c +++ b/drivers/md/dm-kcopyd.c @@ -356,11 +356,8 @@ static int run_io_job(struct kcopyd_job *job) if (job->rw == READ) r = dm_io(&io_req, 1, &job->source, NULL); - else { - if (job->num_dests > 1) - io_req.bi_rw |= REQ_UNPLUG; + else r = dm_io(&io_req, job->num_dests, job->dests, NULL); - } return r; } diff --git a/drivers/md/md.c b/drivers/md/md.c index ca0d79c264b98..28f9c1ee4e3a1 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -777,8 +777,7 @@ void md_super_write(mddev_t *mddev, mdk_rdev_t *rdev, bio->bi_end_io = super_written; atomic_inc(&mddev->pending_writes); - submit_bio(REQ_WRITE | REQ_SYNC | REQ_UNPLUG | REQ_FLUSH | REQ_FUA, - bio); + submit_bio(REQ_WRITE | REQ_SYNC | REQ_FLUSH | REQ_FUA, bio); } void md_super_wait(mddev_t *mddev) @@ -806,7 +805,7 @@ int sync_page_io(mdk_rdev_t *rdev, sector_t sector, int size, struct completion event; int ret; - rw |= REQ_SYNC | REQ_UNPLUG; + rw |= REQ_SYNC; bio->bi_bdev = (metadata_op && rdev->meta_bdev) ? rdev->meta_bdev : rdev->bdev; diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c index 92ac5192c518b..b76f7cd47401e 100644 --- a/fs/btrfs/extent_io.c +++ b/fs/btrfs/extent_io.c @@ -2182,7 +2182,7 @@ static int __extent_writepage(struct page *page, struct writeback_control *wbc, unsigned long nr_written = 0; if (wbc->sync_mode == WB_SYNC_ALL) - write_flags = WRITE_SYNC_PLUG; + write_flags = WRITE_SYNC; else write_flags = WRITE; diff --git a/fs/buffer.c b/fs/buffer.c index f903f2e5b4fe6..42534f67d71b2 100644 --- a/fs/buffer.c +++ b/fs/buffer.c @@ -767,7 +767,7 @@ static int fsync_buffers_list(spinlock_t *lock, struct list_head *list) * still in flight on potentially older * contents. */ - write_dirty_buffer(bh, WRITE_SYNC_PLUG); + write_dirty_buffer(bh, WRITE_SYNC); /* * Kick off IO for the previous mapping. Note @@ -1602,14 +1602,8 @@ EXPORT_SYMBOL(unmap_underlying_metadata); * prevents this contention from occurring. * * If block_write_full_page() is called with wbc->sync_mode == - * WB_SYNC_ALL, the writes are posted using WRITE_SYNC_PLUG; this - * causes the writes to be flagged as synchronous writes, but the - * block device queue will NOT be unplugged, since usually many pages - * will be pushed to the out before the higher-level caller actually - * waits for the writes to be completed. The various wait functions, - * such as wait_on_writeback_range() will ultimately call sync_page() - * which will ultimately call blk_run_backing_dev(), which will end up - * unplugging the device queue. + * WB_SYNC_ALL, the writes are posted using WRITE_SYNC; this + * causes the writes to be flagged as synchronous writes. */ static int __block_write_full_page(struct inode *inode, struct page *page, get_block_t *get_block, struct writeback_control *wbc, @@ -1622,7 +1616,7 @@ static int __block_write_full_page(struct inode *inode, struct page *page, const unsigned blocksize = 1 << inode->i_blkbits; int nr_underway = 0; int write_op = (wbc->sync_mode == WB_SYNC_ALL ? - WRITE_SYNC_PLUG : WRITE); + WRITE_SYNC : WRITE); BUG_ON(!PageLocked(page)); diff --git a/fs/direct-io.c b/fs/direct-io.c index df709b3b860a4..426083136099e 100644 --- a/fs/direct-io.c +++ b/fs/direct-io.c @@ -1173,7 +1173,7 @@ __blockdev_direct_IO(int rw, struct kiocb *iocb, struct inode *inode, struct dio *dio; if (rw & WRITE) - rw = WRITE_ODIRECT_PLUG; + rw = WRITE_ODIRECT; if (bdev) bdev_blkbits = blksize_bits(bdev_logical_block_size(bdev)); diff --git a/fs/ext4/page-io.c b/fs/ext4/page-io.c index 955cc309142fe..e2cd90e4bb7c9 100644 --- a/fs/ext4/page-io.c +++ b/fs/ext4/page-io.c @@ -310,8 +310,7 @@ static int io_submit_init(struct ext4_io_submit *io, io_end->offset = (page->index << PAGE_CACHE_SHIFT) + bh_offset(bh); io->io_bio = bio; - io->io_op = (wbc->sync_mode == WB_SYNC_ALL ? - WRITE_SYNC_PLUG : WRITE); + io->io_op = (wbc->sync_mode == WB_SYNC_ALL ? WRITE_SYNC : WRITE); io->io_next_block = bh->b_blocknr; return 0; } diff --git a/fs/gfs2/log.c b/fs/gfs2/log.c index eb01f3575e102..7f1c112023424 100644 --- a/fs/gfs2/log.c +++ b/fs/gfs2/log.c @@ -121,7 +121,7 @@ __acquires(&sdp->sd_log_lock) lock_buffer(bh); if (test_clear_buffer_dirty(bh)) { bh->b_end_io = end_buffer_write_sync; - submit_bh(WRITE_SYNC_PLUG, bh); + submit_bh(WRITE_SYNC, bh); } else { unlock_buffer(bh); brelse(bh); @@ -647,7 +647,7 @@ static void gfs2_ordered_write(struct gfs2_sbd *sdp) lock_buffer(bh); if (buffer_mapped(bh) && test_clear_buffer_dirty(bh)) { bh->b_end_io = end_buffer_write_sync; - submit_bh(WRITE_SYNC_PLUG, bh); + submit_bh(WRITE_SYNC, bh); } else { unlock_buffer(bh); brelse(bh); diff --git a/fs/gfs2/lops.c b/fs/gfs2/lops.c index bf33f822058d3..48b545a1979a6 100644 --- a/fs/gfs2/lops.c +++ b/fs/gfs2/lops.c @@ -200,7 +200,7 @@ static void buf_lo_before_commit(struct gfs2_sbd *sdp) } gfs2_log_unlock(sdp); - submit_bh(WRITE_SYNC_PLUG, bh); + submit_bh(WRITE_SYNC, bh); gfs2_log_lock(sdp); n = 0; @@ -210,7 +210,7 @@ static void buf_lo_before_commit(struct gfs2_sbd *sdp) gfs2_log_unlock(sdp); lock_buffer(bd2->bd_bh); bh = gfs2_log_fake_buf(sdp, bd2->bd_bh); - submit_bh(WRITE_SYNC_PLUG, bh); + submit_bh(WRITE_SYNC, bh); gfs2_log_lock(sdp); if (++n >= num) break; @@ -352,7 +352,7 @@ static void revoke_lo_before_commit(struct gfs2_sbd *sdp) sdp->sd_log_num_revoke--; if (offset + sizeof(u64) > sdp->sd_sb.sb_bsize) { - submit_bh(WRITE_SYNC_PLUG, bh); + submit_bh(WRITE_SYNC, bh); bh = gfs2_log_get_buf(sdp); mh = (struct gfs2_meta_header *)bh->b_data; @@ -369,7 +369,7 @@ static void revoke_lo_before_commit(struct gfs2_sbd *sdp) } gfs2_assert_withdraw(sdp, !sdp->sd_log_num_revoke); - submit_bh(WRITE_SYNC_PLUG, bh); + submit_bh(WRITE_SYNC, bh); } static void revoke_lo_before_scan(struct gfs2_jdesc *jd, @@ -571,7 +571,7 @@ static void gfs2_write_blocks(struct gfs2_sbd *sdp, struct buffer_head *bh, ptr = bh_log_ptr(bh); get_bh(bh); - submit_bh(WRITE_SYNC_PLUG, bh); + submit_bh(WRITE_SYNC, bh); gfs2_log_lock(sdp); while(!list_empty(list)) { bd = list_entry(list->next, struct gfs2_bufdata, bd_le.le_list); @@ -597,7 +597,7 @@ static void gfs2_write_blocks(struct gfs2_sbd *sdp, struct buffer_head *bh, } else { bh1 = gfs2_log_fake_buf(sdp, bd->bd_bh); } - submit_bh(WRITE_SYNC_PLUG, bh1); + submit_bh(WRITE_SYNC, bh1); gfs2_log_lock(sdp); ptr += 2; } diff --git a/fs/gfs2/meta_io.c b/fs/gfs2/meta_io.c index a566331db4e1a..867b713cba92b 100644 --- a/fs/gfs2/meta_io.c +++ b/fs/gfs2/meta_io.c @@ -37,7 +37,7 @@ static int gfs2_aspace_writepage(struct page *page, struct writeback_control *wb struct buffer_head *bh, *head; int nr_underway = 0; int write_op = REQ_META | - (wbc->sync_mode == WB_SYNC_ALL ? WRITE_SYNC_PLUG : WRITE); + (wbc->sync_mode == WB_SYNC_ALL ? WRITE_SYNC : WRITE); BUG_ON(!PageLocked(page)); BUG_ON(!page_has_buffers(page)); diff --git a/fs/jbd/commit.c b/fs/jbd/commit.c index 34a4861c14b85..66be299acb1b8 100644 --- a/fs/jbd/commit.c +++ b/fs/jbd/commit.c @@ -333,7 +333,7 @@ void journal_commit_transaction(journal_t *journal) * instead we rely on sync_buffer() doing the unplug for us. */ if (commit_transaction->t_synchronous_commit) - write_op = WRITE_SYNC_PLUG; + write_op = WRITE_SYNC; spin_lock(&commit_transaction->t_handle_lock); while (commit_transaction->t_updates) { DEFINE_WAIT(wait); diff --git a/fs/jbd2/commit.c b/fs/jbd2/commit.c index f3ad1598b2012..3da1cc4346d5e 100644 --- a/fs/jbd2/commit.c +++ b/fs/jbd2/commit.c @@ -137,9 +137,9 @@ static int journal_submit_commit_record(journal_t *journal, if (journal->j_flags & JBD2_BARRIER && !JBD2_HAS_INCOMPAT_FEATURE(journal, JBD2_FEATURE_INCOMPAT_ASYNC_COMMIT)) - ret = submit_bh(WRITE_SYNC_PLUG | WRITE_FLUSH_FUA, bh); + ret = submit_bh(WRITE_SYNC | WRITE_FLUSH_FUA, bh); else - ret = submit_bh(WRITE_SYNC_PLUG, bh); + ret = submit_bh(WRITE_SYNC, bh); *cbh = bh; return ret; @@ -369,7 +369,7 @@ void jbd2_journal_commit_transaction(journal_t *journal) * instead we rely on sync_buffer() doing the unplug for us. */ if (commit_transaction->t_synchronous_commit) - write_op = WRITE_SYNC_PLUG; + write_op = WRITE_SYNC; trace_jbd2_commit_locking(journal, commit_transaction); stats.run.rs_wait = commit_transaction->t_max_wait; stats.run.rs_locked = jiffies; diff --git a/fs/nilfs2/segbuf.c b/fs/nilfs2/segbuf.c index 0f83e93935b2f..2853ff20f85a2 100644 --- a/fs/nilfs2/segbuf.c +++ b/fs/nilfs2/segbuf.c @@ -509,7 +509,7 @@ static int nilfs_segbuf_write(struct nilfs_segment_buffer *segbuf, * Last BIO is always sent through the following * submission. */ - rw |= REQ_SYNC | REQ_UNPLUG; + rw |= REQ_SYNC; res = nilfs_segbuf_submit_bio(segbuf, &wi, rw); } diff --git a/fs/xfs/linux-2.6/xfs_aops.c b/fs/xfs/linux-2.6/xfs_aops.c index 83c1c20d145ad..6bbb0ee33253a 100644 --- a/fs/xfs/linux-2.6/xfs_aops.c +++ b/fs/xfs/linux-2.6/xfs_aops.c @@ -413,8 +413,7 @@ xfs_submit_ioend_bio( if (xfs_ioend_new_eof(ioend)) xfs_mark_inode_dirty(XFS_I(ioend->io_inode)); - submit_bio(wbc->sync_mode == WB_SYNC_ALL ? - WRITE_SYNC_PLUG : WRITE, bio); + submit_bio(wbc->sync_mode == WB_SYNC_ALL ? WRITE_SYNC : WRITE, bio); } STATIC struct bio * diff --git a/include/linux/blk_types.h b/include/linux/blk_types.h index 16b286473042d..be50d9e70a7d4 100644 --- a/include/linux/blk_types.h +++ b/include/linux/blk_types.h @@ -128,7 +128,6 @@ enum rq_flag_bits { __REQ_NOIDLE, /* don't anticipate more IO after this one */ /* bio only flags */ - __REQ_UNPLUG, /* unplug the immediately after submission */ __REQ_RAHEAD, /* read ahead, can fail anytime */ __REQ_THROTTLED, /* This bio has already been subjected to * throttling rules. Don't do it again. */ @@ -172,7 +171,6 @@ enum rq_flag_bits { REQ_NOIDLE | REQ_FLUSH | REQ_FUA) #define REQ_CLONE_MASK REQ_COMMON_MASK -#define REQ_UNPLUG (1 << __REQ_UNPLUG) #define REQ_RAHEAD (1 << __REQ_RAHEAD) #define REQ_THROTTLED (1 << __REQ_THROTTLED) diff --git a/include/linux/fs.h b/include/linux/fs.h index 9f2cf69911b81..543e226ea6a3b 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -135,16 +135,10 @@ struct inodes_stat_t { * block layer could (in theory) choose to ignore this * request if it runs into resource problems. * WRITE A normal async write. Device will be plugged. - * WRITE_SYNC_PLUG Synchronous write. Identical to WRITE, but passes down + * WRITE_SYNC Synchronous write. Identical to WRITE, but passes down * the hint that someone will be waiting on this IO - * shortly. The device must still be unplugged explicitly, - * WRITE_SYNC_PLUG does not do this as we could be - * submitting more writes before we actually wait on any - * of them. - * WRITE_SYNC Like WRITE_SYNC_PLUG, but also unplugs the device - * immediately after submission. The write equivalent - * of READ_SYNC. - * WRITE_ODIRECT_PLUG Special case write for O_DIRECT only. + * shortly. The write equivalent of READ_SYNC. + * WRITE_ODIRECT Special case write for O_DIRECT only. * WRITE_FLUSH Like WRITE_SYNC but with preceding cache flush. * WRITE_FUA Like WRITE_SYNC but data is guaranteed to be on * non-volatile media on completion. @@ -160,18 +154,14 @@ struct inodes_stat_t { #define WRITE RW_MASK #define READA RWA_MASK -#define READ_SYNC (READ | REQ_SYNC | REQ_UNPLUG) +#define READ_SYNC (READ | REQ_SYNC) #define READ_META (READ | REQ_META) -#define WRITE_SYNC_PLUG (WRITE | REQ_SYNC | REQ_NOIDLE) -#define WRITE_SYNC (WRITE | REQ_SYNC | REQ_NOIDLE | REQ_UNPLUG) -#define WRITE_ODIRECT_PLUG (WRITE | REQ_SYNC) +#define WRITE_SYNC (WRITE | REQ_SYNC | REQ_NOIDLE) +#define WRITE_ODIRECT (WRITE | REQ_SYNC) #define WRITE_META (WRITE | REQ_META) -#define WRITE_FLUSH (WRITE | REQ_SYNC | REQ_NOIDLE | REQ_UNPLUG | \ - REQ_FLUSH) -#define WRITE_FUA (WRITE | REQ_SYNC | REQ_NOIDLE | REQ_UNPLUG | \ - REQ_FUA) -#define WRITE_FLUSH_FUA (WRITE | REQ_SYNC | REQ_NOIDLE | REQ_UNPLUG | \ - REQ_FLUSH | REQ_FUA) +#define WRITE_FLUSH (WRITE | REQ_SYNC | REQ_NOIDLE | REQ_FLUSH) +#define WRITE_FUA (WRITE | REQ_SYNC | REQ_NOIDLE | REQ_FUA) +#define WRITE_FLUSH_FUA (WRITE | REQ_SYNC | REQ_NOIDLE | REQ_FLUSH | REQ_FUA) #define SEL_IN 1 #define SEL_OUT 2 diff --git a/kernel/power/block_io.c b/kernel/power/block_io.c index 83bbc7c02df95..d09dd10c5a5ef 100644 --- a/kernel/power/block_io.c +++ b/kernel/power/block_io.c @@ -28,7 +28,7 @@ static int submit(int rw, struct block_device *bdev, sector_t sector, struct page *page, struct bio **bio_chain) { - const int bio_rw = rw | REQ_SYNC | REQ_UNPLUG; + const int bio_rw = rw | REQ_SYNC; struct bio *bio; bio = bio_alloc(__GFP_WAIT | __GFP_HIGH, 1); diff --git a/mm/page_io.c b/mm/page_io.c index 2dee975bf4690..dc76b4d0611ec 100644 --- a/mm/page_io.c +++ b/mm/page_io.c @@ -106,7 +106,7 @@ int swap_writepage(struct page *page, struct writeback_control *wbc) goto out; } if (wbc->sync_mode == WB_SYNC_ALL) - rw |= REQ_SYNC | REQ_UNPLUG; + rw |= REQ_SYNC; count_vm_event(PSWPOUT); set_page_writeback(page); unlock_page(page); -- GitLab From 69d60eb96ae8a73cf9b79cf28051caf973006011 Mon Sep 17 00:00:00 2001 From: Vivek Goyal Date: Wed, 9 Mar 2011 08:27:37 +0100 Subject: [PATCH 0388/2822] blk-throttle: Use blk_plug in throttle dispatch Use plug in throttle dispatch also as we are dispatching a bunch of bios in throttle context and some of them might merge. Signed-off-by: Vivek Goyal Signed-off-by: Jens Axboe --- block/blk-throttle.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/block/blk-throttle.c b/block/blk-throttle.c index b8dcdc2663a11..658ee505315bd 100644 --- a/block/blk-throttle.c +++ b/block/blk-throttle.c @@ -770,6 +770,7 @@ static int throtl_dispatch(struct request_queue *q) unsigned int nr_disp = 0; struct bio_list bio_list_on_stack; struct bio *bio; + struct blk_plug plug; spin_lock_irq(q->queue_lock); @@ -798,8 +799,10 @@ out: * immediate dispatch */ if (nr_disp) { + blk_start_plug(&plug); while((bio = bio_list_pop(&bio_list_on_stack))) generic_make_request(bio); + blk_finish_plug(&plug); } return nr_disp; } -- GitLab From 4d3cf1bc557dc8b88e1cabf1980b3baa3380a641 Mon Sep 17 00:00:00 2001 From: Jiro SEKIBA Date: Thu, 10 Mar 2011 16:54:15 +0900 Subject: [PATCH 0389/2822] nilfs2: move NILFS_SUPER_MAGIC to linux/magic.h move NILFS_SUPER_MAGIC macro to linux/magic.h from linux/nilfs2_fs.h in the same manner as other filesystem magic number defined in the file. Signed-off-by: Jiro SEKIBA Signed-off-by: Ryusuke Konishi --- include/linux/magic.h | 1 + include/linux/nilfs2_fs.h | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/include/linux/magic.h b/include/linux/magic.h index 62730ea2b56e5..248930efdd316 100644 --- a/include/linux/magic.h +++ b/include/linux/magic.h @@ -23,6 +23,7 @@ #define XENFS_SUPER_MAGIC 0xabba1974 #define EXT4_SUPER_MAGIC 0xEF53 #define BTRFS_SUPER_MAGIC 0x9123683E +#define NILFS_SUPER_MAGIC 0x3434 #define HPFS_SUPER_MAGIC 0xf995e849 #define ISOFS_SUPER_MAGIC 0x9660 #define JFFS2_SUPER_MAGIC 0x72b6 diff --git a/include/linux/nilfs2_fs.h b/include/linux/nilfs2_fs.h index ae33ac2db62df..8768c469e93e6 100644 --- a/include/linux/nilfs2_fs.h +++ b/include/linux/nilfs2_fs.h @@ -40,6 +40,7 @@ #include #include +#include #define NILFS_INODE_BMAP_SIZE 7 @@ -242,7 +243,6 @@ struct nilfs_super_block { #define NILFS_USER_INO 11 /* Fisrt user's file inode number */ #define NILFS_SB_OFFSET_BYTES 1024 /* byte offset of nilfs superblock */ -#define NILFS_SUPER_MAGIC 0x3434 /* NILFS filesystem magic number */ #define NILFS_SEG_MIN_BLOCKS 16 /* Minimum number of blocks in a full segment */ -- GitLab From 7d85d61f6ad6e2d6a14b5c20369bc9569f634855 Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Thu, 10 Mar 2011 05:15:00 +0100 Subject: [PATCH 0390/2822] ARM: 6797/1: hw_breakpoint: Fix newlines in WARNings These warnings are missing newlines and spaces causing confusing looking output when they trigger. Acked-by: Will Deacon Signed-off-by: Stephen Boyd Signed-off-by: Russell King --- arch/arm/kernel/hw_breakpoint.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/arch/arm/kernel/hw_breakpoint.c b/arch/arm/kernel/hw_breakpoint.c index 44b84fe6e1b0f..8dbc126f7152d 100644 --- a/arch/arm/kernel/hw_breakpoint.c +++ b/arch/arm/kernel/hw_breakpoint.c @@ -238,8 +238,8 @@ static int enable_monitor_mode(void) ARM_DBG_READ(c1, 0, dscr); /* Ensure that halting mode is disabled. */ - if (WARN_ONCE(dscr & ARM_DSCR_HDBGEN, "halting debug mode enabled." - "Unable to access hardware resources.")) { + if (WARN_ONCE(dscr & ARM_DSCR_HDBGEN, + "halting debug mode enabled. Unable to access hardware resources.\n")) { ret = -EPERM; goto out; } @@ -377,7 +377,7 @@ int arch_install_hw_breakpoint(struct perf_event *bp) } } - if (WARN_ONCE(i == max_slots, "Can't find any breakpoint slot")) { + if (WARN_ONCE(i == max_slots, "Can't find any breakpoint slot\n")) { ret = -EBUSY; goto out; } @@ -423,7 +423,7 @@ void arch_uninstall_hw_breakpoint(struct perf_event *bp) } } - if (WARN_ONCE(i == max_slots, "Can't find any breakpoint slot")) + if (WARN_ONCE(i == max_slots, "Can't find any breakpoint slot\n")) return; /* Reset the control register. */ @@ -635,7 +635,7 @@ int arch_validate_hwbkpt_settings(struct perf_event *bp) if (WARN_ONCE(!bp->overflow_handler && (arch_check_bp_in_kernelspace(bp) || !core_has_mismatch_brps() || !bp->hw.bp_target), - "overflow handler required but none found")) { + "overflow handler required but none found\n")) { ret = -EINVAL; } out: @@ -936,8 +936,8 @@ static int __init arch_hw_breakpoint_init(void) ARM_DBG_READ(c1, 0, dscr); if (dscr & ARM_DSCR_HDBGEN) { max_watchpoint_len = 4; - pr_warning("halting debug mode enabled. Assuming maximum " - "watchpoint size of %u bytes.", max_watchpoint_len); + pr_warning("halting debug mode enabled. Assuming maximum watchpoint size of %u bytes.\n", + max_watchpoint_len); } else { /* Work out the maximum supported watchpoint length. */ max_watchpoint_len = get_max_wp_len(); -- GitLab From 26525618863afcc4aab8b2a83451d37c6f513460 Mon Sep 17 00:00:00 2001 From: Lars Ellenberg Date: Fri, 5 Nov 2010 09:56:33 +0100 Subject: [PATCH 0391/2822] drbd: only reset online-verify start sector if verify completed For network hickups during online-verify, on the next verify triggered, we by default want to resume where it left off. After any replication link interruption, there will be a (possibly empty) resync. Do not reset online-verify start sector if some resync completed, that would defeats the purpose. Only reset the start sector once a verify run is completed. Signed-off-by: Philipp Reisner Signed-off-by: Lars Ellenberg --- drivers/block/drbd/drbd_worker.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/block/drbd/drbd_worker.c b/drivers/block/drbd/drbd_worker.c index e027446590d37..6cfc5417da8e7 100644 --- a/drivers/block/drbd/drbd_worker.c +++ b/drivers/block/drbd/drbd_worker.c @@ -782,6 +782,7 @@ int drbd_resync_finished(struct drbd_conf *mdev) union drbd_state os, ns; struct drbd_work *w; char *khelper_cmd = NULL; + int verify_done = 0; /* Remove all elements from the resync LRU. Since future actions * might set bits in the (main) bitmap, then the entries in the @@ -818,6 +819,8 @@ int drbd_resync_finished(struct drbd_conf *mdev) spin_lock_irq(&mdev->req_lock); os = mdev->state; + verify_done = (os.conn == C_VERIFY_S || os.conn == C_VERIFY_T); + /* This protects us against multiple calls (that can happen in the presence of application IO), and against connectivity loss just before we arrive here. */ if (os.conn <= C_CONNECTED) @@ -827,8 +830,7 @@ int drbd_resync_finished(struct drbd_conf *mdev) ns.conn = C_CONNECTED; dev_info(DEV, "%s done (total %lu sec; paused %lu sec; %lu K/sec)\n", - (os.conn == C_VERIFY_S || os.conn == C_VERIFY_T) ? - "Online verify " : "Resync", + verify_done ? "Online verify " : "Resync", dt + mdev->rs_paused, mdev->rs_paused, dbdt); n_oos = drbd_bm_total_weight(mdev); @@ -905,7 +907,8 @@ out: mdev->rs_total = 0; mdev->rs_failed = 0; mdev->rs_paused = 0; - mdev->ov_start_sector = 0; + if (verify_done) + mdev->ov_start_sector = 0; drbd_md_sync(mdev); -- GitLab From 30b743a2d532af39c9ed13c85d5473f6f620f6c8 Mon Sep 17 00:00:00 2001 From: Lars Ellenberg Date: Fri, 5 Nov 2010 09:39:06 +0100 Subject: [PATCH 0392/2822] drbd: improve online-verify progress tracking For a partial (resumed) online-verify, initialize rs_total not to total bits, but to number of bits to check in this run, to match the meaning rs_total has for actual resync. Signed-off-by: Philipp Reisner Signed-off-by: Lars Ellenberg --- drivers/block/drbd/drbd_main.c | 23 ++++++++++++----------- drivers/block/drbd/drbd_proc.c | 11 ++++++----- drivers/block/drbd/drbd_receiver.c | 3 ++- 3 files changed, 20 insertions(+), 17 deletions(-) diff --git a/drivers/block/drbd/drbd_main.c b/drivers/block/drbd/drbd_main.c index 8a43ce0edeed1..a1a2cb1eadf1c 100644 --- a/drivers/block/drbd/drbd_main.c +++ b/drivers/block/drbd/drbd_main.c @@ -961,6 +961,10 @@ static union drbd_state sanitize_state(struct drbd_conf *mdev, union drbd_state /* helper for __drbd_set_state */ static void set_ov_position(struct drbd_conf *mdev, enum drbd_conns cs) { + if (mdev->agreed_pro_version < 90) + mdev->ov_start_sector = 0; + mdev->rs_total = drbd_bm_bits(mdev); + mdev->ov_position = 0; if (cs == C_VERIFY_T) { /* starting online verify from an arbitrary position * does not fit well into the existing protocol. @@ -970,11 +974,15 @@ static void set_ov_position(struct drbd_conf *mdev, enum drbd_conns cs) mdev->ov_start_sector = ~(sector_t)0; } else { unsigned long bit = BM_SECT_TO_BIT(mdev->ov_start_sector); - if (bit >= mdev->rs_total) + if (bit >= mdev->rs_total) { mdev->ov_start_sector = BM_BIT_TO_SECT(mdev->rs_total - 1); + mdev->rs_total = 1; + } else + mdev->rs_total -= bit; mdev->ov_position = mdev->ov_start_sector; } + mdev->ov_left = mdev->rs_total; } static void drbd_resume_al(struct drbd_conf *mdev) @@ -1081,7 +1089,7 @@ int __drbd_set_state(struct drbd_conf *mdev, if ((os.conn == C_VERIFY_S || os.conn == C_VERIFY_T) && ns.conn < C_CONNECTED) { mdev->ov_start_sector = - BM_BIT_TO_SECT(mdev->rs_total - mdev->ov_left); + BM_BIT_TO_SECT(drbd_bm_bits(mdev) - mdev->ov_left); dev_info(DEV, "Online Verify reached sector %llu\n", (unsigned long long)mdev->ov_start_sector); } @@ -1106,14 +1114,7 @@ int __drbd_set_state(struct drbd_conf *mdev, unsigned long now = jiffies; int i; - mdev->ov_position = 0; - mdev->rs_total = drbd_bm_bits(mdev); - if (mdev->agreed_pro_version >= 90) - set_ov_position(mdev, ns.conn); - else - mdev->ov_start_sector = 0; - mdev->ov_left = mdev->rs_total - - BM_SECT_TO_BIT(mdev->ov_position); + set_ov_position(mdev, ns.conn); mdev->rs_start = now; mdev->rs_last_events = 0; mdev->rs_last_sect_ev = 0; @@ -1121,7 +1122,7 @@ int __drbd_set_state(struct drbd_conf *mdev, mdev->ov_last_oos_start = 0; for (i = 0; i < DRBD_SYNC_MARKS; i++) { - mdev->rs_mark_left[i] = mdev->rs_total; + mdev->rs_mark_left[i] = mdev->ov_left; mdev->rs_mark_time[i] = now; } diff --git a/drivers/block/drbd/drbd_proc.c b/drivers/block/drbd/drbd_proc.c index 7e6ac307e2dec..0b20aa8370229 100644 --- a/drivers/block/drbd/drbd_proc.c +++ b/drivers/block/drbd/drbd_proc.c @@ -239,12 +239,13 @@ static int drbd_seq_show(struct seq_file *seq, void *v) mdev->state.conn == C_SYNC_TARGET) drbd_syncer_progress(mdev, seq); - if (mdev->state.conn == C_VERIFY_S || mdev->state.conn == C_VERIFY_T) + if (mdev->state.conn == C_VERIFY_S || mdev->state.conn == C_VERIFY_T) { + unsigned long bm_bits = drbd_bm_bits(mdev); seq_printf(seq, "\t%3d%% %lu/%lu\n", - (int)((mdev->rs_total-mdev->ov_left) / - (mdev->rs_total/100+1)), - mdev->rs_total - mdev->ov_left, - mdev->rs_total); + (int)((bm_bits-mdev->ov_left) / + (bm_bits/100+1)), + bm_bits - mdev->ov_left, bm_bits); + } if (proc_details >= 1 && get_ldev_if_state(mdev, D_FAILED)) { lc_seq_printf_stats(seq, mdev->resync); diff --git a/drivers/block/drbd/drbd_receiver.c b/drivers/block/drbd/drbd_receiver.c index 8e68be939debe..88856a7f42a05 100644 --- a/drivers/block/drbd/drbd_receiver.c +++ b/drivers/block/drbd/drbd_receiver.c @@ -2005,7 +2005,8 @@ static int receive_DataRequest(struct drbd_conf *mdev, enum drbd_packets cmd, un mdev->agreed_pro_version >= 90) { mdev->ov_start_sector = sector; mdev->ov_position = sector; - mdev->ov_left = mdev->rs_total - BM_SECT_TO_BIT(sector); + mdev->ov_left = drbd_bm_bits(mdev) - BM_SECT_TO_BIT(sector); + mdev->rs_total = mdev->ov_left; dev_info(DEV, "Online Verify start sector: %llu\n", (unsigned long long)sector); } -- GitLab From de228bba676e1f76e5e5f9444e51bb2db003cefb Mon Sep 17 00:00:00 2001 From: Lars Ellenberg Date: Fri, 5 Nov 2010 09:43:15 +0100 Subject: [PATCH 0393/2822] drbd: initialize online-verify progress tracking on verify target For partial (resumed) online verify, initialize the resync step marks once we know what the online verify start sector is. Signed-off-by: Philipp Reisner Signed-off-by: Lars Ellenberg --- drivers/block/drbd/drbd_receiver.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/block/drbd/drbd_receiver.c b/drivers/block/drbd/drbd_receiver.c index 88856a7f42a05..3b95eef075461 100644 --- a/drivers/block/drbd/drbd_receiver.c +++ b/drivers/block/drbd/drbd_receiver.c @@ -2003,10 +2003,16 @@ static int receive_DataRequest(struct drbd_conf *mdev, enum drbd_packets cmd, un case P_OV_REQUEST: if (mdev->ov_start_sector == ~(sector_t)0 && mdev->agreed_pro_version >= 90) { + unsigned long now = jiffies; + int i; mdev->ov_start_sector = sector; mdev->ov_position = sector; mdev->ov_left = drbd_bm_bits(mdev) - BM_SECT_TO_BIT(sector); mdev->rs_total = mdev->ov_left; + for (i = 0; i < DRBD_SYNC_MARKS; i++) { + mdev->rs_mark_left[i] = mdev->ov_left; + mdev->rs_mark_time[i] = now; + } dev_info(DEV, "Online Verify start sector: %llu\n", (unsigned long long)sector); } -- GitLab From c6ea14dfa391da58e309d0d5041564b3d9dbb82f Mon Sep 17 00:00:00 2001 From: Lars Ellenberg Date: Fri, 5 Nov 2010 09:23:37 +0100 Subject: [PATCH 0394/2822] drbd: factor out advancement of resync marks for progress reporting This is in preparation to unify progress reporting of online-verify and resync requests. Signed-off-by: Philipp Reisner Signed-off-by: Lars Ellenberg --- drivers/block/drbd/drbd_actlog.c | 30 +++++++++++++++++------------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/drivers/block/drbd/drbd_actlog.c b/drivers/block/drbd/drbd_actlog.c index aca302492ff20..b3f18545b4692 100644 --- a/drivers/block/drbd/drbd_actlog.c +++ b/drivers/block/drbd/drbd_actlog.c @@ -919,6 +919,22 @@ static void drbd_try_clear_on_disk_bm(struct drbd_conf *mdev, sector_t sector, } } +void drbd_advance_rs_marks(struct drbd_conf *mdev, unsigned long still_to_go) +{ + unsigned long now = jiffies; + unsigned long last = mdev->rs_mark_time[mdev->rs_last_mark]; + int next = (mdev->rs_last_mark + 1) % DRBD_SYNC_MARKS; + if (time_after_eq(now, last + DRBD_SYNC_MARK_STEP)) { + if (mdev->rs_mark_left[mdev->rs_last_mark] != still_to_go && + mdev->state.conn != C_PAUSED_SYNC_T && + mdev->state.conn != C_PAUSED_SYNC_S) { + mdev->rs_mark_time[next] = now; + mdev->rs_mark_left[next] = still_to_go; + mdev->rs_last_mark = next; + } + } +} + /* clear the bit corresponding to the piece of storage in question: * size byte of data starting from sector. Only clear a bits of the affected * one ore more _aligned_ BM_BLOCK_SIZE blocks. @@ -969,19 +985,7 @@ void __drbd_set_in_sync(struct drbd_conf *mdev, sector_t sector, int size, */ count = drbd_bm_clear_bits(mdev, sbnr, ebnr); if (count && get_ldev(mdev)) { - unsigned long now = jiffies; - unsigned long last = mdev->rs_mark_time[mdev->rs_last_mark]; - int next = (mdev->rs_last_mark + 1) % DRBD_SYNC_MARKS; - if (time_after_eq(now, last + DRBD_SYNC_MARK_STEP)) { - unsigned long tw = drbd_bm_total_weight(mdev); - if (mdev->rs_mark_left[mdev->rs_last_mark] != tw && - mdev->state.conn != C_PAUSED_SYNC_T && - mdev->state.conn != C_PAUSED_SYNC_S) { - mdev->rs_mark_time[next] = now; - mdev->rs_mark_left[next] = tw; - mdev->rs_last_mark = next; - } - } + drbd_advance_rs_marks(mdev, drbd_bm_total_weight(mdev)); spin_lock_irqsave(&mdev->al_lock, flags); drbd_try_clear_on_disk_bm(mdev, sector, count, TRUE); spin_unlock_irqrestore(&mdev->al_lock, flags); -- GitLab From ea5442aff68c559c951373739201721185191748 Mon Sep 17 00:00:00 2001 From: Lars Ellenberg Date: Fri, 5 Nov 2010 09:48:01 +0100 Subject: [PATCH 0395/2822] drbd: advance progress step marks for online-verify Signed-off-by: Philipp Reisner Signed-off-by: Lars Ellenberg --- drivers/block/drbd/drbd_int.h | 1 + drivers/block/drbd/drbd_receiver.c | 8 +++++++- drivers/block/drbd/drbd_worker.c | 8 +++++++- 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/drivers/block/drbd/drbd_int.h b/drivers/block/drbd/drbd_int.h index b0bd27dfc1e8a..6cba131011d57 100644 --- a/drivers/block/drbd/drbd_int.h +++ b/drivers/block/drbd/drbd_int.h @@ -1619,6 +1619,7 @@ extern int drbd_rs_del_all(struct drbd_conf *mdev); extern void drbd_rs_failed_io(struct drbd_conf *mdev, sector_t sector, int size); extern int drbd_al_read_log(struct drbd_conf *mdev, struct drbd_backing_dev *); +extern void drbd_advance_rs_marks(struct drbd_conf *mdev, unsigned long still_to_go); extern void __drbd_set_in_sync(struct drbd_conf *mdev, sector_t sector, int size, const char *file, const unsigned int line); #define drbd_set_in_sync(mdev, sector, size) \ diff --git a/drivers/block/drbd/drbd_receiver.c b/drivers/block/drbd/drbd_receiver.c index 3b95eef075461..10db70a233766 100644 --- a/drivers/block/drbd/drbd_receiver.c +++ b/drivers/block/drbd/drbd_receiver.c @@ -4340,7 +4340,13 @@ static int got_OVResult(struct drbd_conf *mdev, struct p_header80 *h) drbd_rs_complete_io(mdev, sector); dec_rs_pending(mdev); - if (--mdev->ov_left == 0) { + --mdev->ov_left; + + /* let's advance progress step marks only for every other megabyte */ + if ((mdev->ov_left & 0x200) == 0x200) + drbd_advance_rs_marks(mdev, mdev->ov_left); + + if (mdev->ov_left == 0) { w = kmalloc(sizeof(*w), GFP_NOIO); if (w) { w->cb = w_ov_finished; diff --git a/drivers/block/drbd/drbd_worker.c b/drivers/block/drbd/drbd_worker.c index 6cfc5417da8e7..a050eb0d93bad 100644 --- a/drivers/block/drbd/drbd_worker.c +++ b/drivers/block/drbd/drbd_worker.c @@ -1185,7 +1185,13 @@ int w_e_end_ov_reply(struct drbd_conf *mdev, struct drbd_work *w, int cancel) drbd_free_ee(mdev, e); - if (--mdev->ov_left == 0) { + --mdev->ov_left; + + /* let's advance progress step marks only for every other megabyte */ + if ((mdev->ov_left & 0x200) == 0x200) + drbd_advance_rs_marks(mdev, mdev->ov_left); + + if (mdev->ov_left == 0) { ov_oos_print(mdev); drbd_resync_finished(mdev); } -- GitLab From 439d595379f87ec95249da21122eb085866f8ba9 Mon Sep 17 00:00:00 2001 From: Lars Ellenberg Date: Fri, 5 Nov 2010 09:52:46 +0100 Subject: [PATCH 0396/2822] drbd: show progress bar and ETA for online-verify Signed-off-by: Philipp Reisner Signed-off-by: Lars Ellenberg --- drivers/block/drbd/drbd_int.h | 5 +++- drivers/block/drbd/drbd_proc.c | 52 ++++++++++++++++++++++++++-------- 2 files changed, 44 insertions(+), 13 deletions(-) diff --git a/drivers/block/drbd/drbd_int.h b/drivers/block/drbd/drbd_int.h index 6cba131011d57..7131bf2af6ae7 100644 --- a/drivers/block/drbd/drbd_int.h +++ b/drivers/block/drbd/drbd_int.h @@ -2157,7 +2157,10 @@ static inline void drbd_get_syncer_progress(struct drbd_conf *mdev, * units of BM_BLOCK_SIZE. * for the percentage, we don't care. */ - *bits_left = drbd_bm_total_weight(mdev) - mdev->rs_failed; + if (mdev->state.conn == C_VERIFY_S || mdev->state.conn == C_VERIFY_T) + *bits_left = mdev->ov_left; + else + *bits_left = drbd_bm_total_weight(mdev) - mdev->rs_failed; /* >> 10 to prevent overflow, * +1 to prevent division by zero */ if (*bits_left > mdev->rs_total) { diff --git a/drivers/block/drbd/drbd_proc.c b/drivers/block/drbd/drbd_proc.c index 0b20aa8370229..0ec6f4b6a4a80 100644 --- a/drivers/block/drbd/drbd_proc.c +++ b/drivers/block/drbd/drbd_proc.c @@ -45,6 +45,19 @@ const struct file_operations drbd_proc_fops = { .release = single_release, }; +void seq_printf_with_thousands_grouping(struct seq_file *seq, long v) +{ + /* v is in kB/sec. We don't expect TiByte/sec yet. */ + if (unlikely(v >= 1000000)) { + /* cool: > GiByte/s */ + seq_printf(seq, "%ld,", v / 1000000); + v /= 1000000; + seq_printf(seq, "%03ld,%03ld", v/1000, v % 1000); + } else if (likely(v >= 1000)) + seq_printf(seq, "%ld,%03ld", v/1000, v % 1000); + else + seq_printf(seq, "%ld", v); +} /*lge * progress bars shamelessly adapted from driver/md/md.c @@ -94,6 +107,7 @@ static void drbd_syncer_progress(struct drbd_conf *mdev, struct seq_file *seq) /* Rolling marks. last_mark+1 may just now be modified. last_mark+2 is * at least (DRBD_SYNC_MARKS-2)*DRBD_SYNC_MARK_STEP old, and has at * least DRBD_SYNC_MARK_STEP time before it will be modified. */ + /* ------------------------ ~18s average ------------------------ */ i = (mdev->rs_last_mark + 2) % DRBD_SYNC_MARKS; dt = (jiffies - mdev->rs_mark_time[i]) / HZ; if (dt > (DRBD_SYNC_MARK_STEP * DRBD_SYNC_MARKS)) @@ -107,14 +121,29 @@ static void drbd_syncer_progress(struct drbd_conf *mdev, struct seq_file *seq) seq_printf(seq, "finish: %lu:%02lu:%02lu", rt / 3600, (rt % 3600) / 60, rt % 60); - /* current speed average over (SYNC_MARKS * SYNC_MARK_STEP) jiffies */ dbdt = Bit2KB(db/dt); - if (dbdt > 1000) - seq_printf(seq, " speed: %ld,%03ld", - dbdt/1000, dbdt % 1000); - else - seq_printf(seq, " speed: %ld", dbdt); + seq_printf(seq, " speed: "); + seq_printf_with_thousands_grouping(seq, dbdt); + seq_printf(seq, " ("); + /* ------------------------- ~3s average ------------------------ */ + if (proc_details >= 1) { + /* this is what drbd_rs_should_slow_down() uses */ + i = (mdev->rs_last_mark + DRBD_SYNC_MARKS-1) % DRBD_SYNC_MARKS; + dt = (jiffies - mdev->rs_mark_time[i]) / HZ; + if (dt > (DRBD_SYNC_MARK_STEP * DRBD_SYNC_MARKS)) + stalled = 1; + + if (!dt) + dt++; + db = mdev->rs_mark_left[i] - rs_left; + rt = (dt * (rs_left / (db/100+1)))/100; /* seconds */ + + dbdt = Bit2KB(db/dt); + seq_printf_with_thousands_grouping(seq, dbdt); + seq_printf(seq, " -- "); + } + /* --------------------- long term average ---------------------- */ /* mean speed since syncer started * we do account for PausedSync periods */ dt = (jiffies - mdev->rs_start - mdev->rs_paused) / HZ; @@ -122,11 +151,8 @@ static void drbd_syncer_progress(struct drbd_conf *mdev, struct seq_file *seq) dt = 1; db = mdev->rs_total - rs_left; dbdt = Bit2KB(db/dt); - if (dbdt > 1000) - seq_printf(seq, " (%ld,%03ld)", - dbdt/1000, dbdt % 1000); - else - seq_printf(seq, " (%ld)", dbdt); + seq_printf_with_thousands_grouping(seq, dbdt); + seq_printf(seq, ")"); if (mdev->state.conn == C_SYNC_TARGET) { if (mdev->c_sync_rate > 1000) @@ -236,7 +262,9 @@ static int drbd_seq_show(struct seq_file *seq, void *v) Bit2KB(drbd_bm_total_weight(mdev))); } if (mdev->state.conn == C_SYNC_SOURCE || - mdev->state.conn == C_SYNC_TARGET) + mdev->state.conn == C_SYNC_TARGET || + mdev->state.conn == C_VERIFY_S || + mdev->state.conn == C_VERIFY_T) drbd_syncer_progress(mdev, seq); if (mdev->state.conn == C_VERIFY_S || mdev->state.conn == C_VERIFY_T) { -- GitLab From 9bd28d3c90c80c7ec46085de281b38f67331da41 Mon Sep 17 00:00:00 2001 From: Lars Ellenberg Date: Fri, 5 Nov 2010 09:55:18 +0100 Subject: [PATCH 0397/2822] drbd: factor out drbd_rs_controller_reset Preparation patch to be able to use the auto-throttling resync controller for online-verify requests as well. Signed-off-by: Philipp Reisner Signed-off-by: Lars Ellenberg --- drivers/block/drbd/drbd_int.h | 1 + drivers/block/drbd/drbd_worker.c | 19 ++++++++++++------- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/drivers/block/drbd/drbd_int.h b/drivers/block/drbd/drbd_int.h index 7131bf2af6ae7..85207b275e411 100644 --- a/drivers/block/drbd/drbd_int.h +++ b/drivers/block/drbd/drbd_int.h @@ -1499,6 +1499,7 @@ extern int drbd_resync_finished(struct drbd_conf *mdev); extern int drbd_md_sync_page_io(struct drbd_conf *mdev, struct drbd_backing_dev *bdev, sector_t sector, int rw); extern void drbd_ov_oos_found(struct drbd_conf*, sector_t, int); +extern void drbd_rs_controller_reset(struct drbd_conf *mdev); static inline void ov_oos_print(struct drbd_conf *mdev) { diff --git a/drivers/block/drbd/drbd_worker.c b/drivers/block/drbd/drbd_worker.c index a050eb0d93bad..971e9b3b13ba0 100644 --- a/drivers/block/drbd/drbd_worker.c +++ b/drivers/block/drbd/drbd_worker.c @@ -1439,6 +1439,17 @@ int drbd_alter_sa(struct drbd_conf *mdev, int na) return retcode; } +void drbd_rs_controller_reset(struct drbd_conf *mdev) +{ + atomic_set(&mdev->rs_sect_in, 0); + atomic_set(&mdev->rs_sect_ev, 0); + mdev->rs_in_flight = 0; + mdev->rs_planed = 0; + spin_lock(&mdev->peer_seq_lock); + fifo_set(&mdev->rs_plan_s, 0); + spin_unlock(&mdev->peer_seq_lock); +} + /** * drbd_start_resync() - Start the resync process * @mdev: DRBD device. @@ -1556,13 +1567,7 @@ void drbd_start_resync(struct drbd_conf *mdev, enum drbd_conns side) drbd_resync_finished(mdev); } - atomic_set(&mdev->rs_sect_in, 0); - atomic_set(&mdev->rs_sect_ev, 0); - mdev->rs_in_flight = 0; - mdev->rs_planed = 0; - spin_lock(&mdev->peer_seq_lock); - fifo_set(&mdev->rs_plan_s, 0); - spin_unlock(&mdev->peer_seq_lock); + drbd_rs_controller_reset(mdev); /* ns.conn may already be != mdev->state.conn, * we may have been paused in between, or become paused until * the timer triggers. -- GitLab From e65f440d474d7d6a6fd8a2c844e851d8c96ed9c5 Mon Sep 17 00:00:00 2001 From: Lars Ellenberg Date: Fri, 5 Nov 2010 10:04:07 +0100 Subject: [PATCH 0398/2822] drbd: factor out drbd_rs_number_requests Preparation patch to be able to use the auto-throttling resync controller for online-verify requests as well. Signed-off-by: Philipp Reisner Signed-off-by: Lars Ellenberg --- drivers/block/drbd/drbd_worker.c | 61 +++++++++++++++----------------- 1 file changed, 29 insertions(+), 32 deletions(-) diff --git a/drivers/block/drbd/drbd_worker.c b/drivers/block/drbd/drbd_worker.c index 971e9b3b13ba0..6d111c8515f77 100644 --- a/drivers/block/drbd/drbd_worker.c +++ b/drivers/block/drbd/drbd_worker.c @@ -492,6 +492,32 @@ int drbd_rs_controller(struct drbd_conf *mdev) return req_sect; } +int drbd_rs_number_requests(struct drbd_conf *mdev) +{ + int number; + if (mdev->rs_plan_s.size) { /* mdev->sync_conf.c_plan_ahead */ + number = drbd_rs_controller(mdev) >> (BM_BLOCK_SHIFT - 9); + mdev->c_sync_rate = number * HZ * (BM_BLOCK_SIZE / 1024) / SLEEP_TIME; + } else { + mdev->c_sync_rate = mdev->sync_conf.rate; + number = SLEEP_TIME * mdev->c_sync_rate / ((BM_BLOCK_SIZE / 1024) * HZ); + } + + /* Throttle resync on lower level disk activity, which may also be + * caused by application IO on Primary/SyncTarget. + * Keep this after the call to drbd_rs_controller, as that assumes + * to be called as precisely as possible every SLEEP_TIME, + * and would be confused otherwise. */ + if (number && drbd_rs_should_slow_down(mdev)) { + mdev->c_sync_rate = 1; + number = 0; + } + + /* ignore the amount of pending requests, the resync controller should + * throttle down to incoming reply rate soon enough anyways. */ + return number; +} + int w_make_resync_request(struct drbd_conf *mdev, struct drbd_work *w, int cancel) { @@ -499,7 +525,7 @@ int w_make_resync_request(struct drbd_conf *mdev, sector_t sector; const sector_t capacity = drbd_get_capacity(mdev->this_bdev); int max_segment_size; - int number, rollback_i, size, pe, mx; + int number, rollback_i, size; int align, queued, sndbuf; int i = 0; @@ -537,39 +563,10 @@ int w_make_resync_request(struct drbd_conf *mdev, mdev->agreed_pro_version < 94 ? queue_max_segment_size(mdev->rq_queue) : mdev->agreed_pro_version < 95 ? DRBD_MAX_SIZE_H80_PACKET : DRBD_MAX_SEGMENT_SIZE; - if (mdev->rs_plan_s.size) { /* mdev->sync_conf.c_plan_ahead */ - number = drbd_rs_controller(mdev) >> (BM_BLOCK_SHIFT - 9); - mdev->c_sync_rate = number * HZ * (BM_BLOCK_SIZE / 1024) / SLEEP_TIME; - } else { - mdev->c_sync_rate = mdev->sync_conf.rate; - number = SLEEP_TIME * mdev->c_sync_rate / ((BM_BLOCK_SIZE / 1024) * HZ); - } - - /* Throttle resync on lower level disk activity, which may also be - * caused by application IO on Primary/SyncTarget. - * Keep this after the call to drbd_rs_controller, as that assumes - * to be called as precisely as possible every SLEEP_TIME, - * and would be confused otherwise. */ - if (drbd_rs_should_slow_down(mdev)) + number = drbd_rs_number_requests(mdev); + if (number == 0) goto requeue; - mutex_lock(&mdev->data.mutex); - if (mdev->data.socket) - mx = mdev->data.socket->sk->sk_rcvbuf / sizeof(struct p_block_req); - else - mx = 1; - mutex_unlock(&mdev->data.mutex); - - /* For resync rates >160MB/sec, allow more pending RS requests */ - if (number > mx) - mx = number; - - /* Limit the number of pending RS requests to no more than the peer's receive buffer */ - pe = atomic_read(&mdev->rs_pending_cnt); - if ((pe + number) > mx) { - number = mx - pe; - } - for (i = 0; i < number; i++) { /* Stop generating RS requests, when half of the send buffer is filled */ mutex_lock(&mdev->data.mutex); -- GitLab From 2649f0809f55e4df98c333a2b85c6fc8fee04804 Mon Sep 17 00:00:00 2001 From: Lars Ellenberg Date: Fri, 5 Nov 2010 10:05:47 +0100 Subject: [PATCH 0399/2822] drbd: use the resync controller for online-verify requests as well Signed-off-by: Philipp Reisner Signed-off-by: Lars Ellenberg --- drivers/block/drbd/drbd_main.c | 2 ++ drivers/block/drbd/drbd_proc.c | 3 ++- drivers/block/drbd/drbd_receiver.c | 10 ++++++++-- drivers/block/drbd/drbd_worker.c | 8 ++------ 4 files changed, 14 insertions(+), 9 deletions(-) diff --git a/drivers/block/drbd/drbd_main.c b/drivers/block/drbd/drbd_main.c index a1a2cb1eadf1c..6afb81f807bd4 100644 --- a/drivers/block/drbd/drbd_main.c +++ b/drivers/block/drbd/drbd_main.c @@ -1126,6 +1126,8 @@ int __drbd_set_state(struct drbd_conf *mdev, mdev->rs_mark_time[i] = now; } + drbd_rs_controller_reset(mdev); + if (ns.conn == C_VERIFY_S) { dev_info(DEV, "Starting Online Verify from sector %llu\n", (unsigned long long)mdev->ov_position); diff --git a/drivers/block/drbd/drbd_proc.c b/drivers/block/drbd/drbd_proc.c index 0ec6f4b6a4a80..fab3fde3477b3 100644 --- a/drivers/block/drbd/drbd_proc.c +++ b/drivers/block/drbd/drbd_proc.c @@ -154,7 +154,8 @@ static void drbd_syncer_progress(struct drbd_conf *mdev, struct seq_file *seq) seq_printf_with_thousands_grouping(seq, dbdt); seq_printf(seq, ")"); - if (mdev->state.conn == C_SYNC_TARGET) { + if (mdev->state.conn == C_SYNC_TARGET || + mdev->state.conn == C_VERIFY_S) { if (mdev->c_sync_rate > 1000) seq_printf(seq, " want: %d,%03d", mdev->c_sync_rate / 1000, mdev->c_sync_rate % 1000); diff --git a/drivers/block/drbd/drbd_receiver.c b/drivers/block/drbd/drbd_receiver.c index 10db70a233766..1c56af03c38b2 100644 --- a/drivers/block/drbd/drbd_receiver.c +++ b/drivers/block/drbd/drbd_receiver.c @@ -1883,8 +1883,12 @@ int drbd_rs_should_slow_down(struct drbd_conf *mdev) /* sync speed average over the last 2*DRBD_SYNC_MARK_STEP, * approx. */ - i = (mdev->rs_last_mark + DRBD_SYNC_MARKS-2) % DRBD_SYNC_MARKS; - rs_left = drbd_bm_total_weight(mdev) - mdev->rs_failed; + i = (mdev->rs_last_mark + DRBD_SYNC_MARKS-1) % DRBD_SYNC_MARKS; + + if (mdev->state.conn == C_VERIFY_S || mdev->state.conn == C_VERIFY_T) + rs_left = mdev->ov_left; + else + rs_left = drbd_bm_total_weight(mdev) - mdev->rs_failed; dt = ((long)jiffies - (long)mdev->rs_mark_time[i]) / HZ; if (!dt) @@ -1992,6 +1996,8 @@ static int receive_DataRequest(struct drbd_conf *mdev, enum drbd_packets cmd, un D_ASSERT(mdev->agreed_pro_version >= 89); e->w.cb = w_e_end_csum_rs_req; } else if (cmd == P_OV_REPLY) { + /* track progress, we may need to throttle */ + atomic_add(size >> 9, &mdev->rs_sect_in); e->w.cb = w_e_end_ov_reply; dec_rs_pending(mdev); /* drbd_rs_begin_io done when we sent this request, diff --git a/drivers/block/drbd/drbd_worker.c b/drivers/block/drbd/drbd_worker.c index 6d111c8515f77..af805efc94d7c 100644 --- a/drivers/block/drbd/drbd_worker.c +++ b/drivers/block/drbd/drbd_worker.c @@ -708,11 +708,7 @@ static int w_make_ov_request(struct drbd_conf *mdev, struct drbd_work *w, int ca return 0; } - number = SLEEP_TIME*mdev->sync_conf.rate / ((BM_BLOCK_SIZE/1024)*HZ); - if (atomic_read(&mdev->rs_pending_cnt) > number) - goto requeue; - - number -= atomic_read(&mdev->rs_pending_cnt); + number = drbd_rs_number_requests(mdev); sector = mdev->ov_position; for (i = 0; i < number; i++) { @@ -741,11 +737,11 @@ static int w_make_ov_request(struct drbd_conf *mdev, struct drbd_work *w, int ca mdev->ov_position = sector; requeue: + mdev->rs_in_flight += (i << (BM_BLOCK_SHIFT - 9)); mod_timer(&mdev->resync_timer, jiffies + SLEEP_TIME); return 1; } - int w_ov_finished(struct drbd_conf *mdev, struct drbd_work *w, int cancel) { kfree(w); -- GitLab From 18edc0b9d7dac2f74117a0bdb98f2e705eb74d82 Mon Sep 17 00:00:00 2001 From: Lars Ellenberg Date: Tue, 9 Nov 2010 14:12:10 +0100 Subject: [PATCH 0400/2822] drbd: fix potential wrap of 32bit oos:%lu display in /proc/drbd When converting bits (4k resolution, still) to kB, we shift left. If it was a large number of bits on a 32bit box (>= 4 TiB storage), we may wrap the 32bit unsigned long base type, resulting in incorrect display. Signed-off-by: Philipp Reisner Signed-off-by: Lars Ellenberg --- drivers/block/drbd/drbd_proc.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/block/drbd/drbd_proc.c b/drivers/block/drbd/drbd_proc.c index fab3fde3477b3..07368b75392ab 100644 --- a/drivers/block/drbd/drbd_proc.c +++ b/drivers/block/drbd/drbd_proc.c @@ -259,8 +259,9 @@ static int drbd_seq_show(struct seq_file *seq, void *v) mdev->epochs, write_ordering_chars[mdev->write_ordering] ); - seq_printf(seq, " oos:%lu\n", - Bit2KB(drbd_bm_total_weight(mdev))); + seq_printf(seq, " oos:%llu\n", + Bit2KB((unsigned long long) + drbd_bm_total_weight(mdev))); } if (mdev->state.conn == C_SYNC_SOURCE || mdev->state.conn == C_SYNC_TARGET || -- GitLab From 5f9915bbb8e0975ce99f893c29b8e89100b33399 Mon Sep 17 00:00:00 2001 From: Lars Ellenberg Date: Tue, 9 Nov 2010 14:15:24 +0100 Subject: [PATCH 0401/2822] drbd: further converge progress display of resync and online-verify Show progressbar and ETA always, with proc_details >= 1 also show the current sector position for both resync and online-verify on both nodes. Signed-off-by: Philipp Reisner Signed-off-by: Lars Ellenberg --- drivers/block/drbd/drbd_proc.c | 46 ++++++++++++++++++------------ drivers/block/drbd/drbd_receiver.c | 4 +++ 2 files changed, 31 insertions(+), 19 deletions(-) diff --git a/drivers/block/drbd/drbd_proc.c b/drivers/block/drbd/drbd_proc.c index 07368b75392ab..329b66a91e449 100644 --- a/drivers/block/drbd/drbd_proc.c +++ b/drivers/block/drbd/drbd_proc.c @@ -84,7 +84,12 @@ static void drbd_syncer_progress(struct drbd_conf *mdev, struct seq_file *seq) seq_printf(seq, "."); seq_printf(seq, "] "); - seq_printf(seq, "sync'ed:%3u.%u%% ", res / 10, res % 10); + if (mdev->state.conn == C_VERIFY_S || mdev->state.conn == C_VERIFY_T) + seq_printf(seq, "verified:"); + else + seq_printf(seq, "sync'ed:"); + seq_printf(seq, "%3u.%u%% ", res / 10, res % 10); + /* if more than 1 GB display in MB */ if (mdev->rs_total > 0x100000L) seq_printf(seq, "(%lu/%lu)M\n\t", @@ -130,14 +135,9 @@ static void drbd_syncer_progress(struct drbd_conf *mdev, struct seq_file *seq) /* this is what drbd_rs_should_slow_down() uses */ i = (mdev->rs_last_mark + DRBD_SYNC_MARKS-1) % DRBD_SYNC_MARKS; dt = (jiffies - mdev->rs_mark_time[i]) / HZ; - if (dt > (DRBD_SYNC_MARK_STEP * DRBD_SYNC_MARKS)) - stalled = 1; - if (!dt) dt++; db = mdev->rs_mark_left[i] - rs_left; - rt = (dt * (rs_left / (db/100+1)))/100; /* seconds */ - dbdt = Bit2KB(db/dt); seq_printf_with_thousands_grouping(seq, dbdt); seq_printf(seq, " -- "); @@ -156,13 +156,29 @@ static void drbd_syncer_progress(struct drbd_conf *mdev, struct seq_file *seq) if (mdev->state.conn == C_SYNC_TARGET || mdev->state.conn == C_VERIFY_S) { - if (mdev->c_sync_rate > 1000) - seq_printf(seq, " want: %d,%03d", - mdev->c_sync_rate / 1000, mdev->c_sync_rate % 1000); - else - seq_printf(seq, " want: %d", mdev->c_sync_rate); + seq_printf(seq, " want: "); + seq_printf_with_thousands_grouping(seq, mdev->c_sync_rate); } seq_printf(seq, " K/sec%s\n", stalled ? " (stalled)" : ""); + + if (proc_details >= 1) { + /* 64 bit: + * we convert to sectors in the display below. */ + u64 bm_bits = drbd_bm_bits(mdev); + u64 bit_pos; + if (mdev->state.conn == C_VERIFY_S || + mdev->state.conn == C_VERIFY_T) + bit_pos = bm_bits - mdev->ov_left; + else + bit_pos = mdev->bm_resync_fo; + /* Total sectors may be slightly off for oddly + * sized devices. So what. */ + seq_printf(seq, + "\t%3d%% sector pos: %llu/%llu\n", + (int)(bit_pos / (bm_bits/100+1)), + (unsigned long long) BM_BIT_TO_SECT(bit_pos), + (unsigned long long) BM_BIT_TO_SECT(bm_bits)); + } } static void resync_dump_detail(struct seq_file *seq, struct lc_element *e) @@ -269,14 +285,6 @@ static int drbd_seq_show(struct seq_file *seq, void *v) mdev->state.conn == C_VERIFY_T) drbd_syncer_progress(mdev, seq); - if (mdev->state.conn == C_VERIFY_S || mdev->state.conn == C_VERIFY_T) { - unsigned long bm_bits = drbd_bm_bits(mdev); - seq_printf(seq, "\t%3d%% %lu/%lu\n", - (int)((bm_bits-mdev->ov_left) / - (bm_bits/100+1)), - bm_bits - mdev->ov_left, bm_bits); - } - if (proc_details >= 1 && get_ldev_if_state(mdev, D_FAILED)) { lc_seq_printf_stats(seq, mdev->resync); lc_seq_printf_stats(seq, mdev->act_log); diff --git a/drivers/block/drbd/drbd_receiver.c b/drivers/block/drbd/drbd_receiver.c index 1c56af03c38b2..d0e19a242af45 100644 --- a/drivers/block/drbd/drbd_receiver.c +++ b/drivers/block/drbd/drbd_receiver.c @@ -1974,6 +1974,8 @@ static int receive_DataRequest(struct drbd_conf *mdev, enum drbd_packets cmd, un case P_RS_DATA_REQUEST: e->w.cb = w_e_end_rsdata_req; fault_type = DRBD_FAULT_RS_RD; + /* used in the sector offset progress display */ + mdev->bm_resync_fo = BM_SECT_TO_BIT(sector); break; case P_OV_REPLY: @@ -1995,6 +1997,8 @@ static int receive_DataRequest(struct drbd_conf *mdev, enum drbd_packets cmd, un if (cmd == P_CSUM_RS_REQUEST) { D_ASSERT(mdev->agreed_pro_version >= 89); e->w.cb = w_e_end_csum_rs_req; + /* used in the sector offset progress display */ + mdev->bm_resync_fo = BM_SECT_TO_BIT(sector); } else if (cmd == P_OV_REPLY) { /* track progress, we may need to throttle */ atomic_add(size >> 9, &mdev->rs_sect_in); -- GitLab From 470be44ab1841f3261a4d758450a42e6b79e9551 Mon Sep 17 00:00:00 2001 From: Lars Ellenberg Date: Wed, 10 Nov 2010 10:36:52 +0100 Subject: [PATCH 0402/2822] drbd: detect modification of in-flight buffers With data-integrity digest enabled, double-check on the sending side for modifications by upper layers of buffers under write back, so we can tell it appart from corruption on the "wire". Signed-off-by: Philipp Reisner Signed-off-by: Lars Ellenberg --- drivers/block/drbd/drbd_main.c | 28 +++++++++++++++++++++++++++- drivers/block/drbd/drbd_receiver.c | 3 ++- 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/drivers/block/drbd/drbd_main.c b/drivers/block/drbd/drbd_main.c index 6afb81f807bd4..451fc36a85cb3 100644 --- a/drivers/block/drbd/drbd_main.c +++ b/drivers/block/drbd/drbd_main.c @@ -2537,10 +2537,36 @@ int drbd_send_dblock(struct drbd_conf *mdev, struct drbd_request *req) ok = drbd_send(mdev, mdev->data.socket, dgb, dgs, 0); } if (ok) { - if (mdev->net_conf->wire_protocol == DRBD_PROT_A) + /* For protocol A, we have to memcpy the payload into + * socket buffers, as we may complete right away + * as soon as we handed it over to tcp, at which point the data + * pages may become invalid. + * + * For data-integrity enabled, we copy it as well, so we can be + * sure that even if the bio pages may still be modified, it + * won't change the data on the wire, thus if the digest checks + * out ok after sending on this side, but does not fit on the + * receiving side, we sure have detected corruption elsewhere. + */ + if (mdev->net_conf->wire_protocol == DRBD_PROT_A || dgs) ok = _drbd_send_bio(mdev, req->master_bio); else ok = _drbd_send_zc_bio(mdev, req->master_bio); + + /* double check digest, sometimes buffers have been modified in flight. */ + if (dgs > 0 && dgs <= 64) { + /* 64 byte, 512 bit, is the larges digest size + * currently supported in kernel crypto. */ + unsigned char digest[64]; + drbd_csum_bio(mdev, mdev->integrity_w_tfm, req->master_bio, digest); + if (memcmp(mdev->int_dig_out, digest, dgs)) { + dev_warn(DEV, + "Digest mismatch, buffer modified by upper layers during write: %llus +%u\n", + (unsigned long long)req->sector, req->size); + } + } /* else if (dgs > 64) { + ... Be noisy about digest too large ... + } */ } drbd_put_data_sock(mdev); diff --git a/drivers/block/drbd/drbd_receiver.c b/drivers/block/drbd/drbd_receiver.c index d0e19a242af45..ca213c6e5f9d4 100644 --- a/drivers/block/drbd/drbd_receiver.c +++ b/drivers/block/drbd/drbd_receiver.c @@ -1281,7 +1281,8 @@ read_in_block(struct drbd_conf *mdev, u64 id, sector_t sector, int data_size) __ if (dgs) { drbd_csum_ee(mdev, mdev->integrity_r_tfm, e, dig_vv); if (memcmp(dig_in, dig_vv, dgs)) { - dev_err(DEV, "Digest integrity check FAILED.\n"); + dev_err(DEV, "Digest integrity check FAILED: %llus +%u\n", + (unsigned long long)sector, data_size); drbd_bcast_ee(mdev, "digest failed", dgs, dig_in, dig_vv, e); drbd_free_ee(mdev, e); -- GitLab From 3129b1b9aed15bbebde1b2a5719434273feb295d Mon Sep 17 00:00:00 2001 From: Lars Ellenberg Date: Thu, 11 Nov 2010 10:47:05 +0100 Subject: [PATCH 0403/2822] drbd: debug: limit nelink-broadcast of request on digest mismatch to 32k We used to be limited to 32k requests, but have increased that limit to 128k now. This part of the code can only deal with 32k, it would scramble arbitrary pages for larger requests. As it is used for debugging only anyways, it is ok to simply truncate the dumped data here. Signed-off-by: Philipp Reisner Signed-off-by: Lars Ellenberg --- drivers/block/drbd/drbd_nl.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/block/drbd/drbd_nl.c b/drivers/block/drbd/drbd_nl.c index 8cbfaa687d723..dad559810ed62 100644 --- a/drivers/block/drbd/drbd_nl.c +++ b/drivers/block/drbd/drbd_nl.c @@ -2398,10 +2398,11 @@ void drbd_bcast_ee(struct drbd_conf *mdev, tl = tl_add_int(tl, T_ee_sector, &e->sector); tl = tl_add_int(tl, T_ee_block_id, &e->block_id); + /* dump the first 32k */ + len = min_t(unsigned, e->size, 32 << 10); put_unaligned(T_ee_data, tl++); - put_unaligned(e->size, tl++); + put_unaligned(len, tl++); - len = e->size; page = e->pages; page_chain_for_each(page) { void *d = kmap_atomic(page, KM_USER0); @@ -2410,6 +2411,8 @@ void drbd_bcast_ee(struct drbd_conf *mdev, kunmap_atomic(d, KM_USER0); tl = (unsigned short*)((char*)tl + l); len -= l; + if (len == 0) + break; } put_unaligned(TT_END, tl++); /* Close the tag list */ -- GitLab From 1816a2b47afae838e53a177d5d166cc7be97d6b5 Mon Sep 17 00:00:00 2001 From: Lars Ellenberg Date: Thu, 11 Nov 2010 15:19:07 +0100 Subject: [PATCH 0404/2822] drbd: properly use max_hw_sectors to limit the our bio size To ease tracking of bios in some hash tables, we want it to not cross certain boundaries (128k, used to be 32k). We limit the maximum bio size using queue parameters. Historically some defines and variables we use there have been named max_segment_size, which was misguided. Rename them to max_bio_size, and use [blk_]queue_max_hw_sectors where appropriate. Signed-off-by: Philipp Reisner Signed-off-by: Lars Ellenberg --- drivers/block/drbd/drbd_actlog.c | 8 ++++---- drivers/block/drbd/drbd_int.h | 4 ++-- drivers/block/drbd/drbd_main.c | 6 +++--- drivers/block/drbd/drbd_nl.c | 27 +++++++++++++-------------- drivers/block/drbd/drbd_receiver.c | 18 +++++++++--------- drivers/block/drbd/drbd_req.c | 8 ++++---- drivers/block/drbd/drbd_worker.c | 12 ++++++------ 7 files changed, 41 insertions(+), 42 deletions(-) diff --git a/drivers/block/drbd/drbd_actlog.c b/drivers/block/drbd/drbd_actlog.c index b3f18545b4692..b4adb58c7472c 100644 --- a/drivers/block/drbd/drbd_actlog.c +++ b/drivers/block/drbd/drbd_actlog.c @@ -952,7 +952,7 @@ void __drbd_set_in_sync(struct drbd_conf *mdev, sector_t sector, int size, int wake_up = 0; unsigned long flags; - if (size <= 0 || (size & 0x1ff) != 0 || size > DRBD_MAX_SEGMENT_SIZE) { + if (size <= 0 || (size & 0x1ff) != 0 || size > DRBD_MAX_BIO_SIZE) { dev_err(DEV, "drbd_set_in_sync: sector=%llus size=%d nonsense!\n", (unsigned long long)sector, size); return; @@ -1002,7 +1002,7 @@ void __drbd_set_in_sync(struct drbd_conf *mdev, sector_t sector, int size, /* * this is intended to set one request worth of data out of sync. * affects at least 1 bit, - * and at most 1+DRBD_MAX_SEGMENT_SIZE/BM_BLOCK_SIZE bits. + * and at most 1+DRBD_MAX_BIO_SIZE/BM_BLOCK_SIZE bits. * * called by tl_clear and drbd_send_dblock (==drbd_make_request). * so this can be _any_ process. @@ -1015,7 +1015,7 @@ void __drbd_set_out_of_sync(struct drbd_conf *mdev, sector_t sector, int size, unsigned int enr, count; struct lc_element *e; - if (size <= 0 || (size & 0x1ff) != 0 || size > DRBD_MAX_SEGMENT_SIZE) { + if (size <= 0 || (size & 0x1ff) != 0 || size > DRBD_MAX_BIO_SIZE) { dev_err(DEV, "sector: %llus, size: %d\n", (unsigned long long)sector, size); return; @@ -1387,7 +1387,7 @@ void drbd_rs_failed_io(struct drbd_conf *mdev, sector_t sector, int size) sector_t esector, nr_sectors; int wake_up = 0; - if (size <= 0 || (size & 0x1ff) != 0 || size > DRBD_MAX_SEGMENT_SIZE) { + if (size <= 0 || (size & 0x1ff) != 0 || size > DRBD_MAX_BIO_SIZE) { dev_err(DEV, "drbd_rs_failed_io: sector=%llus size=%d nonsense!\n", (unsigned long long)sector, size); return; diff --git a/drivers/block/drbd/drbd_int.h b/drivers/block/drbd/drbd_int.h index 85207b275e411..bcba2742cfba3 100644 --- a/drivers/block/drbd/drbd_int.h +++ b/drivers/block/drbd/drbd_int.h @@ -512,7 +512,7 @@ struct p_sizes { u64 d_size; /* size of disk */ u64 u_size; /* user requested size */ u64 c_size; /* current exported size */ - u32 max_segment_size; /* Maximal size of a BIO */ + u32 max_bio_size; /* Maximal size of a BIO */ u16 queue_order_type; /* not yet implemented in DRBD*/ u16 dds_flags; /* use enum dds_flags here. */ } __packed; @@ -1398,7 +1398,7 @@ struct bm_extent { * With a value of 8 all IO in one 128K block make it to the same slot of the * hash table. */ #define HT_SHIFT 8 -#define DRBD_MAX_SEGMENT_SIZE (1U<<(9+HT_SHIFT)) +#define DRBD_MAX_BIO_SIZE (1U<<(9+HT_SHIFT)) #define DRBD_MAX_SIZE_H80_PACKET (1 << 15) /* The old header only allows packets up to 32Kib data */ diff --git a/drivers/block/drbd/drbd_main.c b/drivers/block/drbd/drbd_main.c index 451fc36a85cb3..9d9c2ed31e9af 100644 --- a/drivers/block/drbd/drbd_main.c +++ b/drivers/block/drbd/drbd_main.c @@ -1924,7 +1924,7 @@ int drbd_send_sizes(struct drbd_conf *mdev, int trigger_reply, enum dds_flags fl p.d_size = cpu_to_be64(d_size); p.u_size = cpu_to_be64(u_size); p.c_size = cpu_to_be64(trigger_reply ? 0 : drbd_get_capacity(mdev->this_bdev)); - p.max_segment_size = cpu_to_be32(queue_max_segment_size(mdev->rq_queue)); + p.max_bio_size = cpu_to_be32(queue_max_hw_sectors(mdev->rq_queue) << 9); p.queue_order_type = cpu_to_be16(q_order_type); p.dds_flags = cpu_to_be16(flags); @@ -2952,7 +2952,7 @@ static void drbd_destroy_mempools(void) static int drbd_create_mempools(void) { struct page *page; - const int number = (DRBD_MAX_SEGMENT_SIZE/PAGE_SIZE) * minor_count; + const int number = (DRBD_MAX_BIO_SIZE/PAGE_SIZE) * minor_count; int i; /* prepare our caches and mempools */ @@ -3218,7 +3218,7 @@ struct drbd_conf *drbd_new_device(unsigned int minor) q->backing_dev_info.congested_data = mdev; blk_queue_make_request(q, drbd_make_request_26); - blk_queue_max_segment_size(q, DRBD_MAX_SEGMENT_SIZE); + blk_queue_max_hw_sectors(q, DRBD_MAX_BIO_SIZE >> 9); blk_queue_bounce_limit(q, BLK_BOUNCE_ANY); blk_queue_merge_bvec(q, drbd_merge_bvec); q->queue_lock = &mdev->req_lock; diff --git a/drivers/block/drbd/drbd_nl.c b/drivers/block/drbd/drbd_nl.c index dad559810ed62..9e27d82a9a192 100644 --- a/drivers/block/drbd/drbd_nl.c +++ b/drivers/block/drbd/drbd_nl.c @@ -765,22 +765,21 @@ static int drbd_check_al_size(struct drbd_conf *mdev) return 0; } -void drbd_setup_queue_param(struct drbd_conf *mdev, unsigned int max_seg_s) __must_hold(local) +void drbd_setup_queue_param(struct drbd_conf *mdev, unsigned int max_bio_size) __must_hold(local) { struct request_queue * const q = mdev->rq_queue; struct request_queue * const b = mdev->ldev->backing_bdev->bd_disk->queue; int max_segments = mdev->ldev->dc.max_bio_bvecs; + int max_hw_sectors = min(queue_max_hw_sectors(b), max_bio_size >> 9); - max_seg_s = min(queue_max_sectors(b) * queue_logical_block_size(b), max_seg_s); - - blk_queue_max_hw_sectors(q, max_seg_s >> 9); - blk_queue_max_segments(q, max_segments ? max_segments : BLK_MAX_SEGMENTS); - blk_queue_max_segment_size(q, max_seg_s); blk_queue_logical_block_size(q, 512); - blk_queue_segment_boundary(q, PAGE_SIZE-1); - blk_stack_limits(&q->limits, &b->limits, 0); + blk_queue_max_hw_sectors(q, max_hw_sectors); + /* This is the workaround for "bio would need to, but cannot, be split" */ + blk_queue_max_segments(q, max_segments ? max_segments : BLK_MAX_SEGMENTS); + blk_queue_segment_boundary(q, PAGE_CACHE_SIZE-1); + blk_queue_stack_limits(q, b); - dev_info(DEV, "max_segment_size ( = BIO size ) = %u\n", queue_max_segment_size(q)); + dev_info(DEV, "max BIO size = %u\n", queue_max_hw_sectors(q) << 9); if (q->backing_dev_info.ra_pages != b->backing_dev_info.ra_pages) { dev_info(DEV, "Adjusting my ra_pages to backing device's (%lu -> %lu)\n", @@ -858,7 +857,7 @@ static int drbd_nl_disk_conf(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp struct block_device *bdev; struct lru_cache *resync_lru = NULL; union drbd_state ns, os; - unsigned int max_seg_s; + unsigned int max_bio_size; int rv; int cp_discovered = 0; int logical_block_size; @@ -1109,20 +1108,20 @@ static int drbd_nl_disk_conf(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp mdev->read_cnt = 0; mdev->writ_cnt = 0; - max_seg_s = DRBD_MAX_SEGMENT_SIZE; + max_bio_size = DRBD_MAX_BIO_SIZE; if (mdev->state.conn == C_CONNECTED) { /* We are Primary, Connected, and now attach a new local * backing store. We must not increase the user visible maximum * bio size on this device to something the peer may not be * able to handle. */ if (mdev->agreed_pro_version < 94) - max_seg_s = queue_max_segment_size(mdev->rq_queue); + max_bio_size = queue_max_hw_sectors(mdev->rq_queue) << 9; else if (mdev->agreed_pro_version == 94) - max_seg_s = DRBD_MAX_SIZE_H80_PACKET; + max_bio_size = DRBD_MAX_SIZE_H80_PACKET; /* else: drbd 8.3.9 and later, stay with default */ } - drbd_setup_queue_param(mdev, max_seg_s); + drbd_setup_queue_param(mdev, max_bio_size); /* If I am currently not R_PRIMARY, * but meta data primary indicator is set, diff --git a/drivers/block/drbd/drbd_receiver.c b/drivers/block/drbd/drbd_receiver.c index ca213c6e5f9d4..79e7b57006b1c 100644 --- a/drivers/block/drbd/drbd_receiver.c +++ b/drivers/block/drbd/drbd_receiver.c @@ -277,7 +277,7 @@ static void drbd_pp_free(struct drbd_conf *mdev, struct page *page, int is_net) atomic_t *a = is_net ? &mdev->pp_in_use_by_net : &mdev->pp_in_use; int i; - if (drbd_pp_vacant > (DRBD_MAX_SEGMENT_SIZE/PAGE_SIZE)*minor_count) + if (drbd_pp_vacant > (DRBD_MAX_BIO_SIZE/PAGE_SIZE)*minor_count) i = page_chain_free(page); else { struct page *tmp; @@ -1240,7 +1240,7 @@ read_in_block(struct drbd_conf *mdev, u64 id, sector_t sector, int data_size) __ data_size -= dgs; ERR_IF(data_size & 0x1ff) return NULL; - ERR_IF(data_size > DRBD_MAX_SEGMENT_SIZE) return NULL; + ERR_IF(data_size > DRBD_MAX_BIO_SIZE) return NULL; /* even though we trust out peer, * we sometimes have to double check. */ @@ -1917,7 +1917,7 @@ static int receive_DataRequest(struct drbd_conf *mdev, enum drbd_packets cmd, un sector = be64_to_cpu(p->sector); size = be32_to_cpu(p->blksize); - if (size <= 0 || (size & 0x1ff) != 0 || size > DRBD_MAX_SEGMENT_SIZE) { + if (size <= 0 || (size & 0x1ff) != 0 || size > DRBD_MAX_BIO_SIZE) { dev_err(DEV, "%s:%d: sector: %llus, size: %u\n", __FILE__, __LINE__, (unsigned long long)sector, size); return FALSE; @@ -2897,7 +2897,7 @@ static int receive_sizes(struct drbd_conf *mdev, enum drbd_packets cmd, unsigned { struct p_sizes *p = &mdev->data.rbuf.sizes; enum determine_dev_size dd = unchanged; - unsigned int max_seg_s; + unsigned int max_bio_size; sector_t p_size, p_usize, my_usize; int ldsc = 0; /* local disk size changed */ enum dds_flags ddsf; @@ -2970,14 +2970,14 @@ static int receive_sizes(struct drbd_conf *mdev, enum drbd_packets cmd, unsigned } if (mdev->agreed_pro_version < 94) - max_seg_s = be32_to_cpu(p->max_segment_size); + max_bio_size = be32_to_cpu(p->max_bio_size); else if (mdev->agreed_pro_version == 94) - max_seg_s = DRBD_MAX_SIZE_H80_PACKET; + max_bio_size = DRBD_MAX_SIZE_H80_PACKET; else /* drbd 8.3.8 onwards */ - max_seg_s = DRBD_MAX_SEGMENT_SIZE; + max_bio_size = DRBD_MAX_BIO_SIZE; - if (max_seg_s != queue_max_segment_size(mdev->rq_queue)) - drbd_setup_queue_param(mdev, max_seg_s); + if (max_bio_size != queue_max_hw_sectors(mdev->rq_queue) << 9) + drbd_setup_queue_param(mdev, max_bio_size); drbd_setup_order_type(mdev, be16_to_cpu(p->queue_order_type)); put_ldev(mdev); diff --git a/drivers/block/drbd/drbd_req.c b/drivers/block/drbd/drbd_req.c index ad3fc6228f279..08f53ce9b88f0 100644 --- a/drivers/block/drbd/drbd_req.c +++ b/drivers/block/drbd/drbd_req.c @@ -1047,7 +1047,7 @@ int drbd_make_request_26(struct request_queue *q, struct bio *bio) /* can this bio be split generically? * Maybe add our own split-arbitrary-bios function. */ - if (bio->bi_vcnt != 1 || bio->bi_idx != 0 || bio->bi_size > DRBD_MAX_SEGMENT_SIZE) { + if (bio->bi_vcnt != 1 || bio->bi_idx != 0 || bio->bi_size > DRBD_MAX_BIO_SIZE) { /* rather error out here than BUG in bio_split */ dev_err(DEV, "bio would need to, but cannot, be split: " "(vcnt=%u,idx=%u,size=%u,sector=%llu)\n", @@ -1098,7 +1098,7 @@ int drbd_make_request_26(struct request_queue *q, struct bio *bio) } /* This is called by bio_add_page(). With this function we reduce - * the number of BIOs that span over multiple DRBD_MAX_SEGMENT_SIZEs + * the number of BIOs that span over multiple DRBD_MAX_BIO_SIZEs * units (was AL_EXTENTs). * * we do the calculation within the lower 32bit of the byte offsets, @@ -1118,8 +1118,8 @@ int drbd_merge_bvec(struct request_queue *q, struct bvec_merge_data *bvm, struct unsigned int bio_size = bvm->bi_size; int limit, backing_limit; - limit = DRBD_MAX_SEGMENT_SIZE - - ((bio_offset & (DRBD_MAX_SEGMENT_SIZE-1)) + bio_size); + limit = DRBD_MAX_BIO_SIZE + - ((bio_offset & (DRBD_MAX_BIO_SIZE-1)) + bio_size); if (limit < 0) limit = 0; if (bio_size == 0) { diff --git a/drivers/block/drbd/drbd_worker.c b/drivers/block/drbd/drbd_worker.c index af805efc94d7c..782d87237cb47 100644 --- a/drivers/block/drbd/drbd_worker.c +++ b/drivers/block/drbd/drbd_worker.c @@ -524,7 +524,7 @@ int w_make_resync_request(struct drbd_conf *mdev, unsigned long bit; sector_t sector; const sector_t capacity = drbd_get_capacity(mdev->this_bdev); - int max_segment_size; + int max_bio_size; int number, rollback_i, size; int align, queued, sndbuf; int i = 0; @@ -559,9 +559,9 @@ int w_make_resync_request(struct drbd_conf *mdev, /* starting with drbd 8.3.8, we can handle multi-bio EEs, * if it should be necessary */ - max_segment_size = - mdev->agreed_pro_version < 94 ? queue_max_segment_size(mdev->rq_queue) : - mdev->agreed_pro_version < 95 ? DRBD_MAX_SIZE_H80_PACKET : DRBD_MAX_SEGMENT_SIZE; + max_bio_size = + mdev->agreed_pro_version < 94 ? queue_max_hw_sectors(mdev->rq_queue) << 9 : + mdev->agreed_pro_version < 95 ? DRBD_MAX_SIZE_H80_PACKET : DRBD_MAX_BIO_SIZE; number = drbd_rs_number_requests(mdev); if (number == 0) @@ -605,7 +605,7 @@ next_sector: goto next_sector; } -#if DRBD_MAX_SEGMENT_SIZE > BM_BLOCK_SIZE +#if DRBD_MAX_BIO_SIZE > BM_BLOCK_SIZE /* try to find some adjacent bits. * we stop if we have already the maximum req size. * @@ -615,7 +615,7 @@ next_sector: align = 1; rollback_i = i; for (;;) { - if (size + BM_BLOCK_SIZE > max_segment_size) + if (size + BM_BLOCK_SIZE > max_bio_size) break; /* Be always aligned */ -- GitLab From 4896e8c1b8fb7e46a65a6676e271fc047a260a3e Mon Sep 17 00:00:00 2001 From: Lars Ellenberg Date: Thu, 11 Nov 2010 22:41:04 +0100 Subject: [PATCH 0405/2822] drbd: restore compatibility with 32bit kernels With commit drbd: further converge progress display of resync and online-verify accidentally an u64/u64 div was introduced, causing an unresolvable symbol __udivdi3 to be reference. Actually for that division, 32bit are still suficient for now, so we can revert to unsigned long instead. Signed-off-by: Philipp Reisner Signed-off-by: Lars Ellenberg --- drivers/block/drbd/drbd_proc.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/block/drbd/drbd_proc.c b/drivers/block/drbd/drbd_proc.c index 329b66a91e449..49d817cfe865b 100644 --- a/drivers/block/drbd/drbd_proc.c +++ b/drivers/block/drbd/drbd_proc.c @@ -164,8 +164,8 @@ static void drbd_syncer_progress(struct drbd_conf *mdev, struct seq_file *seq) if (proc_details >= 1) { /* 64 bit: * we convert to sectors in the display below. */ - u64 bm_bits = drbd_bm_bits(mdev); - u64 bit_pos; + unsigned long bm_bits = drbd_bm_bits(mdev); + unsigned long bit_pos; if (mdev->state.conn == C_VERIFY_S || mdev->state.conn == C_VERIFY_T) bit_pos = bm_bits - mdev->ov_left; @@ -176,8 +176,8 @@ static void drbd_syncer_progress(struct drbd_conf *mdev, struct seq_file *seq) seq_printf(seq, "\t%3d%% sector pos: %llu/%llu\n", (int)(bit_pos / (bm_bits/100+1)), - (unsigned long long) BM_BIT_TO_SECT(bit_pos), - (unsigned long long) BM_BIT_TO_SECT(bm_bits)); + (unsigned long long)bit_pos * BM_SECT_PER_BIT, + (unsigned long long)bm_bits * BM_SECT_PER_BIT); } } -- GitLab From 688593c5a82068aea64df0b836793dfbbaa646d7 Mon Sep 17 00:00:00 2001 From: Lars Ellenberg Date: Wed, 17 Nov 2010 22:25:03 +0100 Subject: [PATCH 0406/2822] drbd: Renamed write_flags_to_bio() to wire_flags_to_bio() Signed-off-by: Philipp Reisner Signed-off-by: Lars Ellenberg --- drivers/block/drbd/drbd_receiver.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/drivers/block/drbd/drbd_receiver.c b/drivers/block/drbd/drbd_receiver.c index 79e7b57006b1c..f3052d871d312 100644 --- a/drivers/block/drbd/drbd_receiver.c +++ b/drivers/block/drbd/drbd_receiver.c @@ -1612,15 +1612,15 @@ static int drbd_wait_peer_seq(struct drbd_conf *mdev, const u32 packet_seq) return ret; } -static unsigned long write_flags_to_bio(struct drbd_conf *mdev, u32 dpf) +/* see also bio_flags_to_wire() + * DRBD_REQ_*, because we need to semantically map the flags to data packet + * flags and back. We may replicate to other kernel versions. */ +static unsigned long wire_flags_to_bio(struct drbd_conf *mdev, u32 dpf) { - if (mdev->agreed_pro_version >= 95) - return (dpf & DP_RW_SYNC ? REQ_SYNC : 0) | - (dpf & DP_FUA ? REQ_FUA : 0) | - (dpf & DP_FLUSH ? REQ_FUA : 0) | - (dpf & DP_DISCARD ? REQ_DISCARD : 0); - else - return dpf & DP_RW_SYNC ? REQ_SYNC : 0; + return (dpf & DP_RW_SYNC ? REQ_SYNC : 0) | + (dpf & DP_FUA ? REQ_FUA : 0) | + (dpf & DP_FLUSH ? REQ_FLUSH : 0) | + (dpf & DP_DISCARD ? REQ_DISCARD : 0); } /* mirrored write */ @@ -1660,18 +1660,18 @@ static int receive_Data(struct drbd_conf *mdev, enum drbd_packets cmd, unsigned e->w.cb = e_end_block; + dp_flags = be32_to_cpu(p->dp_flags); + rw |= wire_flags_to_bio(mdev, dp_flags); + + if (dp_flags & DP_MAY_SET_IN_SYNC) + e->flags |= EE_MAY_SET_IN_SYNC; + spin_lock(&mdev->epoch_lock); e->epoch = mdev->current_epoch; atomic_inc(&e->epoch->epoch_size); atomic_inc(&e->epoch->active); spin_unlock(&mdev->epoch_lock); - dp_flags = be32_to_cpu(p->dp_flags); - rw |= write_flags_to_bio(mdev, dp_flags); - - if (dp_flags & DP_MAY_SET_IN_SYNC) - e->flags |= EE_MAY_SET_IN_SYNC; - /* I'm the receiver, I do hold a net_cnt reference. */ if (!mdev->net_conf->two_primaries) { spin_lock_irq(&mdev->req_lock); -- GitLab From 759fbdfba66e620aceb3e73167e6003d1b8b0b0b Mon Sep 17 00:00:00 2001 From: Philipp Reisner Date: Tue, 26 Oct 2010 16:02:27 +0200 Subject: [PATCH 0407/2822] drbd: Track the numbers of sectors in flight Signed-off-by: Philipp Reisner Signed-off-by: Lars Ellenberg --- drivers/block/drbd/drbd_int.h | 1 + drivers/block/drbd/drbd_main.c | 1 + drivers/block/drbd/drbd_req.c | 13 ++++++++++++- drivers/block/drbd/drbd_req.h | 12 +++++++----- 4 files changed, 21 insertions(+), 6 deletions(-) diff --git a/drivers/block/drbd/drbd_int.h b/drivers/block/drbd/drbd_int.h index bcba2742cfba3..c804e44b9455b 100644 --- a/drivers/block/drbd/drbd_int.h +++ b/drivers/block/drbd/drbd_int.h @@ -1102,6 +1102,7 @@ struct drbd_conf { struct fifo_buffer rs_plan_s; /* correction values of resync planer */ int rs_in_flight; /* resync sectors in flight (to proxy, in proxy and from proxy) */ int rs_planed; /* resync sectors already planed */ + atomic_t ap_in_flight; /* App sectors in flight (waiting for ack) */ }; static inline struct drbd_conf *minor_to_mdev(unsigned int minor) diff --git a/drivers/block/drbd/drbd_main.c b/drivers/block/drbd/drbd_main.c index 9d9c2ed31e9af..e81d009dd0612 100644 --- a/drivers/block/drbd/drbd_main.c +++ b/drivers/block/drbd/drbd_main.c @@ -2799,6 +2799,7 @@ void drbd_init_set_defaults(struct drbd_conf *mdev) atomic_set(&mdev->pp_in_use_by_net, 0); atomic_set(&mdev->rs_sect_in, 0); atomic_set(&mdev->rs_sect_ev, 0); + atomic_set(&mdev->ap_in_flight, 0); mutex_init(&mdev->md_io_mutex); mutex_init(&mdev->data.mutex); diff --git a/drivers/block/drbd/drbd_req.c b/drivers/block/drbd/drbd_req.c index 08f53ce9b88f0..5c60d77d447ce 100644 --- a/drivers/block/drbd/drbd_req.c +++ b/drivers/block/drbd/drbd_req.c @@ -558,6 +558,9 @@ int __req_mod(struct drbd_request *req, enum drbd_req_event what, case handed_over_to_network: /* assert something? */ + if (bio_data_dir(req->master_bio) == WRITE) + atomic_add(req->size>>9, &mdev->ap_in_flight); + if (bio_data_dir(req->master_bio) == WRITE && mdev->net_conf->wire_protocol == DRBD_PROT_A) { /* this is what is dangerous about protocol A: @@ -591,6 +594,9 @@ int __req_mod(struct drbd_request *req, enum drbd_req_event what, dec_ap_pending(mdev); req->rq_state &= ~(RQ_NET_OK|RQ_NET_PENDING); req->rq_state |= RQ_NET_DONE; + if (req->rq_state & RQ_NET_SENT && req->rq_state & RQ_WRITE) + atomic_sub(req->size>>9, &mdev->ap_in_flight); + /* if it is still queued, we may not complete it here. * it will be canceled soon. */ if (!(req->rq_state & RQ_NET_QUEUED)) @@ -628,14 +634,17 @@ int __req_mod(struct drbd_request *req, enum drbd_req_event what, req->rq_state |= RQ_NET_OK; D_ASSERT(req->rq_state & RQ_NET_PENDING); dec_ap_pending(mdev); + atomic_sub(req->size>>9, &mdev->ap_in_flight); req->rq_state &= ~RQ_NET_PENDING; _req_may_be_done_not_susp(req, m); break; case neg_acked: /* assert something? */ - if (req->rq_state & RQ_NET_PENDING) + if (req->rq_state & RQ_NET_PENDING) { dec_ap_pending(mdev); + atomic_sub(req->size>>9, &mdev->ap_in_flight); + } req->rq_state &= ~(RQ_NET_OK|RQ_NET_PENDING); req->rq_state |= RQ_NET_DONE; @@ -692,6 +701,8 @@ int __req_mod(struct drbd_request *req, enum drbd_req_event what, } D_ASSERT(req->rq_state & RQ_NET_SENT); req->rq_state |= RQ_NET_DONE; + if (mdev->net_conf->wire_protocol == DRBD_PROT_A) + atomic_sub(req->size>>9, &mdev->ap_in_flight); _req_may_be_done(req, m); /* Allowed while state.susp */ break; diff --git a/drivers/block/drbd/drbd_req.h b/drivers/block/drbd/drbd_req.h index ab2bd09d54b4b..69d350fe7c1e6 100644 --- a/drivers/block/drbd/drbd_req.h +++ b/drivers/block/drbd/drbd_req.h @@ -338,19 +338,21 @@ static inline int _req_mod(struct drbd_request *req, enum drbd_req_event what) return rv; } -/* completion of master bio is outside of spinlock. - * If you need it irqsave, do it your self! - * Which means: don't use from bio endio callback. */ +/* completion of master bio is outside of our spinlock. + * We still may or may not be inside some irqs disabled section + * of the lower level driver completion callback, so we need to + * spin_lock_irqsave here. */ static inline int req_mod(struct drbd_request *req, enum drbd_req_event what) { + unsigned long flags; struct drbd_conf *mdev = req->mdev; struct bio_and_error m; int rv; - spin_lock_irq(&mdev->req_lock); + spin_lock_irqsave(&mdev->req_lock, flags); rv = __req_mod(req, what, &m); - spin_unlock_irq(&mdev->req_lock); + spin_unlock_irqrestore(&mdev->req_lock, flags); if (m.bio) complete_master_bio(mdev, &m); -- GitLab From 422028b1ca4c07995af82a18abced022ff4c296c Mon Sep 17 00:00:00 2001 From: Philipp Reisner Date: Wed, 27 Oct 2010 11:12:07 +0200 Subject: [PATCH 0408/2822] drbd: New configuration parameters for dealing with network congestion net { on_congestion {block|pull-ahead|disconnect}; congestion-fill {sectors}; congestion-extents {al-extents}; } Signed-off-by: Philipp Reisner Signed-off-by: Lars Ellenberg --- drivers/block/drbd/drbd_nl.c | 7 +++++++ include/linux/drbd.h | 7 +++++++ include/linux/drbd_limits.h | 9 +++++++++ include/linux/drbd_nl.h | 3 +++ 4 files changed, 26 insertions(+) diff --git a/drivers/block/drbd/drbd_nl.c b/drivers/block/drbd/drbd_nl.c index 9e27d82a9a192..f969d8717e235 100644 --- a/drivers/block/drbd/drbd_nl.c +++ b/drivers/block/drbd/drbd_nl.c @@ -1323,6 +1323,8 @@ static int drbd_nl_net_conf(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp, new_conf->wire_protocol = DRBD_PROT_C; new_conf->ping_timeo = DRBD_PING_TIMEO_DEF; new_conf->rr_conflict = DRBD_RR_CONFLICT_DEF; + new_conf->on_congestion = DRBD_ON_CONGESTION_DEF; + new_conf->cong_extents = DRBD_CONG_EXTENTS_DEF; if (!net_conf_from_tags(mdev, nlp->tag_list, new_conf)) { retcode = ERR_MANDATORY_TAG; @@ -1344,6 +1346,11 @@ static int drbd_nl_net_conf(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp, } } + if (new_conf->on_congestion != OC_BLOCK && new_conf->wire_protocol != DRBD_PROT_A) { + retcode = ERR_CONG_NOT_PROTO_A; + goto fail; + } + if (mdev->state.role == R_PRIMARY && new_conf->want_lose) { retcode = ERR_DISCARD; goto fail; diff --git a/include/linux/drbd.h b/include/linux/drbd.h index ef44c7a0638cd..03a08baabf110 100644 --- a/include/linux/drbd.h +++ b/include/linux/drbd.h @@ -96,6 +96,12 @@ enum drbd_on_no_data { OND_SUSPEND_IO }; +enum drbd_on_congestion { + OC_BLOCK, + OC_PULL_AHEAD, + OC_DISCONNECT, +}; + /* KEEP the order, do not delete or insert. Only append. */ enum drbd_ret_codes { ERR_CODE_BASE = 100, @@ -146,6 +152,7 @@ enum drbd_ret_codes { ERR_PERM = 152, ERR_NEED_APV_93 = 153, ERR_STONITH_AND_PROT_A = 154, + ERR_CONG_NOT_PROTO_A = 155, /* insert new ones above this line */ AFTER_LAST_ERR_CODE diff --git a/include/linux/drbd_limits.h b/include/linux/drbd_limits.h index 4ac33f34b77e4..abf418724e52f 100644 --- a/include/linux/drbd_limits.h +++ b/include/linux/drbd_limits.h @@ -129,6 +129,7 @@ #define DRBD_AFTER_SB_2P_DEF ASB_DISCONNECT #define DRBD_RR_CONFLICT_DEF ASB_DISCONNECT #define DRBD_ON_NO_DATA_DEF OND_IO_ERROR +#define DRBD_ON_CONGESTION_DEF OC_BLOCK #define DRBD_MAX_BIO_BVECS_MIN 0 #define DRBD_MAX_BIO_BVECS_MAX 128 @@ -154,5 +155,13 @@ #define DRBD_C_MIN_RATE_MAX (4 << 20) #define DRBD_C_MIN_RATE_DEF 4096 +#define DRBD_CONG_FILL_MIN 0 +#define DRBD_CONG_FILL_MAX (10<<21) /* 10GByte in sectors */ +#define DRBD_CONG_FILL_DEF 0 + +#define DRBD_CONG_EXTENTS_MIN DRBD_AL_EXTENTS_MIN +#define DRBD_CONG_EXTENTS_MAX DRBD_AL_EXTENTS_MAX +#define DRBD_CONG_EXTENTS_DEF DRBD_AL_EXTENTS_DEF + #undef RANGE #endif diff --git a/include/linux/drbd_nl.h b/include/linux/drbd_nl.h index ade91107c9a50..8cde3945d1f7d 100644 --- a/include/linux/drbd_nl.h +++ b/include/linux/drbd_nl.h @@ -56,6 +56,9 @@ NL_PACKET(net_conf, 5, NL_INTEGER( 39, T_MAY_IGNORE, rr_conflict) NL_INTEGER( 40, T_MAY_IGNORE, ping_timeo) NL_INTEGER( 67, T_MAY_IGNORE, rcvbuf_size) + NL_INTEGER( 81, T_MAY_IGNORE, on_congestion) + NL_INTEGER( 82, T_MAY_IGNORE, cong_fill) + NL_INTEGER( 83, T_MAY_IGNORE, cong_extents) /* 59 addr_family was available in GIT, never released */ NL_BIT( 60, T_MANDATORY, mind_af) NL_BIT( 27, T_MAY_IGNORE, want_lose) -- GitLab From 67531718d8f1259f01ab84c2aa25f7b03c7afd46 Mon Sep 17 00:00:00 2001 From: Philipp Reisner Date: Wed, 27 Oct 2010 12:21:30 +0200 Subject: [PATCH 0409/2822] drbd: Implemented two new connection states Ahead/Behind In this connection mode, the ahead node no longer replicates application IO. The behind's disk becomes out dated. Signed-off-by: Philipp Reisner Signed-off-by: Lars Ellenberg --- drivers/block/drbd/drbd_int.h | 2 ++ drivers/block/drbd/drbd_main.c | 12 ++++++++++-- drivers/block/drbd/drbd_receiver.c | 3 +++ drivers/block/drbd/drbd_req.c | 23 +++++++++++++++++++++++ drivers/block/drbd/drbd_strings.c | 4 +++- include/linux/drbd.h | 4 ++++ 6 files changed, 45 insertions(+), 3 deletions(-) diff --git a/drivers/block/drbd/drbd_int.h b/drivers/block/drbd/drbd_int.h index c804e44b9455b..21b7439438cd7 100644 --- a/drivers/block/drbd/drbd_int.h +++ b/drivers/block/drbd/drbd_int.h @@ -2217,6 +2217,8 @@ static inline int drbd_state_is_stable(union drbd_state s) case C_VERIFY_T: case C_PAUSED_SYNC_S: case C_PAUSED_SYNC_T: + case C_AHEAD: + case C_BEHIND: /* maybe stable, look at the disk state */ break; diff --git a/drivers/block/drbd/drbd_main.c b/drivers/block/drbd/drbd_main.c index e81d009dd0612..46f27d6c0b21c 100644 --- a/drivers/block/drbd/drbd_main.c +++ b/drivers/block/drbd/drbd_main.c @@ -871,16 +871,19 @@ static union drbd_state sanitize_state(struct drbd_conf *mdev, union drbd_state if (ns.conn >= C_CONNECTED && ((ns.disk == D_CONSISTENT || ns.disk == D_OUTDATED) || - (ns.disk == D_NEGOTIATING && ns.conn == C_WF_BITMAP_T))) { + (ns.disk == D_NEGOTIATING && ns.conn == C_WF_BITMAP_T) || + ns.conn >= C_AHEAD)) { switch (ns.conn) { case C_WF_BITMAP_T: case C_PAUSED_SYNC_T: + case C_BEHIND: ns.disk = D_OUTDATED; break; case C_CONNECTED: case C_WF_BITMAP_S: case C_SYNC_SOURCE: case C_PAUSED_SYNC_S: + case C_AHEAD: ns.disk = D_UP_TO_DATE; break; case C_SYNC_TARGET: @@ -893,16 +896,18 @@ static union drbd_state sanitize_state(struct drbd_conf *mdev, union drbd_state } if (ns.conn >= C_CONNECTED && - (ns.pdsk == D_CONSISTENT || ns.pdsk == D_OUTDATED)) { + (ns.pdsk == D_CONSISTENT || ns.pdsk == D_OUTDATED || ns.conn >= C_AHEAD)) { switch (ns.conn) { case C_CONNECTED: case C_WF_BITMAP_T: case C_PAUSED_SYNC_T: case C_SYNC_TARGET: + case C_BEHIND: ns.pdsk = D_UP_TO_DATE; break; case C_WF_BITMAP_S: case C_PAUSED_SYNC_S: + case C_AHEAD: /* remap any consistent state to D_OUTDATED, * but disallow "upgrade" of not even consistent states. */ @@ -1374,6 +1379,9 @@ static void after_state_ch(struct drbd_conf *mdev, union drbd_state os, if (os.conn == C_WF_REPORT_PARAMS && ns.conn >= C_CONNECTED) drbd_send_state(mdev); + if (os.conn != C_AHEAD && ns.conn == C_AHEAD) + drbd_send_state(mdev); + /* We are in the progress to start a full sync... */ if ((os.conn != C_STARTING_SYNC_T && ns.conn == C_STARTING_SYNC_T) || (os.conn != C_STARTING_SYNC_S && ns.conn == C_STARTING_SYNC_S)) diff --git a/drivers/block/drbd/drbd_receiver.c b/drivers/block/drbd/drbd_receiver.c index f3052d871d312..b19e8b2c4ce5b 100644 --- a/drivers/block/drbd/drbd_receiver.c +++ b/drivers/block/drbd/drbd_receiver.c @@ -3179,6 +3179,9 @@ static int receive_state(struct drbd_conf *mdev, enum drbd_packets cmd, unsigned if (ns.conn == C_WF_REPORT_PARAMS) ns.conn = C_CONNECTED; + if (peer_state.conn == C_AHEAD) + ns.conn = C_BEHIND; + if (mdev->p_uuid && peer_state.disk >= D_NEGOTIATING && get_ldev_if_state(mdev, D_NEGOTIATING)) { int cr; /* consider resync */ diff --git a/drivers/block/drbd/drbd_req.c b/drivers/block/drbd/drbd_req.c index 5c60d77d447ce..60288fb3c4d71 100644 --- a/drivers/block/drbd/drbd_req.c +++ b/drivers/block/drbd/drbd_req.c @@ -948,6 +948,29 @@ allocate_barrier: ? queue_for_net_write : queue_for_net_read); } + + if (remote && mdev->net_conf->on_congestion != OC_BLOCK) { + int congested = 0; + + if (mdev->net_conf->cong_fill && + atomic_read(&mdev->ap_in_flight) >= mdev->net_conf->cong_fill) { + dev_info(DEV, "Congestion-fill threshold reached\n"); + congested = 1; + } + + if (mdev->act_log->used >= mdev->net_conf->cong_extents) { + dev_info(DEV, "Congestion-extents threshold reached\n"); + congested = 1; + } + + if (congested) { + if (mdev->net_conf->on_congestion == OC_PULL_AHEAD) + _drbd_set_state(_NS(mdev, conn, C_AHEAD), 0, NULL); + else /*mdev->net_conf->on_congestion == OC_DISCONNECT */ + _drbd_set_state(_NS(mdev, conn, C_DISCONNECTING), 0, NULL); + } + } + spin_unlock_irq(&mdev->req_lock); kfree(b); /* if someone else has beaten us to it... */ diff --git a/drivers/block/drbd/drbd_strings.c b/drivers/block/drbd/drbd_strings.c index 85179e1fb50a6..5b970adc3b6f5 100644 --- a/drivers/block/drbd/drbd_strings.c +++ b/drivers/block/drbd/drbd_strings.c @@ -48,6 +48,8 @@ static const char *drbd_conn_s_names[] = { [C_PAUSED_SYNC_T] = "PausedSyncT", [C_VERIFY_S] = "VerifyS", [C_VERIFY_T] = "VerifyT", + [C_AHEAD] = "Ahead", + [C_BEHIND] = "Behind", }; static const char *drbd_role_s_names[] = { @@ -92,7 +94,7 @@ static const char *drbd_state_sw_errors[] = { const char *drbd_conn_str(enum drbd_conns s) { /* enums are unsigned... */ - return s > C_PAUSED_SYNC_T ? "TOO_LARGE" : drbd_conn_s_names[s]; + return s > C_BEHIND ? "TOO_LARGE" : drbd_conn_s_names[s]; } const char *drbd_role_str(enum drbd_role s) diff --git a/include/linux/drbd.h b/include/linux/drbd.h index 03a08baabf110..23f31be6f00d0 100644 --- a/include/linux/drbd.h +++ b/include/linux/drbd.h @@ -206,6 +206,10 @@ enum drbd_conns { C_VERIFY_T, C_PAUSED_SYNC_S, C_PAUSED_SYNC_T, + + C_AHEAD, + C_BEHIND, + C_MASK = 31 }; -- GitLab From 73a01a18b9c28a0fab1131ece5b0a9bc00a879b8 Mon Sep 17 00:00:00 2001 From: Philipp Reisner Date: Wed, 27 Oct 2010 14:33:00 +0200 Subject: [PATCH 0410/2822] drbd: New packet for Ahead/Behind mode: P_OUT_OF_SYNC Signed-off-by: Philipp Reisner Signed-off-by: Lars Ellenberg --- drivers/block/drbd/drbd_actlog.c | 10 ++++--- drivers/block/drbd/drbd_int.h | 14 +++++++++- drivers/block/drbd/drbd_main.c | 10 +++++++ drivers/block/drbd/drbd_receiver.c | 10 +++++++ drivers/block/drbd/drbd_req.c | 44 ++++++++++++++++++++++-------- drivers/block/drbd/drbd_req.h | 4 ++- drivers/block/drbd/drbd_worker.c | 16 +++++++++++ include/linux/drbd.h | 2 +- 8 files changed, 91 insertions(+), 19 deletions(-) diff --git a/drivers/block/drbd/drbd_actlog.c b/drivers/block/drbd/drbd_actlog.c index b4adb58c7472c..33f6cc537d08e 100644 --- a/drivers/block/drbd/drbd_actlog.c +++ b/drivers/block/drbd/drbd_actlog.c @@ -1007,22 +1007,22 @@ void __drbd_set_in_sync(struct drbd_conf *mdev, sector_t sector, int size, * called by tl_clear and drbd_send_dblock (==drbd_make_request). * so this can be _any_ process. */ -void __drbd_set_out_of_sync(struct drbd_conf *mdev, sector_t sector, int size, +int __drbd_set_out_of_sync(struct drbd_conf *mdev, sector_t sector, int size, const char *file, const unsigned int line) { unsigned long sbnr, ebnr, lbnr, flags; sector_t esector, nr_sectors; - unsigned int enr, count; + unsigned int enr, count = 0; struct lc_element *e; if (size <= 0 || (size & 0x1ff) != 0 || size > DRBD_MAX_BIO_SIZE) { dev_err(DEV, "sector: %llus, size: %d\n", (unsigned long long)sector, size); - return; + return 0; } if (!get_ldev(mdev)) - return; /* no disk, no metadata, no bitmap to set bits in */ + return 0; /* no disk, no metadata, no bitmap to set bits in */ nr_sectors = drbd_get_capacity(mdev->this_bdev); esector = sector + (size >> 9) - 1; @@ -1052,6 +1052,8 @@ void __drbd_set_out_of_sync(struct drbd_conf *mdev, sector_t sector, int size, out: put_ldev(mdev); + + return count; } static diff --git a/drivers/block/drbd/drbd_int.h b/drivers/block/drbd/drbd_int.h index 21b7439438cd7..471331236826d 100644 --- a/drivers/block/drbd/drbd_int.h +++ b/drivers/block/drbd/drbd_int.h @@ -212,6 +212,7 @@ enum drbd_packets { /* P_CKPT_FENCE_REQ = 0x25, * currently reserved for protocol D */ /* P_CKPT_DISABLE_REQ = 0x26, * currently reserved for protocol D */ P_DELAY_PROBE = 0x27, /* is used on BOTH sockets */ + P_OUT_OF_SYNC = 0x28, /* Mark as out of sync (Outrunning), data socket */ P_MAX_CMD = 0x28, P_MAY_IGNORE = 0x100, /* Flag to test if (cmd > P_MAY_IGNORE) ... */ @@ -269,6 +270,7 @@ static inline const char *cmdname(enum drbd_packets cmd) [P_RS_IS_IN_SYNC] = "CsumRSIsInSync", [P_COMPRESSED_BITMAP] = "CBitmap", [P_DELAY_PROBE] = "DelayProbe", + [P_OUT_OF_SYNC] = "OutOfSync", [P_MAX_CMD] = NULL, }; @@ -550,6 +552,13 @@ struct p_discard { u32 pad; } __packed; +struct p_block_desc { + struct p_header80 head; + u64 sector; + u32 blksize; + u32 pad; /* to multiple of 8 Byte */ +} __packed; + /* Valid values for the encoding field. * Bump proto version when changing this. */ enum drbd_bitmap_code { @@ -647,6 +656,7 @@ union p_polymorph { struct p_block_req block_req; struct p_delay_probe93 delay_probe93; struct p_rs_uuid rs_uuid; + struct p_block_desc block_desc; } __packed; /**********************************************************************/ @@ -1221,6 +1231,7 @@ extern int drbd_send_ack_dp(struct drbd_conf *mdev, enum drbd_packets cmd, struct p_data *dp, int data_size); extern int drbd_send_ack_ex(struct drbd_conf *mdev, enum drbd_packets cmd, sector_t sector, int blksize, u64 block_id); +extern int drbd_send_oos(struct drbd_conf *mdev, struct drbd_request *req); extern int drbd_send_block(struct drbd_conf *mdev, enum drbd_packets cmd, struct drbd_epoch_entry *e); extern int drbd_send_dblock(struct drbd_conf *mdev, struct drbd_request *req); @@ -1534,6 +1545,7 @@ extern int w_send_read_req(struct drbd_conf *, struct drbd_work *, int); extern int w_prev_work_done(struct drbd_conf *, struct drbd_work *, int); extern int w_e_reissue(struct drbd_conf *, struct drbd_work *, int); extern int w_restart_disk_io(struct drbd_conf *, struct drbd_work *, int); +extern int w_send_oos(struct drbd_conf *, struct drbd_work *, int); extern void resync_timer_fn(unsigned long data); @@ -1626,7 +1638,7 @@ extern void __drbd_set_in_sync(struct drbd_conf *mdev, sector_t sector, int size, const char *file, const unsigned int line); #define drbd_set_in_sync(mdev, sector, size) \ __drbd_set_in_sync(mdev, sector, size, __FILE__, __LINE__) -extern void __drbd_set_out_of_sync(struct drbd_conf *mdev, sector_t sector, +extern int __drbd_set_out_of_sync(struct drbd_conf *mdev, sector_t sector, int size, const char *file, const unsigned int line); #define drbd_set_out_of_sync(mdev, sector, size) \ __drbd_set_out_of_sync(mdev, sector, size, __FILE__, __LINE__) diff --git a/drivers/block/drbd/drbd_main.c b/drivers/block/drbd/drbd_main.c index 46f27d6c0b21c..0dc93f43a4760 100644 --- a/drivers/block/drbd/drbd_main.c +++ b/drivers/block/drbd/drbd_main.c @@ -2634,6 +2634,16 @@ int drbd_send_block(struct drbd_conf *mdev, enum drbd_packets cmd, return ok; } +int drbd_send_oos(struct drbd_conf *mdev, struct drbd_request *req) +{ + struct p_block_desc p; + + p.sector = cpu_to_be64(req->sector); + p.blksize = cpu_to_be32(req->size); + + return drbd_send_cmd(mdev, USE_DATA_SOCKET, P_OUT_OF_SYNC, &p.head, sizeof(p)); +} + /* drbd_send distinguishes two cases: diff --git a/drivers/block/drbd/drbd_receiver.c b/drivers/block/drbd/drbd_receiver.c index b19e8b2c4ce5b..04a08e7541cce 100644 --- a/drivers/block/drbd/drbd_receiver.c +++ b/drivers/block/drbd/drbd_receiver.c @@ -3562,6 +3562,15 @@ static int receive_UnplugRemote(struct drbd_conf *mdev, enum drbd_packets cmd, u return TRUE; } +static int receive_out_of_sync(struct drbd_conf *mdev, enum drbd_packets cmd, unsigned int data_size) +{ + struct p_block_desc *p = &mdev->data.rbuf.block_desc; + + drbd_set_out_of_sync(mdev, be64_to_cpu(p->sector), be32_to_cpu(p->blksize)); + + return TRUE; +} + typedef int (*drbd_cmd_handler_f)(struct drbd_conf *, enum drbd_packets cmd, unsigned int to_receive); struct data_cmd { @@ -3592,6 +3601,7 @@ static struct data_cmd drbd_cmd_handler[] = { [P_OV_REPLY] = { 1, sizeof(struct p_block_req), receive_DataRequest }, [P_CSUM_RS_REQUEST] = { 1, sizeof(struct p_block_req), receive_DataRequest }, [P_DELAY_PROBE] = { 0, sizeof(struct p_delay_probe93), receive_skip }, + [P_OUT_OF_SYNC] = { 0, sizeof(struct p_block_desc), receive_out_of_sync }, /* anything missing from this table is in * the asender_tbl, see get_asender_cmd */ [P_MAX_CMD] = { 0, 0, NULL }, diff --git a/drivers/block/drbd/drbd_req.c b/drivers/block/drbd/drbd_req.c index 60288fb3c4d71..a8d1ff2bda278 100644 --- a/drivers/block/drbd/drbd_req.c +++ b/drivers/block/drbd/drbd_req.c @@ -142,7 +142,7 @@ static void _about_to_complete_local_write(struct drbd_conf *mdev, /* before we can signal completion to the upper layers, * we may need to close the current epoch */ - if (mdev->state.conn >= C_CONNECTED && + if (mdev->state.conn >= C_CONNECTED && mdev->state.conn < C_AHEAD && req->epoch == mdev->newest_tle->br_number) queue_barrier(mdev); @@ -545,6 +545,14 @@ int __req_mod(struct drbd_request *req, enum drbd_req_event what, break; + case queue_for_send_oos: + req->rq_state |= RQ_NET_QUEUED; + req->w.cb = w_send_oos; + drbd_queue_work(&mdev->data.work, &req->w); + break; + + case oos_handed_to_network: + /* actually the same */ case send_canceled: /* treat it the same */ case send_failed: @@ -756,7 +764,7 @@ static int drbd_make_request_common(struct drbd_conf *mdev, struct bio *bio) const sector_t sector = bio->bi_sector; struct drbd_tl_epoch *b = NULL; struct drbd_request *req; - int local, remote; + int local, remote, send_oos = 0; int err = -EIO; int ret = 0; @@ -820,8 +828,11 @@ static int drbd_make_request_common(struct drbd_conf *mdev, struct bio *bio) } remote = remote && (mdev->state.pdsk == D_UP_TO_DATE || - (mdev->state.pdsk == D_INCONSISTENT && - mdev->state.conn >= C_CONNECTED)); + (mdev->state.pdsk >= D_INCONSISTENT && + mdev->state.conn >= C_CONNECTED && + mdev->state.conn < C_AHEAD)); + send_oos = (rw == WRITE && mdev->state.conn == C_AHEAD && + mdev->state.pdsk >= D_INCONSISTENT); if (!(local || remote) && !is_susp(mdev->state)) { if (__ratelimit(&drbd_ratelimit_state)) @@ -835,7 +846,7 @@ static int drbd_make_request_common(struct drbd_conf *mdev, struct bio *bio) * but there is a race between testing the bit and pointer outside the * spinlock, and grabbing the spinlock. * if we lost that race, we retry. */ - if (rw == WRITE && remote && + if (rw == WRITE && (remote || send_oos) && mdev->unused_spare_tle == NULL && test_bit(CREATE_BARRIER, &mdev->flags)) { allocate_barrier: @@ -860,11 +871,15 @@ allocate_barrier: goto fail_free_complete; } - if (remote) { + if (remote || send_oos) { remote = (mdev->state.pdsk == D_UP_TO_DATE || - (mdev->state.pdsk == D_INCONSISTENT && - mdev->state.conn >= C_CONNECTED)); - if (!remote) + (mdev->state.pdsk >= D_INCONSISTENT && + mdev->state.conn >= C_CONNECTED && + mdev->state.conn < C_AHEAD)); + send_oos = (rw == WRITE && mdev->state.conn == C_AHEAD && + mdev->state.pdsk >= D_INCONSISTENT); + + if (!(remote || send_oos)) dev_warn(DEV, "lost connection while grabbing the req_lock!\n"); if (!(local || remote)) { dev_err(DEV, "IO ERROR: neither local nor remote disk\n"); @@ -877,7 +892,7 @@ allocate_barrier: mdev->unused_spare_tle = b; b = NULL; } - if (rw == WRITE && remote && + if (rw == WRITE && (remote || send_oos) && mdev->unused_spare_tle == NULL && test_bit(CREATE_BARRIER, &mdev->flags)) { /* someone closed the current epoch @@ -900,7 +915,7 @@ allocate_barrier: * barrier packet. To get the write ordering right, we only have to * make sure that, if this is a write request and it triggered a * barrier packet, this request is queued within the same spinlock. */ - if (remote && mdev->unused_spare_tle && + if ((remote || send_oos) && mdev->unused_spare_tle && test_and_clear_bit(CREATE_BARRIER, &mdev->flags)) { _tl_add_barrier(mdev, mdev->unused_spare_tle); mdev->unused_spare_tle = NULL; @@ -948,8 +963,11 @@ allocate_barrier: ? queue_for_net_write : queue_for_net_read); } + if (send_oos && drbd_set_out_of_sync(mdev, sector, size)) + _req_mod(req, queue_for_send_oos); - if (remote && mdev->net_conf->on_congestion != OC_BLOCK) { + if (remote && + mdev->net_conf->on_congestion != OC_BLOCK && mdev->agreed_pro_version >= 96) { int congested = 0; if (mdev->net_conf->cong_fill && @@ -964,6 +982,8 @@ allocate_barrier: } if (congested) { + queue_barrier(mdev); + if (mdev->net_conf->on_congestion == OC_PULL_AHEAD) _drbd_set_state(_NS(mdev, conn, C_AHEAD), 0, NULL); else /*mdev->net_conf->on_congestion == OC_DISCONNECT */ diff --git a/drivers/block/drbd/drbd_req.h b/drivers/block/drbd/drbd_req.h index 69d350fe7c1e6..40d3dcd8fc815 100644 --- a/drivers/block/drbd/drbd_req.h +++ b/drivers/block/drbd/drbd_req.h @@ -82,14 +82,16 @@ enum drbd_req_event { to_be_submitted, /* XXX yes, now I am inconsistent... - * these two are not "events" but "actions" + * these are not "events" but "actions" * oh, well... */ queue_for_net_write, queue_for_net_read, + queue_for_send_oos, send_canceled, send_failed, handed_over_to_network, + oos_handed_to_network, connection_lost_while_pending, read_retry_remote_canceled, recv_acked_by_peer, diff --git a/drivers/block/drbd/drbd_worker.c b/drivers/block/drbd/drbd_worker.c index 782d87237cb47..67499077c4828 100644 --- a/drivers/block/drbd/drbd_worker.c +++ b/drivers/block/drbd/drbd_worker.c @@ -1237,6 +1237,22 @@ int w_send_write_hint(struct drbd_conf *mdev, struct drbd_work *w, int cancel) return drbd_send_short_cmd(mdev, P_UNPLUG_REMOTE); } +int w_send_oos(struct drbd_conf *mdev, struct drbd_work *w, int cancel) +{ + struct drbd_request *req = container_of(w, struct drbd_request, w); + int ok; + + if (unlikely(cancel)) { + req_mod(req, send_canceled); + return 1; + } + + ok = drbd_send_oos(mdev, req); + req_mod(req, oos_handed_to_network); + + return ok; +} + /** * w_send_dblock() - Worker callback to send a P_DATA packet in order to mirror a write request * @mdev: DRBD device. diff --git a/include/linux/drbd.h b/include/linux/drbd.h index 23f31be6f00d0..41da654cc0b18 100644 --- a/include/linux/drbd.h +++ b/include/linux/drbd.h @@ -56,7 +56,7 @@ extern const char *drbd_buildtag(void); #define REL_VERSION "8.3.9" #define API_VERSION 88 #define PRO_VERSION_MIN 86 -#define PRO_VERSION_MAX 95 +#define PRO_VERSION_MAX 96 enum drbd_io_error_p { -- GitLab From c4752ef1284519c3baa1c3b19df34a80b4905245 Mon Sep 17 00:00:00 2001 From: Philipp Reisner Date: Wed, 27 Oct 2010 17:32:36 +0200 Subject: [PATCH 0411/2822] drbd: When proxy's buffer drained off go into regular resync mode Signed-off-by: Philipp Reisner Signed-off-by: Lars Ellenberg --- drivers/block/drbd/drbd_int.h | 4 +++- drivers/block/drbd/drbd_main.c | 1 + drivers/block/drbd/drbd_receiver.c | 9 +++++++++ drivers/block/drbd/drbd_worker.c | 10 +++++++++- 4 files changed, 22 insertions(+), 2 deletions(-) diff --git a/drivers/block/drbd/drbd_int.h b/drivers/block/drbd/drbd_int.h index 471331236826d..da02cce374c99 100644 --- a/drivers/block/drbd/drbd_int.h +++ b/drivers/block/drbd/drbd_int.h @@ -973,7 +973,8 @@ struct drbd_conf { struct drbd_work resync_work, unplug_work, go_diskless, - md_sync_work; + md_sync_work, + start_resync_work; struct timer_list resync_timer; struct timer_list md_sync_timer; #ifdef DRBD_DEBUG_MD_SYNC @@ -1546,6 +1547,7 @@ extern int w_prev_work_done(struct drbd_conf *, struct drbd_work *, int); extern int w_e_reissue(struct drbd_conf *, struct drbd_work *, int); extern int w_restart_disk_io(struct drbd_conf *, struct drbd_work *, int); extern int w_send_oos(struct drbd_conf *, struct drbd_work *, int); +extern int w_start_resync(struct drbd_conf *, struct drbd_work *, int); extern void resync_timer_fn(unsigned long data); diff --git a/drivers/block/drbd/drbd_main.c b/drivers/block/drbd/drbd_main.c index 0dc93f43a4760..f49505cf8d0f4 100644 --- a/drivers/block/drbd/drbd_main.c +++ b/drivers/block/drbd/drbd_main.c @@ -2846,6 +2846,7 @@ void drbd_init_set_defaults(struct drbd_conf *mdev) INIT_LIST_HEAD(&mdev->unplug_work.list); INIT_LIST_HEAD(&mdev->go_diskless.list); INIT_LIST_HEAD(&mdev->md_sync_work.list); + INIT_LIST_HEAD(&mdev->start_resync_work.list); INIT_LIST_HEAD(&mdev->bm_io_work.w.list); mdev->resync_work.cb = w_resync_inactive; diff --git a/drivers/block/drbd/drbd_receiver.c b/drivers/block/drbd/drbd_receiver.c index 04a08e7541cce..ee9238e593277 100644 --- a/drivers/block/drbd/drbd_receiver.c +++ b/drivers/block/drbd/drbd_receiver.c @@ -3279,6 +3279,7 @@ static int receive_sync_uuid(struct drbd_conf *mdev, enum drbd_packets cmd, unsi wait_event(mdev->misc_wait, mdev->state.conn == C_WF_SYNC_UUID || + mdev->state.conn == C_BEHIND || mdev->state.conn < C_CONNECTED || mdev->state.disk < D_NEGOTIATING); @@ -4338,6 +4339,14 @@ static int got_BarrierAck(struct drbd_conf *mdev, struct p_header80 *h) tl_release(mdev, p->barrier, be32_to_cpu(p->set_size)); + if (mdev->state.conn == C_AHEAD && + atomic_read(&mdev->ap_in_flight) == 0 && + list_empty(&mdev->start_resync_work.list)) { + struct drbd_work *w = &mdev->start_resync_work; + w->cb = w_start_resync; + drbd_queue_work_front(&mdev->data.work, w); + } + return TRUE; } diff --git a/drivers/block/drbd/drbd_worker.c b/drivers/block/drbd/drbd_worker.c index 67499077c4828..c9e7cb7c788ab 100644 --- a/drivers/block/drbd/drbd_worker.c +++ b/drivers/block/drbd/drbd_worker.c @@ -742,6 +742,14 @@ static int w_make_ov_request(struct drbd_conf *mdev, struct drbd_work *w, int ca return 1; } + +int w_start_resync(struct drbd_conf *mdev, struct drbd_work *w, int cancel) +{ + drbd_start_resync(mdev, C_SYNC_SOURCE); + + return 1; +} + int w_ov_finished(struct drbd_conf *mdev, struct drbd_work *w, int cancel) { kfree(w); @@ -1472,7 +1480,7 @@ void drbd_start_resync(struct drbd_conf *mdev, enum drbd_conns side) union drbd_state ns; int r; - if (mdev->state.conn >= C_SYNC_SOURCE) { + if (mdev->state.conn >= C_SYNC_SOURCE && mdev->state.conn < C_AHEAD) { dev_err(DEV, "Resync already running!\n"); return; } -- GitLab From 59817f4fab6a165ba83ce399464ba38432db8233 Mon Sep 17 00:00:00 2001 From: Philipp Reisner Date: Fri, 29 Oct 2010 12:44:20 +0200 Subject: [PATCH 0412/2822] drbd: Do not cleanup resync LRU for the Ahead/Behind SyncSource/SyncTarget transitions This one should be replaced with moving this cleanup to the 'right' position. Signed-off-by: Philipp Reisner Signed-off-by: Lars Ellenberg --- drivers/block/drbd/drbd_worker.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/block/drbd/drbd_worker.c b/drivers/block/drbd/drbd_worker.c index c9e7cb7c788ab..982d68432a0f5 100644 --- a/drivers/block/drbd/drbd_worker.c +++ b/drivers/block/drbd/drbd_worker.c @@ -1485,8 +1485,13 @@ void drbd_start_resync(struct drbd_conf *mdev, enum drbd_conns side) return; } - /* In case a previous resync run was aborted by an IO error/detach on the peer. */ - drbd_rs_cancel_all(mdev); + if (mdev->state.conn < C_AHEAD) { + /* In case a previous resync run was aborted by an IO error/detach on the peer. */ + drbd_rs_cancel_all(mdev); + /* This should be done when we abort the resync. We definitely do not + want to have this for connections going back and forth between + Ahead/Behind and SyncSource/SyncTarget */ + } if (side == C_SYNC_TARGET) { /* Since application IO was locked out during C_WF_BITMAP_T and -- GitLab From e3555d8545976703938d1b59e2db509426dbe02c Mon Sep 17 00:00:00 2001 From: Philipp Reisner Date: Sun, 7 Nov 2010 15:56:29 +0100 Subject: [PATCH 0413/2822] drbd: Implemented priority inheritance for resync requests We only issue resync requests if there is no significant application IO going on. = Application IO has higher priority than resnyc IO. If application IO can not be started because the resync process locked an resync_lru entry, start the IO operations necessary to release the lock ASAP. Signed-off-by: Philipp Reisner Signed-off-by: Lars Ellenberg --- drivers/block/drbd/drbd_actlog.c | 4 ++-- drivers/block/drbd/drbd_int.h | 3 ++- drivers/block/drbd/drbd_receiver.c | 22 ++++++++++++++++++---- drivers/block/drbd/drbd_worker.c | 18 +++++------------- 4 files changed, 27 insertions(+), 20 deletions(-) diff --git a/drivers/block/drbd/drbd_actlog.c b/drivers/block/drbd/drbd_actlog.c index 33f6cc537d08e..28f85d950781e 100644 --- a/drivers/block/drbd/drbd_actlog.c +++ b/drivers/block/drbd/drbd_actlog.c @@ -182,6 +182,7 @@ static struct lc_element *_al_get(struct drbd_conf *mdev, unsigned int enr) if (unlikely(tmp != NULL)) { struct bm_extent *bm_ext = lc_entry(tmp, struct bm_extent, lce); if (test_bit(BME_NO_WRITES, &bm_ext->flags)) { + set_bit(BME_PRIORITY, &bm_ext->flags); spin_unlock_irq(&mdev->al_lock); return NULL; } @@ -1297,8 +1298,7 @@ void drbd_rs_complete_io(struct drbd_conf *mdev, sector_t sector) } if (lc_put(mdev->resync, &bm_ext->lce) == 0) { - clear_bit(BME_LOCKED, &bm_ext->flags); - clear_bit(BME_NO_WRITES, &bm_ext->flags); + bm_ext->flags = 0; /* clear BME_LOCKED, BME_NO_WRITES and BME_PRIORITY */ mdev->resync_locked--; wake_up(&mdev->al_wait); } diff --git a/drivers/block/drbd/drbd_int.h b/drivers/block/drbd/drbd_int.h index da02cce374c99..366873d661b82 100644 --- a/drivers/block/drbd/drbd_int.h +++ b/drivers/block/drbd/drbd_int.h @@ -1326,6 +1326,7 @@ struct bm_extent { #define BME_NO_WRITES 0 /* bm_extent.flags: no more requests on this one! */ #define BME_LOCKED 1 /* bm_extent.flags: syncer active on this one. */ +#define BME_PRIORITY 2 /* finish resync IO on this extent ASAP! App IO waiting! */ /* drbd_bitmap.c */ /* @@ -1552,7 +1553,7 @@ extern int w_start_resync(struct drbd_conf *, struct drbd_work *, int); extern void resync_timer_fn(unsigned long data); /* drbd_receiver.c */ -extern int drbd_rs_should_slow_down(struct drbd_conf *mdev); +extern int drbd_rs_should_slow_down(struct drbd_conf *mdev, sector_t sector); extern int drbd_submit_ee(struct drbd_conf *mdev, struct drbd_epoch_entry *e, const unsigned rw, const int fault_type); extern int drbd_release_ee(struct drbd_conf *mdev, struct list_head *list); diff --git a/drivers/block/drbd/drbd_receiver.c b/drivers/block/drbd/drbd_receiver.c index ee9238e593277..0630a2e122d33 100644 --- a/drivers/block/drbd/drbd_receiver.c +++ b/drivers/block/drbd/drbd_receiver.c @@ -1862,10 +1862,11 @@ out_interrupted: * The current sync rate used here uses only the most recent two step marks, * to have a short time average so we can react faster. */ -int drbd_rs_should_slow_down(struct drbd_conf *mdev) +int drbd_rs_should_slow_down(struct drbd_conf *mdev, sector_t sector) { struct gendisk *disk = mdev->ldev->backing_bdev->bd_contains->bd_disk; unsigned long db, dt, dbdt; + struct lc_element *tmp; int curr_events; int throttle = 0; @@ -1873,9 +1874,22 @@ int drbd_rs_should_slow_down(struct drbd_conf *mdev) if (mdev->sync_conf.c_min_rate == 0) return 0; + spin_lock_irq(&mdev->al_lock); + tmp = lc_find(mdev->resync, BM_SECT_TO_EXT(sector)); + if (tmp) { + struct bm_extent *bm_ext = lc_entry(tmp, struct bm_extent, lce); + if (test_bit(BME_PRIORITY, &bm_ext->flags)) { + spin_unlock_irq(&mdev->al_lock); + return 0; + } + /* Do not slow down if app IO is already waiting for this extent */ + } + spin_unlock_irq(&mdev->al_lock); + curr_events = (int)part_stat_read(&disk->part0, sectors[0]) + (int)part_stat_read(&disk->part0, sectors[1]) - atomic_read(&mdev->rs_sect_ev); + if (!mdev->rs_last_events || curr_events - mdev->rs_last_events > 64) { unsigned long rs_left; int i; @@ -2060,9 +2074,9 @@ static int receive_DataRequest(struct drbd_conf *mdev, enum drbd_packets cmd, un * we would also throttle its application reads. * In that case, throttling is done on the SyncTarget only. */ - if (mdev->state.peer != R_PRIMARY && drbd_rs_should_slow_down(mdev)) - msleep(100); - if (drbd_rs_begin_io(mdev, e->sector)) + if (mdev->state.peer != R_PRIMARY && drbd_rs_should_slow_down(mdev, sector)) + schedule_timeout_uninterruptible(HZ/10); + if (drbd_rs_begin_io(mdev, sector)) goto out_free_e; submit_for_resync: diff --git a/drivers/block/drbd/drbd_worker.c b/drivers/block/drbd/drbd_worker.c index 982d68432a0f5..4008130f2b2cc 100644 --- a/drivers/block/drbd/drbd_worker.c +++ b/drivers/block/drbd/drbd_worker.c @@ -355,7 +355,7 @@ static int read_for_csum(struct drbd_conf *mdev, sector_t sector, int size) if (!get_ldev(mdev)) return -EIO; - if (drbd_rs_should_slow_down(mdev)) + if (drbd_rs_should_slow_down(mdev, sector)) goto defer; /* GFP_TRY, because if there is no memory available right now, this may @@ -503,16 +503,6 @@ int drbd_rs_number_requests(struct drbd_conf *mdev) number = SLEEP_TIME * mdev->c_sync_rate / ((BM_BLOCK_SIZE / 1024) * HZ); } - /* Throttle resync on lower level disk activity, which may also be - * caused by application IO on Primary/SyncTarget. - * Keep this after the call to drbd_rs_controller, as that assumes - * to be called as precisely as possible every SLEEP_TIME, - * and would be confused otherwise. */ - if (number && drbd_rs_should_slow_down(mdev)) { - mdev->c_sync_rate = 1; - number = 0; - } - /* ignore the amount of pending requests, the resync controller should * throttle down to incoming reply rate soon enough anyways. */ return number; @@ -594,7 +584,8 @@ next_sector: sector = BM_BIT_TO_SECT(bit); - if (drbd_try_rs_begin_io(mdev, sector)) { + if (drbd_rs_should_slow_down(mdev, sector) || + drbd_try_rs_begin_io(mdev, sector)) { mdev->bm_resync_fo = bit; goto requeue; } @@ -719,7 +710,8 @@ static int w_make_ov_request(struct drbd_conf *mdev, struct drbd_work *w, int ca size = BM_BLOCK_SIZE; - if (drbd_try_rs_begin_io(mdev, sector)) { + if (drbd_rs_should_slow_down(mdev, sector) || + drbd_try_rs_begin_io(mdev, sector)) { mdev->ov_position = sector; goto requeue; } -- GitLab From 9d77a5fee9d2a1ea4cd9a841d27b107df5913b33 Mon Sep 17 00:00:00 2001 From: Philipp Reisner Date: Sun, 7 Nov 2010 18:02:56 +0100 Subject: [PATCH 0414/2822] drbd: Make some functions static Signed-off-by: Philipp Reisner Signed-off-by: Lars Ellenberg --- drivers/block/drbd/drbd_int.h | 1 - drivers/block/drbd/drbd_worker.c | 10 ++++++---- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/drivers/block/drbd/drbd_int.h b/drivers/block/drbd/drbd_int.h index 366873d661b82..77ac6765fd576 100644 --- a/drivers/block/drbd/drbd_int.h +++ b/drivers/block/drbd/drbd_int.h @@ -1540,7 +1540,6 @@ extern int w_ov_finished(struct drbd_conf *, struct drbd_work *, int); extern int w_resync_inactive(struct drbd_conf *, struct drbd_work *, int); extern int w_resume_next_sg(struct drbd_conf *, struct drbd_work *, int); extern int w_send_write_hint(struct drbd_conf *, struct drbd_work *, int); -extern int w_make_resync_request(struct drbd_conf *, struct drbd_work *, int); extern int w_send_dblock(struct drbd_conf *, struct drbd_work *, int); extern int w_send_barrier(struct drbd_conf *, struct drbd_work *, int); extern int w_send_read_req(struct drbd_conf *, struct drbd_work *, int); diff --git a/drivers/block/drbd/drbd_worker.c b/drivers/block/drbd/drbd_worker.c index 4008130f2b2cc..ab5cff502f5b5 100644 --- a/drivers/block/drbd/drbd_worker.c +++ b/drivers/block/drbd/drbd_worker.c @@ -39,6 +39,8 @@ #include "drbd_req.h" static int w_make_ov_request(struct drbd_conf *mdev, struct drbd_work *w, int cancel); +static int w_make_resync_request(struct drbd_conf *mdev, + struct drbd_work *w, int cancel); @@ -438,7 +440,7 @@ static void fifo_add_val(struct fifo_buffer *fb, int value) fb->values[i] += value; } -int drbd_rs_controller(struct drbd_conf *mdev) +static int drbd_rs_controller(struct drbd_conf *mdev) { unsigned int sect_in; /* Number of sectors that came in since the last turn */ unsigned int want; /* The number of sectors we want in the proxy */ @@ -492,7 +494,7 @@ int drbd_rs_controller(struct drbd_conf *mdev) return req_sect; } -int drbd_rs_number_requests(struct drbd_conf *mdev) +static int drbd_rs_number_requests(struct drbd_conf *mdev) { int number; if (mdev->rs_plan_s.size) { /* mdev->sync_conf.c_plan_ahead */ @@ -508,8 +510,8 @@ int drbd_rs_number_requests(struct drbd_conf *mdev) return number; } -int w_make_resync_request(struct drbd_conf *mdev, - struct drbd_work *w, int cancel) +static int w_make_resync_request(struct drbd_conf *mdev, + struct drbd_work *w, int cancel) { unsigned long bit; sector_t sector; -- GitLab From f91ab6282df251d28aa4ad1bd85194ebe0a0115b Mon Sep 17 00:00:00 2001 From: Philipp Reisner Date: Tue, 9 Nov 2010 13:59:41 +0100 Subject: [PATCH 0415/2822] drbd: Implemented side-stepping in drbd_res_begin_io() Before: drbd_rs_begin_io() locked app-IO out of an RS extent, and waited then until all previous app-IO in that area finished. (But not only until the disk-IO was finished but until the barrier/epoch ack came in for that == round trip time latency ++) After: As soon as a new app-IO waits wants to start new IO on that RS extent, drbd_rs_begin_io() steps aside (clearing the BME_NO_WRITES flag again). It retries after 100ms. Signed-off-by: Philipp Reisner Signed-off-by: Lars Ellenberg --- drivers/block/drbd/drbd_actlog.c | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/drivers/block/drbd/drbd_actlog.c b/drivers/block/drbd/drbd_actlog.c index 28f85d950781e..5570d9bdc863d 100644 --- a/drivers/block/drbd/drbd_actlog.c +++ b/drivers/block/drbd/drbd_actlog.c @@ -176,14 +176,17 @@ static struct lc_element *_al_get(struct drbd_conf *mdev, unsigned int enr) struct lc_element *al_ext; struct lc_element *tmp; unsigned long al_flags = 0; + int wake; spin_lock_irq(&mdev->al_lock); tmp = lc_find(mdev->resync, enr/AL_EXT_PER_BM_SECT); if (unlikely(tmp != NULL)) { struct bm_extent *bm_ext = lc_entry(tmp, struct bm_extent, lce); if (test_bit(BME_NO_WRITES, &bm_ext->flags)) { - set_bit(BME_PRIORITY, &bm_ext->flags); + wake = !test_and_set_bit(BME_PRIORITY, &bm_ext->flags); spin_unlock_irq(&mdev->al_lock); + if (wake) + wake_up(&mdev->al_wait); return NULL; } } @@ -1135,7 +1138,10 @@ int drbd_rs_begin_io(struct drbd_conf *mdev, sector_t sector) unsigned int enr = BM_SECT_TO_EXT(sector); struct bm_extent *bm_ext; int i, sig; + int sa = 200; /* Step aside 200 times, then grab the extent and let app-IO wait. + 200 times -> 20 seconds. */ +retry: sig = wait_event_interruptible(mdev->al_wait, (bm_ext = _bme_get(mdev, enr))); if (sig) @@ -1146,16 +1152,24 @@ int drbd_rs_begin_io(struct drbd_conf *mdev, sector_t sector) for (i = 0; i < AL_EXT_PER_BM_SECT; i++) { sig = wait_event_interruptible(mdev->al_wait, - !_is_in_al(mdev, enr * AL_EXT_PER_BM_SECT + i)); - if (sig) { + !_is_in_al(mdev, enr * AL_EXT_PER_BM_SECT + i) || + (test_bit(BME_PRIORITY, &bm_ext->flags) && sa)); + + if (sig || (test_bit(BME_PRIORITY, &bm_ext->flags) && sa)) { spin_lock_irq(&mdev->al_lock); if (lc_put(mdev->resync, &bm_ext->lce) == 0) { - clear_bit(BME_NO_WRITES, &bm_ext->flags); + bm_ext->flags = 0; /* clears BME_NO_WRITES and eventually BME_PRIORITY */ mdev->resync_locked--; wake_up(&mdev->al_wait); } spin_unlock_irq(&mdev->al_lock); - return -EINTR; + if (sig) + return -EINTR; + if (schedule_timeout_interruptible(HZ/10)) + return -EINTR; + if (--sa == 0) + dev_warn(DEV,"drbd_rs_begin_io() no longer stepping aside.\n"); + goto retry; } } set_bit(BME_LOCKED, &bm_ext->flags); -- GitLab From aeda1cd6a58009ef21b6d9c09b1a3ded726c2d10 Mon Sep 17 00:00:00 2001 From: Philipp Reisner Date: Tue, 9 Nov 2010 17:45:06 +0100 Subject: [PATCH 0416/2822] drbd: Begin to account BIO processing time before inc_ap_bio() Since inc_ap_bio() might sleep already Signed-off-by: Philipp Reisner Signed-off-by: Lars Ellenberg --- drivers/block/drbd/drbd_req.c | 12 ++++++++---- drivers/block/drbd/drbd_req.h | 1 - 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/drivers/block/drbd/drbd_req.c b/drivers/block/drbd/drbd_req.c index a8d1ff2bda278..eff0fbf69dd42 100644 --- a/drivers/block/drbd/drbd_req.c +++ b/drivers/block/drbd/drbd_req.c @@ -757,7 +757,7 @@ static int drbd_may_do_local_read(struct drbd_conf *mdev, sector_t sector, int s return 0 == drbd_bm_count_bits(mdev, sbnr, ebnr); } -static int drbd_make_request_common(struct drbd_conf *mdev, struct bio *bio) +static int drbd_make_request_common(struct drbd_conf *mdev, struct bio *bio, unsigned long start_time) { const int rw = bio_rw(bio); const int size = bio->bi_size; @@ -778,6 +778,7 @@ static int drbd_make_request_common(struct drbd_conf *mdev, struct bio *bio) bio_endio(bio, -ENOMEM); return 0; } + req->start_time = start_time; local = get_ldev(mdev); if (!local) { @@ -1076,12 +1077,15 @@ int drbd_make_request_26(struct request_queue *q, struct bio *bio) { unsigned int s_enr, e_enr; struct drbd_conf *mdev = (struct drbd_conf *) q->queuedata; + unsigned long start_time; if (drbd_fail_request_early(mdev, bio_data_dir(bio) & WRITE)) { bio_endio(bio, -EPERM); return 0; } + start_time = jiffies; + /* * what we "blindly" assume: */ @@ -1096,7 +1100,7 @@ int drbd_make_request_26(struct request_queue *q, struct bio *bio) if (likely(s_enr == e_enr)) { inc_ap_bio(mdev, 1); - return drbd_make_request_common(mdev, bio); + return drbd_make_request_common(mdev, bio, start_time); } /* can this bio be split generically? @@ -1138,10 +1142,10 @@ int drbd_make_request_26(struct request_queue *q, struct bio *bio) D_ASSERT(e_enr == s_enr + 1); - while (drbd_make_request_common(mdev, &bp->bio1)) + while (drbd_make_request_common(mdev, &bp->bio1, start_time)) inc_ap_bio(mdev, 1); - while (drbd_make_request_common(mdev, &bp->bio2)) + while (drbd_make_request_common(mdev, &bp->bio2, start_time)) inc_ap_bio(mdev, 1); dec_ap_bio(mdev); diff --git a/drivers/block/drbd/drbd_req.h b/drivers/block/drbd/drbd_req.h index 40d3dcd8fc815..077c47b1e9d78 100644 --- a/drivers/block/drbd/drbd_req.h +++ b/drivers/block/drbd/drbd_req.h @@ -291,7 +291,6 @@ static inline struct drbd_request *drbd_req_new(struct drbd_conf *mdev, req->epoch = 0; req->sector = bio_src->bi_sector; req->size = bio_src->bi_size; - req->start_time = jiffies; INIT_HLIST_NODE(&req->colision); INIT_LIST_HEAD(&req->tl_requests); INIT_LIST_HEAD(&req->w.list); -- GitLab From 127b317844e7cc0458743b604998bece95eab030 Mon Sep 17 00:00:00 2001 From: Philipp Reisner Date: Tue, 16 Nov 2010 10:07:53 +0100 Subject: [PATCH 0417/2822] drbd: use test_and_set_bit() to decide if bm_io_work should be queued Signed-off-by: Philipp Reisner Signed-off-by: Lars Ellenberg --- drivers/block/drbd/drbd_main.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/block/drbd/drbd_main.c b/drivers/block/drbd/drbd_main.c index f49505cf8d0f4..843b909669200 100644 --- a/drivers/block/drbd/drbd_main.c +++ b/drivers/block/drbd/drbd_main.c @@ -3772,6 +3772,7 @@ static int w_bitmap_io(struct drbd_conf *mdev, struct drbd_work *w, int unused) drbd_bm_unlock(mdev); clear_bit(BITMAP_IO, &mdev->flags); + smp_mb__after_clear_bit(); wake_up(&mdev->misc_wait); if (work->done) @@ -3850,11 +3851,8 @@ void drbd_queue_bitmap_io(struct drbd_conf *mdev, set_bit(BITMAP_IO, &mdev->flags); if (atomic_read(&mdev->ap_bio_cnt) == 0) { - if (list_empty(&mdev->bm_io_work.w.list)) { - set_bit(BITMAP_IO_QUEUED, &mdev->flags); + if (!test_and_set_bit(BITMAP_IO_QUEUED, &mdev->flags)) drbd_queue_work(&mdev->data.work, &mdev->bm_io_work.w); - } else - dev_err(DEV, "FIXME avoided double queuing bm_io_work\n"); } } -- GitLab From 8869d683b7491467fd39fcbe79756fce3e6f35e7 Mon Sep 17 00:00:00 2001 From: Philipp Reisner Date: Wed, 17 Nov 2010 18:24:19 +0100 Subject: [PATCH 0418/2822] drbd: Fixed inc_ap_bio() The condition must be checked after perpare_to_wait(). The old implementaion could loose wakeup events. Never observed in real life. Signed-off-by: Philipp Reisner Signed-off-by: Lars Ellenberg --- drivers/block/drbd/drbd_int.h | 31 ++++++++++++++----------------- 1 file changed, 14 insertions(+), 17 deletions(-) diff --git a/drivers/block/drbd/drbd_int.h b/drivers/block/drbd/drbd_int.h index 77ac6765fd576..9a944604939fb 100644 --- a/drivers/block/drbd/drbd_int.h +++ b/drivers/block/drbd/drbd_int.h @@ -2309,15 +2309,21 @@ static inline int __inc_ap_bio_cond(struct drbd_conf *mdev) return 1; } -/* I'd like to use wait_event_lock_irq, - * but I'm not sure when it got introduced, - * and not sure when it has 3 or 4 arguments */ -static inline void inc_ap_bio(struct drbd_conf *mdev, int count) +static inline int _inc_ap_bio_cond(struct drbd_conf *mdev, int count) { - /* compare with after_state_ch, - * os.conn != C_WF_BITMAP_S && ns.conn == C_WF_BITMAP_S */ - DEFINE_WAIT(wait); + int rv = 0; + + spin_lock_irq(&mdev->req_lock); + rv = __inc_ap_bio_cond(mdev); + if (rv) + atomic_add(count, &mdev->ap_bio_cnt); + spin_unlock_irq(&mdev->req_lock); + + return rv; +} +static inline void inc_ap_bio(struct drbd_conf *mdev, int count) +{ /* we wait here * as long as the device is suspended * until the bitmap is no longer on the fly during connection @@ -2326,16 +2332,7 @@ static inline void inc_ap_bio(struct drbd_conf *mdev, int count) * to avoid races with the reconnect code, * we need to atomic_inc within the spinlock. */ - spin_lock_irq(&mdev->req_lock); - while (!__inc_ap_bio_cond(mdev)) { - prepare_to_wait(&mdev->misc_wait, &wait, TASK_UNINTERRUPTIBLE); - spin_unlock_irq(&mdev->req_lock); - schedule(); - finish_wait(&mdev->misc_wait, &wait); - spin_lock_irq(&mdev->req_lock); - } - atomic_add(count, &mdev->ap_bio_cnt); - spin_unlock_irq(&mdev->req_lock); + wait_event(mdev->misc_wait, _inc_ap_bio_cond(mdev, count)); } static inline void dec_ap_bio(struct drbd_conf *mdev) -- GitLab From 22afd7ee94c1c5857323b677267ba8bace09bcef Mon Sep 17 00:00:00 2001 From: Philipp Reisner Date: Tue, 16 Nov 2010 15:30:44 +0100 Subject: [PATCH 0419/2822] drbd: Fixed race condition in drbd_queue_bitmap_io May only test for ap_bio_cnt == 0 under req_lock. It can increase only under req_lock. Signed-off-by: Philipp Reisner Signed-off-by: Lars Ellenberg --- drivers/block/drbd/drbd_main.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/block/drbd/drbd_main.c b/drivers/block/drbd/drbd_main.c index 843b909669200..975dc5a665499 100644 --- a/drivers/block/drbd/drbd_main.c +++ b/drivers/block/drbd/drbd_main.c @@ -3849,11 +3849,13 @@ void drbd_queue_bitmap_io(struct drbd_conf *mdev, mdev->bm_io_work.done = done; mdev->bm_io_work.why = why; + spin_lock_irq(&mdev->req_lock); set_bit(BITMAP_IO, &mdev->flags); if (atomic_read(&mdev->ap_bio_cnt) == 0) { if (!test_and_set_bit(BITMAP_IO_QUEUED, &mdev->flags)) drbd_queue_work(&mdev->data.work, &mdev->bm_io_work.w); } + spin_unlock_irq(&mdev->req_lock); } /** -- GitLab From ab17b68f4579b460753a416b0afc4446381d876f Mon Sep 17 00:00:00 2001 From: Philipp Reisner Date: Wed, 17 Nov 2010 16:54:36 +0100 Subject: [PATCH 0420/2822] drbd: Improvements in sanitize_state() The relevant change is that the state change to C_FW_BITMAP_S should implicitly change pdsk to C_CONSISTENT. (Think of it as C_OUTDATED, only without the guarantee that the peer has the outdated written to its meta data) At that opportunity I restructured the switch statement so that it gets evaluated every time. (Has declarative character) Signed-off-by: Philipp Reisner Signed-off-by: Lars Ellenberg --- drivers/block/drbd/drbd_main.c | 144 ++++++++++++++++++++------------- 1 file changed, 89 insertions(+), 55 deletions(-) diff --git a/drivers/block/drbd/drbd_main.c b/drivers/block/drbd/drbd_main.c index 975dc5a665499..74a6d55259af6 100644 --- a/drivers/block/drbd/drbd_main.c +++ b/drivers/block/drbd/drbd_main.c @@ -817,6 +817,7 @@ static union drbd_state sanitize_state(struct drbd_conf *mdev, union drbd_state union drbd_state ns, const char **warn_sync_abort) { enum drbd_fencing_p fp; + enum drbd_disk_state disk_min, disk_max, pdsk_min, pdsk_max; fp = FP_DONT_CARE; if (get_ldev(mdev)) { @@ -869,61 +870,6 @@ static union drbd_state sanitize_state(struct drbd_conf *mdev, union drbd_state ns.conn = C_CONNECTED; } - if (ns.conn >= C_CONNECTED && - ((ns.disk == D_CONSISTENT || ns.disk == D_OUTDATED) || - (ns.disk == D_NEGOTIATING && ns.conn == C_WF_BITMAP_T) || - ns.conn >= C_AHEAD)) { - switch (ns.conn) { - case C_WF_BITMAP_T: - case C_PAUSED_SYNC_T: - case C_BEHIND: - ns.disk = D_OUTDATED; - break; - case C_CONNECTED: - case C_WF_BITMAP_S: - case C_SYNC_SOURCE: - case C_PAUSED_SYNC_S: - case C_AHEAD: - ns.disk = D_UP_TO_DATE; - break; - case C_SYNC_TARGET: - ns.disk = D_INCONSISTENT; - dev_warn(DEV, "Implicitly set disk state Inconsistent!\n"); - break; - } - if (os.disk == D_OUTDATED && ns.disk == D_UP_TO_DATE) - dev_warn(DEV, "Implicitly set disk from Outdated to UpToDate\n"); - } - - if (ns.conn >= C_CONNECTED && - (ns.pdsk == D_CONSISTENT || ns.pdsk == D_OUTDATED || ns.conn >= C_AHEAD)) { - switch (ns.conn) { - case C_CONNECTED: - case C_WF_BITMAP_T: - case C_PAUSED_SYNC_T: - case C_SYNC_TARGET: - case C_BEHIND: - ns.pdsk = D_UP_TO_DATE; - break; - case C_WF_BITMAP_S: - case C_PAUSED_SYNC_S: - case C_AHEAD: - /* remap any consistent state to D_OUTDATED, - * but disallow "upgrade" of not even consistent states. - */ - ns.pdsk = - (D_DISKLESS < os.pdsk && os.pdsk < D_OUTDATED) - ? os.pdsk : D_OUTDATED; - break; - case C_SYNC_SOURCE: - ns.pdsk = D_INCONSISTENT; - dev_warn(DEV, "Implicitly set pdsk Inconsistent!\n"); - break; - } - if (os.pdsk == D_OUTDATED && ns.pdsk == D_UP_TO_DATE) - dev_warn(DEV, "Implicitly set pdsk from Outdated to UpToDate\n"); - } - /* Connection breaks down before we finished "Negotiating" */ if (ns.conn < C_CONNECTED && ns.disk == D_NEGOTIATING && get_ldev_if_state(mdev, D_NEGOTIATING)) { @@ -938,6 +884,94 @@ static union drbd_state sanitize_state(struct drbd_conf *mdev, union drbd_state put_ldev(mdev); } + /* D_CONSISTENT and D_OUTDATED vanish when we get connected */ + if (ns.conn >= C_CONNECTED && ns.conn < C_AHEAD) { + if (ns.disk == D_CONSISTENT || ns.disk == D_OUTDATED) + ns.disk = D_UP_TO_DATE; + if (ns.pdsk == D_CONSISTENT || ns.pdsk == D_OUTDATED) + ns.pdsk = D_UP_TO_DATE; + } + + /* Implications of the connection stat on the disk states */ + disk_min = D_DISKLESS; + disk_max = D_UP_TO_DATE; + pdsk_min = D_INCONSISTENT; + pdsk_max = D_UNKNOWN; + switch ((enum drbd_conns)ns.conn) { + case C_WF_BITMAP_T: + case C_PAUSED_SYNC_T: + case C_STARTING_SYNC_T: + case C_WF_SYNC_UUID: + case C_BEHIND: + disk_min = D_INCONSISTENT; + disk_max = D_OUTDATED; + pdsk_min = D_UP_TO_DATE; + pdsk_max = D_UP_TO_DATE; + break; + case C_VERIFY_S: + case C_VERIFY_T: + disk_min = D_UP_TO_DATE; + disk_max = D_UP_TO_DATE; + pdsk_min = D_UP_TO_DATE; + pdsk_max = D_UP_TO_DATE; + break; + case C_CONNECTED: + disk_min = D_DISKLESS; + disk_max = D_UP_TO_DATE; + pdsk_min = D_DISKLESS; + pdsk_max = D_UP_TO_DATE; + break; + case C_WF_BITMAP_S: + case C_PAUSED_SYNC_S: + case C_STARTING_SYNC_S: + case C_AHEAD: + disk_min = D_UP_TO_DATE; + disk_max = D_UP_TO_DATE; + pdsk_min = D_INCONSISTENT; + pdsk_max = D_CONSISTENT; /* D_OUTDATED would be nice. But explicit outdate necessary*/ + break; + case C_SYNC_TARGET: + disk_min = D_INCONSISTENT; + disk_max = D_INCONSISTENT; + pdsk_min = D_UP_TO_DATE; + pdsk_max = D_UP_TO_DATE; + break; + case C_SYNC_SOURCE: + disk_min = D_UP_TO_DATE; + disk_max = D_UP_TO_DATE; + pdsk_min = D_INCONSISTENT; + pdsk_max = D_INCONSISTENT; + break; + case C_STANDALONE: + case C_DISCONNECTING: + case C_UNCONNECTED: + case C_TIMEOUT: + case C_BROKEN_PIPE: + case C_NETWORK_FAILURE: + case C_PROTOCOL_ERROR: + case C_TEAR_DOWN: + case C_WF_CONNECTION: + case C_WF_REPORT_PARAMS: + case C_MASK: + break; + } + if (ns.disk > disk_max) + ns.disk = disk_max; + + if (ns.disk < disk_min) { + dev_warn(DEV, "Implicitly set disk from %s to %s\n", + drbd_disk_str(ns.disk), drbd_disk_str(disk_min)); + ns.disk = disk_min; + } + if (ns.pdsk > pdsk_max) + ns.pdsk = pdsk_max; + + if (ns.pdsk < pdsk_min) { + dev_warn(DEV, "Implicitly set pdsk from %s to %s\n", + drbd_disk_str(ns.pdsk), drbd_disk_str(pdsk_min)); + ns.pdsk = pdsk_min; + } + if (fp == FP_STONITH && (ns.role == R_PRIMARY && ns.conn < C_CONNECTED && ns.pdsk > D_OUTDATED) && !(os.role == R_PRIMARY && os.conn < C_CONNECTED && os.pdsk > D_OUTDATED)) -- GitLab From 3719094ec2dec411b3151f10048316d787e086f9 Mon Sep 17 00:00:00 2001 From: Philipp Reisner Date: Wed, 10 Nov 2010 12:08:37 +0100 Subject: [PATCH 0421/2822] drbd: Starting with protocol 96 we can allow app-IO while receiving the bitmap * C_STARTING_SYNC_S, C_STARTING_SYNC_T In these states the bitmap gets written to disk. Locking out of app-IO is done by using the drbd_queue_bitmap_io() and drbd_bitmap_io() functions these days. It is no longer necessary to lock out app-IO based on the connection state. App-IO that may come in after the BITMAP_IO flag got cleared before the state transition to C_SYNC_(SOURCE|TARGET) does not get mirrored, sets a bit in the local bitmap, that is already set, therefore changes nothing. * C_WF_BITMAP_S In this state we send updates (P_OUT_OF_SYNC packets). With that we make sure they have the same number of bits when going into the C_SYNC_(SOURCE|TARGET) connection state. * C_UNCONNECTED: The receiver starts, no need to lock out IO. * C_DISCONNECTING: in drbd_disconnect() we had a wait_event() to wait until ap_bio_cnt reaches 0. Removed that. * C_TIMEOUT, C_BROKEN_PIPE, C_NETWORK_FAILURE C_PROTOCOL_ERROR, C_TEAR_DOWN: Same as C_DISCONNECTING * C_WF_REPORT_PARAMS: IO still possible since that is still like C_WF_CONNECTION. And we do not need to send barriers in C_WF_BITMAP_S connection state. Allow concurrent accesses to the bitmap when receiving the bitmap. Everything gets ORed anyways. A drbd_free_tl_hash() is in after_state_chg_work(). At that point all the work items of the last connections must have been processed. Introduced a call to drbd_free_tl_hash() into drbd_free_mdev() for paranoia reasons. Signed-off-by: Philipp Reisner Signed-off-by: Lars Ellenberg --- drivers/block/drbd/drbd_int.h | 19 +++++++++------ drivers/block/drbd/drbd_main.c | 1 + drivers/block/drbd/drbd_receiver.c | 13 ++--------- drivers/block/drbd/drbd_req.c | 37 +++++++++++++++++++----------- 4 files changed, 39 insertions(+), 31 deletions(-) diff --git a/drivers/block/drbd/drbd_int.h b/drivers/block/drbd/drbd_int.h index 9a944604939fb..38bbaba8bd895 100644 --- a/drivers/block/drbd/drbd_int.h +++ b/drivers/block/drbd/drbd_int.h @@ -2213,8 +2213,9 @@ static inline int drbd_get_max_buffers(struct drbd_conf *mdev) return mxb; } -static inline int drbd_state_is_stable(union drbd_state s) +static inline int drbd_state_is_stable(struct drbd_conf *mdev) { + union drbd_state s = mdev->state; /* DO NOT add a default clause, we want the compiler to warn us * for any newly introduced state we may have forgotten to add here */ @@ -2233,11 +2234,7 @@ static inline int drbd_state_is_stable(union drbd_state s) case C_PAUSED_SYNC_T: case C_AHEAD: case C_BEHIND: - /* maybe stable, look at the disk state */ - break; - - /* no new io accepted during tansitional states - * like handshake or teardown */ + /* transitional states, IO allowed */ case C_DISCONNECTING: case C_UNCONNECTED: case C_TIMEOUT: @@ -2248,7 +2245,15 @@ static inline int drbd_state_is_stable(union drbd_state s) case C_WF_REPORT_PARAMS: case C_STARTING_SYNC_S: case C_STARTING_SYNC_T: + break; + + /* Allow IO in BM exchange states with new protocols */ case C_WF_BITMAP_S: + if (mdev->agreed_pro_version < 96) + return 0; + break; + + /* no new io accepted in these states */ case C_WF_BITMAP_T: case C_WF_SYNC_UUID: case C_MASK: @@ -2297,7 +2302,7 @@ static inline int __inc_ap_bio_cond(struct drbd_conf *mdev) * to start during "stable" states. */ /* no new io accepted when attaching or detaching the disk */ - if (!drbd_state_is_stable(mdev->state)) + if (!drbd_state_is_stable(mdev)) return 0; /* since some older kernels don't have atomic_add_unless, diff --git a/drivers/block/drbd/drbd_main.c b/drivers/block/drbd/drbd_main.c index 74a6d55259af6..14afbd4e53a5c 100644 --- a/drivers/block/drbd/drbd_main.c +++ b/drivers/block/drbd/drbd_main.c @@ -3334,6 +3334,7 @@ void drbd_free_mdev(struct drbd_conf *mdev) put_disk(mdev->vdisk); blk_cleanup_queue(mdev->rq_queue); free_cpumask_var(mdev->cpu_mask); + drbd_free_tl_hash(mdev); kfree(mdev); } diff --git a/drivers/block/drbd/drbd_receiver.c b/drivers/block/drbd/drbd_receiver.c index 0630a2e122d33..f4aba9f894ba5 100644 --- a/drivers/block/drbd/drbd_receiver.c +++ b/drivers/block/drbd/drbd_receiver.c @@ -3468,9 +3468,7 @@ static int receive_bitmap(struct drbd_conf *mdev, enum drbd_packets cmd, unsigne int ok = FALSE; struct p_header80 *h = &mdev->data.rbuf.header.h80; - wait_event(mdev->misc_wait, !atomic_read(&mdev->ap_bio_cnt)); - - drbd_bm_lock(mdev, "receive bitmap"); + /* drbd_bm_lock(mdev, "receive bitmap"); By intention no bm_lock */ /* maybe we should use some per thread scratch page, * and allocate that during initial device creation? */ @@ -3542,7 +3540,7 @@ static int receive_bitmap(struct drbd_conf *mdev, enum drbd_packets cmd, unsigne ok = TRUE; out: - drbd_bm_unlock(mdev); + /* drbd_bm_unlock(mdev); by intention no lock */ if (ok && mdev->state.conn == C_WF_BITMAP_S) drbd_start_resync(mdev, C_SYNC_SOURCE); free_page((unsigned long) buffer); @@ -3804,13 +3802,6 @@ static void drbd_disconnect(struct drbd_conf *mdev) if (os.conn == C_DISCONNECTING) { wait_event(mdev->net_cnt_wait, atomic_read(&mdev->net_cnt) == 0); - if (!is_susp(mdev->state)) { - /* we must not free the tl_hash - * while application io is still on the fly */ - wait_event(mdev->misc_wait, !atomic_read(&mdev->ap_bio_cnt)); - drbd_free_tl_hash(mdev); - } - crypto_free_hash(mdev->cram_hmac_tfm); mdev->cram_hmac_tfm = NULL; diff --git a/drivers/block/drbd/drbd_req.c b/drivers/block/drbd/drbd_req.c index eff0fbf69dd42..4cb8247d83c91 100644 --- a/drivers/block/drbd/drbd_req.c +++ b/drivers/block/drbd/drbd_req.c @@ -142,7 +142,7 @@ static void _about_to_complete_local_write(struct drbd_conf *mdev, /* before we can signal completion to the upper layers, * we may need to close the current epoch */ - if (mdev->state.conn >= C_CONNECTED && mdev->state.conn < C_AHEAD && + if (mdev->state.conn >= C_WF_BITMAP_T && mdev->state.conn < C_AHEAD && req->epoch == mdev->newest_tle->br_number) queue_barrier(mdev); @@ -757,6 +757,23 @@ static int drbd_may_do_local_read(struct drbd_conf *mdev, sector_t sector, int s return 0 == drbd_bm_count_bits(mdev, sbnr, ebnr); } +static int drbd_should_do_remote(struct drbd_conf *mdev) +{ + union drbd_state s = mdev->state; + + return s.pdsk == D_UP_TO_DATE || + (s.pdsk >= D_INCONSISTENT && + s.conn >= C_WF_BITMAP_T && + s.conn < C_AHEAD); +} +static int drbd_should_send_oos(struct drbd_conf *mdev) +{ + union drbd_state s = mdev->state; + + return s.pdsk >= D_INCONSISTENT && + (s.conn == C_AHEAD || s.conn == C_WF_BITMAP_S); +} + static int drbd_make_request_common(struct drbd_conf *mdev, struct bio *bio, unsigned long start_time) { const int rw = bio_rw(bio); @@ -828,12 +845,9 @@ static int drbd_make_request_common(struct drbd_conf *mdev, struct bio *bio, uns drbd_al_begin_io(mdev, sector); } - remote = remote && (mdev->state.pdsk == D_UP_TO_DATE || - (mdev->state.pdsk >= D_INCONSISTENT && - mdev->state.conn >= C_CONNECTED && - mdev->state.conn < C_AHEAD)); - send_oos = (rw == WRITE && mdev->state.conn == C_AHEAD && - mdev->state.pdsk >= D_INCONSISTENT); + remote = remote && drbd_should_do_remote(mdev); + send_oos = rw == WRITE && drbd_should_send_oos(mdev); + D_ASSERT(!(remote && send_oos)); if (!(local || remote) && !is_susp(mdev->state)) { if (__ratelimit(&drbd_ratelimit_state)) @@ -873,12 +887,9 @@ allocate_barrier: } if (remote || send_oos) { - remote = (mdev->state.pdsk == D_UP_TO_DATE || - (mdev->state.pdsk >= D_INCONSISTENT && - mdev->state.conn >= C_CONNECTED && - mdev->state.conn < C_AHEAD)); - send_oos = (rw == WRITE && mdev->state.conn == C_AHEAD && - mdev->state.pdsk >= D_INCONSISTENT); + remote = drbd_should_do_remote(mdev); + send_oos = rw == WRITE && drbd_should_send_oos(mdev); + D_ASSERT(!(remote && send_oos)); if (!(remote || send_oos)) dev_warn(DEV, "lost connection while grabbing the req_lock!\n"); -- GitLab From 1fc80cf37810d6b00cac27a219b8ecab2010adac Mon Sep 17 00:00:00 2001 From: Philipp Reisner Date: Mon, 22 Nov 2010 14:18:47 +0100 Subject: [PATCH 0422/2822] drbd: Becoming sync target may not happen out of < C_WF_REPORT_PARAMS This patch is acutally a necessary addendum to the patch "fix for spurious full sync (becoming sync target looked like invalidate)" Signed-off-by: Philipp Reisner Signed-off-by: Lars Ellenberg --- drivers/block/drbd/drbd_main.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/block/drbd/drbd_main.c b/drivers/block/drbd/drbd_main.c index 14afbd4e53a5c..8b8a38dc6492f 100644 --- a/drivers/block/drbd/drbd_main.c +++ b/drivers/block/drbd/drbd_main.c @@ -800,6 +800,10 @@ static int is_valid_state_transition(struct drbd_conf *mdev, os.conn < C_CONNECTED) rv = SS_NEED_CONNECTION; + if ((ns.conn == C_SYNC_TARGET || ns.conn == C_SYNC_SOURCE) + && os.conn < C_WF_REPORT_PARAMS) + rv = SS_NEED_CONNECTION; /* No NetworkFailure -> SyncTarget etc... */ + return rv; } -- GitLab From c507f46f26661d4d0dc95a1b1271df5855ab4602 Mon Sep 17 00:00:00 2001 From: Philipp Reisner Date: Mon, 22 Nov 2010 15:49:17 +0100 Subject: [PATCH 0423/2822] drbd: Removed 20 seconds upper bound for side-stepping Given low-enough network bandwidth combined with a IO pattern that hammers onto a single RS-extent, side-stepping might be necessary for much longer times. Changed the code to print a single informal message after 20 seconds, but it keeps on stepping aside forever. Signed-off-by: Philipp Reisner Signed-off-by: Lars Ellenberg --- drivers/block/drbd/drbd_actlog.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/block/drbd/drbd_actlog.c b/drivers/block/drbd/drbd_actlog.c index 5570d9bdc863d..4a1b199f4ae72 100644 --- a/drivers/block/drbd/drbd_actlog.c +++ b/drivers/block/drbd/drbd_actlog.c @@ -1153,7 +1153,7 @@ retry: for (i = 0; i < AL_EXT_PER_BM_SECT; i++) { sig = wait_event_interruptible(mdev->al_wait, !_is_in_al(mdev, enr * AL_EXT_PER_BM_SECT + i) || - (test_bit(BME_PRIORITY, &bm_ext->flags) && sa)); + test_bit(BME_PRIORITY, &bm_ext->flags)); if (sig || (test_bit(BME_PRIORITY, &bm_ext->flags) && sa)) { spin_lock_irq(&mdev->al_lock); @@ -1167,8 +1167,9 @@ retry: return -EINTR; if (schedule_timeout_interruptible(HZ/10)) return -EINTR; - if (--sa == 0) - dev_warn(DEV,"drbd_rs_begin_io() no longer stepping aside.\n"); + if (sa && --sa == 0) + dev_warn(DEV,"drbd_rs_begin_io() stepped aside for 20sec." + "Resync stalled?\n"); goto retry; } } -- GitLab From 3da127fa887e5187ede702b835770634d705f8b2 Mon Sep 17 00:00:00 2001 From: Lars Ellenberg Date: Wed, 24 Nov 2010 10:33:02 +0100 Subject: [PATCH 0424/2822] drbd: increase module count on /proc/drbd access If someone holds /proc/drbd open, previously rmmod would "succeed" in starting the unload, but then block on remove_proc_entry, leading to a situation where the lsmod does not show drbd anymore, but /proc/drbd being still there (but no longer accessible). I'd rather have rmmod fail up front in this case. Signed-off-by: Philipp Reisner Signed-off-by: Lars Ellenberg --- drivers/block/drbd/drbd_proc.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/drivers/block/drbd/drbd_proc.c b/drivers/block/drbd/drbd_proc.c index 49d817cfe865b..efba62cd2e582 100644 --- a/drivers/block/drbd/drbd_proc.c +++ b/drivers/block/drbd/drbd_proc.c @@ -34,6 +34,7 @@ #include "drbd_int.h" static int drbd_proc_open(struct inode *inode, struct file *file); +static int drbd_proc_release(struct inode *inode, struct file *file); struct proc_dir_entry *drbd_proc; @@ -42,7 +43,7 @@ const struct file_operations drbd_proc_fops = { .open = drbd_proc_open, .read = seq_read, .llseek = seq_lseek, - .release = single_release, + .release = drbd_proc_release, }; void seq_printf_with_thousands_grouping(struct seq_file *seq, long v) @@ -304,7 +305,15 @@ static int drbd_seq_show(struct seq_file *seq, void *v) static int drbd_proc_open(struct inode *inode, struct file *file) { - return single_open(file, drbd_seq_show, PDE(inode)->data); + if (try_module_get(THIS_MODULE)) + return single_open(file, drbd_seq_show, PDE(inode)->data); + return -ENODEV; +} + +static int drbd_proc_release(struct inode *inode, struct file *file) +{ + module_put(THIS_MODULE); + return single_release(inode, file); } /* PROC FS stuff end */ -- GitLab From 17a93f3007c13003c739a19d0814cb5c2d21daba Mon Sep 17 00:00:00 2001 From: Lars Ellenberg Date: Wed, 24 Nov 2010 10:37:35 +0100 Subject: [PATCH 0425/2822] drbd: remove /proc/drbd before unregistering from netlink There still exists a (theoretical) race on module unload, where /proc/drbd may still exist, but the netlink callback has been unregistered already, allowing drbdsetup to shout without listeners, and get no reply. Reorder remove_proc_entry and unregister of netlink callback. drbdsetup first checks for existence of the proc entry, and if that is missing, won't even try to contact the module. Signed-off-by: Philipp Reisner Signed-off-by: Lars Ellenberg --- drivers/block/drbd/drbd_main.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/drivers/block/drbd/drbd_main.c b/drivers/block/drbd/drbd_main.c index 8b8a38dc6492f..150ed16d26efa 100644 --- a/drivers/block/drbd/drbd_main.c +++ b/drivers/block/drbd/drbd_main.c @@ -3174,11 +3174,20 @@ static void drbd_cleanup(void) unregister_reboot_notifier(&drbd_notifier); + /* first remove proc, + * drbdsetup uses it's presence to detect + * whether DRBD is loaded. + * If we would get stuck in proc removal, + * but have netlink already deregistered, + * some drbdsetup commands may wait forever + * for an answer. + */ + if (drbd_proc) + remove_proc_entry("drbd", NULL); + drbd_nl_cleanup(); if (minor_table) { - if (drbd_proc) - remove_proc_entry("drbd", NULL); i = minor_count; while (i--) drbd_delete_device(i); -- GitLab From 3e3a7766c2e6995ac98e7855017abc3544d54e08 Mon Sep 17 00:00:00 2001 From: Lars Ellenberg Date: Wed, 24 Nov 2010 10:41:45 +0100 Subject: [PATCH 0426/2822] drbd: use kzalloc and memset(,0,) to start with clean buffers in drbd_nl Make sure we start with clean buffers to not accidentally send garbage back to userspace. Note: has not been observed; but just in case. Signed-off-by: Philipp Reisner Signed-off-by: Lars Ellenberg --- drivers/block/drbd/drbd_nl.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/block/drbd/drbd_nl.c b/drivers/block/drbd/drbd_nl.c index f969d8717e235..80a389d24cdd4 100644 --- a/drivers/block/drbd/drbd_nl.c +++ b/drivers/block/drbd/drbd_nl.c @@ -2211,7 +2211,7 @@ static void drbd_connector_callback(struct cn_msg *req, struct netlink_skb_parms reply_size += cm->reply_body_size; /* allocation not in the IO path, cqueue thread context */ - cn_reply = kmalloc(reply_size, GFP_KERNEL); + cn_reply = kzalloc(reply_size, GFP_KERNEL); if (!cn_reply) { retcode = ERR_NOMEM; goto fail; @@ -2382,7 +2382,7 @@ void drbd_bcast_ee(struct drbd_conf *mdev, /* receiver thread context, which is not in the writeout path (of this node), * but may be in the writeout path of the _other_ node. * GFP_NOIO to avoid potential "distributed deadlock". */ - cn_reply = kmalloc( + cn_reply = kzalloc( sizeof(struct cn_msg)+ sizeof(struct drbd_nl_cfg_reply)+ sizeof(struct dump_ee_tag_len_struct)+ @@ -2517,6 +2517,7 @@ void drbd_nl_send_reply(struct cn_msg *req, int ret_code) (struct drbd_nl_cfg_reply *)cn_reply->data; int rr; + memset(buffer, 0, sizeof(buffer)); cn_reply->id = req->id; cn_reply->seq = req->seq; -- GitLab From 42ff269d1022a86be4f526cf674998c47b7ab856 Mon Sep 17 00:00:00 2001 From: Lars Ellenberg Date: Wed, 24 Nov 2010 10:11:14 +0100 Subject: [PATCH 0427/2822] drbd: add packet_type 27 (return_code_only) to netlink api In case we ever should add an other packet type, we must not reuse 27, as that currently used for "empty" return code only replies. Document it as such. Signed-off-by: Philipp Reisner Signed-off-by: Lars Ellenberg --- drivers/block/drbd/drbd_nl.c | 6 ++++-- include/linux/drbd_nl.h | 6 +++++- include/linux/drbd_tag_magic.h | 1 + 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/drivers/block/drbd/drbd_nl.c b/drivers/block/drbd/drbd_nl.c index 80a389d24cdd4..6a6dde6c51c60 100644 --- a/drivers/block/drbd/drbd_nl.c +++ b/drivers/block/drbd/drbd_nl.c @@ -2195,7 +2195,8 @@ static void drbd_connector_callback(struct cn_msg *req, struct netlink_skb_parms goto fail; } - if (nlp->packet_type >= P_nl_after_last_packet) { + if (nlp->packet_type >= P_nl_after_last_packet || + nlp->packet_type == P_return_code_only) { retcode = ERR_PACKET_NR; goto fail; } @@ -2219,7 +2220,7 @@ static void drbd_connector_callback(struct cn_msg *req, struct netlink_skb_parms reply = (struct drbd_nl_cfg_reply *) cn_reply->data; reply->packet_type = - cm->reply_body_size ? nlp->packet_type : P_nl_after_last_packet; + cm->reply_body_size ? nlp->packet_type : P_return_code_only; reply->minor = nlp->drbd_minor; reply->ret_code = NO_ERROR; /* Might by modified by cm->function. */ /* reply->tag_list; might be modified by cm->function. */ @@ -2525,6 +2526,7 @@ void drbd_nl_send_reply(struct cn_msg *req, int ret_code) cn_reply->len = sizeof(struct drbd_nl_cfg_reply); cn_reply->flags = 0; + reply->packet_type = P_return_code_only; reply->minor = ((struct drbd_nl_cfg_req *)req->data)->drbd_minor; reply->ret_code = ret_code; diff --git a/include/linux/drbd_nl.h b/include/linux/drbd_nl.h index 8cde3945d1f7d..6fc614b06c4dc 100644 --- a/include/linux/drbd_nl.h +++ b/include/linux/drbd_nl.h @@ -146,9 +146,13 @@ NL_PACKET(new_c_uuid, 26, NL_BIT( 63, T_MANDATORY, clear_bm) ) +#ifdef NL_RESPONSE +NL_RESPONSE(return_code_only, 27) +#endif + #undef NL_PACKET #undef NL_INTEGER #undef NL_INT64 #undef NL_BIT #undef NL_STRING - +#undef NL_RESPONSE diff --git a/include/linux/drbd_tag_magic.h b/include/linux/drbd_tag_magic.h index fcdff8410e99d..f14a165e82dc1 100644 --- a/include/linux/drbd_tag_magic.h +++ b/include/linux/drbd_tag_magic.h @@ -7,6 +7,7 @@ /* declare packet_type enums */ enum packet_types { #define NL_PACKET(name, number, fields) P_ ## name = number, +#define NL_RESPONSE(name, number) P_ ## name = number, #define NL_INTEGER(pn, pr, member) #define NL_INT64(pn, pr, member) #define NL_BIT(pn, pr, member) -- GitLab From 2561b9c1f1d63077c41903fc6ad58dc9ec47248b Mon Sep 17 00:00:00 2001 From: Philipp Reisner Date: Fri, 3 Dec 2010 15:22:48 +0100 Subject: [PATCH 0428/2822] drbd: --force option for disconnect As the network connection can be lost at any time, a --force option for disconnect is just a matter of completeness. Signed-off-by: Philipp Reisner Signed-off-by: Lars Ellenberg --- drivers/block/drbd/drbd_nl.c | 15 +++++++++++++++ include/linux/drbd_nl.h | 4 +++- 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/drivers/block/drbd/drbd_nl.c b/drivers/block/drbd/drbd_nl.c index 6a6dde6c51c60..cd0459f0403fb 100644 --- a/drivers/block/drbd/drbd_nl.c +++ b/drivers/block/drbd/drbd_nl.c @@ -1531,6 +1531,21 @@ static int drbd_nl_disconnect(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nl struct drbd_nl_cfg_reply *reply) { int retcode; + struct disconnect dc; + + memset(&dc, 0, sizeof(struct disconnect)); + if (!disconnect_from_tags(mdev, nlp->tag_list, &dc)) { + retcode = ERR_MANDATORY_TAG; + goto fail; + } + + if (dc.force) { + spin_lock_irq(&mdev->req_lock); + if (mdev->state.conn >= C_WF_CONNECTION) + _drbd_set_state(_NS(mdev, conn, C_DISCONNECTING), CS_HARD, NULL); + spin_unlock_irq(&mdev->req_lock); + goto done; + } retcode = _drbd_request_state(mdev, NS(conn, C_DISCONNECTING), CS_ORDERED); diff --git a/include/linux/drbd_nl.h b/include/linux/drbd_nl.h index 6fc614b06c4dc..ab6159e4fcf0c 100644 --- a/include/linux/drbd_nl.h +++ b/include/linux/drbd_nl.h @@ -69,7 +69,9 @@ NL_PACKET(net_conf, 5, NL_BIT( 70, T_MANDATORY, dry_run) ) -NL_PACKET(disconnect, 6, ) +NL_PACKET(disconnect, 6, + NL_BIT( 84, T_MAY_IGNORE, force) +) NL_PACKET(resize, 7, NL_INT64( 29, T_MAY_IGNORE, resize_size) -- GitLab From 09b9e7979378fe070784de20e50bb1d42aa643ab Mon Sep 17 00:00:00 2001 From: Philipp Reisner Date: Fri, 3 Dec 2010 16:04:24 +0100 Subject: [PATCH 0429/2822] drbd: Implemented the before-resync-source handler Signed-off-by: Philipp Reisner Signed-off-by: Lars Ellenberg --- drivers/block/drbd/drbd_worker.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/drivers/block/drbd/drbd_worker.c b/drivers/block/drbd/drbd_worker.c index ab5cff502f5b5..e201f6f82c0ee 100644 --- a/drivers/block/drbd/drbd_worker.c +++ b/drivers/block/drbd/drbd_worker.c @@ -1499,6 +1499,20 @@ void drbd_start_resync(struct drbd_conf *mdev, enum drbd_conns side) drbd_force_state(mdev, NS(conn, C_DISCONNECTING)); return; } + } else /* C_SYNC_SOURCE */ { + r = drbd_khelper(mdev, "before-resync-source"); + r = (r >> 8) & 0xff; + if (r > 0) { + if (r == 3) { + dev_info(DEV, "before-resync-source handler returned %d, " + "ignoring. Old userland tools?", r); + } else { + dev_info(DEV, "before-resync-source handler returned %d, " + "dropping connection.\n", r); + drbd_force_state(mdev, NS(conn, C_DISCONNECTING)); + return; + } + } } drbd_state_lock(mdev); -- GitLab From 8a3c104438be4986a77f332009b695fcac48f620 Mon Sep 17 00:00:00 2001 From: Lars Ellenberg Date: Sun, 5 Dec 2010 14:11:14 +0100 Subject: [PATCH 0430/2822] drbd: fix regression, we need to close drbd epochs during normal operation commit e2041475e6ddb081734d161f6421977323f5a9b9 drbd: Starting with protocol 96 we can allow app-IO while receiving the bitmap Contained a bad chunk that tried to optimize away drbd barriers during bitmap exchange, but accidentally dropped them for normal mode as well. Impact: depending on activity log size and access pattern, activity log extents may not be recycled in time, causeing IO to block indefinetely. Fix: skip drbd barriers only if there is no connection to send them on, or the request being completed has not been on the network at all. Signed-off-by: Philipp Reisner Signed-off-by: Lars Ellenberg --- drivers/block/drbd/drbd_req.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/drivers/block/drbd/drbd_req.c b/drivers/block/drbd/drbd_req.c index 4cb8247d83c91..de5fe70f2b420 100644 --- a/drivers/block/drbd/drbd_req.c +++ b/drivers/block/drbd/drbd_req.c @@ -140,9 +140,14 @@ static void _about_to_complete_local_write(struct drbd_conf *mdev, struct hlist_node *n; struct hlist_head *slot; - /* before we can signal completion to the upper layers, - * we may need to close the current epoch */ - if (mdev->state.conn >= C_WF_BITMAP_T && mdev->state.conn < C_AHEAD && + /* Before we can signal completion to the upper layers, + * we may need to close the current epoch. + * We can skip this, if this request has not even been sent, because we + * did not have a fully established connection yet/anymore, during + * bitmap exchange, or while we are C_AHEAD due to congestion policy. + */ + if (mdev->state.conn >= C_CONNECTED && + (s & RQ_NET_SENT) != 0 && req->epoch == mdev->newest_tle->br_number) queue_barrier(mdev); -- GitLab From 7e458c32da946bd4f6aea476b61b79575578f834 Mon Sep 17 00:00:00 2001 From: Andreas Gruenbacher Date: Wed, 8 Dec 2010 19:02:09 +0100 Subject: [PATCH 0431/2822] drbd: Removed an unnecessary #undef Signed-off-by: Philipp Reisner Signed-off-by: Lars Ellenberg --- drivers/block/drbd/drbd_receiver.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/block/drbd/drbd_receiver.c b/drivers/block/drbd/drbd_receiver.c index f4aba9f894ba5..f8cd3f230d847 100644 --- a/drivers/block/drbd/drbd_receiver.c +++ b/drivers/block/drbd/drbd_receiver.c @@ -2963,7 +2963,6 @@ static int receive_sizes(struct drbd_conf *mdev, enum drbd_packets cmd, unsigned } put_ldev(mdev); } -#undef min_not_zero ddsf = be16_to_cpu(p->dds_flags); if (get_ldev(mdev)) { -- GitLab From 220df4d006ed561b8fd4fbd8c01c6c28d6143653 Mon Sep 17 00:00:00 2001 From: Lars Ellenberg Date: Thu, 9 Dec 2010 15:21:02 +0100 Subject: [PATCH 0432/2822] drbd: fix incomplete error message Signed-off-by: Philipp Reisner Signed-off-by: Lars Ellenberg --- drivers/block/drbd/drbd_receiver.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/block/drbd/drbd_receiver.c b/drivers/block/drbd/drbd_receiver.c index f8cd3f230d847..55fee1a6c647c 100644 --- a/drivers/block/drbd/drbd_receiver.c +++ b/drivers/block/drbd/drbd_receiver.c @@ -2499,7 +2499,7 @@ static enum drbd_conns drbd_sync_handshake(struct drbd_conf *mdev, enum drbd_rol return C_MASK; } if (hg == -1001) { - dev_alert(DEV, "To resolve this both sides have to support at least protocol\n"); + dev_alert(DEV, "To resolve this both sides have to support at least protocol 91\n"); return C_MASK; } -- GitLab From cab2f74b45127a78b9a2980f54ca16cc9f45ddac Mon Sep 17 00:00:00 2001 From: Andreas Gruenbacher Date: Thu, 9 Dec 2010 16:08:46 +0100 Subject: [PATCH 0433/2822] drbd: Make sure that drbd_send() has sent the right number of bytes Reviewed-by: Lars Ellenberg Signed-off-by: Philipp Reisner --- drivers/block/drbd/drbd_main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/block/drbd/drbd_main.c b/drivers/block/drbd/drbd_main.c index 150ed16d26efa..50b6841d135b3 100644 --- a/drivers/block/drbd/drbd_main.c +++ b/drivers/block/drbd/drbd_main.c @@ -2580,7 +2580,7 @@ int drbd_send_dblock(struct drbd_conf *mdev, struct drbd_request *req) if (ok && dgs) { dgb = mdev->int_dig_out; drbd_csum_bio(mdev, mdev->integrity_w_tfm, req->master_bio, dgb); - ok = drbd_send(mdev, mdev->data.socket, dgb, dgs, 0); + ok = dgs == drbd_send(mdev, mdev->data.socket, dgb, dgs, 0); } if (ok) { /* For protocol A, we have to memcpy the payload into @@ -2662,7 +2662,7 @@ int drbd_send_block(struct drbd_conf *mdev, enum drbd_packets cmd, if (ok && dgs) { dgb = mdev->int_dig_out; drbd_csum_ee(mdev, mdev->integrity_w_tfm, e, dgb); - ok = drbd_send(mdev, mdev->data.socket, dgb, dgs, 0); + ok = dgs == drbd_send(mdev, mdev->data.socket, dgb, dgs, 0); } if (ok) ok = _drbd_send_zc_ee(mdev, e); -- GitLab From 96756784a6250c7d9878671ef3386b93b0c576d4 Mon Sep 17 00:00:00 2001 From: Andreas Gruenbacher Date: Thu, 9 Dec 2010 16:23:43 +0100 Subject: [PATCH 0434/2822] drbd: Remove left-over prototype Signed-off-by: Philipp Reisner Signed-off-by: Lars Ellenberg --- drivers/block/drbd/drbd_int.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/block/drbd/drbd_int.h b/drivers/block/drbd/drbd_int.h index 38bbaba8bd895..3268d201025bc 100644 --- a/drivers/block/drbd/drbd_int.h +++ b/drivers/block/drbd/drbd_int.h @@ -1236,8 +1236,6 @@ extern int drbd_send_oos(struct drbd_conf *mdev, struct drbd_request *req); extern int drbd_send_block(struct drbd_conf *mdev, enum drbd_packets cmd, struct drbd_epoch_entry *e); extern int drbd_send_dblock(struct drbd_conf *mdev, struct drbd_request *req); -extern int _drbd_send_barrier(struct drbd_conf *mdev, - struct drbd_tl_epoch *barrier); extern int drbd_send_drequest(struct drbd_conf *mdev, int cmd, sector_t sector, int size, u64 block_id); extern int drbd_send_drequest_csum(struct drbd_conf *mdev, -- GitLab From 2f58dcfc85b6800efd938f755e6c5f9979f4aa5c Mon Sep 17 00:00:00 2001 From: Andreas Gruenbacher Date: Mon, 13 Dec 2010 17:48:19 +0100 Subject: [PATCH 0435/2822] drbd: Rename drbd_make_request_26 to drbd_make_request Signed-off-by: Philipp Reisner Signed-off-by: Lars Ellenberg --- drivers/block/drbd/drbd_int.h | 2 +- drivers/block/drbd/drbd_main.c | 2 +- drivers/block/drbd/drbd_req.c | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/block/drbd/drbd_int.h b/drivers/block/drbd/drbd_int.h index 3268d201025bc..7514cf7a958cf 100644 --- a/drivers/block/drbd/drbd_int.h +++ b/drivers/block/drbd/drbd_int.h @@ -1479,7 +1479,7 @@ extern void drbd_free_mdev(struct drbd_conf *mdev); extern int proc_details; /* drbd_req */ -extern int drbd_make_request_26(struct request_queue *q, struct bio *bio); +extern int drbd_make_request(struct request_queue *q, struct bio *bio); extern int drbd_read_remote(struct drbd_conf *mdev, struct drbd_request *req); extern int drbd_merge_bvec(struct request_queue *q, struct bvec_merge_data *bvm, struct bio_vec *bvec); extern int is_valid_ar_handle(struct drbd_request *, sector_t); diff --git a/drivers/block/drbd/drbd_main.c b/drivers/block/drbd/drbd_main.c index 50b6841d135b3..7d60527c3b5aa 100644 --- a/drivers/block/drbd/drbd_main.c +++ b/drivers/block/drbd/drbd_main.c @@ -3284,7 +3284,7 @@ struct drbd_conf *drbd_new_device(unsigned int minor) q->backing_dev_info.congested_fn = drbd_congested; q->backing_dev_info.congested_data = mdev; - blk_queue_make_request(q, drbd_make_request_26); + blk_queue_make_request(q, drbd_make_request); blk_queue_max_hw_sectors(q, DRBD_MAX_BIO_SIZE >> 9); blk_queue_bounce_limit(q, BLK_BOUNCE_ANY); blk_queue_merge_bvec(q, drbd_merge_bvec); diff --git a/drivers/block/drbd/drbd_req.c b/drivers/block/drbd/drbd_req.c index de5fe70f2b420..079213d934905 100644 --- a/drivers/block/drbd/drbd_req.c +++ b/drivers/block/drbd/drbd_req.c @@ -884,7 +884,7 @@ allocate_barrier: if (is_susp(mdev->state)) { /* If we got suspended, use the retry mechanism of generic_make_request() to restart processing of this - bio. In the next call to drbd_make_request_26 + bio. In the next call to drbd_make_request we sleep in inc_ap_bio() */ ret = 1; spin_unlock_irq(&mdev->req_lock); @@ -1089,7 +1089,7 @@ static int drbd_fail_request_early(struct drbd_conf *mdev, int is_write) return 0; } -int drbd_make_request_26(struct request_queue *q, struct bio *bio) +int drbd_make_request(struct request_queue *q, struct bio *bio) { unsigned int s_enr, e_enr; struct drbd_conf *mdev = (struct drbd_conf *) q->queuedata; @@ -1182,7 +1182,7 @@ int drbd_make_request_26(struct request_queue *q, struct bio *bio) * As long as the BIO is empty we have to allow at least one bvec, * regardless of size and offset. so the resulting bio may still * cross extent boundaries. those are dealt with (bio_split) in - * drbd_make_request_26. + * drbd_make_request. */ int drbd_merge_bvec(struct request_queue *q, struct bvec_merge_data *bvm, struct bio_vec *bvec) { -- GitLab From 662d91a23a8e8451ca47c08d5cff710fd080fd3a Mon Sep 17 00:00:00 2001 From: Andreas Gruenbacher Date: Tue, 7 Dec 2010 03:01:41 +0100 Subject: [PATCH 0436/2822] drbd: Get rid of unnecessary macros (1) This macro doesn't save much code, but makes things a lot harder to read. Signed-off-by: Philipp Reisner Signed-off-by: Lars Ellenberg --- drivers/block/drbd/drbd_main.c | 71 +++++++++++++++++++--------------- 1 file changed, 40 insertions(+), 31 deletions(-) diff --git a/drivers/block/drbd/drbd_main.c b/drivers/block/drbd/drbd_main.c index 7d60527c3b5aa..f43e2aa354a6b 100644 --- a/drivers/block/drbd/drbd_main.c +++ b/drivers/block/drbd/drbd_main.c @@ -674,21 +674,6 @@ void print_st_err(struct drbd_conf *mdev, } -#define drbd_peer_str drbd_role_str -#define drbd_pdsk_str drbd_disk_str - -#define drbd_susp_str(A) ((A) ? "1" : "0") -#define drbd_aftr_isp_str(A) ((A) ? "1" : "0") -#define drbd_peer_isp_str(A) ((A) ? "1" : "0") -#define drbd_user_isp_str(A) ((A) ? "1" : "0") - -#define PSC(A) \ - ({ if (ns.A != os.A) { \ - pbp += sprintf(pbp, #A "( %s -> %s ) ", \ - drbd_##A##_str(os.A), \ - drbd_##A##_str(ns.A)); \ - } }) - /** * is_valid_state() - Returns an SS_ error code if ns is not valid * @mdev: DRBD device. @@ -1084,22 +1069,46 @@ int __drbd_set_state(struct drbd_conf *mdev, dev_warn(DEV, "%s aborted.\n", warn_sync_abort); { - char *pbp, pb[300]; - pbp = pb; - *pbp = 0; - PSC(role); - PSC(peer); - PSC(conn); - PSC(disk); - PSC(pdsk); - if (is_susp(ns) != is_susp(os)) - pbp += sprintf(pbp, "susp( %s -> %s ) ", - drbd_susp_str(is_susp(os)), - drbd_susp_str(is_susp(ns))); - PSC(aftr_isp); - PSC(peer_isp); - PSC(user_isp); - dev_info(DEV, "%s\n", pb); + char *pbp, pb[300]; + pbp = pb; + *pbp = 0; + if (ns.role != os.role) + pbp += sprintf(pbp, "role( %s -> %s ) ", + drbd_role_str(os.role), + drbd_role_str(ns.role)); + if (ns.peer != os.peer) + pbp += sprintf(pbp, "peer( %s -> %s ) ", + drbd_role_str(os.peer), + drbd_role_str(ns.peer)); + if (ns.conn != os.conn) + pbp += sprintf(pbp, "conn( %s -> %s ) ", + drbd_conn_str(os.conn), + drbd_conn_str(ns.conn)); + if (ns.disk != os.disk) + pbp += sprintf(pbp, "disk( %s -> %s ) ", + drbd_disk_str(os.disk), + drbd_disk_str(ns.disk)); + if (ns.pdsk != os.pdsk) + pbp += sprintf(pbp, "pdsk( %s -> %s ) ", + drbd_disk_str(os.pdsk), + drbd_disk_str(ns.pdsk)); + if (is_susp(ns) != is_susp(os)) + pbp += sprintf(pbp, "susp( %d -> %d ) ", + is_susp(os), + is_susp(ns)); + if (ns.aftr_isp != os.aftr_isp) + pbp += sprintf(pbp, "aftr_isp( %d -> %d ) ", + os.aftr_isp, + ns.aftr_isp); + if (ns.peer_isp != os.peer_isp) + pbp += sprintf(pbp, "peer_isp( %d -> %d ) ", + os.peer_isp, + ns.peer_isp); + if (ns.user_isp != os.user_isp) + pbp += sprintf(pbp, "user_isp( %d -> %d ) ", + os.user_isp, + ns.user_isp); + dev_info(DEV, "%s\n", pb); } /* solve the race between becoming unconfigured, -- GitLab From 0cf9d27e38447efe5e5edce155a66a782a5aac4a Mon Sep 17 00:00:00 2001 From: Andreas Gruenbacher Date: Tue, 7 Dec 2010 10:43:29 +0100 Subject: [PATCH 0437/2822] drbd: Get rid of unnecessary macros (2) The FAULT_ACTIVE macro just wraps the drbd_insert_fault macro for no apparent reason. Signed-off-by: Philipp Reisner Signed-off-by: Lars Ellenberg --- drivers/block/drbd/drbd_actlog.c | 4 ++-- drivers/block/drbd/drbd_bitmap.c | 4 ++-- drivers/block/drbd/drbd_int.h | 9 ++++----- drivers/block/drbd/drbd_receiver.c | 4 ++-- drivers/block/drbd/drbd_req.c | 6 +++--- drivers/block/drbd/drbd_wrappers.h | 2 +- 6 files changed, 14 insertions(+), 15 deletions(-) diff --git a/drivers/block/drbd/drbd_actlog.c b/drivers/block/drbd/drbd_actlog.c index 4a1b199f4ae72..2e8a95ce79b15 100644 --- a/drivers/block/drbd/drbd_actlog.c +++ b/drivers/block/drbd/drbd_actlog.c @@ -92,7 +92,7 @@ static int _drbd_md_sync_page_io(struct drbd_conf *mdev, bio->bi_end_io = drbd_md_io_complete; bio->bi_rw = rw; - if (FAULT_ACTIVE(mdev, (rw & WRITE) ? DRBD_FAULT_MD_WR : DRBD_FAULT_MD_RD)) + if (drbd_insert_fault(mdev, (rw & WRITE) ? DRBD_FAULT_MD_WR : DRBD_FAULT_MD_RD)) bio_endio(bio, -EIO); else submit_bio(rw, bio); @@ -685,7 +685,7 @@ void drbd_al_to_on_disk_bm(struct drbd_conf *mdev) for (i = 0; i < nr_elements; i++) { if (bios[i] == NULL) break; - if (FAULT_ACTIVE(mdev, DRBD_FAULT_MD_WR)) { + if (drbd_insert_fault(mdev, DRBD_FAULT_MD_WR)) { bios[i]->bi_rw = WRITE; bio_endio(bios[i], -EIO); } else { diff --git a/drivers/block/drbd/drbd_bitmap.c b/drivers/block/drbd/drbd_bitmap.c index 0645ca829a941..5dafbabe96170 100644 --- a/drivers/block/drbd/drbd_bitmap.c +++ b/drivers/block/drbd/drbd_bitmap.c @@ -502,7 +502,7 @@ int drbd_bm_resize(struct drbd_conf *mdev, sector_t capacity, int set_new_bits) D_ASSERT(b->bm_pages != NULL); npages = b->bm_pages; } else { - if (FAULT_ACTIVE(mdev, DRBD_FAULT_BM_ALLOC)) + if (drbd_insert_fault(mdev, DRBD_FAULT_BM_ALLOC)) npages = NULL; else npages = bm_realloc_pages(b, want); @@ -768,7 +768,7 @@ static void bm_page_io_async(struct drbd_conf *mdev, struct drbd_bitmap *b, int bio->bi_private = b; bio->bi_end_io = bm_async_io_complete; - if (FAULT_ACTIVE(mdev, (rw & WRITE) ? DRBD_FAULT_MD_WR : DRBD_FAULT_MD_RD)) { + if (drbd_insert_fault(mdev, (rw & WRITE) ? DRBD_FAULT_MD_WR : DRBD_FAULT_MD_RD)) { bio->bi_rw |= rw; bio_endio(bio, -EIO); } else { diff --git a/drivers/block/drbd/drbd_int.h b/drivers/block/drbd/drbd_int.h index 7514cf7a958cf..c81710a42111d 100644 --- a/drivers/block/drbd/drbd_int.h +++ b/drivers/block/drbd/drbd_int.h @@ -137,20 +137,19 @@ enum { DRBD_FAULT_MAX, }; -#ifdef CONFIG_DRBD_FAULT_INJECTION extern unsigned int _drbd_insert_fault(struct drbd_conf *mdev, unsigned int type); + static inline int drbd_insert_fault(struct drbd_conf *mdev, unsigned int type) { +#ifdef CONFIG_DRBD_FAULT_INJECTION return fault_rate && (enable_faults & (1<> PAGE_SHIFT; - if (FAULT_ACTIVE(mdev, DRBD_FAULT_AL_EE)) + if (drbd_insert_fault(mdev, DRBD_FAULT_AL_EE)) return NULL; e = mempool_alloc(drbd_ee_mempool, gfp_mask & ~__GFP_HIGHMEM); @@ -1264,7 +1264,7 @@ read_in_block(struct drbd_conf *mdev, u64 id, sector_t sector, int data_size) __ unsigned len = min_t(int, ds, PAGE_SIZE); data = kmap(page); rr = drbd_recv(mdev, data, len); - if (FAULT_ACTIVE(mdev, DRBD_FAULT_RECEIVE)) { + if (drbd_insert_fault(mdev, DRBD_FAULT_RECEIVE)) { dev_err(DEV, "Fault injection: Corrupting data on receive\n"); data[0] = data[0] ^ (unsigned long)-1; } diff --git a/drivers/block/drbd/drbd_req.c b/drivers/block/drbd/drbd_req.c index 079213d934905..53e7cc5064562 100644 --- a/drivers/block/drbd/drbd_req.c +++ b/drivers/block/drbd/drbd_req.c @@ -1020,9 +1020,9 @@ allocate_barrier: * stable storage, and this is a WRITE, we may not even submit * this bio. */ if (get_ldev(mdev)) { - if (FAULT_ACTIVE(mdev, rw == WRITE ? DRBD_FAULT_DT_WR - : rw == READ ? DRBD_FAULT_DT_RD - : DRBD_FAULT_DT_RA)) + if (drbd_insert_fault(mdev, rw == WRITE ? DRBD_FAULT_DT_WR + : rw == READ ? DRBD_FAULT_DT_RD + : DRBD_FAULT_DT_RA)) bio_endio(req->private_bio, -EIO); else generic_make_request(req->private_bio); diff --git a/drivers/block/drbd/drbd_wrappers.h b/drivers/block/drbd/drbd_wrappers.h index 53586fa5ae1b0..151f1a37478f9 100644 --- a/drivers/block/drbd/drbd_wrappers.h +++ b/drivers/block/drbd/drbd_wrappers.h @@ -39,7 +39,7 @@ static inline void drbd_generic_make_request(struct drbd_conf *mdev, return; } - if (FAULT_ACTIVE(mdev, fault_type)) + if (drbd_insert_fault(mdev, fault_type)) bio_endio(bio, -EIO); else generic_make_request(bio); -- GitLab From 116676ca621a862a8124969772f4dd61c8b40eee Mon Sep 17 00:00:00 2001 From: Andreas Gruenbacher Date: Wed, 8 Dec 2010 13:33:11 +0100 Subject: [PATCH 0438/2822] drbd: Rename enum drbd_ret_codes to enum drbd_ret_code Signed-off-by: Philipp Reisner Signed-off-by: Lars Ellenberg --- drivers/block/drbd/drbd_main.c | 2 +- drivers/block/drbd/drbd_nl.c | 4 ++-- include/linux/drbd.h | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/block/drbd/drbd_main.c b/drivers/block/drbd/drbd_main.c index f43e2aa354a6b..8d69e3a1b3c2c 100644 --- a/drivers/block/drbd/drbd_main.c +++ b/drivers/block/drbd/drbd_main.c @@ -3570,7 +3570,7 @@ void drbd_md_sync(struct drbd_conf *mdev) * @mdev: DRBD device. * @bdev: Device from which the meta data should be read in. * - * Return 0 (NO_ERROR) on success, and an enum drbd_ret_codes in case + * Return 0 (NO_ERROR) on success, and an enum drbd_ret_code in case * something goes wrong. Currently only: ERR_IO_MD_DISK, ERR_MD_INVALID. */ int drbd_md_read(struct drbd_conf *mdev, struct drbd_backing_dev *bdev) diff --git a/drivers/block/drbd/drbd_nl.c b/drivers/block/drbd/drbd_nl.c index cd0459f0403fb..fe336592e538e 100644 --- a/drivers/block/drbd/drbd_nl.c +++ b/drivers/block/drbd/drbd_nl.c @@ -849,7 +849,7 @@ static void drbd_suspend_al(struct drbd_conf *mdev) static int drbd_nl_disk_conf(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp, struct drbd_nl_cfg_reply *reply) { - enum drbd_ret_codes retcode; + enum drbd_ret_code retcode; enum determine_dev_size dd; sector_t max_possible_sectors; sector_t min_md_device_sectors; @@ -1278,7 +1278,7 @@ static int drbd_nl_net_conf(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp, struct drbd_nl_cfg_reply *reply) { int i, ns; - enum drbd_ret_codes retcode; + enum drbd_ret_code retcode; struct net_conf *new_conf = NULL; struct crypto_hash *tfm = NULL; struct crypto_hash *integrity_w_tfm = NULL; diff --git a/include/linux/drbd.h b/include/linux/drbd.h index 41da654cc0b18..d92f989036c92 100644 --- a/include/linux/drbd.h +++ b/include/linux/drbd.h @@ -103,7 +103,7 @@ enum drbd_on_congestion { }; /* KEEP the order, do not delete or insert. Only append. */ -enum drbd_ret_codes { +enum drbd_ret_code { ERR_CODE_BASE = 100, NO_ERROR = 101, ERR_LOCAL_ADDR = 102, -- GitLab From c8b325632f0e5ffdaeca3d1f3be77c9399316a40 Mon Sep 17 00:00:00 2001 From: Andreas Gruenbacher Date: Wed, 8 Dec 2010 01:06:16 +0100 Subject: [PATCH 0439/2822] drbd: Rename enum drbd_state_ret_codes to enum drbd_state_rv Signed-off-by: Philipp Reisner Signed-off-by: Lars Ellenberg --- drivers/block/drbd/drbd_main.c | 5 +++-- drivers/block/drbd/drbd_strings.c | 2 +- include/linux/drbd.h | 4 ++-- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/drivers/block/drbd/drbd_main.c b/drivers/block/drbd/drbd_main.c index 8d69e3a1b3c2c..cddf311b74293 100644 --- a/drivers/block/drbd/drbd_main.c +++ b/drivers/block/drbd/drbd_main.c @@ -510,8 +510,9 @@ static union drbd_state sanitize_state(struct drbd_conf *mdev, union drbd_state int drbd_send_state_req(struct drbd_conf *, union drbd_state, union drbd_state); -static enum drbd_state_ret_codes _req_st_cond(struct drbd_conf *mdev, - union drbd_state mask, union drbd_state val) +static enum drbd_state_rv +_req_st_cond(struct drbd_conf *mdev, union drbd_state mask, + union drbd_state val) { union drbd_state os, ns; unsigned long flags; diff --git a/drivers/block/drbd/drbd_strings.c b/drivers/block/drbd/drbd_strings.c index 5b970adc3b6f5..c44a2a6027724 100644 --- a/drivers/block/drbd/drbd_strings.c +++ b/drivers/block/drbd/drbd_strings.c @@ -107,7 +107,7 @@ const char *drbd_disk_str(enum drbd_disk_state s) return s > D_UP_TO_DATE ? "TOO_LARGE" : drbd_disk_s_names[s]; } -const char *drbd_set_st_err_str(enum drbd_state_ret_codes err) +const char *drbd_set_st_err_str(enum drbd_state_rv err) { return err <= SS_AFTER_LAST_ERROR ? "TOO_SMALL" : err > SS_TWO_PRIMARIES ? "TOO_LARGE" diff --git a/include/linux/drbd.h b/include/linux/drbd.h index d92f989036c92..d10431fab0047 100644 --- a/include/linux/drbd.h +++ b/include/linux/drbd.h @@ -270,7 +270,7 @@ union drbd_state { unsigned int i; }; -enum drbd_state_ret_codes { +enum drbd_state_rv { SS_CW_NO_NEED = 4, SS_CW_SUCCESS = 3, SS_NOTHING_TO_DO = 2, @@ -301,7 +301,7 @@ enum drbd_state_ret_codes { extern const char *drbd_conn_str(enum drbd_conns); extern const char *drbd_role_str(enum drbd_role); extern const char *drbd_disk_str(enum drbd_disk_state); -extern const char *drbd_set_st_err_str(enum drbd_state_ret_codes); +extern const char *drbd_set_st_err_str(enum drbd_state_rv); #define SHARED_SECRET_MAX 64 -- GitLab From bf885f8a6772fb48409dd505a09d974a5e621f22 Mon Sep 17 00:00:00 2001 From: Andreas Gruenbacher Date: Wed, 8 Dec 2010 00:39:32 +0100 Subject: [PATCH 0440/2822] drbd: Be more explicit about functions that return an enum drbd_state_rv Signed-off-by: Philipp Reisner Signed-off-by: Lars Ellenberg --- drivers/block/drbd/drbd_int.h | 32 +++++++++------- drivers/block/drbd/drbd_main.c | 59 ++++++++++++++++-------------- drivers/block/drbd/drbd_nl.c | 29 ++++++++------- drivers/block/drbd/drbd_receiver.c | 2 +- 4 files changed, 67 insertions(+), 55 deletions(-) diff --git a/drivers/block/drbd/drbd_int.h b/drivers/block/drbd/drbd_int.h index c81710a42111d..749607a494e68 100644 --- a/drivers/block/drbd/drbd_int.h +++ b/drivers/block/drbd/drbd_int.h @@ -1174,14 +1174,19 @@ enum dds_flags { }; extern void drbd_init_set_defaults(struct drbd_conf *mdev); -extern int drbd_change_state(struct drbd_conf *mdev, enum chg_state_flags f, - union drbd_state mask, union drbd_state val); +extern enum drbd_state_rv drbd_change_state(struct drbd_conf *mdev, + enum chg_state_flags f, + union drbd_state mask, + union drbd_state val); extern void drbd_force_state(struct drbd_conf *, union drbd_state, union drbd_state); -extern int _drbd_request_state(struct drbd_conf *, union drbd_state, - union drbd_state, enum chg_state_flags); -extern int __drbd_set_state(struct drbd_conf *, union drbd_state, - enum chg_state_flags, struct completion *done); +extern enum drbd_state_rv _drbd_request_state(struct drbd_conf *, + union drbd_state, + union drbd_state, + enum chg_state_flags); +extern enum drbd_state_rv __drbd_set_state(struct drbd_conf *, union drbd_state, + enum chg_state_flags, + struct completion *done); extern void print_st_err(struct drbd_conf *, union drbd_state, union drbd_state, int); extern int drbd_thread_start(struct drbd_thread *thi); @@ -1245,7 +1250,7 @@ extern int drbd_send_ov_request(struct drbd_conf *mdev,sector_t sector,int size) extern int drbd_send_bitmap(struct drbd_conf *mdev); extern int _drbd_send_bitmap(struct drbd_conf *mdev); -extern int drbd_send_sr_reply(struct drbd_conf *mdev, int retcode); +extern int drbd_send_sr_reply(struct drbd_conf *mdev, enum drbd_state_rv retcode); extern void drbd_free_bc(struct drbd_backing_dev *ldev); extern void drbd_mdev_cleanup(struct drbd_conf *mdev); @@ -1493,8 +1498,9 @@ enum determine_dev_size { dev_size_error = -1, unchanged = 0, shrunk = 1, grew = extern enum determine_dev_size drbd_determin_dev_size(struct drbd_conf *, enum dds_flags) __must_hold(local); extern void resync_after_online_grow(struct drbd_conf *); extern void drbd_setup_queue_param(struct drbd_conf *mdev, unsigned int) __must_hold(local); -extern int drbd_set_role(struct drbd_conf *mdev, enum drbd_role new_role, - int force); +extern enum drbd_state_rv drbd_set_role(struct drbd_conf *mdev, + enum drbd_role new_role, + int force); extern enum drbd_disk_state drbd_try_outdate_peer(struct drbd_conf *mdev); extern void drbd_try_outdate_peer_async(struct drbd_conf *mdev); extern int drbd_khelper(struct drbd_conf *mdev, char *cmd); @@ -1761,11 +1767,11 @@ static inline void drbd_state_unlock(struct drbd_conf *mdev) wake_up(&mdev->misc_wait); } -static inline int _drbd_set_state(struct drbd_conf *mdev, - union drbd_state ns, enum chg_state_flags flags, - struct completion *done) +static inline enum drbd_state_rv +_drbd_set_state(struct drbd_conf *mdev, union drbd_state ns, + enum chg_state_flags flags, struct completion *done) { - int rv; + enum drbd_state_rv rv; read_lock(&global_state_lock); rv = __drbd_set_state(mdev, ns, flags, done); diff --git a/drivers/block/drbd/drbd_main.c b/drivers/block/drbd/drbd_main.c index cddf311b74293..a101dceb2d494 100644 --- a/drivers/block/drbd/drbd_main.c +++ b/drivers/block/drbd/drbd_main.c @@ -473,12 +473,13 @@ static int cl_wide_st_chg(struct drbd_conf *mdev, (os.conn == C_CONNECTED && ns.conn == C_VERIFY_S); } -int drbd_change_state(struct drbd_conf *mdev, enum chg_state_flags f, - union drbd_state mask, union drbd_state val) +enum drbd_state_rv +drbd_change_state(struct drbd_conf *mdev, enum chg_state_flags f, + union drbd_state mask, union drbd_state val) { unsigned long flags; union drbd_state os, ns; - int rv; + enum drbd_state_rv rv; spin_lock_irqsave(&mdev->req_lock, flags); os = mdev->state; @@ -502,9 +503,10 @@ void drbd_force_state(struct drbd_conf *mdev, drbd_change_state(mdev, CS_HARD, mask, val); } -static int is_valid_state(struct drbd_conf *mdev, union drbd_state ns); -static int is_valid_state_transition(struct drbd_conf *, - union drbd_state, union drbd_state); +static enum drbd_state_rv is_valid_state(struct drbd_conf *, union drbd_state); +static enum drbd_state_rv is_valid_state_transition(struct drbd_conf *, + union drbd_state, + union drbd_state); static union drbd_state sanitize_state(struct drbd_conf *mdev, union drbd_state os, union drbd_state ns, const char **warn_sync_abort); int drbd_send_state_req(struct drbd_conf *, @@ -516,7 +518,7 @@ _req_st_cond(struct drbd_conf *mdev, union drbd_state mask, { union drbd_state os, ns; unsigned long flags; - int rv; + enum drbd_state_rv rv; if (test_and_clear_bit(CL_ST_CHG_SUCCESS, &mdev->flags)) return SS_CW_SUCCESS; @@ -537,7 +539,7 @@ _req_st_cond(struct drbd_conf *mdev, union drbd_state mask, if (rv == SS_SUCCESS) { rv = is_valid_state_transition(mdev, ns, os); if (rv == SS_SUCCESS) - rv = 0; /* cont waiting, otherwise fail. */ + rv = SS_UNKNOWN_ERROR; /* cont waiting, otherwise fail. */ } } spin_unlock_irqrestore(&mdev->req_lock, flags); @@ -555,14 +557,14 @@ _req_st_cond(struct drbd_conf *mdev, union drbd_state mask, * Should not be called directly, use drbd_request_state() or * _drbd_request_state(). */ -static int drbd_req_state(struct drbd_conf *mdev, - union drbd_state mask, union drbd_state val, - enum chg_state_flags f) +static enum drbd_state_rv +drbd_req_state(struct drbd_conf *mdev, union drbd_state mask, + union drbd_state val, enum chg_state_flags f) { struct completion done; unsigned long flags; union drbd_state os, ns; - int rv; + enum drbd_state_rv rv; init_completion(&done); @@ -637,10 +639,11 @@ abort: * Cousin of drbd_request_state(), useful with the CS_WAIT_COMPLETE * flag, or when logging of failed state change requests is not desired. */ -int _drbd_request_state(struct drbd_conf *mdev, union drbd_state mask, - union drbd_state val, enum chg_state_flags f) +enum drbd_state_rv +_drbd_request_state(struct drbd_conf *mdev, union drbd_state mask, + union drbd_state val, enum chg_state_flags f) { - int rv; + enum drbd_state_rv rv; wait_event(mdev->state_wait, (rv = drbd_req_state(mdev, mask, val, f)) != SS_IN_TRANSIENT_STATE); @@ -664,8 +667,8 @@ static void print_st(struct drbd_conf *mdev, char *name, union drbd_state ns) ); } -void print_st_err(struct drbd_conf *mdev, - union drbd_state os, union drbd_state ns, int err) +void print_st_err(struct drbd_conf *mdev, union drbd_state os, + union drbd_state ns, enum drbd_state_rv err) { if (err == SS_IN_TRANSIENT_STATE) return; @@ -680,12 +683,13 @@ void print_st_err(struct drbd_conf *mdev, * @mdev: DRBD device. * @ns: State to consider. */ -static int is_valid_state(struct drbd_conf *mdev, union drbd_state ns) +static enum drbd_state_rv +is_valid_state(struct drbd_conf *mdev, union drbd_state ns) { /* See drbd_state_sw_errors in drbd_strings.c */ enum drbd_fencing_p fp; - int rv = SS_SUCCESS; + enum drbd_state_rv rv = SS_SUCCESS; fp = FP_DONT_CARE; if (get_ldev(mdev)) { @@ -748,10 +752,11 @@ static int is_valid_state(struct drbd_conf *mdev, union drbd_state ns) * @ns: new state. * @os: old state. */ -static int is_valid_state_transition(struct drbd_conf *mdev, - union drbd_state ns, union drbd_state os) +static enum drbd_state_rv +is_valid_state_transition(struct drbd_conf *mdev, union drbd_state ns, + union drbd_state os) { - int rv = SS_SUCCESS; + enum drbd_state_rv rv = SS_SUCCESS; if ((ns.conn == C_STARTING_SYNC_T || ns.conn == C_STARTING_SYNC_S) && os.conn > C_CONNECTED) @@ -1029,12 +1034,12 @@ static void drbd_resume_al(struct drbd_conf *mdev) * * Caller needs to hold req_lock, and global_state_lock. Do not call directly. */ -int __drbd_set_state(struct drbd_conf *mdev, - union drbd_state ns, enum chg_state_flags flags, - struct completion *done) +enum drbd_state_rv +__drbd_set_state(struct drbd_conf *mdev, union drbd_state ns, + enum chg_state_flags flags, struct completion *done) { union drbd_state os; - int rv = SS_SUCCESS; + enum drbd_state_rv rv = SS_SUCCESS; const char *warn_sync_abort = NULL; struct after_state_chg_work *ascw; @@ -2031,7 +2036,7 @@ int drbd_send_state_req(struct drbd_conf *mdev, (struct p_header80 *)&p, sizeof(p)); } -int drbd_send_sr_reply(struct drbd_conf *mdev, int retcode) +int drbd_send_sr_reply(struct drbd_conf *mdev, enum drbd_state_rv retcode) { struct p_req_state_reply p; diff --git a/drivers/block/drbd/drbd_nl.c b/drivers/block/drbd/drbd_nl.c index fe336592e538e..7a2faf6d48e26 100644 --- a/drivers/block/drbd/drbd_nl.c +++ b/drivers/block/drbd/drbd_nl.c @@ -288,10 +288,11 @@ void drbd_try_outdate_peer_async(struct drbd_conf *mdev) dev_err(DEV, "out of mem, failed to invoke fence-peer helper\n"); } -int drbd_set_role(struct drbd_conf *mdev, enum drbd_role new_role, int force) +enum drbd_state_rv +drbd_set_role(struct drbd_conf *mdev, enum drbd_role new_role, int force) { const int max_tries = 4; - int r = 0; + enum drbd_state_rv rv = SS_UNKNOWN_ERROR; int try = 0; int forced = 0; union drbd_state mask, val; @@ -306,17 +307,17 @@ int drbd_set_role(struct drbd_conf *mdev, enum drbd_role new_role, int force) val.i = 0; val.role = new_role; while (try++ < max_tries) { - r = _drbd_request_state(mdev, mask, val, CS_WAIT_COMPLETE); + rv = _drbd_request_state(mdev, mask, val, CS_WAIT_COMPLETE); /* in case we first succeeded to outdate, * but now suddenly could establish a connection */ - if (r == SS_CW_FAILED_BY_PEER && mask.pdsk != 0) { + if (rv == SS_CW_FAILED_BY_PEER && mask.pdsk != 0) { val.pdsk = 0; mask.pdsk = 0; continue; } - if (r == SS_NO_UP_TO_DATE_DISK && force && + if (rv == SS_NO_UP_TO_DATE_DISK && force && (mdev->state.disk < D_UP_TO_DATE && mdev->state.disk >= D_INCONSISTENT)) { mask.disk = D_MASK; @@ -325,7 +326,7 @@ int drbd_set_role(struct drbd_conf *mdev, enum drbd_role new_role, int force) continue; } - if (r == SS_NO_UP_TO_DATE_DISK && + if (rv == SS_NO_UP_TO_DATE_DISK && mdev->state.disk == D_CONSISTENT && mask.pdsk == 0) { D_ASSERT(mdev->state.pdsk == D_UNKNOWN); nps = drbd_try_outdate_peer(mdev); @@ -341,9 +342,9 @@ int drbd_set_role(struct drbd_conf *mdev, enum drbd_role new_role, int force) continue; } - if (r == SS_NOTHING_TO_DO) + if (rv == SS_NOTHING_TO_DO) goto fail; - if (r == SS_PRIMARY_NOP && mask.pdsk == 0) { + if (rv == SS_PRIMARY_NOP && mask.pdsk == 0) { nps = drbd_try_outdate_peer(mdev); if (force && nps > D_OUTDATED) { @@ -356,7 +357,7 @@ int drbd_set_role(struct drbd_conf *mdev, enum drbd_role new_role, int force) continue; } - if (r == SS_TWO_PRIMARIES) { + if (rv == SS_TWO_PRIMARIES) { /* Maybe the peer is detected as dead very soon... retry at most once more in this case. */ __set_current_state(TASK_INTERRUPTIBLE); @@ -365,16 +366,16 @@ int drbd_set_role(struct drbd_conf *mdev, enum drbd_role new_role, int force) try = max_tries - 1; continue; } - if (r < SS_SUCCESS) { - r = _drbd_request_state(mdev, mask, val, + if (rv < SS_SUCCESS) { + rv = _drbd_request_state(mdev, mask, val, CS_VERBOSE + CS_WAIT_COMPLETE); - if (r < SS_SUCCESS) + if (rv < SS_SUCCESS) goto fail; } break; } - if (r < SS_SUCCESS) + if (rv < SS_SUCCESS) goto fail; if (forced) @@ -423,7 +424,7 @@ int drbd_set_role(struct drbd_conf *mdev, enum drbd_role new_role, int force) kobject_uevent(&disk_to_dev(mdev->vdisk)->kobj, KOBJ_CHANGE); fail: mutex_unlock(&mdev->state_mutex); - return r; + return rv; } static struct drbd_conf *ensure_mdev(int minor, int create) diff --git a/drivers/block/drbd/drbd_receiver.c b/drivers/block/drbd/drbd_receiver.c index d34d093278c7b..c116cbdc9dca0 100644 --- a/drivers/block/drbd/drbd_receiver.c +++ b/drivers/block/drbd/drbd_receiver.c @@ -3112,7 +3112,7 @@ static int receive_req_state(struct drbd_conf *mdev, enum drbd_packets cmd, unsi { struct p_req_state *p = &mdev->data.rbuf.req_state; union drbd_state mask, val; - int rv; + enum drbd_state_rv rv; mask.i = be32_to_cpu(p->mask); val.i = be32_to_cpu(p->val); -- GitLab From bb4379464efeb4624757e2cc0bf9207a309c1075 Mon Sep 17 00:00:00 2001 From: Andreas Gruenbacher Date: Thu, 9 Dec 2010 14:02:35 +0100 Subject: [PATCH 0441/2822] drbd: Another small enum drbd_state_rv cleanup Signed-off-by: Philipp Reisner Signed-off-by: Lars Ellenberg --- drivers/block/drbd/drbd_receiver.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/drivers/block/drbd/drbd_receiver.c b/drivers/block/drbd/drbd_receiver.c index c116cbdc9dca0..8088744d0ec12 100644 --- a/drivers/block/drbd/drbd_receiver.c +++ b/drivers/block/drbd/drbd_receiver.c @@ -2209,12 +2209,14 @@ static int drbd_asb_recover_1p(struct drbd_conf *mdev) __must_hold(local) case ASB_CALL_HELPER: hg = drbd_asb_recover_0p(mdev); if (hg == -1 && mdev->state.role == R_PRIMARY) { - self = drbd_set_role(mdev, R_SECONDARY, 0); + enum drbd_state_rv rv2; + + drbd_set_role(mdev, R_SECONDARY, 0); /* drbd_change_state() does not sleep while in SS_IN_TRANSIENT_STATE, * we might be here in C_WF_REPORT_PARAMS which is transient. * we do not need to wait for the after state change work either. */ - self = drbd_change_state(mdev, CS_VERBOSE, NS(role, R_SECONDARY)); - if (self != SS_SUCCESS) { + rv2 = drbd_change_state(mdev, CS_VERBOSE, NS(role, R_SECONDARY)); + if (rv2 != SS_SUCCESS) { drbd_khelper(mdev, "pri-lost-after-sb"); } else { dev_warn(DEV, "Successfully gave up primary role.\n"); @@ -2252,11 +2254,13 @@ static int drbd_asb_recover_2p(struct drbd_conf *mdev) __must_hold(local) case ASB_CALL_HELPER: hg = drbd_asb_recover_0p(mdev); if (hg == -1) { + enum drbd_state_rv rv2; + /* drbd_change_state() does not sleep while in SS_IN_TRANSIENT_STATE, * we might be here in C_WF_REPORT_PARAMS which is transient. * we do not need to wait for the after state change work either. */ - self = drbd_change_state(mdev, CS_VERBOSE, NS(role, R_SECONDARY)); - if (self != SS_SUCCESS) { + rv2 = drbd_change_state(mdev, CS_VERBOSE, NS(role, R_SECONDARY)); + if (rv2 != SS_SUCCESS) { drbd_khelper(mdev, "pri-lost-after-sb"); } else { dev_warn(DEV, "Successfully gave up primary role.\n"); -- GitLab From 6184ea2145609b4ad63b141bf1f8124135ff4949 Mon Sep 17 00:00:00 2001 From: Andreas Gruenbacher Date: Thu, 9 Dec 2010 14:23:27 +0100 Subject: [PATCH 0442/2822] drbd: This code is dead now Signed-off-by: Philipp Reisner Signed-off-by: Lars Ellenberg --- drivers/block/drbd/drbd_receiver.c | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/drivers/block/drbd/drbd_receiver.c b/drivers/block/drbd/drbd_receiver.c index 8088744d0ec12..00dcb1172ca81 100644 --- a/drivers/block/drbd/drbd_receiver.c +++ b/drivers/block/drbd/drbd_receiver.c @@ -2179,10 +2179,7 @@ static int drbd_asb_recover_0p(struct drbd_conf *mdev) __must_hold(local) static int drbd_asb_recover_1p(struct drbd_conf *mdev) __must_hold(local) { - int self, peer, hg, rv = -100; - - self = mdev->ldev->md.uuid[UI_BITMAP] & 1; - peer = mdev->p_uuid[UI_BITMAP] & 1; + int hg, rv = -100; switch (mdev->net_conf->after_sb_1p) { case ASB_DISCARD_YOUNGER_PRI: @@ -2231,10 +2228,7 @@ static int drbd_asb_recover_1p(struct drbd_conf *mdev) __must_hold(local) static int drbd_asb_recover_2p(struct drbd_conf *mdev) __must_hold(local) { - int self, peer, hg, rv = -100; - - self = mdev->ldev->md.uuid[UI_BITMAP] & 1; - peer = mdev->p_uuid[UI_BITMAP] & 1; + int hg, rv = -100; switch (mdev->net_conf->after_sb_2p) { case ASB_DISCARD_YOUNGER_PRI: -- GitLab From 81e84650c200de0695372461964dd960365696db Mon Sep 17 00:00:00 2001 From: Andreas Gruenbacher Date: Thu, 9 Dec 2010 15:03:57 +0100 Subject: [PATCH 0443/2822] drbd: Use the standard bool, true, and false keywords Signed-off-by: Philipp Reisner Signed-off-by: Lars Ellenberg --- drivers/block/drbd/drbd_actlog.c | 8 +- drivers/block/drbd/drbd_bitmap.c | 4 +- drivers/block/drbd/drbd_int.h | 13 +-- drivers/block/drbd/drbd_main.c | 30 +++---- drivers/block/drbd/drbd_nl.c | 4 +- drivers/block/drbd/drbd_receiver.c | 128 ++++++++++++++--------------- drivers/block/drbd/drbd_req.c | 4 +- drivers/block/drbd/drbd_worker.c | 4 +- 8 files changed, 94 insertions(+), 101 deletions(-) diff --git a/drivers/block/drbd/drbd_actlog.c b/drivers/block/drbd/drbd_actlog.c index 2e8a95ce79b15..e3f0f4d31d757 100644 --- a/drivers/block/drbd/drbd_actlog.c +++ b/drivers/block/drbd/drbd_actlog.c @@ -338,7 +338,7 @@ w_al_write_transaction(struct drbd_conf *mdev, struct drbd_work *w, int unused) + mdev->ldev->md.al_offset + mdev->al_tr_pos; if (!drbd_md_sync_page_io(mdev, mdev->ldev, sector, WRITE)) - drbd_chk_io_error(mdev, 1, TRUE); + drbd_chk_io_error(mdev, 1, true); if (++mdev->al_tr_pos > div_ceil(mdev->act_log->nr_elements, AL_EXTENTS_PT)) @@ -528,7 +528,7 @@ static void atodb_endio(struct bio *bio, int error) if (!error && !uptodate) error = -EIO; - drbd_chk_io_error(mdev, error, TRUE); + drbd_chk_io_error(mdev, error, true); if (error && wc->error == 0) wc->error = error; @@ -991,7 +991,7 @@ void __drbd_set_in_sync(struct drbd_conf *mdev, sector_t sector, int size, if (count && get_ldev(mdev)) { drbd_advance_rs_marks(mdev, drbd_bm_total_weight(mdev)); spin_lock_irqsave(&mdev->al_lock, flags); - drbd_try_clear_on_disk_bm(mdev, sector, count, TRUE); + drbd_try_clear_on_disk_bm(mdev, sector, count, true); spin_unlock_irqrestore(&mdev->al_lock, flags); /* just wake_up unconditional now, various lc_chaged(), @@ -1441,7 +1441,7 @@ void drbd_rs_failed_io(struct drbd_conf *mdev, sector_t sector, int size) mdev->rs_failed += count; if (get_ldev(mdev)) { - drbd_try_clear_on_disk_bm(mdev, sector, count, FALSE); + drbd_try_clear_on_disk_bm(mdev, sector, count, false); put_ldev(mdev); } diff --git a/drivers/block/drbd/drbd_bitmap.c b/drivers/block/drbd/drbd_bitmap.c index 5dafbabe96170..9390e9526786e 100644 --- a/drivers/block/drbd/drbd_bitmap.c +++ b/drivers/block/drbd/drbd_bitmap.c @@ -844,7 +844,7 @@ static int bm_rw(struct drbd_conf *mdev, int rw) __must_hold(local) if (test_bit(BM_MD_IO_ERROR, &b->bm_flags)) { dev_alert(DEV, "we had at least one MD IO ERROR during bitmap IO\n"); - drbd_chk_io_error(mdev, 1, TRUE); + drbd_chk_io_error(mdev, 1, true); err = -EIO; } @@ -916,7 +916,7 @@ int drbd_bm_write_sect(struct drbd_conf *mdev, unsigned long enr) __must_hold(lo dev_err(DEV, "IO ERROR writing bitmap sector %lu " "(meta-disk sector %llus)\n", enr, (unsigned long long)on_disk_sector); - drbd_chk_io_error(mdev, 1, TRUE); + drbd_chk_io_error(mdev, 1, true); for (i = 0; i < AL_EXT_PER_BM_SECT; i++) drbd_bm_ALe_set_all(mdev, enr*AL_EXT_PER_BM_SECT+i); } diff --git a/drivers/block/drbd/drbd_int.h b/drivers/block/drbd/drbd_int.h index 749607a494e68..0855934e19d0c 100644 --- a/drivers/block/drbd/drbd_int.h +++ b/drivers/block/drbd/drbd_int.h @@ -72,13 +72,6 @@ extern int fault_devs; extern char usermode_helper[]; -#ifndef TRUE -#define TRUE 1 -#endif -#ifndef FALSE -#define FALSE 0 -#endif - /* I don't remember why XCPU ... * This is used to wake the asender, * and to interrupt sending the sending task @@ -2002,17 +1995,17 @@ static inline int drbd_send_ping_ack(struct drbd_conf *mdev) static inline void drbd_thread_stop(struct drbd_thread *thi) { - _drbd_thread_stop(thi, FALSE, TRUE); + _drbd_thread_stop(thi, false, true); } static inline void drbd_thread_stop_nowait(struct drbd_thread *thi) { - _drbd_thread_stop(thi, FALSE, FALSE); + _drbd_thread_stop(thi, false, false); } static inline void drbd_thread_restart_nowait(struct drbd_thread *thi) { - _drbd_thread_stop(thi, TRUE, FALSE); + _drbd_thread_stop(thi, true, false); } /* counts how many answer packets packets we expect from our peer, diff --git a/drivers/block/drbd/drbd_main.c b/drivers/block/drbd/drbd_main.c index a101dceb2d494..7eb447d20cced 100644 --- a/drivers/block/drbd/drbd_main.c +++ b/drivers/block/drbd/drbd_main.c @@ -456,7 +456,7 @@ void tl_restart(struct drbd_conf *mdev, enum drbd_req_event what) } /** - * cl_wide_st_chg() - TRUE if the state change is a cluster wide one + * cl_wide_st_chg() - true if the state change is a cluster wide one * @mdev: DRBD device. * @os: old (current) state. * @ns: new (wanted) state. @@ -1623,7 +1623,7 @@ int drbd_thread_start(struct drbd_thread *thi) if (!try_module_get(THIS_MODULE)) { dev_err(DEV, "Failed to get module reference in drbd_thread_start\n"); spin_unlock_irqrestore(&thi->t_lock, flags); - return FALSE; + return false; } init_completion(&thi->stop); @@ -1640,7 +1640,7 @@ int drbd_thread_start(struct drbd_thread *thi) dev_err(DEV, "Couldn't start thread\n"); module_put(THIS_MODULE); - return FALSE; + return false; } spin_lock_irqsave(&thi->t_lock, flags); thi->task = nt; @@ -1660,7 +1660,7 @@ int drbd_thread_start(struct drbd_thread *thi) break; } - return TRUE; + return true; } @@ -1758,8 +1758,8 @@ int _drbd_send_cmd(struct drbd_conf *mdev, struct socket *sock, { int sent, ok; - ERR_IF(!h) return FALSE; - ERR_IF(!size) return FALSE; + ERR_IF(!h) return false; + ERR_IF(!size) return false; h->magic = BE_DRBD_MAGIC; h->command = cpu_to_be16(cmd); @@ -2196,14 +2196,14 @@ int _drbd_send_bitmap(struct drbd_conf *mdev) struct p_header80 *p; int ret; - ERR_IF(!mdev->bitmap) return FALSE; + ERR_IF(!mdev->bitmap) return false; /* maybe we should use some per thread scratch page, * and allocate that during initial device creation? */ p = (struct p_header80 *) __get_free_page(GFP_NOIO); if (!p) { dev_err(DEV, "failed to allocate one page buffer in %s\n", __func__); - return FALSE; + return false; } if (get_ldev(mdev)) { @@ -2256,7 +2256,7 @@ int drbd_send_b_ack(struct drbd_conf *mdev, u32 barrier_nr, u32 set_size) p.set_size = cpu_to_be32(set_size); if (mdev->state.conn < C_CONNECTED) - return FALSE; + return false; ok = drbd_send_cmd(mdev, USE_META_SOCKET, P_BARRIER_ACK, (struct p_header80 *)&p, sizeof(p)); return ok; @@ -2284,7 +2284,7 @@ static int _drbd_send_ack(struct drbd_conf *mdev, enum drbd_packets cmd, p.seq_num = cpu_to_be32(atomic_add_return(1, &mdev->packet_seq)); if (!mdev->meta.socket || mdev->state.conn < C_CONNECTED) - return FALSE; + return false; ok = drbd_send_cmd(mdev, USE_META_SOCKET, cmd, (struct p_header80 *)&p, sizeof(p)); return ok; @@ -2390,8 +2390,8 @@ int drbd_send_ov_request(struct drbd_conf *mdev, sector_t sector, int size) } /* called on sndtimeo - * returns FALSE if we should retry, - * TRUE if we think connection is dead + * returns false if we should retry, + * true if we think connection is dead */ static int we_should_drop_the_connection(struct drbd_conf *mdev, struct socket *sock) { @@ -2404,7 +2404,7 @@ static int we_should_drop_the_connection(struct drbd_conf *mdev, struct socket * || mdev->state.conn < C_CONNECTED; if (drop_it) - return TRUE; + return true; drop_it = !--mdev->ko_count; if (!drop_it) { @@ -3283,7 +3283,7 @@ struct drbd_conf *drbd_new_device(unsigned int minor) goto out_no_disk; mdev->vdisk = disk; - set_disk_ro(disk, TRUE); + set_disk_ro(disk, true); disk->queue = q; disk->major = DRBD_MAJOR; @@ -3560,7 +3560,7 @@ void drbd_md_sync(struct drbd_conf *mdev) if (!drbd_md_sync_page_io(mdev, mdev->ldev, sector, WRITE)) { /* this was a try anyways ... */ dev_err(DEV, "meta data update failed!\n"); - drbd_chk_io_error(mdev, 1, TRUE); + drbd_chk_io_error(mdev, 1, true); } /* Update mdev->ldev->md.la_size_sect, diff --git a/drivers/block/drbd/drbd_nl.c b/drivers/block/drbd/drbd_nl.c index 7a2faf6d48e26..9e94c348c42c6 100644 --- a/drivers/block/drbd/drbd_nl.c +++ b/drivers/block/drbd/drbd_nl.c @@ -385,7 +385,7 @@ drbd_set_role(struct drbd_conf *mdev, enum drbd_role new_role, int force) wait_event(mdev->misc_wait, atomic_read(&mdev->ap_pending_cnt) == 0); if (new_role == R_SECONDARY) { - set_disk_ro(mdev->vdisk, TRUE); + set_disk_ro(mdev->vdisk, true); if (get_ldev(mdev)) { mdev->ldev->md.uuid[UI_CURRENT] &= ~(u64)1; put_ldev(mdev); @@ -395,7 +395,7 @@ drbd_set_role(struct drbd_conf *mdev, enum drbd_role new_role, int force) mdev->net_conf->want_lose = 0; put_net_conf(mdev); } - set_disk_ro(mdev->vdisk, FALSE); + set_disk_ro(mdev->vdisk, false); if (get_ldev(mdev)) { if (((mdev->state.conn < C_CONNECTED || mdev->state.pdsk <= D_FAILED) diff --git a/drivers/block/drbd/drbd_receiver.c b/drivers/block/drbd/drbd_receiver.c index 00dcb1172ca81..732aacb46a321 100644 --- a/drivers/block/drbd/drbd_receiver.c +++ b/drivers/block/drbd/drbd_receiver.c @@ -725,16 +725,16 @@ static int drbd_socket_okay(struct drbd_conf *mdev, struct socket **sock) char tb[4]; if (!*sock) - return FALSE; + return false; rr = drbd_recv_short(mdev, *sock, tb, 4, MSG_DONTWAIT | MSG_PEEK); if (rr > 0 || rr == -EAGAIN) { - return TRUE; + return true; } else { sock_release(*sock); *sock = NULL; - return FALSE; + return false; } } @@ -933,7 +933,7 @@ static int drbd_recv_header(struct drbd_conf *mdev, enum drbd_packets *cmd, unsi r = drbd_recv(mdev, h, sizeof(*h)); if (unlikely(r != sizeof(*h))) { dev_err(DEV, "short read expecting header on sock: r=%d\n", r); - return FALSE; + return false; } if (likely(h->h80.magic == BE_DRBD_MAGIC)) { @@ -947,11 +947,11 @@ static int drbd_recv_header(struct drbd_conf *mdev, enum drbd_packets *cmd, unsi be32_to_cpu(h->h80.magic), be16_to_cpu(h->h80.command), be16_to_cpu(h->h80.length)); - return FALSE; + return false; } mdev->last_received = jiffies; - return TRUE; + return true; } static void drbd_flush(struct drbd_conf *mdev) @@ -1160,7 +1160,7 @@ static int receive_Barrier(struct drbd_conf *mdev, enum drbd_packets cmd, unsign switch (mdev->write_ordering) { case WO_none: if (rv == FE_RECYCLED) - return TRUE; + return true; /* receiver context, in the writeout path of the other node. * avoid potential distributed deadlock */ @@ -1188,10 +1188,10 @@ static int receive_Barrier(struct drbd_conf *mdev, enum drbd_packets cmd, unsign D_ASSERT(atomic_read(&epoch->active) == 0); D_ASSERT(epoch->flags == 0); - return TRUE; + return true; default: dev_err(DEV, "Strangeness in mdev->write_ordering %d\n", mdev->write_ordering); - return FALSE; + return false; } epoch->flags = 0; @@ -1209,7 +1209,7 @@ static int receive_Barrier(struct drbd_conf *mdev, enum drbd_packets cmd, unsign } spin_unlock(&mdev->epoch_lock); - return TRUE; + return true; } /* used from receive_RSDataReply (recv_resync_read) @@ -1303,7 +1303,7 @@ static int drbd_drain_block(struct drbd_conf *mdev, int data_size) void *data; if (!data_size) - return TRUE; + return true; page = drbd_pp_alloc(mdev, 1, 1); @@ -1426,7 +1426,7 @@ static int recv_resync_read(struct drbd_conf *mdev, sector_t sector, int data_si atomic_add(data_size >> 9, &mdev->rs_sect_ev); if (drbd_submit_ee(mdev, e, WRITE, DRBD_FAULT_RS_WR) == 0) - return TRUE; + return true; /* drbd_submit_ee currently fails for one reason only: * not being able to allocate enough bios. @@ -1438,7 +1438,7 @@ static int recv_resync_read(struct drbd_conf *mdev, sector_t sector, int data_si drbd_free_ee(mdev, e); fail: put_ldev(mdev); - return FALSE; + return false; } static int receive_DataReply(struct drbd_conf *mdev, enum drbd_packets cmd, unsigned int data_size) @@ -1455,7 +1455,7 @@ static int receive_DataReply(struct drbd_conf *mdev, enum drbd_packets cmd, unsi spin_unlock_irq(&mdev->req_lock); if (unlikely(!req)) { dev_err(DEV, "Got a corrupt block_id/sector pair(1).\n"); - return FALSE; + return false; } /* hlist_del(&req->colision) is done in _req_may_be_done, to avoid @@ -1655,7 +1655,7 @@ static int receive_Data(struct drbd_conf *mdev, enum drbd_packets cmd, unsigned e = read_in_block(mdev, p->block_id, sector, data_size); if (!e) { put_ldev(mdev); - return FALSE; + return false; } e->w.cb = e_end_block; @@ -1774,7 +1774,7 @@ static int receive_Data(struct drbd_conf *mdev, enum drbd_packets cmd, unsigned put_ldev(mdev); wake_asender(mdev); finish_wait(&mdev->misc_wait, &wait); - return TRUE; + return true; } if (signal_pending(current)) { @@ -1830,7 +1830,7 @@ static int receive_Data(struct drbd_conf *mdev, enum drbd_packets cmd, unsigned } if (drbd_submit_ee(mdev, e, rw, DRBD_FAULT_DT_WR) == 0) - return TRUE; + return true; /* drbd_submit_ee currently fails for one reason only: * not being able to allocate enough bios. @@ -1848,7 +1848,7 @@ out_interrupted: * receive a barrier... atomic_inc(&mdev->epoch_size); */ put_ldev(mdev); drbd_free_ee(mdev, e); - return FALSE; + return false; } /* We may throttle resync, if the lower device seems to be busy, @@ -1934,12 +1934,12 @@ static int receive_DataRequest(struct drbd_conf *mdev, enum drbd_packets cmd, un if (size <= 0 || (size & 0x1ff) != 0 || size > DRBD_MAX_BIO_SIZE) { dev_err(DEV, "%s:%d: sector: %llus, size: %u\n", __FILE__, __LINE__, (unsigned long long)sector, size); - return FALSE; + return false; } if (sector + (size>>9) > capacity) { dev_err(DEV, "%s:%d: sector: %llus, size: %u\n", __FILE__, __LINE__, (unsigned long long)sector, size); - return FALSE; + return false; } if (!get_ldev_if_state(mdev, D_UP_TO_DATE)) { @@ -1976,7 +1976,7 @@ static int receive_DataRequest(struct drbd_conf *mdev, enum drbd_packets cmd, un e = drbd_alloc_ee(mdev, p->block_id, sector, size, GFP_NOIO); if (!e) { put_ldev(mdev); - return FALSE; + return false; } switch (cmd) { @@ -2089,7 +2089,7 @@ submit: spin_unlock_irq(&mdev->req_lock); if (drbd_submit_ee(mdev, e, READ, fault_type) == 0) - return TRUE; + return true; /* drbd_submit_ee currently fails for one reason only: * not being able to allocate enough bios. @@ -2102,7 +2102,7 @@ submit: out_free_e: put_ldev(mdev); drbd_free_ee(mdev, e); - return FALSE; + return false; } static int drbd_asb_recover_0p(struct drbd_conf *mdev) __must_hold(local) @@ -2690,7 +2690,7 @@ static int receive_protocol(struct drbd_conf *mdev, enum drbd_packets cmd, unsig unsigned char *my_alg = mdev->net_conf->integrity_alg; if (drbd_recv(mdev, p_integrity_alg, data_size) != data_size) - return FALSE; + return false; p_integrity_alg[SHARED_SECRET_MAX-1] = 0; if (strcmp(p_integrity_alg, my_alg)) { @@ -2701,11 +2701,11 @@ static int receive_protocol(struct drbd_conf *mdev, enum drbd_packets cmd, unsig my_alg[0] ? my_alg : (unsigned char *)""); } - return TRUE; + return true; disconnect: drbd_force_state(mdev, NS(conn, C_DISCONNECTING)); - return FALSE; + return false; } /* helper function @@ -2737,7 +2737,7 @@ struct crypto_hash *drbd_crypto_alloc_digest_safe(const struct drbd_conf *mdev, static int receive_SyncParam(struct drbd_conf *mdev, enum drbd_packets cmd, unsigned int packet_size) { - int ok = TRUE; + int ok = true; struct p_rs_param_95 *p = &mdev->data.rbuf.rs_param_95; unsigned int header_size, data_size, exp_max_sz; struct crypto_hash *verify_tfm = NULL; @@ -2755,7 +2755,7 @@ static int receive_SyncParam(struct drbd_conf *mdev, enum drbd_packets cmd, unsi if (packet_size > exp_max_sz) { dev_err(DEV, "SyncParam packet too long: received %u, expected <= %u bytes\n", packet_size, exp_max_sz); - return FALSE; + return false; } if (apv <= 88) { @@ -2775,7 +2775,7 @@ static int receive_SyncParam(struct drbd_conf *mdev, enum drbd_packets cmd, unsi memset(p->verify_alg, 0, 2 * SHARED_SECRET_MAX); if (drbd_recv(mdev, &p->head.payload, header_size) != header_size) - return FALSE; + return false; mdev->sync_conf.rate = be32_to_cpu(p->rate); @@ -2785,11 +2785,11 @@ static int receive_SyncParam(struct drbd_conf *mdev, enum drbd_packets cmd, unsi dev_err(DEV, "verify-alg too long, " "peer wants %u, accepting only %u byte\n", data_size, SHARED_SECRET_MAX); - return FALSE; + return false; } if (drbd_recv(mdev, p->verify_alg, data_size) != data_size) - return FALSE; + return false; /* we expect NUL terminated string */ /* but just in case someone tries to be evil */ @@ -2883,7 +2883,7 @@ disconnect: /* but free the verify_tfm again, if csums_tfm did not work out */ crypto_free_hash(verify_tfm); drbd_force_state(mdev, NS(conn, C_DISCONNECTING)); - return FALSE; + return false; } static void drbd_setup_order_type(struct drbd_conf *mdev, int peer) @@ -2920,7 +2920,7 @@ static int receive_sizes(struct drbd_conf *mdev, enum drbd_packets cmd, unsigned if (p_size == 0 && mdev->state.disk == D_DISKLESS) { dev_err(DEV, "some backing storage is needed\n"); drbd_force_state(mdev, NS(conn, C_DISCONNECTING)); - return FALSE; + return false; } /* just store the peer's disk size for now. @@ -2957,7 +2957,7 @@ static int receive_sizes(struct drbd_conf *mdev, enum drbd_packets cmd, unsigned drbd_force_state(mdev, NS(conn, C_DISCONNECTING)); mdev->ldev->dc.disk_size = my_usize; put_ldev(mdev); - return FALSE; + return false; } put_ldev(mdev); } @@ -2967,7 +2967,7 @@ static int receive_sizes(struct drbd_conf *mdev, enum drbd_packets cmd, unsigned dd = drbd_determin_dev_size(mdev, ddsf); put_ldev(mdev); if (dd == dev_size_error) - return FALSE; + return false; drbd_md_sync(mdev); } else { /* I am diskless, need to accept the peer's size. */ @@ -3014,7 +3014,7 @@ static int receive_sizes(struct drbd_conf *mdev, enum drbd_packets cmd, unsigned } } - return TRUE; + return true; } static int receive_uuids(struct drbd_conf *mdev, enum drbd_packets cmd, unsigned int data_size) @@ -3038,7 +3038,7 @@ static int receive_uuids(struct drbd_conf *mdev, enum drbd_packets cmd, unsigned dev_err(DEV, "Can only connect to data with current UUID=%016llX\n", (unsigned long long)mdev->ed_uuid); drbd_force_state(mdev, NS(conn, C_DISCONNECTING)); - return FALSE; + return false; } if (get_ldev(mdev)) { @@ -3073,7 +3073,7 @@ static int receive_uuids(struct drbd_conf *mdev, enum drbd_packets cmd, unsigned if (mdev->state.conn >= C_CONNECTED && mdev->state.disk < D_INCONSISTENT) drbd_set_ed_uuid(mdev, p_uuid[UI_CURRENT]); - return TRUE; + return true; } /** @@ -3118,7 +3118,7 @@ static int receive_req_state(struct drbd_conf *mdev, enum drbd_packets cmd, unsi if (test_bit(DISCARD_CONCURRENT, &mdev->flags) && test_bit(CLUSTER_ST_CHANGE, &mdev->flags)) { drbd_send_sr_reply(mdev, SS_CONCURRENT_ST_CHG); - return TRUE; + return true; } mask = convert_state(mask); @@ -3129,7 +3129,7 @@ static int receive_req_state(struct drbd_conf *mdev, enum drbd_packets cmd, unsi drbd_send_sr_reply(mdev, rv); drbd_md_sync(mdev); - return TRUE; + return true; } static int receive_state(struct drbd_conf *mdev, enum drbd_packets cmd, unsigned int data_size) @@ -3174,7 +3174,7 @@ static int receive_state(struct drbd_conf *mdev, enum drbd_packets cmd, unsigned peer_state.conn == C_CONNECTED) { if (drbd_bm_total_weight(mdev) <= mdev->rs_failed) drbd_resync_finished(mdev); - return TRUE; + return true; } } @@ -3227,10 +3227,10 @@ static int receive_state(struct drbd_conf *mdev, enum drbd_packets cmd, unsigned real_peer_disk = D_DISKLESS; } else { if (test_and_clear_bit(CONN_DRY_RUN, &mdev->flags)) - return FALSE; + return false; D_ASSERT(os.conn == C_WF_REPORT_PARAMS); drbd_force_state(mdev, NS(conn, C_DISCONNECTING)); - return FALSE; + return false; } } } @@ -3255,7 +3255,7 @@ static int receive_state(struct drbd_conf *mdev, enum drbd_packets cmd, unsigned drbd_uuid_new_current(mdev); clear_bit(NEW_CUR_UUID, &mdev->flags); drbd_force_state(mdev, NS2(conn, C_PROTOCOL_ERROR, susp, 0)); - return FALSE; + return false; } rv = _drbd_set_state(mdev, ns, cs_flags, NULL); ns = mdev->state; @@ -3263,7 +3263,7 @@ static int receive_state(struct drbd_conf *mdev, enum drbd_packets cmd, unsigned if (rv < SS_SUCCESS) { drbd_force_state(mdev, NS(conn, C_DISCONNECTING)); - return FALSE; + return false; } if (os.conn > C_WF_REPORT_PARAMS) { @@ -3281,7 +3281,7 @@ static int receive_state(struct drbd_conf *mdev, enum drbd_packets cmd, unsigned drbd_md_sync(mdev); /* update connected indicator, la_size, ... */ - return TRUE; + return true; } static int receive_sync_uuid(struct drbd_conf *mdev, enum drbd_packets cmd, unsigned int data_size) @@ -3308,7 +3308,7 @@ static int receive_sync_uuid(struct drbd_conf *mdev, enum drbd_packets cmd, unsi } else dev_err(DEV, "Ignoring SyncUUID packet!\n"); - return TRUE; + return true; } enum receive_bitmap_ret { OK, DONE, FAILED }; @@ -3462,7 +3462,7 @@ static int receive_bitmap(struct drbd_conf *mdev, enum drbd_packets cmd, unsigne struct bm_xfer_ctx c; void *buffer; enum receive_bitmap_ret ret; - int ok = FALSE; + int ok = false; struct p_header80 *h = &mdev->data.rbuf.header.h80; /* drbd_bm_lock(mdev, "receive bitmap"); By intention no bm_lock */ @@ -3535,7 +3535,7 @@ static int receive_bitmap(struct drbd_conf *mdev, enum drbd_packets cmd, unsigne drbd_conn_str(mdev->state.conn)); } - ok = TRUE; + ok = true; out: /* drbd_bm_unlock(mdev); by intention no lock */ if (ok && mdev->state.conn == C_WF_BITMAP_S) @@ -3569,7 +3569,7 @@ static int receive_UnplugRemote(struct drbd_conf *mdev, enum drbd_packets cmd, u * with the data requests being unplugged */ drbd_tcp_quickack(mdev->data.socket); - return TRUE; + return true; } static int receive_out_of_sync(struct drbd_conf *mdev, enum drbd_packets cmd, unsigned int data_size) @@ -3578,7 +3578,7 @@ static int receive_out_of_sync(struct drbd_conf *mdev, enum drbd_packets cmd, un drbd_set_out_of_sync(mdev, be64_to_cpu(p->sector), be32_to_cpu(p->blksize)); - return TRUE; + return true; } typedef int (*drbd_cmd_handler_f)(struct drbd_conf *, enum drbd_packets cmd, unsigned int to_receive); @@ -4147,7 +4147,7 @@ static int got_RqSReply(struct drbd_conf *mdev, struct p_header80 *h) } wake_up(&mdev->state_wait); - return TRUE; + return true; } static int got_Ping(struct drbd_conf *mdev, struct p_header80 *h) @@ -4163,7 +4163,7 @@ static int got_PingAck(struct drbd_conf *mdev, struct p_header80 *h) if (!test_and_set_bit(GOT_PING_ACK, &mdev->flags)) wake_up(&mdev->misc_wait); - return TRUE; + return true; } static int got_IsInSync(struct drbd_conf *mdev, struct p_header80 *h) @@ -4186,7 +4186,7 @@ static int got_IsInSync(struct drbd_conf *mdev, struct p_header80 *h) dec_rs_pending(mdev); atomic_add(blksize >> 9, &mdev->rs_sect_in); - return TRUE; + return true; } /* when we receive the ACK for a write request, @@ -4230,14 +4230,14 @@ static int validate_req_change_req_state(struct drbd_conf *mdev, if (unlikely(!req)) { spin_unlock_irq(&mdev->req_lock); dev_err(DEV, "%s: got a corrupt block_id/sector pair\n", func); - return FALSE; + return false; } __req_mod(req, what, &m); spin_unlock_irq(&mdev->req_lock); if (m.bio) complete_master_bio(mdev, &m); - return TRUE; + return true; } static int got_BlockAck(struct drbd_conf *mdev, struct p_header80 *h) @@ -4252,7 +4252,7 @@ static int got_BlockAck(struct drbd_conf *mdev, struct p_header80 *h) if (is_syncer_block_id(p->block_id)) { drbd_set_in_sync(mdev, sector, blksize); dec_rs_pending(mdev); - return TRUE; + return true; } switch (be16_to_cpu(h->command)) { case P_RS_WRITE_ACK: @@ -4273,7 +4273,7 @@ static int got_BlockAck(struct drbd_conf *mdev, struct p_header80 *h) break; default: D_ASSERT(0); - return FALSE; + return false; } return validate_req_change_req_state(mdev, p->block_id, sector, @@ -4294,7 +4294,7 @@ static int got_NegAck(struct drbd_conf *mdev, struct p_header80 *h) int size = be32_to_cpu(p->blksize); dec_rs_pending(mdev); drbd_rs_failed_io(mdev, sector, size); - return TRUE; + return true; } return validate_req_change_req_state(mdev, p->block_id, sector, _ack_id_to_req, __func__ , neg_acked); @@ -4332,7 +4332,7 @@ static int got_NegRSDReply(struct drbd_conf *mdev, struct p_header80 *h) put_ldev(mdev); } - return TRUE; + return true; } static int got_BarrierAck(struct drbd_conf *mdev, struct p_header80 *h) @@ -4349,7 +4349,7 @@ static int got_BarrierAck(struct drbd_conf *mdev, struct p_header80 *h) drbd_queue_work_front(&mdev->data.work, w); } - return TRUE; + return true; } static int got_OVResult(struct drbd_conf *mdev, struct p_header80 *h) @@ -4370,7 +4370,7 @@ static int got_OVResult(struct drbd_conf *mdev, struct p_header80 *h) ov_oos_print(mdev); if (!get_ldev(mdev)) - return TRUE; + return true; drbd_rs_complete_io(mdev, sector); dec_rs_pending(mdev); @@ -4393,12 +4393,12 @@ static int got_OVResult(struct drbd_conf *mdev, struct p_header80 *h) } } put_ldev(mdev); - return TRUE; + return true; } static int got_skip(struct drbd_conf *mdev, struct p_header80 *h) { - return TRUE; + return true; } struct asender_cmd { diff --git a/drivers/block/drbd/drbd_req.c b/drivers/block/drbd/drbd_req.c index 53e7cc5064562..528909090df72 100644 --- a/drivers/block/drbd/drbd_req.c +++ b/drivers/block/drbd/drbd_req.c @@ -445,7 +445,7 @@ int __req_mod(struct drbd_request *req, enum drbd_req_event what, req->rq_state |= RQ_LOCAL_COMPLETED; req->rq_state &= ~RQ_LOCAL_PENDING; - __drbd_chk_io_error(mdev, FALSE); + __drbd_chk_io_error(mdev, false); _req_may_be_done_not_susp(req, m); put_ldev(mdev); break; @@ -466,7 +466,7 @@ int __req_mod(struct drbd_request *req, enum drbd_req_event what, D_ASSERT(!(req->rq_state & RQ_NET_MASK)); - __drbd_chk_io_error(mdev, FALSE); + __drbd_chk_io_error(mdev, false); put_ldev(mdev); /* no point in retrying if there is no good remote data, diff --git a/drivers/block/drbd/drbd_worker.c b/drivers/block/drbd/drbd_worker.c index e201f6f82c0ee..9fe3e890da0f0 100644 --- a/drivers/block/drbd/drbd_worker.c +++ b/drivers/block/drbd/drbd_worker.c @@ -96,7 +96,7 @@ void drbd_endio_read_sec_final(struct drbd_epoch_entry *e) __releases(local) if (list_empty(&mdev->read_ee)) wake_up(&mdev->ee_wait); if (test_bit(__EE_WAS_ERROR, &e->flags)) - __drbd_chk_io_error(mdev, FALSE); + __drbd_chk_io_error(mdev, false); spin_unlock_irqrestore(&mdev->req_lock, flags); drbd_queue_work(&mdev->data.work, &e->w); @@ -139,7 +139,7 @@ static void drbd_endio_write_sec_final(struct drbd_epoch_entry *e) __releases(lo : list_empty(&mdev->active_ee); if (test_bit(__EE_WAS_ERROR, &e->flags)) - __drbd_chk_io_error(mdev, FALSE); + __drbd_chk_io_error(mdev, false); spin_unlock_irqrestore(&mdev->req_lock, flags); if (is_syncer_req) -- GitLab From f2024e7ce29f4287395ce879364cd68c7ac226f2 Mon Sep 17 00:00:00 2001 From: Andreas Gruenbacher Date: Fri, 10 Dec 2010 13:44:05 +0100 Subject: [PATCH 0444/2822] drbd: drbd_nl_disk_conf: Avoid a compiler warning MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Warning: comparison between ‘enum drbd_ret_code’ and ‘enum drbd_state_rv’ Signed-off-by: Philipp Reisner Signed-off-by: Lars Ellenberg --- drivers/block/drbd/drbd_nl.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/block/drbd/drbd_nl.c b/drivers/block/drbd/drbd_nl.c index 9e94c348c42c6..ada5483f7e56d 100644 --- a/drivers/block/drbd/drbd_nl.c +++ b/drivers/block/drbd/drbd_nl.c @@ -859,7 +859,7 @@ static int drbd_nl_disk_conf(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp struct lru_cache *resync_lru = NULL; union drbd_state ns, os; unsigned int max_bio_size; - int rv; + enum drbd_state_rv rv; int cp_discovered = 0; int logical_block_size; @@ -1005,9 +1005,10 @@ static int drbd_nl_disk_conf(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp /* and for any other previously queued work */ drbd_flush_workqueue(mdev); - retcode = _drbd_request_state(mdev, NS(disk, D_ATTACHING), CS_VERBOSE); + rv = _drbd_request_state(mdev, NS(disk, D_ATTACHING), CS_VERBOSE); + retcode = rv; /* FIXME: Type mismatch. */ drbd_resume_io(mdev); - if (retcode < SS_SUCCESS) + if (rv < SS_SUCCESS) goto fail; if (!get_ldev_if_state(mdev, D_ATTACHING)) -- GitLab From 4114be815f9811da42a21dc2f7ff552833660595 Mon Sep 17 00:00:00 2001 From: Andreas Gruenbacher Date: Fri, 10 Dec 2010 17:09:10 +0100 Subject: [PATCH 0445/2822] drbd: receive_bitmap: Fix the wrong return value Signed-off-by: Philipp Reisner Signed-off-by: Lars Ellenberg --- drivers/block/drbd/drbd_receiver.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/block/drbd/drbd_receiver.c b/drivers/block/drbd/drbd_receiver.c index 732aacb46a321..44b102d41b4a1 100644 --- a/drivers/block/drbd/drbd_receiver.c +++ b/drivers/block/drbd/drbd_receiver.c @@ -3499,7 +3499,7 @@ static int receive_bitmap(struct drbd_conf *mdev, enum drbd_packets cmd, unsigne goto out; if (data_size <= (sizeof(*p) - sizeof(p->head))) { dev_err(DEV, "ReportCBitmap packet too small (l:%u)\n", data_size); - return FAILED; + return false; } ret = decode_bitmap_c(mdev, p, &c); } else { -- GitLab From de1f8e4a0af3c2d0dff9f6341fead4b509941282 Mon Sep 17 00:00:00 2001 From: Andreas Gruenbacher Date: Fri, 10 Dec 2010 21:04:00 +0100 Subject: [PATCH 0446/2822] drbd: receive_bitmap: Avoid casting enum drbd_state_rv to int Signed-off-by: Philipp Reisner Signed-off-by: Lars Ellenberg --- drivers/block/drbd/drbd_receiver.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/block/drbd/drbd_receiver.c b/drivers/block/drbd/drbd_receiver.c index 44b102d41b4a1..2a604e7b7a013 100644 --- a/drivers/block/drbd/drbd_receiver.c +++ b/drivers/block/drbd/drbd_receiver.c @@ -3522,12 +3522,14 @@ static int receive_bitmap(struct drbd_conf *mdev, enum drbd_packets cmd, unsigne INFO_bm_xfer_stats(mdev, "receive", &c); if (mdev->state.conn == C_WF_BITMAP_T) { + enum drbd_state_rv rv; + ok = !drbd_send_bitmap(mdev); if (!ok) goto out; /* Omit CS_ORDERED with this state transition to avoid deadlocks. */ - ok = _drbd_request_state(mdev, NS(conn, C_WF_SYNC_UUID), CS_VERBOSE); - D_ASSERT(ok == SS_SUCCESS); + rv = _drbd_request_state(mdev, NS(conn, C_WF_SYNC_UUID), CS_VERBOSE); + D_ASSERT(rv == SS_SUCCESS); } else if (mdev->state.conn != C_WF_BITMAP_S) { /* admin may have requested C_DISCONNECTING, * other threads may have noticed network errors */ -- GitLab From 78fcbdae224469cb48767fa29ca41f1d5890e57c Mon Sep 17 00:00:00 2001 From: Andreas Gruenbacher Date: Fri, 10 Dec 2010 22:18:27 +0100 Subject: [PATCH 0447/2822] drbd: receive_bitmap: Missing free_page() on error path Signed-off-by: Philipp Reisner Signed-off-by: Lars Ellenberg --- drivers/block/drbd/drbd_receiver.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/block/drbd/drbd_receiver.c b/drivers/block/drbd/drbd_receiver.c index 2a604e7b7a013..f217d351d77c0 100644 --- a/drivers/block/drbd/drbd_receiver.c +++ b/drivers/block/drbd/drbd_receiver.c @@ -3499,7 +3499,7 @@ static int receive_bitmap(struct drbd_conf *mdev, enum drbd_packets cmd, unsigne goto out; if (data_size <= (sizeof(*p) - sizeof(p->head))) { dev_err(DEV, "ReportCBitmap packet too small (l:%u)\n", data_size); - return false; + goto out; } ret = decode_bitmap_c(mdev, p, &c); } else { -- GitLab From f70af118e3f3638698ac08959a41b9f9fe7237c8 Mon Sep 17 00:00:00 2001 From: Andreas Gruenbacher Date: Sat, 11 Dec 2010 18:51:50 +0100 Subject: [PATCH 0448/2822] drbd: send_bitmap_rle_or_plain: Get rid of ugly and useless enum Signed-off-by: Philipp Reisner Signed-off-by: Lars Ellenberg --- drivers/block/drbd/drbd_main.c | 33 +++++++++++++++++++++------------ 1 file changed, 21 insertions(+), 12 deletions(-) diff --git a/drivers/block/drbd/drbd_main.c b/drivers/block/drbd/drbd_main.c index 7eb447d20cced..7c72595b7ff0b 100644 --- a/drivers/block/drbd/drbd_main.c +++ b/drivers/block/drbd/drbd_main.c @@ -2140,9 +2140,15 @@ int fill_bitmap_rle_bits(struct drbd_conf *mdev, return len; } -enum { OK, FAILED, DONE } +/** + * send_bitmap_rle_or_plain + * + * Return 0 when done, 1 when another iteration is needed, and a negative error + * code upon failure. + */ +static int send_bitmap_rle_or_plain(struct drbd_conf *mdev, - struct p_header80 *h, struct bm_xfer_ctx *c) + struct p_header80 *h, struct bm_xfer_ctx *c) { struct p_compressed_bm *p = (void*)h; unsigned long num_words; @@ -2152,7 +2158,7 @@ send_bitmap_rle_or_plain(struct drbd_conf *mdev, len = fill_bitmap_rle_bits(mdev, p, c); if (len < 0) - return FAILED; + return -EIO; if (len) { DCBP_set_code(p, RLE_VLI_Bits); @@ -2182,11 +2188,14 @@ send_bitmap_rle_or_plain(struct drbd_conf *mdev, if (c->bit_offset > c->bm_bits) c->bit_offset = c->bm_bits; } - ok = ok ? ((len == 0) ? DONE : OK) : FAILED; - - if (ok == DONE) - INFO_bm_xfer_stats(mdev, "send", c); - return ok; + if (ok) { + if (len == 0) { + INFO_bm_xfer_stats(mdev, "send", c); + return 0; + } else + return 1; + } + return -EIO; } /* See the comment at receive_bitmap() */ @@ -2194,7 +2203,7 @@ int _drbd_send_bitmap(struct drbd_conf *mdev) { struct bm_xfer_ctx c; struct p_header80 *p; - int ret; + int err; ERR_IF(!mdev->bitmap) return false; @@ -2229,11 +2238,11 @@ int _drbd_send_bitmap(struct drbd_conf *mdev) }; do { - ret = send_bitmap_rle_or_plain(mdev, p, &c); - } while (ret == OK); + err = send_bitmap_rle_or_plain(mdev, p, &c); + } while (err > 0); free_page((unsigned long) p); - return (ret == DONE); + return err == 0; } int drbd_send_bitmap(struct drbd_conf *mdev) -- GitLab From 2c46407d241f4b0e5b87959aae8f50f41fdd2a3a Mon Sep 17 00:00:00 2001 From: Andreas Gruenbacher Date: Sat, 11 Dec 2010 21:53:12 +0100 Subject: [PATCH 0449/2822] drbd: receive_bitmap_plain: Get rid of ugly and useless enum Signed-off-by: Philipp Reisner Signed-off-by: Lars Ellenberg --- drivers/block/drbd/drbd_receiver.c | 73 +++++++++++++++++++----------- 1 file changed, 47 insertions(+), 26 deletions(-) diff --git a/drivers/block/drbd/drbd_receiver.c b/drivers/block/drbd/drbd_receiver.c index f217d351d77c0..be7fc67eeeca7 100644 --- a/drivers/block/drbd/drbd_receiver.c +++ b/drivers/block/drbd/drbd_receiver.c @@ -3311,23 +3311,32 @@ static int receive_sync_uuid(struct drbd_conf *mdev, enum drbd_packets cmd, unsi return true; } -enum receive_bitmap_ret { OK, DONE, FAILED }; - -static enum receive_bitmap_ret +/** + * receive_bitmap_plain + * + * Return 0 when done, 1 when another iteration is needed, and a negative error + * code upon failure. + */ +static int receive_bitmap_plain(struct drbd_conf *mdev, unsigned int data_size, unsigned long *buffer, struct bm_xfer_ctx *c) { unsigned num_words = min_t(size_t, BM_PACKET_WORDS, c->bm_words - c->word_offset); unsigned want = num_words * sizeof(long); + int err; if (want != data_size) { dev_err(DEV, "%s:want (%u) != data_size (%u)\n", __func__, want, data_size); - return FAILED; + return -EIO; } if (want == 0) - return DONE; - if (drbd_recv(mdev, buffer, want) != want) - return FAILED; + return 0; + err = drbd_recv(mdev, buffer, want); + if (err != want) { + if (err >= 0) + err = -EIO; + return err; + } drbd_bm_merge_lel(mdev, c->word_offset, num_words, buffer); @@ -3336,10 +3345,16 @@ receive_bitmap_plain(struct drbd_conf *mdev, unsigned int data_size, if (c->bit_offset > c->bm_bits) c->bit_offset = c->bm_bits; - return OK; + return 1; } -static enum receive_bitmap_ret +/** + * recv_bm_rle_bits + * + * Return 0 when done, 1 when another iteration is needed, and a negative error + * code upon failure. + */ +static int recv_bm_rle_bits(struct drbd_conf *mdev, struct p_compressed_bm *p, struct bm_xfer_ctx *c) @@ -3359,18 +3374,18 @@ recv_bm_rle_bits(struct drbd_conf *mdev, bits = bitstream_get_bits(&bs, &look_ahead, 64); if (bits < 0) - return FAILED; + return -EIO; for (have = bits; have > 0; s += rl, toggle = !toggle) { bits = vli_decode_bits(&rl, look_ahead); if (bits <= 0) - return FAILED; + return -EIO; if (toggle) { e = s + rl -1; if (e >= c->bm_bits) { dev_err(DEV, "bitmap overflow (e:%lu) while decoding bm RLE packet\n", e); - return FAILED; + return -EIO; } _drbd_bm_set_bits(mdev, s, e); } @@ -3380,14 +3395,14 @@ recv_bm_rle_bits(struct drbd_conf *mdev, have, bits, look_ahead, (unsigned int)(bs.cur.b - p->code), (unsigned int)bs.buf_len); - return FAILED; + return -EIO; } look_ahead >>= bits; have -= bits; bits = bitstream_get_bits(&bs, &tmp, 64 - have); if (bits < 0) - return FAILED; + return -EIO; look_ahead |= tmp << have; have += bits; } @@ -3395,10 +3410,16 @@ recv_bm_rle_bits(struct drbd_conf *mdev, c->bit_offset = s; bm_xfer_ctx_bit_to_word_offset(c); - return (s == c->bm_bits) ? DONE : OK; + return (s != c->bm_bits); } -static enum receive_bitmap_ret +/** + * decode_bitmap_c + * + * Return 0 when done, 1 when another iteration is needed, and a negative error + * code upon failure. + */ +static int decode_bitmap_c(struct drbd_conf *mdev, struct p_compressed_bm *p, struct bm_xfer_ctx *c) @@ -3412,7 +3433,7 @@ decode_bitmap_c(struct drbd_conf *mdev, dev_err(DEV, "receive_bitmap_c: unknown encoding %u\n", p->encoding); drbd_force_state(mdev, NS(conn, C_PROTOCOL_ERROR)); - return FAILED; + return -EIO; } void INFO_bm_xfer_stats(struct drbd_conf *mdev, @@ -3461,7 +3482,7 @@ static int receive_bitmap(struct drbd_conf *mdev, enum drbd_packets cmd, unsigne { struct bm_xfer_ctx c; void *buffer; - enum receive_bitmap_ret ret; + int err; int ok = false; struct p_header80 *h = &mdev->data.rbuf.header.h80; @@ -3480,9 +3501,9 @@ static int receive_bitmap(struct drbd_conf *mdev, enum drbd_packets cmd, unsigne .bm_words = drbd_bm_words(mdev), }; - do { + for(;;) { if (cmd == P_BITMAP) { - ret = receive_bitmap_plain(mdev, data_size, buffer, &c); + err = receive_bitmap_plain(mdev, data_size, buffer, &c); } else if (cmd == P_COMPRESSED_BITMAP) { /* MAYBE: sanity check that we speak proto >= 90, * and the feature is enabled! */ @@ -3501,7 +3522,7 @@ static int receive_bitmap(struct drbd_conf *mdev, enum drbd_packets cmd, unsigne dev_err(DEV, "ReportCBitmap packet too small (l:%u)\n", data_size); goto out; } - ret = decode_bitmap_c(mdev, p, &c); + err = decode_bitmap_c(mdev, p, &c); } else { dev_warn(DEV, "receive_bitmap: cmd neither ReportBitMap nor ReportCBitMap (is 0x%x)", cmd); goto out; @@ -3510,14 +3531,14 @@ static int receive_bitmap(struct drbd_conf *mdev, enum drbd_packets cmd, unsigne c.packets[cmd == P_BITMAP]++; c.bytes[cmd == P_BITMAP] += sizeof(struct p_header80) + data_size; - if (ret != OK) + if (err <= 0) { + if (err < 0) + goto out; break; - + } if (!drbd_recv_header(mdev, &cmd, &data_size)) goto out; - } while (ret == OK); - if (ret == FAILED) - goto out; + } INFO_bm_xfer_stats(mdev, "receive", &c); -- GitLab From 24dccabb390412d04435e11cfb535df51def7b2d Mon Sep 17 00:00:00 2001 From: Andreas Gruenbacher Date: Sun, 12 Dec 2010 17:45:41 +0100 Subject: [PATCH 0450/2822] drbd: Fix: drbd_bitmap_io does not return an enum determine_dev_size I guess bitmap I/O errors are supposed to cause drbd_determin_dev_size to return dev_size_error. Signed-off-by: Philipp Reisner Signed-off-by: Lars Ellenberg --- drivers/block/drbd/drbd_nl.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/block/drbd/drbd_nl.c b/drivers/block/drbd/drbd_nl.c index ada5483f7e56d..2f07249821438 100644 --- a/drivers/block/drbd/drbd_nl.c +++ b/drivers/block/drbd/drbd_nl.c @@ -643,11 +643,17 @@ enum determine_dev_size drbd_determin_dev_size(struct drbd_conf *mdev, enum dds_ || prev_size != mdev->ldev->md.md_size_sect; if (la_size_changed || md_moved) { + int err; + drbd_al_shrink(mdev); /* All extents inactive. */ dev_info(DEV, "Writing the whole bitmap, %s\n", la_size_changed && md_moved ? "size changed and md moved" : la_size_changed ? "size changed" : "md moved"); - rv = drbd_bitmap_io(mdev, &drbd_bm_write, "size changed"); /* does drbd_resume_io() ! */ + err = drbd_bitmap_io(mdev, &drbd_bm_write, "size changed"); /* does drbd_resume_io() ! */ + if (err) { + rv = dev_size_error; + goto out; + } drbd_md_mark_dirty(mdev); } -- GitLab From 1b881ef77537f1077482f9946a6a99b4e2dd54b2 Mon Sep 17 00:00:00 2001 From: Andreas Gruenbacher Date: Mon, 13 Dec 2010 18:03:38 +0100 Subject: [PATCH 0451/2822] drbd: Rename __inc_ap_bio_cond to may_inc_ap_bio The old name is confusing: the function does not increment anything. Also rename _inc_ap_bio_cond to inc_ap_bio_cond: there is no need for an underscore. Finally, make it clear that these functions return boolean values. Signed-off-by: Philipp Reisner Signed-off-by: Lars Ellenberg --- drivers/block/drbd/drbd_int.h | 22 +++++++++++----------- drivers/block/drbd/drbd_main.c | 2 +- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/drivers/block/drbd/drbd_int.h b/drivers/block/drbd/drbd_int.h index 0855934e19d0c..f6da48bb8c707 100644 --- a/drivers/block/drbd/drbd_int.h +++ b/drivers/block/drbd/drbd_int.h @@ -2284,14 +2284,14 @@ static inline int is_susp(union drbd_state s) return s.susp || s.susp_nod || s.susp_fen; } -static inline int __inc_ap_bio_cond(struct drbd_conf *mdev) +static inline bool may_inc_ap_bio(struct drbd_conf *mdev) { int mxb = drbd_get_max_buffers(mdev); if (is_susp(mdev->state)) - return 0; + return false; if (test_bit(SUSPEND_IO, &mdev->flags)) - return 0; + return false; /* to avoid potential deadlock or bitmap corruption, * in various places, we only allow new application io @@ -2299,23 +2299,23 @@ static inline int __inc_ap_bio_cond(struct drbd_conf *mdev) /* no new io accepted when attaching or detaching the disk */ if (!drbd_state_is_stable(mdev)) - return 0; + return false; /* since some older kernels don't have atomic_add_unless, * and we are within the spinlock anyways, we have this workaround. */ if (atomic_read(&mdev->ap_bio_cnt) > mxb) - return 0; + return false; if (test_bit(BITMAP_IO, &mdev->flags)) - return 0; - return 1; + return false; + return true; } -static inline int _inc_ap_bio_cond(struct drbd_conf *mdev, int count) +static inline bool inc_ap_bio_cond(struct drbd_conf *mdev, int count) { - int rv = 0; + bool rv = false; spin_lock_irq(&mdev->req_lock); - rv = __inc_ap_bio_cond(mdev); + rv = may_inc_ap_bio(mdev); if (rv) atomic_add(count, &mdev->ap_bio_cnt); spin_unlock_irq(&mdev->req_lock); @@ -2333,7 +2333,7 @@ static inline void inc_ap_bio(struct drbd_conf *mdev, int count) * to avoid races with the reconnect code, * we need to atomic_inc within the spinlock. */ - wait_event(mdev->misc_wait, _inc_ap_bio_cond(mdev, count)); + wait_event(mdev->misc_wait, inc_ap_bio_cond(mdev, count)); } static inline void dec_ap_bio(struct drbd_conf *mdev) diff --git a/drivers/block/drbd/drbd_main.c b/drivers/block/drbd/drbd_main.c index 7c72595b7ff0b..67fffad213ec9 100644 --- a/drivers/block/drbd/drbd_main.c +++ b/drivers/block/drbd/drbd_main.c @@ -3239,7 +3239,7 @@ static int drbd_congested(void *congested_data, int bdi_bits) char reason = '-'; int r = 0; - if (!__inc_ap_bio_cond(mdev)) { + if (!may_inc_ap_bio(mdev)) { /* DRBD has frozen IO */ r = bdi_bits; reason = 'd'; -- GitLab From 7777a8ba1fc980e5edfe492ebf5a1676497b8db2 Mon Sep 17 00:00:00 2001 From: Lars Ellenberg Date: Wed, 15 Dec 2010 23:21:39 +0100 Subject: [PATCH 0452/2822] drbd: bitmap: don't count unused bits (fix non-terminating resync) We trusted the on-disk bitmap to have unused bits cleared. In case that is not true for whatever reason, and we take a code path where the unused bits don't get cleared elsewhere (bm_clear_surplus is not called), we may miscount the bits, and get confused during resync, waiting for bits to get cleared that we don't even use: the resync process would not terminate. Fix this by masking out unused bits in __bm_count_bits. Signed-off-by: Philipp Reisner Signed-off-by: Lars Ellenberg --- drivers/block/drbd/drbd_bitmap.c | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/drivers/block/drbd/drbd_bitmap.c b/drivers/block/drbd/drbd_bitmap.c index 9390e9526786e..c5361487cf471 100644 --- a/drivers/block/drbd/drbd_bitmap.c +++ b/drivers/block/drbd/drbd_bitmap.c @@ -376,9 +376,16 @@ static unsigned long __bm_count_bits(struct drbd_bitmap *b, const int swap_endia unsigned long *p_addr, *bm, offset = 0; unsigned long bits = 0; unsigned long i, do_now; + unsigned long words; - while (offset < b->bm_words) { - i = do_now = min_t(size_t, b->bm_words-offset, LWPP); + /* due to 64bit alignment, the last long on a 32bit arch + * may be not used at all. The last used long will likely + * be only partially used, always. Don't count those bits, + * but mask them out. */ + words = (b->bm_bits + BITS_PER_LONG - 1) >> LN2_BPL; + + while (offset < words) { + i = do_now = min_t(size_t, words-offset, LWPP); p_addr = __bm_map_paddr(b, offset, KM_USER0); bm = p_addr + MLPP(offset); while (i--) { @@ -388,8 +395,20 @@ static unsigned long __bm_count_bits(struct drbd_bitmap *b, const int swap_endia #endif bits += hweight_long(*bm++); } - __bm_unmap(p_addr, KM_USER0); offset += do_now; + if (offset == words) { + /* last word may only be partially used, + * see also bm_clear_surplus. */ + i = (1UL << (b->bm_bits & (BITS_PER_LONG-1))) -1; + if (i) { + bits -= hweight_long(p_addr[do_now-1] & ~i); + p_addr[do_now-1] &= i; + } + /* 32bit arch, may have an unused padding long */ + if (words != b->bm_words) + p_addr[do_now] = 0; + } + __bm_unmap(p_addr, KM_USER0); cond_resched(); } -- GitLab From 95a0f10cddbf93ce89c175ac1c53dad2d20ad309 Mon Sep 17 00:00:00 2001 From: Lars Ellenberg Date: Wed, 15 Dec 2010 08:59:09 +0100 Subject: [PATCH 0453/2822] drbd: store in-core bitmap little endian, regardless of architecture Our on-disk bitmap is a little endian bitstream. Up to now, we have stored the in-core copy of that in native endian, applying byte order conversion when necessary. Instead, keep the bitmap pages little endian, as they are read from disk, and use the generic_*_le_bit family of functions. Signed-off-by: Philipp Reisner Signed-off-by: Lars Ellenberg --- drivers/block/drbd/drbd_bitmap.c | 166 ++++++++++++++++--------------- 1 file changed, 84 insertions(+), 82 deletions(-) diff --git a/drivers/block/drbd/drbd_bitmap.c b/drivers/block/drbd/drbd_bitmap.c index c5361487cf471..8d959ed6c2cce 100644 --- a/drivers/block/drbd/drbd_bitmap.c +++ b/drivers/block/drbd/drbd_bitmap.c @@ -30,6 +30,7 @@ #include #include "drbd_int.h" + /* OPAQUE outside this file! * interface defined in drbd_int.h @@ -154,6 +155,14 @@ void drbd_bm_unlock(struct drbd_conf *mdev) mutex_unlock(&b->bm_change); } +static unsigned int bm_bit_to_page_idx(struct drbd_bitmap *b, u64 bitnr) +{ + /* page_nr = (bitnr/8) >> PAGE_SHIFT; */ + unsigned int page_nr = bitnr >> (PAGE_SHIFT + 3); + BUG_ON(page_nr >= b->bm_number_of_pages); + return page_nr; +} + /* word offset to long pointer */ static unsigned long *__bm_map_paddr(struct drbd_bitmap *b, unsigned long offset, const enum km_type km) { @@ -168,6 +177,17 @@ static unsigned long *__bm_map_paddr(struct drbd_bitmap *b, unsigned long offset return (unsigned long *) kmap_atomic(page, km); } +static unsigned long *__bm_map_pidx(struct drbd_bitmap *b, unsigned int idx, const enum km_type km) +{ + struct page *page = b->bm_pages[idx]; + return (unsigned long *) kmap_atomic(page, km); +} + +static unsigned long *bm_map_pidx(struct drbd_bitmap *b, unsigned int idx) +{ + return __bm_map_pidx(b, idx, KM_IRQ1); +} + static unsigned long * bm_map_paddr(struct drbd_bitmap *b, unsigned long offset) { return __bm_map_paddr(b, offset, KM_IRQ1); @@ -329,22 +349,42 @@ void drbd_bm_cleanup(struct drbd_conf *mdev) * this masks out the remaining bits. * Returns the number of bits cleared. */ +#define BITS_PER_PAGE (1UL << (PAGE_SHIFT + 3)) +#define BITS_PER_PAGE_MASK (BITS_PER_PAGE - 1) +#define BITS_PER_LONG_MASK (BITS_PER_LONG - 1) static int bm_clear_surplus(struct drbd_bitmap *b) { - const unsigned long mask = (1UL << (b->bm_bits & (BITS_PER_LONG-1))) - 1; - size_t w = b->bm_bits >> LN2_BPL; - int cleared = 0; + unsigned long mask; unsigned long *p_addr, *bm; + int tmp; + int cleared = 0; - p_addr = bm_map_paddr(b, w); - bm = p_addr + MLPP(w); - if (w < b->bm_words) { + /* number of bits modulo bits per page */ + tmp = (b->bm_bits & BITS_PER_PAGE_MASK); + /* mask the used bits of the word containing the last bit */ + mask = (1UL << (tmp & BITS_PER_LONG_MASK)) -1; + /* bitmap is always stored little endian, + * on disk and in core memory alike */ + mask = cpu_to_lel(mask); + + /* because of the "extra long to catch oob access" we allocate in + * drbd_bm_resize, bm_number_of_pages -1 is not necessarily the page + * containing the last _relevant_ bitmap word */ + p_addr = bm_map_pidx(b, bm_bit_to_page_idx(b, b->bm_bits - 1)); + bm = p_addr + (tmp/BITS_PER_LONG); + if (mask) { + /* If mask != 0, we are not exactly aligned, so bm now points + * to the long containing the last bit. + * If mask == 0, bm already points to the word immediately + * after the last (long word aligned) bit. */ cleared = hweight_long(*bm & ~mask); *bm &= mask; - w++; bm++; + bm++; } - if (w < b->bm_words) { + if (BITS_PER_LONG == 32 && ((bm - p_addr) & 1) == 1) { + /* on a 32bit arch, we may need to zero out + * a padding long to align with a 64bit remote */ cleared += hweight_long(*bm); *bm = 0; } @@ -354,24 +394,41 @@ static int bm_clear_surplus(struct drbd_bitmap *b) static void bm_set_surplus(struct drbd_bitmap *b) { - const unsigned long mask = (1UL << (b->bm_bits & (BITS_PER_LONG-1))) - 1; - size_t w = b->bm_bits >> LN2_BPL; + unsigned long mask; unsigned long *p_addr, *bm; - - p_addr = bm_map_paddr(b, w); - bm = p_addr + MLPP(w); - if (w < b->bm_words) { + int tmp; + + /* number of bits modulo bits per page */ + tmp = (b->bm_bits & BITS_PER_PAGE_MASK); + /* mask the used bits of the word containing the last bit */ + mask = (1UL << (tmp & BITS_PER_LONG_MASK)) -1; + /* bitmap is always stored little endian, + * on disk and in core memory alike */ + mask = cpu_to_lel(mask); + + /* because of the "extra long to catch oob access" we allocate in + * drbd_bm_resize, bm_number_of_pages -1 is not necessarily the page + * containing the last _relevant_ bitmap word */ + p_addr = bm_map_pidx(b, bm_bit_to_page_idx(b, b->bm_bits - 1)); + bm = p_addr + (tmp/BITS_PER_LONG); + if (mask) { + /* If mask != 0, we are not exactly aligned, so bm now points + * to the long containing the last bit. + * If mask == 0, bm already points to the word immediately + * after the last (long word aligned) bit. */ *bm |= ~mask; - bm++; w++; + bm++; } - if (w < b->bm_words) { - *bm = ~(0UL); + if (BITS_PER_LONG == 32 && ((bm - p_addr) & 1) == 1) { + /* on a 32bit arch, we may need to zero out + * a padding long to align with a 64bit remote */ + *bm = ~0UL; } bm_unmap(p_addr); } -static unsigned long __bm_count_bits(struct drbd_bitmap *b, const int swap_endian) +static unsigned long bm_count_bits(struct drbd_bitmap *b) { unsigned long *p_addr, *bm, offset = 0; unsigned long bits = 0; @@ -389,10 +446,6 @@ static unsigned long __bm_count_bits(struct drbd_bitmap *b, const int swap_endia p_addr = __bm_map_paddr(b, offset, KM_USER0); bm = p_addr + MLPP(offset); while (i--) { -#ifndef __LITTLE_ENDIAN - if (swap_endian) - *bm = lel_to_cpu(*bm); -#endif bits += hweight_long(*bm++); } offset += do_now; @@ -415,16 +468,6 @@ static unsigned long __bm_count_bits(struct drbd_bitmap *b, const int swap_endia return bits; } -static unsigned long bm_count_bits(struct drbd_bitmap *b) -{ - return __bm_count_bits(b, 0); -} - -static unsigned long bm_count_bits_swap_endian(struct drbd_bitmap *b) -{ - return __bm_count_bits(b, 1); -} - /* offset and len in long words.*/ static void bm_memset(struct drbd_bitmap *b, size_t offset, int c, size_t len) { @@ -662,7 +705,7 @@ void drbd_bm_merge_lel(struct drbd_conf *mdev, size_t offset, size_t number, offset += do_now; while (do_now--) { bits = hweight_long(*bm); - word = *bm | lel_to_cpu(*buffer++); + word = *bm | *buffer++; *bm++ = word; b->bm_set += hweight_long(word) - bits; } @@ -709,7 +752,7 @@ void drbd_bm_get_lel(struct drbd_conf *mdev, size_t offset, size_t number, bm = p_addr + MLPP(offset); offset += do_now; while (do_now--) - *buffer++ = cpu_to_lel(*bm++); + *buffer++ = *bm++; bm_unmap(p_addr); } } @@ -795,39 +838,6 @@ static void bm_page_io_async(struct drbd_conf *mdev, struct drbd_bitmap *b, int } } -# if defined(__LITTLE_ENDIAN) - /* nothing to do, on disk == in memory */ -# define bm_cpu_to_lel(x) ((void)0) -# else -static void bm_cpu_to_lel(struct drbd_bitmap *b) -{ - /* need to cpu_to_lel all the pages ... - * this may be optimized by using - * cpu_to_lel(-1) == -1 and cpu_to_lel(0) == 0; - * the following is still not optimal, but better than nothing */ - unsigned int i; - unsigned long *p_addr, *bm; - if (b->bm_set == 0) { - /* no page at all; avoid swap if all is 0 */ - i = b->bm_number_of_pages; - } else if (b->bm_set == b->bm_bits) { - /* only the last page */ - i = b->bm_number_of_pages - 1; - } else { - /* all pages */ - i = 0; - } - for (; i < b->bm_number_of_pages; i++) { - p_addr = kmap_atomic(b->bm_pages[i], KM_USER0); - for (bm = p_addr; bm < p_addr + PAGE_SIZE/sizeof(long); bm++) - *bm = cpu_to_lel(*bm); - kunmap_atomic(p_addr, KM_USER0); - } -} -# endif -/* lel_to_cpu == cpu_to_lel */ -# define bm_lel_to_cpu(x) bm_cpu_to_lel(x) - /* * bm_rw: read/write the whole bitmap from/to its on disk location. */ @@ -847,10 +857,6 @@ static int bm_rw(struct drbd_conf *mdev, int rw) __must_hold(local) bm_words = drbd_bm_words(mdev); num_pages = (bm_words*sizeof(long) + PAGE_SIZE-1) >> PAGE_SHIFT; - /* on disk bitmap is little endian */ - if (rw == WRITE) - bm_cpu_to_lel(b); - now = jiffies; atomic_set(&b->bm_async_io, num_pages); __clear_bit(BM_MD_IO_ERROR, &b->bm_flags); @@ -869,13 +875,9 @@ static int bm_rw(struct drbd_conf *mdev, int rw) __must_hold(local) now = jiffies; if (rw == WRITE) { - /* swap back endianness */ - bm_lel_to_cpu(b); - /* flush bitmap to stable storage */ drbd_md_flush(mdev); } else /* rw == READ */ { - /* just read, if necessary adjust endianness */ - b->bm_set = bm_count_bits_swap_endian(b); + b->bm_set = bm_count_bits(b); dev_info(DEV, "recounting of set bits took additional %lu jiffies\n", jiffies - now); } @@ -969,9 +971,9 @@ static unsigned long __bm_find_next(struct drbd_conf *mdev, unsigned long bm_fo, p_addr = __bm_map_paddr(b, offset, km); if (find_zero_bit) - i = find_next_zero_bit(p_addr, PAGE_SIZE*8, bm_fo & BPP_MASK); + i = generic_find_next_zero_le_bit(p_addr, PAGE_SIZE*8, bm_fo & BPP_MASK); else - i = find_next_bit(p_addr, PAGE_SIZE*8, bm_fo & BPP_MASK); + i = generic_find_next_le_bit(p_addr, PAGE_SIZE*8, bm_fo & BPP_MASK); __bm_unmap(p_addr, km); if (i < PAGE_SIZE*8) { @@ -1064,9 +1066,9 @@ static int __bm_change_bits_to(struct drbd_conf *mdev, const unsigned long s, last_page_nr = page_nr; } if (val) - c += (0 == __test_and_set_bit(bitnr & BPP_MASK, p_addr)); + c += (0 == generic___test_and_set_le_bit(bitnr & BPP_MASK, p_addr)); else - c -= (0 != __test_and_clear_bit(bitnr & BPP_MASK, p_addr)); + c -= (0 != generic___test_and_clear_le_bit(bitnr & BPP_MASK, p_addr)); } if (p_addr) __bm_unmap(p_addr, km); @@ -1211,7 +1213,7 @@ int drbd_bm_test_bit(struct drbd_conf *mdev, const unsigned long bitnr) if (bitnr < b->bm_bits) { unsigned long offset = bitnr>>LN2_BPL; p_addr = bm_map_paddr(b, offset); - i = test_bit(bitnr & BPP_MASK, p_addr) ? 1 : 0; + i = generic_test_le_bit(bitnr & BPP_MASK, p_addr) ? 1 : 0; bm_unmap(p_addr); } else if (bitnr == b->bm_bits) { i = -1; @@ -1255,7 +1257,7 @@ int drbd_bm_count_bits(struct drbd_conf *mdev, const unsigned long s, const unsi ERR_IF (bitnr >= b->bm_bits) { dev_err(DEV, "bitnr=%lu bm_bits=%lu\n", bitnr, b->bm_bits); } else { - c += (0 != test_bit(bitnr - (page_nr << (PAGE_SHIFT+3)), p_addr)); + c += (0 != generic_test_le_bit(bitnr - (page_nr << (PAGE_SHIFT+3)), p_addr)); } } if (p_addr) -- GitLab From 19f843aa08e2d8f87a09b4c2edc43b00638423a8 Mon Sep 17 00:00:00 2001 From: Lars Ellenberg Date: Wed, 15 Dec 2010 08:59:11 +0100 Subject: [PATCH 0454/2822] drbd: bitmap keep track of changes vs on-disk bitmap When we set or clear bits in a bitmap page, also set a flag in the page->private pointer. This allows us to skip writes of unchanged pages. Signed-off-by: Philipp Reisner Signed-off-by: Lars Ellenberg --- drivers/block/drbd/drbd_actlog.c | 132 +++------- drivers/block/drbd/drbd_bitmap.c | 409 +++++++++++++++++++++++-------- drivers/block/drbd/drbd_int.h | 7 +- drivers/block/drbd/drbd_main.c | 27 +- drivers/block/drbd/drbd_nl.c | 11 +- drivers/block/drbd/drbd_worker.c | 7 +- 6 files changed, 373 insertions(+), 220 deletions(-) diff --git a/drivers/block/drbd/drbd_actlog.c b/drivers/block/drbd/drbd_actlog.c index e3f0f4d31d757..090fc2ce0df48 100644 --- a/drivers/block/drbd/drbd_actlog.c +++ b/drivers/block/drbd/drbd_actlog.c @@ -262,6 +262,33 @@ void drbd_al_complete_io(struct drbd_conf *mdev, sector_t sector) spin_unlock_irqrestore(&mdev->al_lock, flags); } +#if (PAGE_SHIFT + 3) < (AL_EXTENT_SHIFT - BM_BLOCK_SHIFT) +/* Currently BM_BLOCK_SHIFT, BM_EXT_SHIFT and AL_EXTENT_SHIFT + * are still coupled, or assume too much about their relation. + * Code below will not work if this is violated. + * Will be cleaned up with some followup patch. + */ +# error FIXME +#endif + +static unsigned int al_extent_to_bm_page(unsigned int al_enr) +{ + return al_enr >> + /* bit to page */ + ((PAGE_SHIFT + 3) - + /* al extent number to bit */ + (AL_EXTENT_SHIFT - BM_BLOCK_SHIFT)); +} + +static unsigned int rs_extent_to_bm_page(unsigned int rs_enr) +{ + return rs_enr >> + /* bit to page */ + ((PAGE_SHIFT + 3) - + /* al extent number to bit */ + (BM_EXT_SHIFT - BM_BLOCK_SHIFT)); +} + int w_al_write_transaction(struct drbd_conf *mdev, struct drbd_work *w, int unused) { @@ -289,7 +316,7 @@ w_al_write_transaction(struct drbd_conf *mdev, struct drbd_work *w, int unused) * For now, we must not write the transaction, * if we cannot write out the bitmap of the evicted extent. */ if (mdev->state.conn < C_CONNECTED && evicted != LC_FREE) - drbd_bm_write_sect(mdev, evicted/AL_EXT_PER_BM_SECT); + drbd_bm_write_page(mdev, al_extent_to_bm_page(evicted)); /* The bitmap write may have failed, causing a state change. */ if (mdev->state.disk < D_INCONSISTENT) { @@ -635,105 +662,6 @@ out_bio_put: return err; } -/** - * drbd_al_to_on_disk_bm() - * Writes bitmap parts covered by active AL extents - * @mdev: DRBD device. - * - * Called when we detach (unconfigure) local storage, - * or when we go from R_PRIMARY to R_SECONDARY role. - */ -void drbd_al_to_on_disk_bm(struct drbd_conf *mdev) -{ - int i, nr_elements; - unsigned int enr; - struct bio **bios; - struct drbd_atodb_wait wc; - - ERR_IF (!get_ldev_if_state(mdev, D_ATTACHING)) - return; /* sorry, I don't have any act_log etc... */ - - wait_event(mdev->al_wait, lc_try_lock(mdev->act_log)); - - nr_elements = mdev->act_log->nr_elements; - - /* GFP_KERNEL, we are not in anyone's write-out path */ - bios = kzalloc(sizeof(struct bio *) * nr_elements, GFP_KERNEL); - if (!bios) - goto submit_one_by_one; - - atomic_set(&wc.count, 0); - init_completion(&wc.io_done); - wc.mdev = mdev; - wc.error = 0; - - for (i = 0; i < nr_elements; i++) { - enr = lc_element_by_index(mdev->act_log, i)->lc_number; - if (enr == LC_FREE) - continue; - /* next statement also does atomic_inc wc.count and local_cnt */ - if (atodb_prepare_unless_covered(mdev, bios, - enr/AL_EXT_PER_BM_SECT, - &wc)) - goto free_bios_submit_one_by_one; - } - - /* unnecessary optimization? */ - lc_unlock(mdev->act_log); - wake_up(&mdev->al_wait); - - /* all prepared, submit them */ - for (i = 0; i < nr_elements; i++) { - if (bios[i] == NULL) - break; - if (drbd_insert_fault(mdev, DRBD_FAULT_MD_WR)) { - bios[i]->bi_rw = WRITE; - bio_endio(bios[i], -EIO); - } else { - submit_bio(WRITE, bios[i]); - } - } - - /* always (try to) flush bitmap to stable storage */ - drbd_md_flush(mdev); - - /* In case we did not submit a single IO do not wait for - * them to complete. ( Because we would wait forever here. ) - * - * In case we had IOs and they are already complete, there - * is not point in waiting anyways. - * Therefore this if () ... */ - if (atomic_read(&wc.count)) - wait_for_completion(&wc.io_done); - - put_ldev(mdev); - - kfree(bios); - return; - - free_bios_submit_one_by_one: - /* free everything by calling the endio callback directly. */ - for (i = 0; i < nr_elements && bios[i]; i++) - bio_endio(bios[i], 0); - - kfree(bios); - - submit_one_by_one: - dev_warn(DEV, "Using the slow drbd_al_to_on_disk_bm()\n"); - - for (i = 0; i < mdev->act_log->nr_elements; i++) { - enr = lc_element_by_index(mdev->act_log, i)->lc_number; - if (enr == LC_FREE) - continue; - /* Really slow: if we have al-extents 16..19 active, - * sector 4 will be written four times! Synchronous! */ - drbd_bm_write_sect(mdev, enr/AL_EXT_PER_BM_SECT); - } - - lc_unlock(mdev->act_log); - wake_up(&mdev->al_wait); - put_ldev(mdev); -} - /** * drbd_al_apply_to_bm() - Sets the bitmap to diry(1) where covered ba active AL extents * @mdev: DRBD device. @@ -813,7 +741,7 @@ static int w_update_odbm(struct drbd_conf *mdev, struct drbd_work *w, int unused return 1; } - drbd_bm_write_sect(mdev, udw->enr); + drbd_bm_write_page(mdev, rs_extent_to_bm_page(udw->enr)); put_ldev(mdev); kfree(udw); @@ -893,7 +821,6 @@ static void drbd_try_clear_on_disk_bm(struct drbd_conf *mdev, sector_t sector, dev_warn(DEV, "Kicking resync_lru element enr=%u " "out with rs_failed=%d\n", ext->lce.lc_number, ext->rs_failed); - set_bit(WRITE_BM_AFTER_RESYNC, &mdev->flags); } ext->rs_left = rs_left; ext->rs_failed = success ? 0 : count; @@ -912,7 +839,6 @@ static void drbd_try_clear_on_disk_bm(struct drbd_conf *mdev, sector_t sector, drbd_queue_work_front(&mdev->data.work, &udw->w); } else { dev_warn(DEV, "Could not kmalloc an udw\n"); - set_bit(WRITE_BM_AFTER_RESYNC, &mdev->flags); } } } else { diff --git a/drivers/block/drbd/drbd_bitmap.c b/drivers/block/drbd/drbd_bitmap.c index 8d959ed6c2cce..72cd41a96ef97 100644 --- a/drivers/block/drbd/drbd_bitmap.c +++ b/drivers/block/drbd/drbd_bitmap.c @@ -70,8 +70,7 @@ struct drbd_bitmap { sector_t bm_dev_capacity; struct mutex bm_change; /* serializes resize operations */ - atomic_t bm_async_io; - wait_queue_head_t bm_io_wait; + wait_queue_head_t bm_io_wait; /* used to serialize IO of single pages */ unsigned long bm_flags; @@ -82,7 +81,7 @@ struct drbd_bitmap { /* definition of bits in bm_flags */ #define BM_LOCKED 0 -#define BM_MD_IO_ERROR 1 +// #define BM_MD_IO_ERROR 1 unused now. #define BM_P_VMALLOCED 2 static int __bm_change_bits_to(struct drbd_conf *mdev, const unsigned long s, @@ -155,26 +154,117 @@ void drbd_bm_unlock(struct drbd_conf *mdev) mutex_unlock(&b->bm_change); } -static unsigned int bm_bit_to_page_idx(struct drbd_bitmap *b, u64 bitnr) +/* we store some "meta" info about our pages in page->private */ +/* at a granularity of 4k storage per bitmap bit: + * one peta byte storage: 1<<50 byte, 1<<38 * 4k storage blocks + * 1<<38 bits, + * 1<<23 4k bitmap pages. + * Use 24 bits as page index, covers 2 peta byte storage + * at a granularity of 4k per bit. + * Used to report the failed page idx on io error from the endio handlers. + */ +#define BM_PAGE_IDX_MASK ((1UL<<24)-1) +/* this page is currently read in, or written back */ +#define BM_PAGE_IO_LOCK 31 +/* if there has been an IO error for this page */ +#define BM_PAGE_IO_ERROR 30 +/* this is to be able to intelligently skip disk IO, + * set if bits have been set since last IO. */ +#define BM_PAGE_NEED_WRITEOUT 29 +/* to mark for lazy writeout once syncer cleared all clearable bits, + * we if bits have been cleared since last IO. */ +#define BM_PAGE_LAZY_WRITEOUT 28 + +/* store_page_idx uses non-atomic assingment. It is only used directly after + * allocating the page. All other bm_set_page_* and bm_clear_page_* need to + * use atomic bit manipulation, as set_out_of_sync (and therefore bitmap + * changes) may happen from various contexts, and wait_on_bit/wake_up_bit + * requires it all to be atomic as well. */ +static void bm_store_page_idx(struct page *page, unsigned long idx) { - /* page_nr = (bitnr/8) >> PAGE_SHIFT; */ - unsigned int page_nr = bitnr >> (PAGE_SHIFT + 3); - BUG_ON(page_nr >= b->bm_number_of_pages); - return page_nr; + BUG_ON(0 != (idx & ~BM_PAGE_IDX_MASK)); + page_private(page) |= idx; } -/* word offset to long pointer */ -static unsigned long *__bm_map_paddr(struct drbd_bitmap *b, unsigned long offset, const enum km_type km) +static unsigned long bm_page_to_idx(struct page *page) { - struct page *page; - unsigned long page_nr; + return page_private(page) & BM_PAGE_IDX_MASK; +} + +/* As is very unlikely that the same page is under IO from more than one + * context, we can get away with a bit per page and one wait queue per bitmap. + */ +static void bm_page_lock_io(struct drbd_conf *mdev, int page_nr) +{ + struct drbd_bitmap *b = mdev->bitmap; + void *addr = &page_private(b->bm_pages[page_nr]); + wait_event(b->bm_io_wait, !test_and_set_bit(BM_PAGE_IO_LOCK, addr)); +} + +static void bm_page_unlock_io(struct drbd_conf *mdev, int page_nr) +{ + struct drbd_bitmap *b = mdev->bitmap; + void *addr = &page_private(b->bm_pages[page_nr]); + clear_bit(BM_PAGE_IO_LOCK, addr); + smp_mb__after_clear_bit(); + wake_up(&mdev->bitmap->bm_io_wait); +} + +/* set _before_ submit_io, so it may be reset due to being changed + * while this page is in flight... will get submitted later again */ +static void bm_set_page_unchanged(struct page *page) +{ + /* use cmpxchg? */ + clear_bit(BM_PAGE_NEED_WRITEOUT, &page_private(page)); + clear_bit(BM_PAGE_LAZY_WRITEOUT, &page_private(page)); +} + +static void bm_set_page_need_writeout(struct page *page) +{ + set_bit(BM_PAGE_NEED_WRITEOUT, &page_private(page)); +} + +static int bm_test_page_unchanged(struct page *page) +{ + volatile const unsigned long *addr = &page_private(page); + return (*addr & ((1UL<> PAGE_SHIFT; */ - page_nr = offset >> (PAGE_SHIFT - LN2_BPL + 3); + unsigned int page_nr = long_nr >> (PAGE_SHIFT - LN2_BPL + 3); BUG_ON(page_nr >= b->bm_number_of_pages); - page = b->bm_pages[page_nr]; + return page_nr; +} - return (unsigned long *) kmap_atomic(page, km); +static unsigned int bm_bit_to_page_idx(struct drbd_bitmap *b, u64 bitnr) +{ + /* page_nr = (bitnr/8) >> PAGE_SHIFT; */ + unsigned int page_nr = bitnr >> (PAGE_SHIFT + 3); + BUG_ON(page_nr >= b->bm_number_of_pages); + return page_nr; } static unsigned long *__bm_map_pidx(struct drbd_bitmap *b, unsigned int idx, const enum km_type km) @@ -188,11 +278,6 @@ static unsigned long *bm_map_pidx(struct drbd_bitmap *b, unsigned int idx) return __bm_map_pidx(b, idx, KM_IRQ1); } -static unsigned long * bm_map_paddr(struct drbd_bitmap *b, unsigned long offset) -{ - return __bm_map_paddr(b, offset, KM_IRQ1); -} - static void __bm_unmap(unsigned long *p_addr, const enum km_type km) { kunmap_atomic(p_addr, km); @@ -222,6 +307,7 @@ static void bm_unmap(unsigned long *p_addr) * to be able to report device specific. */ + static void bm_free_pages(struct page **pages, unsigned long number) { unsigned long i; @@ -289,6 +375,9 @@ static struct page **bm_realloc_pages(struct drbd_bitmap *b, unsigned long want) bm_vk_free(new_pages, vmalloced); return NULL; } + /* we want to know which page it is + * from the endio handlers */ + bm_store_page_idx(page, i); new_pages[i] = page; } } else { @@ -443,7 +532,7 @@ static unsigned long bm_count_bits(struct drbd_bitmap *b) while (offset < words) { i = do_now = min_t(size_t, words-offset, LWPP); - p_addr = __bm_map_paddr(b, offset, KM_USER0); + p_addr = __bm_map_pidx(b, bm_word_to_page_idx(b, offset), KM_USER0); bm = p_addr + MLPP(offset); while (i--) { bits += hweight_long(*bm++); @@ -472,6 +561,7 @@ static unsigned long bm_count_bits(struct drbd_bitmap *b) static void bm_memset(struct drbd_bitmap *b, size_t offset, int c, size_t len) { unsigned long *p_addr, *bm; + unsigned int idx; size_t do_now, end; #define BM_SECTORS_PER_BIT (BM_BLOCK_SIZE/512) @@ -485,7 +575,8 @@ static void bm_memset(struct drbd_bitmap *b, size_t offset, int c, size_t len) while (offset < end) { do_now = min_t(size_t, ALIGN(offset + 1, LWPP), end) - offset; - p_addr = bm_map_paddr(b, offset); + idx = bm_word_to_page_idx(b, offset); + p_addr = bm_map_pidx(b, idx); bm = p_addr + MLPP(offset); if (bm+do_now > p_addr + LWPP) { printk(KERN_ALERT "drbd: BUG BUG BUG! p_addr:%p bm:%p do_now:%d\n", @@ -494,6 +585,7 @@ static void bm_memset(struct drbd_bitmap *b, size_t offset, int c, size_t len) } memset(bm, c, do_now * sizeof(long)); bm_unmap(p_addr); + bm_set_page_need_writeout(b->bm_pages[idx]); offset += do_now; } } @@ -604,7 +696,7 @@ int drbd_bm_resize(struct drbd_conf *mdev, sector_t capacity, int set_new_bits) bm_free_pages(opages + want, have - want); } - p_addr = bm_map_paddr(b, words); + p_addr = bm_map_pidx(b, bm_word_to_page_idx(b, words)); bm = p_addr + MLPP(words); *bm = DRBD_MAGIC; bm_unmap(p_addr); @@ -616,7 +708,7 @@ int drbd_bm_resize(struct drbd_conf *mdev, sector_t capacity, int set_new_bits) bm_vk_free(opages, opages_vmalloced); if (!growing) b->bm_set = bm_count_bits(b); - dev_info(DEV, "resync bitmap: bits=%lu words=%lu\n", bits, words); + dev_info(DEV, "resync bitmap: bits=%lu words=%lu pages=%lu\n", bits, words, want); out: drbd_bm_unlock(mdev); @@ -686,6 +778,7 @@ void drbd_bm_merge_lel(struct drbd_conf *mdev, size_t offset, size_t number, struct drbd_bitmap *b = mdev->bitmap; unsigned long *p_addr, *bm; unsigned long word, bits; + unsigned int idx; size_t end, do_now; end = offset + number; @@ -700,7 +793,8 @@ void drbd_bm_merge_lel(struct drbd_conf *mdev, size_t offset, size_t number, spin_lock_irq(&b->bm_lock); while (offset < end) { do_now = min_t(size_t, ALIGN(offset+1, LWPP), end) - offset; - p_addr = bm_map_paddr(b, offset); + idx = bm_word_to_page_idx(b, offset); + p_addr = bm_map_pidx(b, idx); bm = p_addr + MLPP(offset); offset += do_now; while (do_now--) { @@ -710,6 +804,7 @@ void drbd_bm_merge_lel(struct drbd_conf *mdev, size_t offset, size_t number, b->bm_set += hweight_long(word) - bits; } bm_unmap(p_addr); + bm_set_page_need_writeout(b->bm_pages[idx]); } /* with 32bit <-> 64bit cross-platform connect * this is only correct for current usage, @@ -748,7 +843,7 @@ void drbd_bm_get_lel(struct drbd_conf *mdev, size_t offset, size_t number, else { while (offset < end) { do_now = min_t(size_t, ALIGN(offset+1, LWPP), end) - offset; - p_addr = bm_map_paddr(b, offset); + p_addr = bm_map_pidx(b, bm_word_to_page_idx(b, offset)); bm = p_addr + MLPP(offset); offset += do_now; while (do_now--) @@ -786,9 +881,22 @@ void drbd_bm_clear_all(struct drbd_conf *mdev) spin_unlock_irq(&b->bm_lock); } +struct bm_aio_ctx { + struct drbd_conf *mdev; + atomic_t in_flight; + wait_queue_head_t io_wait; + unsigned flags; +#define BM_AIO_COPY_PAGES 1 + int error; +}; + +/* bv_page may be a copy, or may be the original */ static void bm_async_io_complete(struct bio *bio, int error) { - struct drbd_bitmap *b = bio->bi_private; + struct bm_aio_ctx *ctx = bio->bi_private; + struct drbd_conf *mdev = ctx->mdev; + struct drbd_bitmap *b = mdev->bitmap; + unsigned int idx = bm_page_to_idx(bio->bi_io_vec[0].bv_page); int uptodate = bio_flagged(bio, BIO_UPTODATE); @@ -799,35 +907,79 @@ static void bm_async_io_complete(struct bio *bio, int error) if (!error && !uptodate) error = -EIO; + if (!bm_test_page_unchanged(b->bm_pages[idx])) + dev_info(DEV, "bitmap page idx %u changed during IO!\n", idx); + if (error) { - /* doh. what now? - * for now, set all bits, and flag MD_IO_ERROR */ - __set_bit(BM_MD_IO_ERROR, &b->bm_flags); + /* ctx error will hold the completed-last non-zero error code, + * in case error codes differ. */ + ctx->error = error; + bm_set_page_io_err(b->bm_pages[idx]); + /* Not identical to on disk version of it. + * Is BM_PAGE_IO_ERROR enough? */ + if (__ratelimit(&drbd_ratelimit_state)) + dev_err(DEV, "IO ERROR %d on bitmap page idx %u\n", + error, idx); + } else { + bm_clear_page_io_err(b->bm_pages[idx]); + dynamic_dev_dbg(DEV, "bitmap page idx %u completed\n", idx); } - if (atomic_dec_and_test(&b->bm_async_io)) - wake_up(&b->bm_io_wait); + + bm_page_unlock_io(mdev, idx); + + /* FIXME give back to page pool */ + if (ctx->flags & BM_AIO_COPY_PAGES) + put_page(bio->bi_io_vec[0].bv_page); bio_put(bio); + + if (atomic_dec_and_test(&ctx->in_flight)) + wake_up(&ctx->io_wait); } -static void bm_page_io_async(struct drbd_conf *mdev, struct drbd_bitmap *b, int page_nr, int rw) __must_hold(local) +static void bm_page_io_async(struct bm_aio_ctx *ctx, int page_nr, int rw) __must_hold(local) { /* we are process context. we always get a bio */ struct bio *bio = bio_alloc(GFP_KERNEL, 1); + struct drbd_conf *mdev = ctx->mdev; + struct drbd_bitmap *b = mdev->bitmap; + struct page *page; unsigned int len; + sector_t on_disk_sector = mdev->ldev->md.md_offset + mdev->ldev->md.bm_offset; on_disk_sector += ((sector_t)page_nr) << (PAGE_SHIFT-9); /* this might happen with very small - * flexible external meta data device */ + * flexible external meta data device, + * or with PAGE_SIZE > 4k */ len = min_t(unsigned int, PAGE_SIZE, (drbd_md_last_sector(mdev->ldev) - on_disk_sector + 1)<<9); + /* serialize IO on this page */ + bm_page_lock_io(mdev, page_nr); + /* before memcpy and submit, + * so it can be redirtied any time */ + bm_set_page_unchanged(b->bm_pages[page_nr]); + + if (ctx->flags & BM_AIO_COPY_PAGES) { + /* FIXME alloc_page is good enough for now, but actually needs + * to use pre-allocated page pool */ + void *src, *dest; + page = alloc_page(__GFP_HIGHMEM|__GFP_WAIT); + dest = kmap_atomic(page, KM_USER0); + src = kmap_atomic(b->bm_pages[page_nr], KM_USER1); + memcpy(dest, src, PAGE_SIZE); + kunmap_atomic(src, KM_USER1); + kunmap_atomic(dest, KM_USER0); + bm_store_page_idx(page, page_nr); + } else + page = b->bm_pages[page_nr]; + bio->bi_bdev = mdev->ldev->md_bdev; bio->bi_sector = on_disk_sector; - bio_add_page(bio, b->bm_pages[page_nr], len, 0); - bio->bi_private = b; + bio_add_page(bio, page, len, 0); + bio->bi_private = ctx; bio->bi_end_io = bm_async_io_complete; if (drbd_insert_fault(mdev, (rw & WRITE) ? DRBD_FAULT_MD_WR : DRBD_FAULT_MD_RD)) { @@ -841,36 +993,72 @@ static void bm_page_io_async(struct drbd_conf *mdev, struct drbd_bitmap *b, int /* * bm_rw: read/write the whole bitmap from/to its on disk location. */ -static int bm_rw(struct drbd_conf *mdev, int rw) __must_hold(local) +static int bm_rw(struct drbd_conf *mdev, int rw, unsigned lazy_writeout_upper_idx) __must_hold(local) { + struct bm_aio_ctx ctx = + { .flags = lazy_writeout_upper_idx ? BM_AIO_COPY_PAGES : 0 }; struct drbd_bitmap *b = mdev->bitmap; - /* sector_t sector; */ - int bm_words, num_pages, i; + int last_page, i, count = 0; unsigned long now; char ppb[10]; int err = 0; - WARN_ON(!bm_is_locked(b)); - - /* no spinlock here, the drbd_bm_lock should be enough! */ + /* + * We are protected against bitmap disappearing/resizing by holding an + * ldev reference (caller must have called get_ldev()). + * For read/write, we are protected against changes to the bitmap by + * the bitmap lock (see drbd_bitmap_io). + * For lazy writeout, we don't care for ongoing changes to the bitmap, + * as we submit copies of pages anyways. + */ + if (!ctx.flags) + WARN_ON(!bm_is_locked(b)); - bm_words = drbd_bm_words(mdev); - num_pages = (bm_words*sizeof(long) + PAGE_SIZE-1) >> PAGE_SHIFT; + /* because of the "extra long to catch oob access" we allocate in + * drbd_bm_resize, bm_number_of_pages -1 is not necessarily the page + * containing the last _relevant_ bitmap word */ + last_page = bm_word_to_page_idx(b, b->bm_words - 1); now = jiffies; - atomic_set(&b->bm_async_io, num_pages); - __clear_bit(BM_MD_IO_ERROR, &b->bm_flags); + ctx.mdev = mdev; + atomic_set(&ctx.in_flight, 1); /* one extra ref */ + init_waitqueue_head(&ctx.io_wait); + ctx.error = 0; /* let the layers below us try to merge these bios... */ - for (i = 0; i < num_pages; i++) - bm_page_io_async(mdev, b, i, rw); + for (i = 0; i <= last_page; i++) { + /* ignore completely unchanged pages */ + if (lazy_writeout_upper_idx && i == lazy_writeout_upper_idx) + break; + if (rw & WRITE) { + if (bm_test_page_unchanged(b->bm_pages[i])) { + dynamic_dev_dbg(DEV, "skipped bm write for idx %u\n", i); + continue; + } + /* during lazy writeout, + * ignore those pages not marked for lazy writeout. */ + if (lazy_writeout_upper_idx && + !bm_test_page_lazy_writeout(b->bm_pages[i])) { + dynamic_dev_dbg(DEV, "skipped bm lazy write for idx %u\n", i); + continue; + } + } + atomic_inc(&ctx.in_flight); + bm_page_io_async(&ctx, i, rw); + ++count; + cond_resched(); + } - wait_event(b->bm_io_wait, atomic_read(&b->bm_async_io) == 0); + atomic_dec(&ctx.in_flight); /* drop the extra ref */ + wait_event(ctx.io_wait, atomic_read(&ctx.in_flight) == 0); + dev_info(DEV, "bitmap %s of %u pages took %lu jiffies\n", + rw == WRITE ? "WRITE" : "READ", + count, jiffies - now); - if (test_bit(BM_MD_IO_ERROR, &b->bm_flags)) { + if (ctx.error) { dev_alert(DEV, "we had at least one MD IO ERROR during bitmap IO\n"); drbd_chk_io_error(mdev, 1, true); - err = -EIO; + err = -EIO; /* ctx.error ? */ } now = jiffies; @@ -895,55 +1083,63 @@ static int bm_rw(struct drbd_conf *mdev, int rw) __must_hold(local) */ int drbd_bm_read(struct drbd_conf *mdev) __must_hold(local) { - return bm_rw(mdev, READ); + return bm_rw(mdev, READ, 0); } /** * drbd_bm_write() - Write the whole bitmap to its on disk location. * @mdev: DRBD device. + * + * Will only write pages that have changed since last IO. */ int drbd_bm_write(struct drbd_conf *mdev) __must_hold(local) { - return bm_rw(mdev, WRITE); + return bm_rw(mdev, WRITE, 0); } /** - * drbd_bm_write_sect: Writes a 512 (MD_SECTOR_SIZE) byte piece of the bitmap + * drbd_bm_lazy_write_out() - Write bitmap pages 0 to @upper_idx-1, if they have changed. * @mdev: DRBD device. - * @enr: Extent number in the resync lru (happens to be sector offset) + * @upper_idx: 0: write all changed pages; +ve: page index to stop scanning for changed pages + */ +int drbd_bm_write_lazy(struct drbd_conf *mdev, unsigned upper_idx) __must_hold(local) +{ + return bm_rw(mdev, WRITE, upper_idx); +} + + +/** + * drbd_bm_write_page: Writes a PAGE_SIZE aligned piece of bitmap + * @mdev: DRBD device. + * @idx: bitmap page index * - * The BM_EXT_SIZE is on purpose exactly the amount of the bitmap covered - * by a single sector write. Therefore enr == sector offset from the - * start of the bitmap. + * We don't want to special case on logical_block_size of the underlaying + * device, so we submit PAGE_SIZE aligned pieces containing the requested enr. + * Note that on "most" systems, PAGE_SIZE is 4k. */ -int drbd_bm_write_sect(struct drbd_conf *mdev, unsigned long enr) __must_hold(local) +int drbd_bm_write_page(struct drbd_conf *mdev, unsigned int idx) __must_hold(local) { - sector_t on_disk_sector = enr + mdev->ldev->md.md_offset - + mdev->ldev->md.bm_offset; - int bm_words, num_words, offset; - int err = 0; + struct bm_aio_ctx ctx = { .flags = BM_AIO_COPY_PAGES, }; - mutex_lock(&mdev->md_io_mutex); - bm_words = drbd_bm_words(mdev); - offset = S2W(enr); /* word offset into bitmap */ - num_words = min(S2W(1), bm_words - offset); - if (num_words < S2W(1)) - memset(page_address(mdev->md_io_page), 0, MD_SECTOR_SIZE); - drbd_bm_get_lel(mdev, offset, num_words, - page_address(mdev->md_io_page)); - if (!drbd_md_sync_page_io(mdev, mdev->ldev, on_disk_sector, WRITE)) { - int i; - err = -EIO; - dev_err(DEV, "IO ERROR writing bitmap sector %lu " - "(meta-disk sector %llus)\n", - enr, (unsigned long long)on_disk_sector); - drbd_chk_io_error(mdev, 1, true); - for (i = 0; i < AL_EXT_PER_BM_SECT; i++) - drbd_bm_ALe_set_all(mdev, enr*AL_EXT_PER_BM_SECT+i); + if (bm_test_page_unchanged(mdev->bitmap->bm_pages[idx])) { + dev_info(DEV, "skipped bm page write for idx %u\n", idx); + return 0; } + + ctx.mdev = mdev; + atomic_set(&ctx.in_flight, 1); + init_waitqueue_head(&ctx.io_wait); + + bm_page_io_async(&ctx, idx, WRITE_SYNC); + wait_event(ctx.io_wait, atomic_read(&ctx.in_flight) == 0); + + if (ctx.error) + drbd_chk_io_error(mdev, 1, true); + /* that should force detach, so the in memory bitmap will be + * gone in a moment as well. */ + mdev->bm_writ_cnt++; - mutex_unlock(&mdev->md_io_mutex); - return err; + return ctx.error; } /* NOTE @@ -965,10 +1161,9 @@ static unsigned long __bm_find_next(struct drbd_conf *mdev, unsigned long bm_fo, dev_err(DEV, "bm_fo=%lu bm_bits=%lu\n", bm_fo, b->bm_bits); } else { while (bm_fo < b->bm_bits) { - unsigned long offset; - bit_offset = bm_fo & ~BPP_MASK; /* bit offset of the page */ - offset = bit_offset >> LN2_BPL; /* word offset of the page */ - p_addr = __bm_map_paddr(b, offset, km); + /* bit offset of the first bit in the page */ + bit_offset = bm_fo & ~BPP_MASK; + p_addr = __bm_map_pidx(b, bm_bit_to_page_idx(b, bm_fo), km); if (find_zero_bit) i = generic_find_next_zero_le_bit(p_addr, PAGE_SIZE*8, bm_fo & BPP_MASK); @@ -1048,8 +1243,9 @@ static int __bm_change_bits_to(struct drbd_conf *mdev, const unsigned long s, struct drbd_bitmap *b = mdev->bitmap; unsigned long *p_addr = NULL; unsigned long bitnr; - unsigned long last_page_nr = -1UL; + unsigned int last_page_nr = -1U; int c = 0; + int changed_total = 0; if (e >= b->bm_bits) { dev_err(DEV, "ASSERT FAILED: bit_s=%lu bit_e=%lu bm_bits=%lu\n", @@ -1057,12 +1253,17 @@ static int __bm_change_bits_to(struct drbd_conf *mdev, const unsigned long s, e = b->bm_bits ? b->bm_bits -1 : 0; } for (bitnr = s; bitnr <= e; bitnr++) { - unsigned long offset = bitnr>>LN2_BPL; - unsigned long page_nr = offset >> (PAGE_SHIFT - LN2_BPL + 3); + unsigned int page_nr = bm_bit_to_page_idx(b, bitnr); if (page_nr != last_page_nr) { if (p_addr) __bm_unmap(p_addr, km); - p_addr = __bm_map_paddr(b, offset, km); + if (c < 0) + bm_set_page_lazy_writeout(b->bm_pages[last_page_nr]); + else if (c > 0) + bm_set_page_need_writeout(b->bm_pages[last_page_nr]); + changed_total += c; + c = 0; + p_addr = __bm_map_pidx(b, page_nr, km); last_page_nr = page_nr; } if (val) @@ -1072,8 +1273,13 @@ static int __bm_change_bits_to(struct drbd_conf *mdev, const unsigned long s, } if (p_addr) __bm_unmap(p_addr, km); - b->bm_set += c; - return c; + if (c < 0) + bm_set_page_lazy_writeout(b->bm_pages[last_page_nr]); + else if (c > 0) + bm_set_page_need_writeout(b->bm_pages[last_page_nr]); + changed_total += c; + b->bm_set += changed_total; + return changed_total; } /* returns number of bits actually changed. @@ -1211,8 +1417,7 @@ int drbd_bm_test_bit(struct drbd_conf *mdev, const unsigned long bitnr) if (bm_is_locked(b)) bm_print_lock_info(mdev); if (bitnr < b->bm_bits) { - unsigned long offset = bitnr>>LN2_BPL; - p_addr = bm_map_paddr(b, offset); + p_addr = bm_map_pidx(b, bm_bit_to_page_idx(b, bitnr)); i = generic_test_le_bit(bitnr & BPP_MASK, p_addr) ? 1 : 0; bm_unmap(p_addr); } else if (bitnr == b->bm_bits) { @@ -1231,10 +1436,10 @@ int drbd_bm_count_bits(struct drbd_conf *mdev, const unsigned long s, const unsi { unsigned long flags; struct drbd_bitmap *b = mdev->bitmap; - unsigned long *p_addr = NULL, page_nr = -1; + unsigned long *p_addr = NULL; unsigned long bitnr; + unsigned int page_nr = -1U; int c = 0; - size_t w; /* If this is called without a bitmap, that is a bug. But just to be * robust in case we screwed up elsewhere, in that case pretend there @@ -1247,12 +1452,12 @@ int drbd_bm_count_bits(struct drbd_conf *mdev, const unsigned long s, const unsi if (bm_is_locked(b)) bm_print_lock_info(mdev); for (bitnr = s; bitnr <= e; bitnr++) { - w = bitnr >> LN2_BPL; - if (page_nr != w >> (PAGE_SHIFT - LN2_BPL + 3)) { - page_nr = w >> (PAGE_SHIFT - LN2_BPL + 3); + unsigned int idx = bm_bit_to_page_idx(b, bitnr); + if (page_nr != idx) { + page_nr = idx; if (p_addr) bm_unmap(p_addr); - p_addr = bm_map_paddr(b, w); + p_addr = bm_map_pidx(b, idx); } ERR_IF (bitnr >= b->bm_bits) { dev_err(DEV, "bitnr=%lu bm_bits=%lu\n", bitnr, b->bm_bits); @@ -1300,7 +1505,7 @@ int drbd_bm_e_weight(struct drbd_conf *mdev, unsigned long enr) count = 0; if (s < b->bm_words) { int n = e-s; - p_addr = bm_map_paddr(b, s); + p_addr = bm_map_pidx(b, bm_word_to_page_idx(b, s)); bm = p_addr + MLPP(s); while (n--) count += hweight_long(*bm++); @@ -1335,7 +1540,7 @@ unsigned long drbd_bm_ALe_set_all(struct drbd_conf *mdev, unsigned long al_enr) count = 0; if (s < b->bm_words) { i = do_now = e-s; - p_addr = bm_map_paddr(b, s); + p_addr = bm_map_pidx(b, bm_word_to_page_idx(b, s)); bm = p_addr + MLPP(s); while (i--) { count += hweight_long(*bm); diff --git a/drivers/block/drbd/drbd_int.h b/drivers/block/drbd/drbd_int.h index f6da48bb8c707..74cc50a218226 100644 --- a/drivers/block/drbd/drbd_int.h +++ b/drivers/block/drbd/drbd_int.h @@ -833,7 +833,7 @@ enum { CRASHED_PRIMARY, /* This node was a crashed primary. * Gets cleared when the state.conn * goes into C_CONNECTED state. */ - WRITE_BM_AFTER_RESYNC, /* A kmalloc() during resync failed */ + NO_BARRIER_SUPP, /* underlying block device doesn't implement barriers */ CONSIDER_RESYNC, MD_NO_FUA, /* Users wants us to not use FUA/FLUSH on meta data dev */ @@ -1428,7 +1428,7 @@ extern void _drbd_bm_set_bits(struct drbd_conf *mdev, const unsigned long s, const unsigned long e); extern int drbd_bm_test_bit(struct drbd_conf *mdev, unsigned long bitnr); extern int drbd_bm_e_weight(struct drbd_conf *mdev, unsigned long enr); -extern int drbd_bm_write_sect(struct drbd_conf *mdev, unsigned long enr) __must_hold(local); +extern int drbd_bm_write_page(struct drbd_conf *mdev, unsigned int idx) __must_hold(local); extern int drbd_bm_read(struct drbd_conf *mdev) __must_hold(local); extern int drbd_bm_write(struct drbd_conf *mdev) __must_hold(local); extern unsigned long drbd_bm_ALe_set_all(struct drbd_conf *mdev, @@ -1446,7 +1446,7 @@ extern int drbd_bm_rs_done(struct drbd_conf *mdev); /* for receive_bitmap */ extern void drbd_bm_merge_lel(struct drbd_conf *mdev, size_t offset, size_t number, unsigned long *buffer); -/* for _drbd_send_bitmap and drbd_bm_write_sect */ +/* for _drbd_send_bitmap */ extern void drbd_bm_get_lel(struct drbd_conf *mdev, size_t offset, size_t number, unsigned long *buffer); @@ -1641,7 +1641,6 @@ extern int __drbd_set_out_of_sync(struct drbd_conf *mdev, sector_t sector, #define drbd_set_out_of_sync(mdev, sector, size) \ __drbd_set_out_of_sync(mdev, sector, size, __FILE__, __LINE__) extern void drbd_al_apply_to_bm(struct drbd_conf *mdev); -extern void drbd_al_to_on_disk_bm(struct drbd_conf *mdev); extern void drbd_al_shrink(struct drbd_conf *mdev); diff --git a/drivers/block/drbd/drbd_main.c b/drivers/block/drbd/drbd_main.c index 67fffad213ec9..57ed7181742d8 100644 --- a/drivers/block/drbd/drbd_main.c +++ b/drivers/block/drbd/drbd_main.c @@ -1289,6 +1289,26 @@ static void abw_start_sync(struct drbd_conf *mdev, int rv) } } +int drbd_bitmap_io_from_worker(struct drbd_conf *mdev, int (*io_fn)(struct drbd_conf *), char *why) +{ + int rv; + + D_ASSERT(current == mdev->worker.task); + + /* open coded non-blocking drbd_suspend_io(mdev); */ + set_bit(SUSPEND_IO, &mdev->flags); + if (!is_susp(mdev->state)) + D_ASSERT(atomic_read(&mdev->ap_bio_cnt) == 0); + + drbd_bm_lock(mdev, why); + rv = io_fn(mdev); + drbd_bm_unlock(mdev); + + drbd_resume_io(mdev); + + return rv; +} + /** * after_state_ch() - Perform after state change actions that may sleep * @mdev: DRBD device. @@ -1404,7 +1424,12 @@ static void after_state_ch(struct drbd_conf *mdev, union drbd_state os, /* D_DISKLESS Peer becomes secondary */ if (os.peer == R_PRIMARY && ns.peer == R_SECONDARY) - drbd_al_to_on_disk_bm(mdev); + drbd_bitmap_io_from_worker(mdev, &drbd_bm_write, "demote diskless peer"); + put_ldev(mdev); + } + + if (os.role == R_PRIMARY && ns.role == R_SECONDARY && get_ldev(mdev)) { + drbd_bitmap_io_from_worker(mdev, &drbd_bm_write, "demote"); put_ldev(mdev); } diff --git a/drivers/block/drbd/drbd_nl.c b/drivers/block/drbd/drbd_nl.c index 2f07249821438..77dc022eaf6b1 100644 --- a/drivers/block/drbd/drbd_nl.c +++ b/drivers/block/drbd/drbd_nl.c @@ -407,10 +407,8 @@ drbd_set_role(struct drbd_conf *mdev, enum drbd_role new_role, int force) } } - if ((new_role == R_SECONDARY) && get_ldev(mdev)) { - drbd_al_to_on_disk_bm(mdev); - put_ldev(mdev); - } + /* writeout of activity log covered areas of the bitmap + * to stable storage done in after state change already */ if (mdev->state.conn >= C_WF_REPORT_PARAMS) { /* if this was forced, we should consider sync */ @@ -1174,7 +1172,10 @@ static int drbd_nl_disk_conf(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp if (cp_discovered) { drbd_al_apply_to_bm(mdev); - drbd_al_to_on_disk_bm(mdev); + if (drbd_bitmap_io(mdev, &drbd_bm_write, "crashed primary apply AL")) { + retcode = ERR_IO_MD_DISK; + goto force_diskless_dec; + } } if (_drbd_bm_total_weight(mdev) == drbd_bm_bits(mdev)) diff --git a/drivers/block/drbd/drbd_worker.c b/drivers/block/drbd/drbd_worker.c index 9fe3e890da0f0..d17f2ed777ce3 100644 --- a/drivers/block/drbd/drbd_worker.c +++ b/drivers/block/drbd/drbd_worker.c @@ -907,10 +907,8 @@ out: drbd_md_sync(mdev); - if (test_and_clear_bit(WRITE_BM_AFTER_RESYNC, &mdev->flags)) { - dev_info(DEV, "Writing the whole bitmap\n"); - drbd_queue_bitmap_io(mdev, &drbd_bm_write, NULL, "write from resync_finished"); - } + dev_info(DEV, "Writing changed bitmap pages\n"); + drbd_queue_bitmap_io(mdev, &drbd_bm_write, NULL, "write from resync_finished"); if (khelper_cmd) drbd_khelper(mdev, khelper_cmd); @@ -1127,7 +1125,6 @@ void drbd_ov_oos_found(struct drbd_conf *mdev, sector_t sector, int size) mdev->ov_last_oos_size = size>>9; } drbd_set_out_of_sync(mdev, sector, size); - set_bit(WRITE_BM_AFTER_RESYNC, &mdev->flags); } int w_e_end_ov_reply(struct drbd_conf *mdev, struct drbd_work *w, int cancel) -- GitLab From 4b0715f09655e76ca24c35a9e25e7c464c2f7346 Mon Sep 17 00:00:00 2001 From: Lars Ellenberg Date: Tue, 14 Dec 2010 15:13:04 +0100 Subject: [PATCH 0455/2822] drbd: allow petabyte storage on 64bit arch Signed-off-by: Philipp Reisner Signed-off-by: Lars Ellenberg --- drivers/block/drbd/drbd_bitmap.c | 170 +++++++++++++++++++------------ drivers/block/drbd/drbd_int.h | 41 +++++--- drivers/block/drbd/drbd_nl.c | 8 +- drivers/block/drbd/drbd_proc.c | 6 +- drivers/block/drbd/drbd_worker.c | 2 +- 5 files changed, 142 insertions(+), 85 deletions(-) diff --git a/drivers/block/drbd/drbd_bitmap.c b/drivers/block/drbd/drbd_bitmap.c index 72cd41a96ef97..0e31e573af72b 100644 --- a/drivers/block/drbd/drbd_bitmap.c +++ b/drivers/block/drbd/drbd_bitmap.c @@ -37,10 +37,46 @@ * convention: * function name drbd_bm_... => used elsewhere, "public". * function name bm_... => internal to implementation, "private". + */ + - * Note that since find_first_bit returns int, at the current granularity of - * the bitmap (4KB per byte), this implementation "only" supports up to - * 1<<(32+12) == 16 TB... +/* + * LIMITATIONS: + * We want to support >= peta byte of backend storage, while for now still using + * a granularity of one bit per 4KiB of storage. + * 1 << 50 bytes backend storage (1 PiB) + * 1 << (50 - 12) bits needed + * 38 --> we need u64 to index and count bits + * 1 << (38 - 3) bitmap bytes needed + * 35 --> we still need u64 to index and count bytes + * (that's 32 GiB of bitmap for 1 PiB storage) + * 1 << (35 - 2) 32bit longs needed + * 33 --> we'd even need u64 to index and count 32bit long words. + * 1 << (35 - 3) 64bit longs needed + * 32 --> we could get away with a 32bit unsigned int to index and count + * 64bit long words, but I rather stay with unsigned long for now. + * We probably should neither count nor point to bytes or long words + * directly, but either by bitnumber, or by page index and offset. + * 1 << (35 - 12) + * 22 --> we need that much 4KiB pages of bitmap. + * 1 << (22 + 3) --> on a 64bit arch, + * we need 32 MiB to store the array of page pointers. + * + * Because I'm lazy, and because the resulting patch was too large, too ugly + * and still incomplete, on 32bit we still "only" support 16 TiB (minus some), + * (1 << 32) bits * 4k storage. + * + + * bitmap storage and IO: + * Bitmap is stored little endian on disk, and is kept little endian in + * core memory. Currently we still hold the full bitmap in core as long + * as we are "attached" to a local disk, which at 32 GiB for 1PiB storage + * seems excessive. + * + * We plan to reduce the amount of in-core bitmap pages by pageing them in + * and out against their on-disk location as necessary, but need to make + * sure we don't cause too much meta data IO, and must not deadlock in + * tight memory situations. This needs some more work. */ /* @@ -56,13 +92,9 @@ struct drbd_bitmap { struct page **bm_pages; spinlock_t bm_lock; - /* WARNING unsigned long bm_*: - * 32bit number of bit offset is just enough for 512 MB bitmap. - * it will blow up if we make the bitmap bigger... - * not that it makes much sense to have a bitmap that large, - * rather change the granularity to 16k or 64k or something. - * (that implies other problems, however...) - */ + + /* see LIMITATIONS: above */ + unsigned long bm_set; /* nr of set bits; THINK maybe atomic_t? */ unsigned long bm_bits; size_t bm_words; @@ -517,43 +549,39 @@ static void bm_set_surplus(struct drbd_bitmap *b) bm_unmap(p_addr); } +/* you better not modify the bitmap while this is running, + * or its results will be stale */ static unsigned long bm_count_bits(struct drbd_bitmap *b) { - unsigned long *p_addr, *bm, offset = 0; + unsigned long *p_addr; unsigned long bits = 0; - unsigned long i, do_now; - unsigned long words; - - /* due to 64bit alignment, the last long on a 32bit arch - * may be not used at all. The last used long will likely - * be only partially used, always. Don't count those bits, - * but mask them out. */ - words = (b->bm_bits + BITS_PER_LONG - 1) >> LN2_BPL; - - while (offset < words) { - i = do_now = min_t(size_t, words-offset, LWPP); - p_addr = __bm_map_pidx(b, bm_word_to_page_idx(b, offset), KM_USER0); - bm = p_addr + MLPP(offset); - while (i--) { - bits += hweight_long(*bm++); - } - offset += do_now; - if (offset == words) { - /* last word may only be partially used, - * see also bm_clear_surplus. */ - i = (1UL << (b->bm_bits & (BITS_PER_LONG-1))) -1; - if (i) { - bits -= hweight_long(p_addr[do_now-1] & ~i); - p_addr[do_now-1] &= i; - } - /* 32bit arch, may have an unused padding long */ - if (words != b->bm_words) - p_addr[do_now] = 0; - } + unsigned long mask = (1UL << (b->bm_bits & BITS_PER_LONG_MASK)) -1; + int idx, last_page, i, last_word; + + /* because of the "extra long to catch oob access" we allocate in + * drbd_bm_resize, bm_number_of_pages -1 is not necessarily the page + * containing the last _relevant_ bitmap word */ + last_page = bm_bit_to_page_idx(b, b->bm_bits-1); + + /* all but last page */ + for (idx = 0; idx < last_page; idx++) { + p_addr = __bm_map_pidx(b, idx, KM_USER0); + for (i = 0; i < LWPP; i++) + bits += hweight_long(p_addr[i]); __bm_unmap(p_addr, KM_USER0); cond_resched(); } - + /* last (or only) page */ + last_word = ((b->bm_bits - 1) & BITS_PER_PAGE_MASK) >> LN2_BPL; + p_addr = __bm_map_pidx(b, idx, KM_USER0); + for (i = 0; i < last_word; i++) + bits += hweight_long(p_addr[i]); + p_addr[last_word] &= cpu_to_lel(mask); + bits += hweight_long(p_addr[last_word]); + /* 32bit arch, may have an unused padding long */ + if (BITS_PER_LONG == 32 && (last_word & 1) == 0) + p_addr[last_word+1] = 0; + __bm_unmap(p_addr, KM_USER0); return bits; } @@ -564,8 +592,6 @@ static void bm_memset(struct drbd_bitmap *b, size_t offset, int c, size_t len) unsigned int idx; size_t do_now, end; -#define BM_SECTORS_PER_BIT (BM_BLOCK_SIZE/512) - end = offset + len; if (end > b->bm_words) { @@ -645,8 +671,14 @@ int drbd_bm_resize(struct drbd_conf *mdev, sector_t capacity, int set_new_bits) words = ALIGN(bits, 64) >> LN2_BPL; if (get_ldev(mdev)) { - D_ASSERT((u64)bits <= (((u64)mdev->ldev->md.md_size_sect-MD_BM_OFFSET) << 12)); + u64 bits_on_disk = ((u64)mdev->ldev->md.md_size_sect-MD_BM_OFFSET) << 12; put_ldev(mdev); + if (bits > bits_on_disk) { + dev_info(DEV, "bits = %lu\n", bits); + dev_info(DEV, "bits_on_disk = %llu\n", bits_on_disk); + err = -ENOSPC; + goto out; + } } /* one extra long to catch off by one errors */ @@ -1113,9 +1145,12 @@ int drbd_bm_write_lazy(struct drbd_conf *mdev, unsigned upper_idx) __must_hold(l * @mdev: DRBD device. * @idx: bitmap page index * - * We don't want to special case on logical_block_size of the underlaying - * device, so we submit PAGE_SIZE aligned pieces containing the requested enr. + * We don't want to special case on logical_block_size of the backend device, + * so we submit PAGE_SIZE aligned pieces. * Note that on "most" systems, PAGE_SIZE is 4k. + * + * In case this becomes an issue on systems with larger PAGE_SIZE, + * we may want to change this again to write 4k aligned 4k pieces. */ int drbd_bm_write_page(struct drbd_conf *mdev, unsigned int idx) __must_hold(local) { @@ -1144,52 +1179,57 @@ int drbd_bm_write_page(struct drbd_conf *mdev, unsigned int idx) __must_hold(loc /* NOTE * find_first_bit returns int, we return unsigned long. - * should not make much difference anyways, but ... + * For this to work on 32bit arch with bitnumbers > (1<<32), + * we'd need to return u64, and get a whole lot of other places + * fixed where we still use unsigned long. * * this returns a bit number, NOT a sector! */ -#define BPP_MASK ((1UL << (PAGE_SHIFT+3)) - 1) static unsigned long __bm_find_next(struct drbd_conf *mdev, unsigned long bm_fo, const int find_zero_bit, const enum km_type km) { struct drbd_bitmap *b = mdev->bitmap; - unsigned long i = -1UL; unsigned long *p_addr; - unsigned long bit_offset; /* bit offset of the mapped page. */ + unsigned long bit_offset; + unsigned i; + if (bm_fo > b->bm_bits) { dev_err(DEV, "bm_fo=%lu bm_bits=%lu\n", bm_fo, b->bm_bits); + bm_fo = DRBD_END_OF_BITMAP; } else { while (bm_fo < b->bm_bits) { /* bit offset of the first bit in the page */ - bit_offset = bm_fo & ~BPP_MASK; + bit_offset = bm_fo & ~BITS_PER_PAGE_MASK; p_addr = __bm_map_pidx(b, bm_bit_to_page_idx(b, bm_fo), km); if (find_zero_bit) - i = generic_find_next_zero_le_bit(p_addr, PAGE_SIZE*8, bm_fo & BPP_MASK); + i = generic_find_next_zero_le_bit(p_addr, + PAGE_SIZE*8, bm_fo & BITS_PER_PAGE_MASK); else - i = generic_find_next_le_bit(p_addr, PAGE_SIZE*8, bm_fo & BPP_MASK); + i = generic_find_next_le_bit(p_addr, + PAGE_SIZE*8, bm_fo & BITS_PER_PAGE_MASK); __bm_unmap(p_addr, km); if (i < PAGE_SIZE*8) { - i = bit_offset + i; - if (i >= b->bm_bits) + bm_fo = bit_offset + i; + if (bm_fo >= b->bm_bits) break; goto found; } bm_fo = bit_offset + PAGE_SIZE*8; } - i = -1UL; + bm_fo = DRBD_END_OF_BITMAP; } found: - return i; + return bm_fo; } static unsigned long bm_find_next(struct drbd_conf *mdev, unsigned long bm_fo, const int find_zero_bit) { struct drbd_bitmap *b = mdev->bitmap; - unsigned long i = -1UL; + unsigned long i = DRBD_END_OF_BITMAP; ERR_IF(!b) return i; ERR_IF(!b->bm_pages) return i; @@ -1267,9 +1307,9 @@ static int __bm_change_bits_to(struct drbd_conf *mdev, const unsigned long s, last_page_nr = page_nr; } if (val) - c += (0 == generic___test_and_set_le_bit(bitnr & BPP_MASK, p_addr)); + c += (0 == generic___test_and_set_le_bit(bitnr & BITS_PER_PAGE_MASK, p_addr)); else - c -= (0 != generic___test_and_clear_le_bit(bitnr & BPP_MASK, p_addr)); + c -= (0 != generic___test_and_clear_le_bit(bitnr & BITS_PER_PAGE_MASK, p_addr)); } if (p_addr) __bm_unmap(p_addr, km); @@ -1418,7 +1458,7 @@ int drbd_bm_test_bit(struct drbd_conf *mdev, const unsigned long bitnr) bm_print_lock_info(mdev); if (bitnr < b->bm_bits) { p_addr = bm_map_pidx(b, bm_bit_to_page_idx(b, bitnr)); - i = generic_test_le_bit(bitnr & BPP_MASK, p_addr) ? 1 : 0; + i = generic_test_le_bit(bitnr & BITS_PER_PAGE_MASK, p_addr) ? 1 : 0; bm_unmap(p_addr); } else if (bitnr == b->bm_bits) { i = -1; @@ -1517,13 +1557,15 @@ int drbd_bm_e_weight(struct drbd_conf *mdev, unsigned long enr) return count; } -/* set all bits covered by the AL-extent al_enr */ +/* Set all bits covered by the AL-extent al_enr. + * Returns number of bits changed. */ unsigned long drbd_bm_ALe_set_all(struct drbd_conf *mdev, unsigned long al_enr) { struct drbd_bitmap *b = mdev->bitmap; unsigned long *p_addr, *bm; unsigned long weight; - int count, s, e, i, do_now; + unsigned long s, e; + int count, i, do_now; ERR_IF(!b) return 0; ERR_IF(!b->bm_pages) return 0; @@ -1552,7 +1594,7 @@ unsigned long drbd_bm_ALe_set_all(struct drbd_conf *mdev, unsigned long al_enr) if (e == b->bm_words) b->bm_set -= bm_clear_surplus(b); } else { - dev_err(DEV, "start offset (%d) too large in drbd_bm_ALe_set_all\n", s); + dev_err(DEV, "start offset (%lu) too large in drbd_bm_ALe_set_all\n", s); } weight = b->bm_set - weight; spin_unlock_irq(&b->bm_lock); diff --git a/drivers/block/drbd/drbd_int.h b/drivers/block/drbd/drbd_int.h index 74cc50a218226..5a2d0ec72b34c 100644 --- a/drivers/block/drbd/drbd_int.h +++ b/drivers/block/drbd/drbd_int.h @@ -1003,9 +1003,9 @@ struct drbd_conf { struct hlist_head *tl_hash; unsigned int tl_hash_s; - /* blocks to sync in this run [unit BM_BLOCK_SIZE] */ + /* blocks to resync in this run [unit BM_BLOCK_SIZE] */ unsigned long rs_total; - /* number of sync IOs that failed in this run */ + /* number of resync blocks that failed in this run */ unsigned long rs_failed; /* Syncer's start time [unit jiffies] */ unsigned long rs_start; @@ -1399,7 +1399,9 @@ struct bm_extent { * you should use 64bit OS for that much storage, anyways. */ #define DRBD_MAX_SECTORS_FLEX BM_BIT_TO_SECT(0xffff7fff) #else -#define DRBD_MAX_SECTORS_FLEX BM_BIT_TO_SECT(0x1LU << 32) +/* we allow up to 1 PiB now on 64bit architecture with "flexible" meta data */ +#define DRBD_MAX_SECTORS_FLEX (1UL << 51) +/* corresponds to (1UL << 38) bits right now. */ #endif #endif @@ -1419,11 +1421,15 @@ extern int drbd_bm_resize(struct drbd_conf *mdev, sector_t sectors, int set_new extern void drbd_bm_cleanup(struct drbd_conf *mdev); extern void drbd_bm_set_all(struct drbd_conf *mdev); extern void drbd_bm_clear_all(struct drbd_conf *mdev); +/* set/clear/test only a few bits at a time */ extern int drbd_bm_set_bits( struct drbd_conf *mdev, unsigned long s, unsigned long e); extern int drbd_bm_clear_bits( struct drbd_conf *mdev, unsigned long s, unsigned long e); -/* bm_set_bits variant for use while holding drbd_bm_lock */ +extern int drbd_bm_count_bits( + struct drbd_conf *mdev, const unsigned long s, const unsigned long e); +/* bm_set_bits variant for use while holding drbd_bm_lock, + * may process the whole bitmap in one go */ extern void _drbd_bm_set_bits(struct drbd_conf *mdev, const unsigned long s, const unsigned long e); extern int drbd_bm_test_bit(struct drbd_conf *mdev, unsigned long bitnr); @@ -1436,6 +1442,8 @@ extern unsigned long drbd_bm_ALe_set_all(struct drbd_conf *mdev, extern size_t drbd_bm_words(struct drbd_conf *mdev); extern unsigned long drbd_bm_bits(struct drbd_conf *mdev); extern sector_t drbd_bm_capacity(struct drbd_conf *mdev); + +#define DRBD_END_OF_BITMAP (~(unsigned long)0) extern unsigned long drbd_bm_find_next(struct drbd_conf *mdev, unsigned long bm_fo); /* bm_find_next variants for use while you hold drbd_bm_lock() */ extern unsigned long _drbd_bm_find_next(struct drbd_conf *mdev, unsigned long bm_fo); @@ -1452,8 +1460,6 @@ extern void drbd_bm_get_lel(struct drbd_conf *mdev, size_t offset, extern void drbd_bm_lock(struct drbd_conf *mdev, char *why); extern void drbd_bm_unlock(struct drbd_conf *mdev); - -extern int drbd_bm_count_bits(struct drbd_conf *mdev, const unsigned long s, const unsigned long e); /* drbd_main.c */ extern struct kmem_cache *drbd_request_cache; @@ -2158,10 +2164,8 @@ extern int _get_ldev_if_state(struct drbd_conf *mdev, enum drbd_disk_state mins) static inline void drbd_get_syncer_progress(struct drbd_conf *mdev, unsigned long *bits_left, unsigned int *per_mil_done) { - /* - * this is to break it at compile time when we change that - * (we may feel 4TB maximum storage per drbd is not enough) - */ + /* this is to break it at compile time when we change that, in case we + * want to support more than (1<<32) bits on a 32bit arch. */ typecheck(unsigned long, mdev->rs_total); /* note: both rs_total and rs_left are in bits, i.e. in @@ -2186,10 +2190,19 @@ static inline void drbd_get_syncer_progress(struct drbd_conf *mdev, *bits_left, mdev->rs_total, mdev->rs_failed); *per_mil_done = 0; } else { - /* make sure the calculation happens in long context */ - unsigned long tmp = 1000UL - - (*bits_left >> 10)*1000UL - / ((mdev->rs_total >> 10) + 1UL); + /* Make sure the division happens in long context. + * We allow up to one petabyte storage right now, + * at a granularity of 4k per bit that is 2**38 bits. + * After shift right and multiplication by 1000, + * this should still fit easily into a 32bit long, + * so we don't need a 64bit division on 32bit arch. + * Note: currently we don't support such large bitmaps on 32bit + * arch anyways, but no harm done to be prepared for it here. + */ + unsigned int shift = mdev->rs_total >= (1ULL << 32) ? 16 : 10; + unsigned long left = *bits_left >> shift; + unsigned long total = 1UL + (mdev->rs_total >> shift); + unsigned long tmp = 1000UL - left * 1000UL/total; *per_mil_done = tmp; } } diff --git a/drivers/block/drbd/drbd_nl.c b/drivers/block/drbd/drbd_nl.c index 77dc022eaf6b1..a46bc0287e217 100644 --- a/drivers/block/drbd/drbd_nl.c +++ b/drivers/block/drbd/drbd_nl.c @@ -527,17 +527,19 @@ static void drbd_md_set_sector_offsets(struct drbd_conf *mdev, } } +/* input size is expected to be in KB */ char *ppsize(char *buf, unsigned long long size) { - /* Needs 9 bytes at max. */ + /* Needs 9 bytes at max including trailing NUL: + * -1ULL ==> "16384 EB" */ static char units[] = { 'K', 'M', 'G', 'T', 'P', 'E' }; int base = 0; - while (size >= 10000) { + while (size >= 10000 && base < sizeof(units)-1) { /* shift + round */ size = (size >> 10) + !!(size & (1<<9)); base++; } - sprintf(buf, "%lu %cB", (long)size, units[base]); + sprintf(buf, "%u %cB", (unsigned)size, units[base]); return buf; } diff --git a/drivers/block/drbd/drbd_proc.c b/drivers/block/drbd/drbd_proc.c index efba62cd2e582..2959cdfb77f55 100644 --- a/drivers/block/drbd/drbd_proc.c +++ b/drivers/block/drbd/drbd_proc.c @@ -91,9 +91,9 @@ static void drbd_syncer_progress(struct drbd_conf *mdev, struct seq_file *seq) seq_printf(seq, "sync'ed:"); seq_printf(seq, "%3u.%u%% ", res / 10, res % 10); - /* if more than 1 GB display in MB */ - if (mdev->rs_total > 0x100000L) - seq_printf(seq, "(%lu/%lu)M\n\t", + /* if more than a few GB, display in MB */ + if (mdev->rs_total > (4UL << (30 - BM_BLOCK_SHIFT))) + seq_printf(seq, "(%lu/%lu)M", (unsigned long) Bit2KB(rs_left >> 10), (unsigned long) Bit2KB(mdev->rs_total >> 10)); else diff --git a/drivers/block/drbd/drbd_worker.c b/drivers/block/drbd/drbd_worker.c index d17f2ed777ce3..be46084c254eb 100644 --- a/drivers/block/drbd/drbd_worker.c +++ b/drivers/block/drbd/drbd_worker.c @@ -577,7 +577,7 @@ next_sector: size = BM_BLOCK_SIZE; bit = drbd_bm_find_next(mdev, mdev->bm_resync_fo); - if (bit == -1UL) { + if (bit == DRBD_END_OF_BITMAP) { mdev->bm_resync_fo = drbd_bm_bits(mdev); mdev->resync_work.cb = w_resync_inactive; put_ldev(mdev); -- GitLab From 6850c4421481139dc2cf982358e79c833a50d73c Mon Sep 17 00:00:00 2001 From: Lars Ellenberg Date: Thu, 16 Dec 2010 00:32:38 +0100 Subject: [PATCH 0456/2822] drbd: get rid of unused debug code Long time ago, we had paranoia code in the bitmap that allocated one extra word, assigned a magic value, and checked on every occasion that the magic value was still unchanged. That debug code is unused, the extra long word complicates code a bit. Get rid of it. Signed-off-by: Philipp Reisner Signed-off-by: Lars Ellenberg --- drivers/block/drbd/drbd_bitmap.c | 39 ++++++++------------------------ 1 file changed, 9 insertions(+), 30 deletions(-) diff --git a/drivers/block/drbd/drbd_bitmap.c b/drivers/block/drbd/drbd_bitmap.c index 0e31e573af72b..09d208b858e7b 100644 --- a/drivers/block/drbd/drbd_bitmap.c +++ b/drivers/block/drbd/drbd_bitmap.c @@ -488,10 +488,7 @@ static int bm_clear_surplus(struct drbd_bitmap *b) * on disk and in core memory alike */ mask = cpu_to_lel(mask); - /* because of the "extra long to catch oob access" we allocate in - * drbd_bm_resize, bm_number_of_pages -1 is not necessarily the page - * containing the last _relevant_ bitmap word */ - p_addr = bm_map_pidx(b, bm_bit_to_page_idx(b, b->bm_bits - 1)); + p_addr = bm_map_pidx(b, b->bm_number_of_pages - 1); bm = p_addr + (tmp/BITS_PER_LONG); if (mask) { /* If mask != 0, we are not exactly aligned, so bm now points @@ -527,10 +524,7 @@ static void bm_set_surplus(struct drbd_bitmap *b) * on disk and in core memory alike */ mask = cpu_to_lel(mask); - /* because of the "extra long to catch oob access" we allocate in - * drbd_bm_resize, bm_number_of_pages -1 is not necessarily the page - * containing the last _relevant_ bitmap word */ - p_addr = bm_map_pidx(b, bm_bit_to_page_idx(b, b->bm_bits - 1)); + p_addr = bm_map_pidx(b, b->bm_number_of_pages - 1); bm = p_addr + (tmp/BITS_PER_LONG); if (mask) { /* If mask != 0, we are not exactly aligned, so bm now points @@ -556,15 +550,10 @@ static unsigned long bm_count_bits(struct drbd_bitmap *b) unsigned long *p_addr; unsigned long bits = 0; unsigned long mask = (1UL << (b->bm_bits & BITS_PER_LONG_MASK)) -1; - int idx, last_page, i, last_word; - - /* because of the "extra long to catch oob access" we allocate in - * drbd_bm_resize, bm_number_of_pages -1 is not necessarily the page - * containing the last _relevant_ bitmap word */ - last_page = bm_bit_to_page_idx(b, b->bm_bits-1); + int idx, i, last_word; /* all but last page */ - for (idx = 0; idx < last_page; idx++) { + for (idx = 0; idx < b->bm_number_of_pages - 1; idx++) { p_addr = __bm_map_pidx(b, idx, KM_USER0); for (i = 0; i < LWPP; i++) bits += hweight_long(p_addr[i]); @@ -627,7 +616,7 @@ static void bm_memset(struct drbd_bitmap *b, size_t offset, int c, size_t len) int drbd_bm_resize(struct drbd_conf *mdev, sector_t capacity, int set_new_bits) { struct drbd_bitmap *b = mdev->bitmap; - unsigned long bits, words, owords, obits, *p_addr, *bm; + unsigned long bits, words, owords, obits; unsigned long want, have, onpages; /* number of pages */ struct page **npages, **opages = NULL; int err = 0, growing; @@ -681,8 +670,7 @@ int drbd_bm_resize(struct drbd_conf *mdev, sector_t capacity, int set_new_bits) } } - /* one extra long to catch off by one errors */ - want = ALIGN((words+1)*sizeof(long), PAGE_SIZE) >> PAGE_SHIFT; + want = ALIGN(words*sizeof(long), PAGE_SIZE) >> PAGE_SHIFT; have = b->bm_number_of_pages; if (want == have) { D_ASSERT(b->bm_pages != NULL); @@ -728,11 +716,6 @@ int drbd_bm_resize(struct drbd_conf *mdev, sector_t capacity, int set_new_bits) bm_free_pages(opages + want, have - want); } - p_addr = bm_map_pidx(b, bm_word_to_page_idx(b, words)); - bm = p_addr + MLPP(words); - *bm = DRBD_MAGIC; - bm_unmap(p_addr); - (void)bm_clear_surplus(b); spin_unlock_irq(&b->bm_lock); @@ -845,7 +828,6 @@ void drbd_bm_merge_lel(struct drbd_conf *mdev, size_t offset, size_t number, */ if (end == b->bm_words) b->bm_set -= bm_clear_surplus(b); - spin_unlock_irq(&b->bm_lock); } @@ -1030,7 +1012,7 @@ static int bm_rw(struct drbd_conf *mdev, int rw, unsigned lazy_writeout_upper_id struct bm_aio_ctx ctx = { .flags = lazy_writeout_upper_idx ? BM_AIO_COPY_PAGES : 0 }; struct drbd_bitmap *b = mdev->bitmap; - int last_page, i, count = 0; + int num_pages, i, count = 0; unsigned long now; char ppb[10]; int err = 0; @@ -1046,10 +1028,7 @@ static int bm_rw(struct drbd_conf *mdev, int rw, unsigned lazy_writeout_upper_id if (!ctx.flags) WARN_ON(!bm_is_locked(b)); - /* because of the "extra long to catch oob access" we allocate in - * drbd_bm_resize, bm_number_of_pages -1 is not necessarily the page - * containing the last _relevant_ bitmap word */ - last_page = bm_word_to_page_idx(b, b->bm_words - 1); + num_pages = b->bm_number_of_pages; now = jiffies; ctx.mdev = mdev; @@ -1058,7 +1037,7 @@ static int bm_rw(struct drbd_conf *mdev, int rw, unsigned lazy_writeout_upper_id ctx.error = 0; /* let the layers below us try to merge these bios... */ - for (i = 0; i <= last_page; i++) { + for (i = 0; i < num_pages; i++) { /* ignore completely unchanged pages */ if (lazy_writeout_upper_idx && i == lazy_writeout_upper_idx) break; -- GitLab From 84e7c0f7d123d64d97e1f789ad2f23a72fe8981f Mon Sep 17 00:00:00 2001 From: Lars Ellenberg Date: Thu, 16 Dec 2010 00:37:57 +0100 Subject: [PATCH 0457/2822] drbd: Removed a reference to debug macros removed long time ago Signed-off-by: Philipp Reisner Signed-off-by: Lars Ellenberg --- drivers/block/drbd/drbd_bitmap.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/block/drbd/drbd_bitmap.c b/drivers/block/drbd/drbd_bitmap.c index 09d208b858e7b..423dede458440 100644 --- a/drivers/block/drbd/drbd_bitmap.c +++ b/drivers/block/drbd/drbd_bitmap.c @@ -596,9 +596,8 @@ static void bm_memset(struct drbd_bitmap *b, size_t offset, int c, size_t len) if (bm+do_now > p_addr + LWPP) { printk(KERN_ALERT "drbd: BUG BUG BUG! p_addr:%p bm:%p do_now:%d\n", p_addr, bm, (int)do_now); - break; /* breaks to after catch_oob_access_end() only! */ - } - memset(bm, c, do_now * sizeof(long)); + } else + memset(bm, c, do_now * sizeof(long)); bm_unmap(p_addr); bm_set_page_need_writeout(b->bm_pages[idx]); offset += do_now; -- GitLab From 02851e9f00d78dbc8ded0aacbf9bf3b631d627b3 Mon Sep 17 00:00:00 2001 From: Lars Ellenberg Date: Thu, 16 Dec 2010 14:47:39 +0100 Subject: [PATCH 0458/2822] drbd: move bitmap write from resync_finished to after_state_change We must not call it directly from resync_finished, as we may be in either receiver or worker context there. Signed-off-by: Philipp Reisner Signed-off-by: Lars Ellenberg --- drivers/block/drbd/drbd_main.c | 14 ++++++++++---- drivers/block/drbd/drbd_worker.c | 3 --- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/drivers/block/drbd/drbd_main.c b/drivers/block/drbd/drbd_main.c index 57ed7181742d8..c6c7e3e6dc233 100644 --- a/drivers/block/drbd/drbd_main.c +++ b/drivers/block/drbd/drbd_main.c @@ -1548,6 +1548,9 @@ static void after_state_ch(struct drbd_conf *mdev, union drbd_state os, if (os.disk < D_UP_TO_DATE && os.conn >= C_SYNC_SOURCE && ns.conn == C_CONNECTED) drbd_send_state(mdev); + if (os.conn > C_CONNECTED && ns.conn == C_CONNECTED) + drbd_queue_bitmap_io(mdev, &drbd_bm_write, NULL, "write from resync_finished"); + /* free tl_hash if we Got thawed and are C_STANDALONE */ if (ns.conn == C_STANDALONE && !is_susp(ns) && mdev->tl_hash) drbd_free_tl_hash(mdev); @@ -3860,13 +3863,16 @@ int drbd_bmio_clear_n_write(struct drbd_conf *mdev) static int w_bitmap_io(struct drbd_conf *mdev, struct drbd_work *w, int unused) { struct bm_io_work *work = container_of(w, struct bm_io_work, w); - int rv; + int rv = -EIO; D_ASSERT(atomic_read(&mdev->ap_bio_cnt) == 0); - drbd_bm_lock(mdev, work->why); - rv = work->io_fn(mdev); - drbd_bm_unlock(mdev); + if (get_ldev(mdev)) { + drbd_bm_lock(mdev, work->why); + rv = work->io_fn(mdev); + drbd_bm_unlock(mdev); + put_ldev(mdev); + } clear_bit(BITMAP_IO, &mdev->flags); smp_mb__after_clear_bit(); diff --git a/drivers/block/drbd/drbd_worker.c b/drivers/block/drbd/drbd_worker.c index be46084c254eb..2374454cdf17f 100644 --- a/drivers/block/drbd/drbd_worker.c +++ b/drivers/block/drbd/drbd_worker.c @@ -907,9 +907,6 @@ out: drbd_md_sync(mdev); - dev_info(DEV, "Writing changed bitmap pages\n"); - drbd_queue_bitmap_io(mdev, &drbd_bm_write, NULL, "write from resync_finished"); - if (khelper_cmd) drbd_khelper(mdev, khelper_cmd); -- GitLab From 2265b473aecc1a6fe1f84a0ee272ba39806c2a8a Mon Sep 17 00:00:00 2001 From: Lars Ellenberg Date: Thu, 16 Dec 2010 15:41:26 +0100 Subject: [PATCH 0459/2822] drbd: fix potential dereference of NULL pointer If drbd used to have crypto digest algorithms configured, then is being unconfigured (but not unloaded), it frees the algorithms, but does not reset the config. If it then is reconfigured to use the very same algorithm, it "forgot" to re-allocate the algorithms, thinking that the config has not changed in that aspect. It will then Oops on the first attempt to actually use those algorithms. Fix this by resetting the config to defaults after cleanup. Signed-off-by: Philipp Reisner Signed-off-by: Lars Ellenberg --- drivers/block/drbd/drbd_main.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/block/drbd/drbd_main.c b/drivers/block/drbd/drbd_main.c index c6c7e3e6dc233..4da6f11cc82e6 100644 --- a/drivers/block/drbd/drbd_main.c +++ b/drivers/block/drbd/drbd_main.c @@ -3020,6 +3020,8 @@ void drbd_mdev_cleanup(struct drbd_conf *mdev) D_ASSERT(list_empty(&mdev->resync_work.list)); D_ASSERT(list_empty(&mdev->unplug_work.list)); D_ASSERT(list_empty(&mdev->go_diskless.list)); + + drbd_set_defaults(mdev); } -- GitLab From c88d65e2231dbae4b7cd0ad7b2a919857a1be171 Mon Sep 17 00:00:00 2001 From: Philipp Reisner Date: Mon, 20 Dec 2010 15:29:28 +0100 Subject: [PATCH 0460/2822] drbd: Documenting drbd_should_do_remote() and drbd_should_send_oos() Signed-off-by: Philipp Reisner Signed-off-by: Lars Ellenberg --- drivers/block/drbd/drbd_req.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/drivers/block/drbd/drbd_req.c b/drivers/block/drbd/drbd_req.c index 528909090df72..889175110c918 100644 --- a/drivers/block/drbd/drbd_req.c +++ b/drivers/block/drbd/drbd_req.c @@ -762,7 +762,7 @@ static int drbd_may_do_local_read(struct drbd_conf *mdev, sector_t sector, int s return 0 == drbd_bm_count_bits(mdev, sbnr, ebnr); } -static int drbd_should_do_remote(struct drbd_conf *mdev) +static bool drbd_should_do_remote(struct drbd_conf *mdev) { union drbd_state s = mdev->state; @@ -770,13 +770,17 @@ static int drbd_should_do_remote(struct drbd_conf *mdev) (s.pdsk >= D_INCONSISTENT && s.conn >= C_WF_BITMAP_T && s.conn < C_AHEAD); + /* Before proto 96 that was >= CONNECTED instead of >= C_WF_BITMAP_T. + That is equivalent since before 96 IO was frozen in the C_WF_BITMAP* + states. */ } -static int drbd_should_send_oos(struct drbd_conf *mdev) +static bool drbd_should_send_oos(struct drbd_conf *mdev) { union drbd_state s = mdev->state; - return s.pdsk >= D_INCONSISTENT && - (s.conn == C_AHEAD || s.conn == C_WF_BITMAP_S); + return s.conn == C_AHEAD || s.conn == C_WF_BITMAP_S; + /* pdsk = D_INCONSISTENT as a consequence. Protocol 96 check not necessary + since we enter state C_AHEAD only if proto >= 96 */ } static int drbd_make_request_common(struct drbd_conf *mdev, struct bio *bio, unsigned long start_time) -- GitLab From f735e3635430c6d1c319664d82b34376e3f9aa17 Mon Sep 17 00:00:00 2001 From: Lars Ellenberg Date: Fri, 17 Dec 2010 21:06:18 +0100 Subject: [PATCH 0461/2822] drbd: add debugging assert to make sure the protocol is clean We expect to only receive the recently introduced "set out of sync" packets in specific states. If we receive them in different states, that may confuse the resync process to the point where it won't terminate, or think it made negative progress. Signed-off-by: Philipp Reisner Signed-off-by: Lars Ellenberg --- drivers/block/drbd/drbd_receiver.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/block/drbd/drbd_receiver.c b/drivers/block/drbd/drbd_receiver.c index be7fc67eeeca7..f0a0f66fbe680 100644 --- a/drivers/block/drbd/drbd_receiver.c +++ b/drivers/block/drbd/drbd_receiver.c @@ -3599,6 +3599,16 @@ static int receive_out_of_sync(struct drbd_conf *mdev, enum drbd_packets cmd, un { struct p_block_desc *p = &mdev->data.rbuf.block_desc; + switch (mdev->state.conn) { + case C_WF_SYNC_UUID: + case C_WF_BITMAP_T: + case C_BEHIND: + break; + default: + dev_err(DEV, "ASSERT FAILED cstate = %s, expected: WFSyncUUID|WFBitMapT|Behind\n", + drbd_conn_str(mdev->state.conn)); + } + drbd_set_out_of_sync(mdev, be64_to_cpu(p->sector), be32_to_cpu(p->blksize)); return true; -- GitLab From 5a22db8968a69bec835d1ed9a96ab3381719e0c0 Mon Sep 17 00:00:00 2001 From: Lars Ellenberg Date: Fri, 17 Dec 2010 21:14:23 +0100 Subject: [PATCH 0462/2822] drbd: serialize sending of resync uuid with pending w_send_oos To improve the latency of IO requests during bitmap exchange, we recently allowed writes while waiting for the bitmap, sending "set out-of-sync" information packets for any newly dirtied bits. We have to make sure that the new resync-uuid does not overtake these "set oos" packets. Once the resync-uuid is received, the sync target starts the resync process, and expects the bitmap to only be cleared, not re-set. If we use this protocol extension, we queue the generation and sending of the resync-uuid on the worker, which naturally serializes with all previously queued packets. Signed-off-by: Philipp Reisner Signed-off-by: Lars Ellenberg --- drivers/block/drbd/drbd_int.h | 2 +- drivers/block/drbd/drbd_main.c | 22 +++++++++++++++++++--- drivers/block/drbd/drbd_worker.c | 27 ++++++++++++++------------- 3 files changed, 34 insertions(+), 17 deletions(-) diff --git a/drivers/block/drbd/drbd_int.h b/drivers/block/drbd/drbd_int.h index 5a2d0ec72b34c..ec06e744be42f 100644 --- a/drivers/block/drbd/drbd_int.h +++ b/drivers/block/drbd/drbd_int.h @@ -1204,7 +1204,7 @@ extern int drbd_send(struct drbd_conf *mdev, struct socket *sock, extern int drbd_send_protocol(struct drbd_conf *mdev); extern int drbd_send_uuids(struct drbd_conf *mdev); extern int drbd_send_uuids_skip_initial_sync(struct drbd_conf *mdev); -extern int drbd_send_sync_uuid(struct drbd_conf *mdev, u64 val); +extern int drbd_gen_and_send_sync_uuid(struct drbd_conf *mdev); extern int drbd_send_sizes(struct drbd_conf *mdev, int trigger_reply, enum dds_flags flags); extern int _drbd_send_state(struct drbd_conf *mdev); extern int drbd_send_state(struct drbd_conf *mdev); diff --git a/drivers/block/drbd/drbd_main.c b/drivers/block/drbd/drbd_main.c index 4da6f11cc82e6..2190064d59bd0 100644 --- a/drivers/block/drbd/drbd_main.c +++ b/drivers/block/drbd/drbd_main.c @@ -1387,6 +1387,17 @@ static void after_state_ch(struct drbd_conf *mdev, union drbd_state os, spin_unlock_irq(&mdev->req_lock); } + /* Became sync source. With protocol >= 96, we still need to send out + * the sync uuid now. Need to do that before any drbd_send_state, or + * the other side may go "paused sync" before receiving the sync uuids, + * which is unexpected. */ + if ((os.conn != C_SYNC_SOURCE && os.conn != C_PAUSED_SYNC_S) && + (ns.conn == C_SYNC_SOURCE || ns.conn == C_PAUSED_SYNC_S) && + mdev->agreed_pro_version >= 96 && get_ldev(mdev)) { + drbd_gen_and_send_sync_uuid(mdev); + put_ldev(mdev); + } + /* Do not change the order of the if above and the two below... */ if (os.pdsk == D_DISKLESS && ns.pdsk > D_DISKLESS) { /* attach on the peer */ drbd_send_uuids(mdev); @@ -1980,12 +1991,17 @@ int drbd_send_uuids_skip_initial_sync(struct drbd_conf *mdev) return _drbd_send_uuids(mdev, 8); } - -int drbd_send_sync_uuid(struct drbd_conf *mdev, u64 val) +int drbd_gen_and_send_sync_uuid(struct drbd_conf *mdev) { struct p_rs_uuid p; + u64 uuid; + + D_ASSERT(mdev->state.disk == D_UP_TO_DATE); - p.uuid = cpu_to_be64(val); + get_random_bytes(&uuid, sizeof(u64)); + drbd_uuid_set(mdev, UI_BITMAP, uuid); + drbd_md_sync(mdev); + p.uuid = cpu_to_be64(uuid); return drbd_send_cmd(mdev, USE_DATA_SOCKET, P_SYNC_UUID, (struct p_header80 *)&p, sizeof(p)); diff --git a/drivers/block/drbd/drbd_worker.c b/drivers/block/drbd/drbd_worker.c index 2374454cdf17f..3df37e65c1183 100644 --- a/drivers/block/drbd/drbd_worker.c +++ b/drivers/block/drbd/drbd_worker.c @@ -1516,18 +1516,6 @@ void drbd_start_resync(struct drbd_conf *mdev, enum drbd_conns side) return; } - if (side == C_SYNC_TARGET) { - mdev->bm_resync_fo = 0; - } else /* side == C_SYNC_SOURCE */ { - u64 uuid; - - get_random_bytes(&uuid, sizeof(u64)); - drbd_uuid_set(mdev, UI_BITMAP, uuid); - drbd_send_sync_uuid(mdev, uuid); - - D_ASSERT(mdev->state.disk == D_UP_TO_DATE); - } - write_lock_irq(&global_state_lock); ns = mdev->state; @@ -1565,7 +1553,19 @@ void drbd_start_resync(struct drbd_conf *mdev, enum drbd_conns side) _drbd_pause_after(mdev); } write_unlock_irq(&global_state_lock); - put_ldev(mdev); + + if (side == C_SYNC_TARGET) + mdev->bm_resync_fo = 0; + + /* Since protocol 96, we must serialize drbd_gen_and_send_sync_uuid + * with w_send_oos, or the sync target will get confused as to + * how much bits to resync. We cannot do that always, because for an + * empty resync and protocol < 95, we need to do it here, as we call + * drbd_resync_finished from here in that case. + * We drbd_gen_and_send_sync_uuid here for protocol < 96, + * and from after_state_ch otherwise. */ + if (side == C_SYNC_SOURCE && mdev->agreed_pro_version < 96) + drbd_gen_and_send_sync_uuid(mdev); if (r == SS_SUCCESS) { dev_info(DEV, "Began resync as %s (will sync %lu KB [%lu bits set]).\n", @@ -1601,6 +1601,7 @@ void drbd_start_resync(struct drbd_conf *mdev, enum drbd_conns side) drbd_md_sync(mdev); } + put_ldev(mdev); drbd_state_unlock(mdev); } -- GitLab From 7648cdfe52daf0ca4fa9489879dea9e089b0dfe1 Mon Sep 17 00:00:00 2001 From: Lars Ellenberg Date: Fri, 17 Dec 2010 23:58:41 +0100 Subject: [PATCH 0463/2822] drbd: be less noisy with some log messages We expect changes to a bitmap page in drbd_bm_write_page, that's why we submit a copy page. If a page changes during global writeout, that would be unexpected, and reason to warn, though. Also, often page writeout can be skipped (on activity log transactions during normal operation, for example), no need to log that everytime. Signed-off-by: Philipp Reisner Signed-off-by: Lars Ellenberg --- drivers/block/drbd/drbd_bitmap.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/block/drbd/drbd_bitmap.c b/drivers/block/drbd/drbd_bitmap.c index 423dede458440..314a3632303b7 100644 --- a/drivers/block/drbd/drbd_bitmap.c +++ b/drivers/block/drbd/drbd_bitmap.c @@ -920,8 +920,9 @@ static void bm_async_io_complete(struct bio *bio, int error) if (!error && !uptodate) error = -EIO; - if (!bm_test_page_unchanged(b->bm_pages[idx])) - dev_info(DEV, "bitmap page idx %u changed during IO!\n", idx); + if ((ctx->flags & BM_AIO_COPY_PAGES) == 0 && + !bm_test_page_unchanged(b->bm_pages[idx])) + dev_warn(DEV, "bitmap page idx %u changed during IO!\n", idx); if (error) { /* ctx error will hold the completed-last non-zero error code, @@ -1135,7 +1136,7 @@ int drbd_bm_write_page(struct drbd_conf *mdev, unsigned int idx) __must_hold(loc struct bm_aio_ctx ctx = { .flags = BM_AIO_COPY_PAGES, }; if (bm_test_page_unchanged(mdev->bitmap->bm_pages[idx])) { - dev_info(DEV, "skipped bm page write for idx %u\n", idx); + dynamic_dev_dbg(DEV, "skipped bm page write for idx %u\n", idx); return 0; } -- GitLab From 418e0a927d520f9c8e875ea75abee35d93a0f1b3 Mon Sep 17 00:00:00 2001 From: Lars Ellenberg Date: Sat, 18 Dec 2010 13:36:54 +0100 Subject: [PATCH 0464/2822] drbd: spelling fix in log message Signed-off-by: Philipp Reisner Signed-off-by: Lars Ellenberg --- drivers/block/drbd/drbd_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/block/drbd/drbd_main.c b/drivers/block/drbd/drbd_main.c index 2190064d59bd0..f529c25e1ad5f 100644 --- a/drivers/block/drbd/drbd_main.c +++ b/drivers/block/drbd/drbd_main.c @@ -1351,7 +1351,7 @@ static void after_state_ch(struct drbd_conf *mdev, union drbd_state os, if (ns.conn == C_CONNECTED) what = resend, nsm.susp_nod = 0; else /* ns.conn > C_CONNECTED */ - dev_err(DEV, "Unexpected Resynd going on!\n"); + dev_err(DEV, "Unexpected Resync going on!\n"); } if (os.disk == D_ATTACHING && ns.disk > D_ATTACHING) -- GitLab From 06d33e968d2c58143a7aaafa8963cf6a58099467 Mon Sep 17 00:00:00 2001 From: Lars Ellenberg Date: Sat, 18 Dec 2010 17:00:59 +0100 Subject: [PATCH 0465/2822] drbd: improve on bitmap write out timing Even though we now track the need for bitmap writeout per bitmap page, there is no need to trigger the writeout while a resync is going on. Once the resync is finished (or aborted), we trigger bitmap writeout anyways. Signed-off-by: Philipp Reisner Signed-off-by: Lars Ellenberg --- drivers/block/drbd/drbd_main.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/block/drbd/drbd_main.c b/drivers/block/drbd/drbd_main.c index f529c25e1ad5f..755297a156333 100644 --- a/drivers/block/drbd/drbd_main.c +++ b/drivers/block/drbd/drbd_main.c @@ -1439,7 +1439,11 @@ static void after_state_ch(struct drbd_conf *mdev, union drbd_state os, put_ldev(mdev); } - if (os.role == R_PRIMARY && ns.role == R_SECONDARY && get_ldev(mdev)) { + /* Write out all changed bits on demote. + * Though, no need to da that just yet + * if there is a resync going on still */ + if (os.role == R_PRIMARY && ns.role == R_SECONDARY && + mdev->state.conn <= C_CONNECTED && get_ldev(mdev)) { drbd_bitmap_io_from_worker(mdev, &drbd_bm_write, "demote"); put_ldev(mdev); } @@ -1559,7 +1563,7 @@ static void after_state_ch(struct drbd_conf *mdev, union drbd_state os, if (os.disk < D_UP_TO_DATE && os.conn >= C_SYNC_SOURCE && ns.conn == C_CONNECTED) drbd_send_state(mdev); - if (os.conn > C_CONNECTED && ns.conn == C_CONNECTED) + if (os.conn > C_CONNECTED && ns.conn <= C_CONNECTED) drbd_queue_bitmap_io(mdev, &drbd_bm_write, NULL, "write from resync_finished"); /* free tl_hash if we Got thawed and are C_STANDALONE */ -- GitLab From 725a97e43ee945cc813fffd9e628e50d703b973b Mon Sep 17 00:00:00 2001 From: Lars Ellenberg Date: Sun, 19 Dec 2010 11:29:55 +0100 Subject: [PATCH 0466/2822] drbd: fix potential access of on-stack wait_queue_head_t after return I run into something declaring itself as "spinlock deadlock", BUG: spinlock lockup on CPU#1, kjournald/27816, ffff88000ad6bca0 Pid: 27816, comm: kjournald Tainted: G W 2.6.34.6 #2 Call Trace: [] do_raw_spin_lock+0x11e/0x14d [] _raw_spin_lock_irqsave+0x6a/0x81 [] ? __wake_up+0x22/0x50 [] __wake_up+0x22/0x50 [] bm_async_io_complete+0x258/0x299 [drbd] but the call traces do not fit at all, all other cpus are cpu_idle. I think it may be this race: drbd_bm_write_page wait_queue_head_t io_wait; atomic_t in_flight; bm_async_io submit_bio bm_async_io_complete if (atomic_dec_and_test(in_flight)) wait_event(io_wait, atomic_read(in_flight) == 0) return wake_up(io_wait) The wake_up now accesses the wait_queue_head_t spinlock, which is no longer valid, since the stack frame of drbd_bm_write_page has been clobbered now. Fix this by using struct completion, which does both the condition test as well as the wake_up inside its spinlock, so this race cannot happen. Signed-off-by: Philipp Reisner Signed-off-by: Lars Ellenberg --- drivers/block/drbd/drbd_bitmap.c | 38 ++++++++++++++++++-------------- 1 file changed, 22 insertions(+), 16 deletions(-) diff --git a/drivers/block/drbd/drbd_bitmap.c b/drivers/block/drbd/drbd_bitmap.c index 314a3632303b7..25428bc28476f 100644 --- a/drivers/block/drbd/drbd_bitmap.c +++ b/drivers/block/drbd/drbd_bitmap.c @@ -897,7 +897,7 @@ void drbd_bm_clear_all(struct drbd_conf *mdev) struct bm_aio_ctx { struct drbd_conf *mdev; atomic_t in_flight; - wait_queue_head_t io_wait; + struct completion done; unsigned flags; #define BM_AIO_COPY_PAGES 1 int error; @@ -948,7 +948,7 @@ static void bm_async_io_complete(struct bio *bio, int error) bio_put(bio); if (atomic_dec_and_test(&ctx->in_flight)) - wake_up(&ctx->io_wait); + complete(&ctx->done); } static void bm_page_io_async(struct bm_aio_ctx *ctx, int page_nr, int rw) __must_hold(local) @@ -1009,8 +1009,12 @@ static void bm_page_io_async(struct bm_aio_ctx *ctx, int page_nr, int rw) __must */ static int bm_rw(struct drbd_conf *mdev, int rw, unsigned lazy_writeout_upper_idx) __must_hold(local) { - struct bm_aio_ctx ctx = - { .flags = lazy_writeout_upper_idx ? BM_AIO_COPY_PAGES : 0 }; + struct bm_aio_ctx ctx = { + .mdev = mdev, + .in_flight = ATOMIC_INIT(1), + .done = COMPLETION_INITIALIZER_ONSTACK(ctx.done), + .flags = lazy_writeout_upper_idx ? BM_AIO_COPY_PAGES : 0, + }; struct drbd_bitmap *b = mdev->bitmap; int num_pages, i, count = 0; unsigned long now; @@ -1031,10 +1035,6 @@ static int bm_rw(struct drbd_conf *mdev, int rw, unsigned lazy_writeout_upper_id num_pages = b->bm_number_of_pages; now = jiffies; - ctx.mdev = mdev; - atomic_set(&ctx.in_flight, 1); /* one extra ref */ - init_waitqueue_head(&ctx.io_wait); - ctx.error = 0; /* let the layers below us try to merge these bios... */ for (i = 0; i < num_pages; i++) { @@ -1060,8 +1060,13 @@ static int bm_rw(struct drbd_conf *mdev, int rw, unsigned lazy_writeout_upper_id cond_resched(); } - atomic_dec(&ctx.in_flight); /* drop the extra ref */ - wait_event(ctx.io_wait, atomic_read(&ctx.in_flight) == 0); + /* + * We initialize ctx.in_flight to one to make sure bm_async_io_complete + * will not complete() early, and decrement / test it here. If there + * are still some bios in flight, we need to wait for them here. + */ + if (!atomic_dec_and_test(&ctx.in_flight)) + wait_for_completion(&ctx.done); dev_info(DEV, "bitmap %s of %u pages took %lu jiffies\n", rw == WRITE ? "WRITE" : "READ", count, jiffies - now); @@ -1133,19 +1138,20 @@ int drbd_bm_write_lazy(struct drbd_conf *mdev, unsigned upper_idx) __must_hold(l */ int drbd_bm_write_page(struct drbd_conf *mdev, unsigned int idx) __must_hold(local) { - struct bm_aio_ctx ctx = { .flags = BM_AIO_COPY_PAGES, }; + struct bm_aio_ctx ctx = { + .mdev = mdev, + .in_flight = ATOMIC_INIT(1), + .done = COMPLETION_INITIALIZER_ONSTACK(ctx.done), + .flags = BM_AIO_COPY_PAGES, + }; if (bm_test_page_unchanged(mdev->bitmap->bm_pages[idx])) { dynamic_dev_dbg(DEV, "skipped bm page write for idx %u\n", idx); return 0; } - ctx.mdev = mdev; - atomic_set(&ctx.in_flight, 1); - init_waitqueue_head(&ctx.io_wait); - bm_page_io_async(&ctx, idx, WRITE_SYNC); - wait_event(ctx.io_wait, atomic_read(&ctx.in_flight) == 0); + wait_for_completion(&ctx.done); if (ctx.error) drbd_chk_io_error(mdev, 1, true); -- GitLab From 3f98688afc2ce0138fc88e272bdd128e1e0b0976 Mon Sep 17 00:00:00 2001 From: Philipp Reisner Date: Mon, 20 Dec 2010 14:48:20 +0100 Subject: [PATCH 0467/2822] drbd: There might be a resync after unfreezing IO due to no disk [Bugz 332] When on-no-data-accessible is set to suspend-io, also consider that a Primary, SyncTarget node losses its connection. Signed-off-by: Philipp Reisner Signed-off-by: Lars Ellenberg --- drivers/block/drbd/drbd_main.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/drivers/block/drbd/drbd_main.c b/drivers/block/drbd/drbd_main.c index 755297a156333..9bd53cf2cdb2b 100644 --- a/drivers/block/drbd/drbd_main.c +++ b/drivers/block/drbd/drbd_main.c @@ -1347,16 +1347,14 @@ static void after_state_ch(struct drbd_conf *mdev, union drbd_state os, nsm.i = -1; if (ns.susp_nod) { - if (os.conn < C_CONNECTED && ns.conn >= C_CONNECTED) { - if (ns.conn == C_CONNECTED) - what = resend, nsm.susp_nod = 0; - else /* ns.conn > C_CONNECTED */ - dev_err(DEV, "Unexpected Resync going on!\n"); - } + if (os.conn < C_CONNECTED && ns.conn >= C_CONNECTED) + what = resend; if (os.disk == D_ATTACHING && ns.disk > D_ATTACHING) - what = restart_frozen_disk_io, nsm.susp_nod = 0; + what = restart_frozen_disk_io; + if (what != nothing) + nsm.susp_nod = 0; } if (ns.susp_fen) { -- GitLab From 071942727824bab03b1a3f6b6eeb5b269697b333 Mon Sep 17 00:00:00 2001 From: Lars Ellenberg Date: Mon, 20 Dec 2010 15:38:07 +0100 Subject: [PATCH 0468/2822] drbd: ratelimit io error messages Signed-off-by: Philipp Reisner Signed-off-by: Lars Ellenberg --- drivers/block/drbd/drbd_worker.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/block/drbd/drbd_worker.c b/drivers/block/drbd/drbd_worker.c index 3df37e65c1183..7bfeb79e7105f 100644 --- a/drivers/block/drbd/drbd_worker.c +++ b/drivers/block/drbd/drbd_worker.c @@ -165,14 +165,15 @@ void drbd_endio_sec(struct bio *bio, int error) int uptodate = bio_flagged(bio, BIO_UPTODATE); int is_write = bio_data_dir(bio) == WRITE; - if (error) + if (error && __ratelimit(&drbd_ratelimit_state)) dev_warn(DEV, "%s: error=%d s=%llus\n", is_write ? "write" : "read", error, (unsigned long long)e->sector); if (!error && !uptodate) { - dev_warn(DEV, "%s: setting error to -EIO s=%llus\n", - is_write ? "write" : "read", - (unsigned long long)e->sector); + if (__ratelimit(&drbd_ratelimit_state)) + dev_warn(DEV, "%s: setting error to -EIO s=%llus\n", + is_write ? "write" : "read", + (unsigned long long)e->sector); /* strange behavior of some lower level drivers... * fail the request by clearing the uptodate flag, * but do not return any error?! */ -- GitLab From 617049aa7d753e8c821ac77126ab90e9f1b66d6d Mon Sep 17 00:00:00 2001 From: Philipp Reisner Date: Wed, 22 Dec 2010 12:48:31 +0100 Subject: [PATCH 0469/2822] drbd: Fixed an issue with AHEAD -> SYNC_SOURCE transitions Create a new barrier when leaving the AHEAD mode. Otherwise we trigger the assertion in req_mod(, barrier_acked) D_ASSERT(req->rq_state & RQ_NET_SENT); The new barrier is created by recycling the newest existing one. Signed-off-by: Philipp Reisner Signed-off-by: Lars Ellenberg --- drivers/block/drbd/drbd_main.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/drivers/block/drbd/drbd_main.c b/drivers/block/drbd/drbd_main.c index 9bd53cf2cdb2b..90050ab7adf38 100644 --- a/drivers/block/drbd/drbd_main.c +++ b/drivers/block/drbd/drbd_main.c @@ -335,6 +335,24 @@ bail: drbd_force_state(mdev, NS(conn, C_PROTOCOL_ERROR)); } + +/* In C_AHEAD mode only out_of_sync packets are sent for requests. Detach + * those requests from the newsest barrier when changing to an other cstate. + * + * That headless list vanishes when the last request finished its write or + * send out_of_sync packet. */ +static void tl_forget(struct drbd_conf *mdev) +{ + struct drbd_tl_epoch *b; + + if (test_bit(CREATE_BARRIER, &mdev->flags)) + return; + + b = mdev->newest_tle; + list_del(&b->requests); + _tl_add_barrier(mdev, b); +} + /** * _tl_restart() - Walks the transfer log, and applies an action to all requests * @mdev: DRBD device. @@ -1242,6 +1260,9 @@ __drbd_set_state(struct drbd_conf *mdev, union drbd_state ns, if (os.conn < C_CONNECTED && ns.conn >= C_CONNECTED) drbd_resume_al(mdev); + if (os.conn == C_AHEAD && ns.conn != C_AHEAD) + tl_forget(mdev); + ascw = kmalloc(sizeof(*ascw), GFP_ATOMIC); if (ascw) { ascw->os = os; -- GitLab From d612d309e4c8401ad94c531678b59c4a8b7c41ce Mon Sep 17 00:00:00 2001 From: Philipp Reisner Date: Mon, 27 Dec 2010 10:53:28 +0100 Subject: [PATCH 0470/2822] drbd: No longer answer P_RS_DATA_REQUEST packets when in C_AHEAD mode When the sync source node replies to a P_RS_DATA_REQUEST packet when it is already in ahead mode. I.e. those two packets crossed each other on the wire, that may lead to diverging bitmaps. This never happens in a well-tuned-system. In a well-tuned- system the resync controller has reduced the resync speed to zero long before we got into ahead-mode. But we have to be prepared for the not-well-tuned-system of course as well. Because -> diverging bitmaps = non terminating resync. Signed-off-by: Philipp Reisner Signed-off-by: Lars Ellenberg --- drivers/block/drbd/drbd_int.h | 3 ++- drivers/block/drbd/drbd_receiver.c | 12 +++++++++++- drivers/block/drbd/drbd_worker.c | 4 +++- 3 files changed, 16 insertions(+), 3 deletions(-) diff --git a/drivers/block/drbd/drbd_int.h b/drivers/block/drbd/drbd_int.h index ec06e744be42f..a529285b0cd3c 100644 --- a/drivers/block/drbd/drbd_int.h +++ b/drivers/block/drbd/drbd_int.h @@ -205,8 +205,9 @@ enum drbd_packets { /* P_CKPT_DISABLE_REQ = 0x26, * currently reserved for protocol D */ P_DELAY_PROBE = 0x27, /* is used on BOTH sockets */ P_OUT_OF_SYNC = 0x28, /* Mark as out of sync (Outrunning), data socket */ + P_RS_CANCEL = 0x29, /* meta: Used to cancel RS_DATA_REQUEST packet by SyncSource */ - P_MAX_CMD = 0x28, + P_MAX_CMD = 0x2A, P_MAY_IGNORE = 0x100, /* Flag to test if (cmd > P_MAY_IGNORE) ... */ P_MAX_OPT_CMD = 0x101, diff --git a/drivers/block/drbd/drbd_receiver.c b/drivers/block/drbd/drbd_receiver.c index f0a0f66fbe680..bf865bd834143 100644 --- a/drivers/block/drbd/drbd_receiver.c +++ b/drivers/block/drbd/drbd_receiver.c @@ -4361,7 +4361,16 @@ static int got_NegRSDReply(struct drbd_conf *mdev, struct p_header80 *h) if (get_ldev_if_state(mdev, D_FAILED)) { drbd_rs_complete_io(mdev, sector); - drbd_rs_failed_io(mdev, sector, size); + switch (be16_to_cpu(h->command)) { + case P_NEG_RS_DREPLY: + drbd_rs_failed_io(mdev, sector, size); + case P_RS_CANCEL: + break; + default: + D_ASSERT(0); + put_ldev(mdev); + return false; + } put_ldev(mdev); } @@ -4459,6 +4468,7 @@ static struct asender_cmd *get_asender_cmd(int cmd) [P_STATE_CHG_REPLY] = { sizeof(struct p_req_state_reply), got_RqSReply }, [P_RS_IS_IN_SYNC] = { sizeof(struct p_block_ack), got_IsInSync }, [P_DELAY_PROBE] = { sizeof(struct p_delay_probe93), got_skip }, + [P_RS_CANCEL] = { sizeof(struct p_block_ack), got_NegRSDReply}, [P_MAX_CMD] = { 0, NULL }, }; if (cmd > P_MAX_CMD || asender_tbl[cmd].process == NULL) diff --git a/drivers/block/drbd/drbd_worker.c b/drivers/block/drbd/drbd_worker.c index 7bfeb79e7105f..1d7510ebaa431 100644 --- a/drivers/block/drbd/drbd_worker.c +++ b/drivers/block/drbd/drbd_worker.c @@ -988,7 +988,9 @@ int w_e_end_rsdata_req(struct drbd_conf *mdev, struct drbd_work *w, int cancel) put_ldev(mdev); } - if (likely((e->flags & EE_WAS_ERROR) == 0)) { + if (mdev->state.conn == C_AHEAD) { + ok = drbd_send_ack(mdev, P_RS_CANCEL, e); + } else if (likely((e->flags & EE_WAS_ERROR) == 0)) { if (likely(mdev->state.pdsk >= D_INCONSISTENT)) { inc_rs_pending(mdev); ok = drbd_send_block(mdev, P_RS_DATA_REPLY, e); -- GitLab From da0a78161d2b2da4819a1f05a38bb1dcbe02d951 Mon Sep 17 00:00:00 2001 From: Philipp Reisner Date: Thu, 23 Dec 2010 14:24:33 +0100 Subject: [PATCH 0471/2822] drbd: Be more careful with SyncSource -> Ahead transitions We may not get from SyncSource to Ahead if we have sent some P_RS_DATA_REPLY packets to the peer and are waiting for P_WRITE_ACK. Again, this is not relevant for proper tuned systems, but makes sure that the not-tuned system does not get diverging bitmaps. Signed-off-by: Philipp Reisner Signed-off-by: Lars Ellenberg --- drivers/block/drbd/drbd_receiver.c | 3 ++- drivers/block/drbd/drbd_req.c | 8 +++++++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/drivers/block/drbd/drbd_receiver.c b/drivers/block/drbd/drbd_receiver.c index bf865bd834143..fd0957f9c2305 100644 --- a/drivers/block/drbd/drbd_receiver.c +++ b/drivers/block/drbd/drbd_receiver.c @@ -4385,10 +4385,11 @@ static int got_BarrierAck(struct drbd_conf *mdev, struct p_header80 *h) if (mdev->state.conn == C_AHEAD && atomic_read(&mdev->ap_in_flight) == 0 && + atomic_read(&mdev->rs_pending_cnt) == 0 && list_empty(&mdev->start_resync_work.list)) { struct drbd_work *w = &mdev->start_resync_work; w->cb = w_start_resync; - drbd_queue_work_front(&mdev->data.work, w); + drbd_queue_work(&mdev->data.work, w); } return true; diff --git a/drivers/block/drbd/drbd_req.c b/drivers/block/drbd/drbd_req.c index 889175110c918..a3f6b04ebabad 100644 --- a/drivers/block/drbd/drbd_req.c +++ b/drivers/block/drbd/drbd_req.c @@ -1002,7 +1002,13 @@ allocate_barrier: congested = 1; } - if (congested) { + if (congested && atomic_read(&mdev->rs_pending_cnt) == 0) { + /* rs_pending_cnt must be zero, otherwise the two peers + might get different bitmaps. With sane configurations + the resync stalls long before we might want to go into + AHEAD mode. + We could force the resync into PAUSE mode here if + rs_pending_cnt is > 0 ... */ queue_barrier(mdev); if (mdev->net_conf->on_congestion == OC_PULL_AHEAD) -- GitLab From 794abb753e29e85949b3719dbc2ab6a98711a47e Mon Sep 17 00:00:00 2001 From: Philipp Reisner Date: Mon, 27 Dec 2010 11:51:23 +0100 Subject: [PATCH 0472/2822] drbd: Cleaned up the resync timer logic Besides removed a few lines of code, this moves the inspection of the state from before the queuing process to after the queuing. I.e. more closely to the actual invocation of the work. Signed-off-by: Philipp Reisner Signed-off-by: Lars Ellenberg --- drivers/block/drbd/drbd_int.h | 2 +- drivers/block/drbd/drbd_main.c | 2 +- drivers/block/drbd/drbd_worker.c | 48 ++++++++------------------------ 3 files changed, 13 insertions(+), 39 deletions(-) diff --git a/drivers/block/drbd/drbd_int.h b/drivers/block/drbd/drbd_int.h index a529285b0cd3c..dc11b7070ba9f 100644 --- a/drivers/block/drbd/drbd_int.h +++ b/drivers/block/drbd/drbd_int.h @@ -1540,7 +1540,7 @@ extern int w_e_end_csum_rs_req(struct drbd_conf *, struct drbd_work *, int); extern int w_e_end_ov_reply(struct drbd_conf *, struct drbd_work *, int); extern int w_e_end_ov_req(struct drbd_conf *, struct drbd_work *, int); extern int w_ov_finished(struct drbd_conf *, struct drbd_work *, int); -extern int w_resync_inactive(struct drbd_conf *, struct drbd_work *, int); +extern int w_resync_timer(struct drbd_conf *, struct drbd_work *, int); extern int w_resume_next_sg(struct drbd_conf *, struct drbd_work *, int); extern int w_send_write_hint(struct drbd_conf *, struct drbd_work *, int); extern int w_send_dblock(struct drbd_conf *, struct drbd_work *, int); diff --git a/drivers/block/drbd/drbd_main.c b/drivers/block/drbd/drbd_main.c index 90050ab7adf38..4074d66993076 100644 --- a/drivers/block/drbd/drbd_main.c +++ b/drivers/block/drbd/drbd_main.c @@ -2978,7 +2978,7 @@ void drbd_init_set_defaults(struct drbd_conf *mdev) INIT_LIST_HEAD(&mdev->start_resync_work.list); INIT_LIST_HEAD(&mdev->bm_io_work.w.list); - mdev->resync_work.cb = w_resync_inactive; + mdev->resync_work.cb = w_resync_timer; mdev->unplug_work.cb = w_send_write_hint; mdev->go_diskless.cb = w_go_diskless; mdev->md_sync_work.cb = w_md_sync; diff --git a/drivers/block/drbd/drbd_worker.c b/drivers/block/drbd/drbd_worker.c index 1d7510ebaa431..147f76b268102 100644 --- a/drivers/block/drbd/drbd_worker.c +++ b/drivers/block/drbd/drbd_worker.c @@ -253,13 +253,6 @@ int w_read_retry_remote(struct drbd_conf *mdev, struct drbd_work *w, int cancel) return w_send_read_req(mdev, w, 0); } -int w_resync_inactive(struct drbd_conf *mdev, struct drbd_work *w, int cancel) -{ - ERR_IF(cancel) return 1; - dev_err(DEV, "resync inactive, but callback triggered??\n"); - return 1; /* Simply ignore this! */ -} - void drbd_csum_ee(struct drbd_conf *mdev, struct crypto_hash *tfm, struct drbd_epoch_entry *e, void *digest) { struct hash_desc desc; @@ -389,26 +382,25 @@ defer: return -EAGAIN; } -void resync_timer_fn(unsigned long data) +int w_resync_timer(struct drbd_conf *mdev, struct drbd_work *w, int cancel) { - struct drbd_conf *mdev = (struct drbd_conf *) data; - int queue; - - queue = 1; switch (mdev->state.conn) { case C_VERIFY_S: - mdev->resync_work.cb = w_make_ov_request; + w_make_ov_request(mdev, w, cancel); break; case C_SYNC_TARGET: - mdev->resync_work.cb = w_make_resync_request; + w_make_resync_request(mdev, w, cancel); break; - default: - queue = 0; - mdev->resync_work.cb = w_resync_inactive; } - /* harmless race: list_empty outside data.work.q_lock */ - if (list_empty(&mdev->resync_work.list) && queue) + return 1; +} + +void resync_timer_fn(unsigned long data) +{ + struct drbd_conf *mdev = (struct drbd_conf *) data; + + if (list_empty(&mdev->resync_work.list)) drbd_queue_work(&mdev->data.work, &mdev->resync_work); } @@ -525,15 +517,6 @@ static int w_make_resync_request(struct drbd_conf *mdev, if (unlikely(cancel)) return 1; - if (unlikely(mdev->state.conn < C_CONNECTED)) { - dev_err(DEV, "Confused in w_make_resync_request()! cstate < Connected"); - return 0; - } - - if (mdev->state.conn != C_SYNC_TARGET) - dev_err(DEV, "%s in w_make_resync_request\n", - drbd_conn_str(mdev->state.conn)); - if (mdev->rs_total == 0) { /* empty resync? */ drbd_resync_finished(mdev); @@ -546,7 +529,6 @@ static int w_make_resync_request(struct drbd_conf *mdev, to continue resync with a broken disk makes no sense at all */ dev_err(DEV, "Disk broke down during resync!\n"); - mdev->resync_work.cb = w_resync_inactive; return 1; } @@ -580,7 +562,6 @@ next_sector: if (bit == DRBD_END_OF_BITMAP) { mdev->bm_resync_fo = drbd_bm_bits(mdev); - mdev->resync_work.cb = w_resync_inactive; put_ldev(mdev); return 1; } @@ -676,7 +657,6 @@ next_sector: * resync data block, and the last bit is cleared. * until then resync "work" is "inactive" ... */ - mdev->resync_work.cb = w_resync_inactive; put_ldev(mdev); return 1; } @@ -697,17 +677,11 @@ static int w_make_ov_request(struct drbd_conf *mdev, struct drbd_work *w, int ca if (unlikely(cancel)) return 1; - if (unlikely(mdev->state.conn < C_CONNECTED)) { - dev_err(DEV, "Confused in w_make_ov_request()! cstate < Connected"); - return 0; - } - number = drbd_rs_number_requests(mdev); sector = mdev->ov_position; for (i = 0; i < number; i++) { if (sector >= capacity) { - mdev->resync_work.cb = w_resync_inactive; return 1; } -- GitLab From 110a204a354a5a69f99ed0bc8e6d779e6a94d410 Mon Sep 17 00:00:00 2001 From: Andreas Gruenbacher Date: Mon, 3 Jan 2011 15:47:08 +0100 Subject: [PATCH 0473/2822] drbd: Remove useless / wrong comments Signed-off-by: Philipp Reisner Signed-off-by: Lars Ellenberg --- drivers/block/drbd/drbd_int.h | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/drivers/block/drbd/drbd_int.h b/drivers/block/drbd/drbd_int.h index dc11b7070ba9f..84b4575fdf432 100644 --- a/drivers/block/drbd/drbd_int.h +++ b/drivers/block/drbd/drbd_int.h @@ -680,13 +680,6 @@ static inline enum drbd_thread_state get_t_state(struct drbd_thread *thi) return thi->t_state; } - -/* - * Having this as the first member of a struct provides sort of "inheritance". - * "derived" structs can be "drbd_queue_work()"ed. - * The callback should know and cast back to the descendant struct. - * drbd_request and drbd_epoch_entry are descendants of drbd_work. - */ struct drbd_work; typedef int (*drbd_work_cb)(struct drbd_conf *, struct drbd_work *, int cancel); struct drbd_work { @@ -715,9 +708,6 @@ struct drbd_request { * starting a new epoch... */ - /* up to here, the struct layout is identical to drbd_epoch_entry; - * we might be able to use that to our advantage... */ - struct list_head tl_requests; /* ring list in the transfer log */ struct bio *master_bio; /* master bio pointer */ unsigned long rq_state; /* see comments above _req_mod() */ -- GitLab From 2b8a90b55533c66258a1ff0fb27b8cffa95665c4 Mon Sep 17 00:00:00 2001 From: Philipp Reisner Date: Mon, 10 Jan 2011 11:15:17 +0100 Subject: [PATCH 0474/2822] drbd: Corrected off-by-one error in DRBD_MINOR_COUNT_MAX Signed-off-by: Philipp Reisner Signed-off-by: Lars Ellenberg --- drivers/block/drbd/drbd_main.c | 7 ++++--- include/linux/drbd_limits.h | 3 ++- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/block/drbd/drbd_main.c b/drivers/block/drbd/drbd_main.c index 4074d66993076..da98bff7c3335 100644 --- a/drivers/block/drbd/drbd_main.c +++ b/drivers/block/drbd/drbd_main.c @@ -85,7 +85,8 @@ MODULE_AUTHOR("Philipp Reisner , " MODULE_DESCRIPTION("drbd - Distributed Replicated Block Device v" REL_VERSION); MODULE_VERSION(REL_VERSION); MODULE_LICENSE("GPL"); -MODULE_PARM_DESC(minor_count, "Maximum number of drbd devices (1-255)"); +MODULE_PARM_DESC(minor_count, "Maximum number of drbd devices (" + __stringify(DRBD_MINOR_COUNT_MIN) "-" __stringify(DRBD_MINOR_COUNT_MAX) ")"); MODULE_ALIAS_BLOCKDEV_MAJOR(DRBD_MAJOR); #include @@ -115,7 +116,7 @@ module_param(fault_devs, int, 0644); #endif /* module parameter, defined */ -unsigned int minor_count = 32; +unsigned int minor_count = DRBD_MINOR_COUNT_DEF; int disable_sendpage; int allow_oos; unsigned int cn_idx = CN_IDX_DRBD; @@ -3456,7 +3457,7 @@ int __init drbd_init(void) return -EINVAL; } - if (1 > minor_count || minor_count > 255) { + if (minor_count < DRBD_MINOR_COUNT_MIN || minor_count > DRBD_MINOR_COUNT_MAX) { printk(KERN_ERR "drbd: invalid minor_count (%d)\n", minor_count); #ifdef MODULE diff --git a/include/linux/drbd_limits.h b/include/linux/drbd_limits.h index abf418724e52f..bb264a5732de7 100644 --- a/include/linux/drbd_limits.h +++ b/include/linux/drbd_limits.h @@ -16,7 +16,8 @@ #define DEBUG_RANGE_CHECK 0 #define DRBD_MINOR_COUNT_MIN 1 -#define DRBD_MINOR_COUNT_MAX 255 +#define DRBD_MINOR_COUNT_MAX 256 +#define DRBD_MINOR_COUNT_DEF 32 #define DRBD_DIALOG_REFRESH_MIN 0 #define DRBD_DIALOG_REFRESH_MAX 600 -- GitLab From 4a23f2649698272abcd9e0c9a992d65739f32792 Mon Sep 17 00:00:00 2001 From: Philipp Reisner Date: Tue, 11 Jan 2011 17:42:17 +0100 Subject: [PATCH 0475/2822] drbd: Do not full sync if a P_SYNC_UUID packet gets lost See also commit from 2009-08-15 "drbd_uuid_compare(): Do not full sync in case a P_SYNC_UUID packet gets lost." We saw cases where the History UUIDs where not as expected. So the detection of the special case did not trigger. With the sync UUID no longer being a random number, but deducible from the previous bitmap UUID, the detection of this special case becomes more reliable. The SyncUUID now is the previous bitmap UUID + 0x1000000000000. Rule 5a: Cs = H1p & H1p + Offset = Bp Connection was lost before SyncUUID Packet came through. Corrent (peer) UUIDs: Bp = H1p H1p = H2p H2p = 0 Become Sync target. Rule 7a: Cp = H1s & H1s + Offset = Bs Connection was lost before SyncUUID Packet came through. Correct (own) UUIDs: Bs = H1s H1s = H2s H2s = 0 Become Sync source. Signed-off-by: Philipp Reisner Signed-off-by: Lars Ellenberg --- drivers/block/drbd/drbd_int.h | 1 + drivers/block/drbd/drbd_main.c | 2 +- drivers/block/drbd/drbd_receiver.c | 35 ++++++++++++++++++------------ 3 files changed, 23 insertions(+), 15 deletions(-) diff --git a/drivers/block/drbd/drbd_int.h b/drivers/block/drbd/drbd_int.h index 84b4575fdf432..3c8eecd9666d8 100644 --- a/drivers/block/drbd/drbd_int.h +++ b/drivers/block/drbd/drbd_int.h @@ -97,6 +97,7 @@ extern char usermode_helper[]; #define ID_SYNCER (-1ULL) #define ID_VACANT 0 #define is_syncer_block_id(id) ((id) == ID_SYNCER) +#define UUID_NEW_BM_OFFSET ((u64)0x0001000000000000ULL) struct drbd_conf; diff --git a/drivers/block/drbd/drbd_main.c b/drivers/block/drbd/drbd_main.c index da98bff7c3335..b3b6d3190f652 100644 --- a/drivers/block/drbd/drbd_main.c +++ b/drivers/block/drbd/drbd_main.c @@ -2022,7 +2022,7 @@ int drbd_gen_and_send_sync_uuid(struct drbd_conf *mdev) D_ASSERT(mdev->state.disk == D_UP_TO_DATE); - get_random_bytes(&uuid, sizeof(u64)); + uuid = mdev->ldev->md.uuid[UI_BITMAP] + UUID_NEW_BM_OFFSET; drbd_uuid_set(mdev, UI_BITMAP, uuid); drbd_md_sync(mdev); p.uuid = cpu_to_be64(uuid); diff --git a/drivers/block/drbd/drbd_receiver.c b/drivers/block/drbd/drbd_receiver.c index fd0957f9c2305..7991183749e38 100644 --- a/drivers/block/drbd/drbd_receiver.c +++ b/drivers/block/drbd/drbd_receiver.c @@ -2293,6 +2293,8 @@ static void drbd_uuid_dump(struct drbd_conf *mdev, char *text, u64 *uuid, -2 C_SYNC_TARGET set BitMap -100 after split brain, disconnect -1000 unrelated data +-1091 requires proto 91 +-1096 requires proto 96 */ static int drbd_uuid_compare(struct drbd_conf *mdev, int *rule_nr) __must_hold(local) { @@ -2322,7 +2324,7 @@ static int drbd_uuid_compare(struct drbd_conf *mdev, int *rule_nr) __must_hold(l if (mdev->p_uuid[UI_BITMAP] == (u64)0 && mdev->ldev->md.uuid[UI_BITMAP] != (u64)0) { if (mdev->agreed_pro_version < 91) - return -1001; + return -1091; if ((mdev->ldev->md.uuid[UI_BITMAP] & ~((u64)1)) == (mdev->p_uuid[UI_HISTORY_START] & ~((u64)1)) && (mdev->ldev->md.uuid[UI_HISTORY_START] & ~((u64)1)) == (mdev->p_uuid[UI_HISTORY_START + 1] & ~((u64)1))) { @@ -2343,7 +2345,7 @@ static int drbd_uuid_compare(struct drbd_conf *mdev, int *rule_nr) __must_hold(l if (mdev->ldev->md.uuid[UI_BITMAP] == (u64)0 && mdev->p_uuid[UI_BITMAP] != (u64)0) { if (mdev->agreed_pro_version < 91) - return -1001; + return -1091; if ((mdev->ldev->md.uuid[UI_HISTORY_START] & ~((u64)1)) == (mdev->p_uuid[UI_BITMAP] & ~((u64)1)) && (mdev->ldev->md.uuid[UI_HISTORY_START + 1] & ~((u64)1)) == (mdev->p_uuid[UI_HISTORY_START] & ~((u64)1))) { @@ -2388,17 +2390,22 @@ static int drbd_uuid_compare(struct drbd_conf *mdev, int *rule_nr) __must_hold(l *rule_nr = 51; peer = mdev->p_uuid[UI_HISTORY_START] & ~((u64)1); if (self == peer) { - self = mdev->ldev->md.uuid[UI_HISTORY_START] & ~((u64)1); - peer = mdev->p_uuid[UI_HISTORY_START + 1] & ~((u64)1); - if (self == peer) { + if (mdev->agreed_pro_version < 96 ? + (mdev->ldev->md.uuid[UI_HISTORY_START] & ~((u64)1)) == + (mdev->p_uuid[UI_HISTORY_START + 1] & ~((u64)1)) : + peer + UUID_NEW_BM_OFFSET == (mdev->p_uuid[UI_BITMAP] & ~((u64)1))) { /* The last P_SYNC_UUID did not get though. Undo the last start of resync as sync source modifications of the peer's UUIDs. */ if (mdev->agreed_pro_version < 91) - return -1001; + return -1091; mdev->p_uuid[UI_BITMAP] = mdev->p_uuid[UI_HISTORY_START]; mdev->p_uuid[UI_HISTORY_START] = mdev->p_uuid[UI_HISTORY_START + 1]; + + dev_info(DEV, "Did not got last syncUUID packet, corrected:\n"); + drbd_uuid_dump(mdev, "peer", mdev->p_uuid, mdev->p_uuid[UI_SIZE], mdev->p_uuid[UI_FLAGS]); + return -1; } } @@ -2420,20 +2427,20 @@ static int drbd_uuid_compare(struct drbd_conf *mdev, int *rule_nr) __must_hold(l *rule_nr = 71; self = mdev->ldev->md.uuid[UI_HISTORY_START] & ~((u64)1); if (self == peer) { - self = mdev->ldev->md.uuid[UI_HISTORY_START + 1] & ~((u64)1); - peer = mdev->p_uuid[UI_HISTORY_START] & ~((u64)1); - if (self == peer) { + if (mdev->agreed_pro_version < 96 ? + (mdev->ldev->md.uuid[UI_HISTORY_START + 1] & ~((u64)1)) == + (mdev->p_uuid[UI_HISTORY_START] & ~((u64)1)) : + self + UUID_NEW_BM_OFFSET == (mdev->ldev->md.uuid[UI_BITMAP] & ~((u64)1))) { /* The last P_SYNC_UUID did not get though. Undo the last start of resync as sync source modifications of our UUIDs. */ if (mdev->agreed_pro_version < 91) - return -1001; + return -1091; _drbd_uuid_set(mdev, UI_BITMAP, mdev->ldev->md.uuid[UI_HISTORY_START]); _drbd_uuid_set(mdev, UI_HISTORY_START, mdev->ldev->md.uuid[UI_HISTORY_START + 1]); - dev_info(DEV, "Undid last start of resync:\n"); - + dev_info(DEV, "Last syncUUID did not get through, corrected:\n"); drbd_uuid_dump(mdev, "self", mdev->ldev->md.uuid, mdev->state.disk >= D_NEGOTIATING ? drbd_bm_total_weight(mdev) : 0, 0); @@ -2496,8 +2503,8 @@ static enum drbd_conns drbd_sync_handshake(struct drbd_conf *mdev, enum drbd_rol dev_alert(DEV, "Unrelated data, aborting!\n"); return C_MASK; } - if (hg == -1001) { - dev_alert(DEV, "To resolve this both sides have to support at least protocol 91\n"); + if (hg < -1000) { + dev_alert(DEV, "To resolve this both sides have to support at least protocol %d\n", -hg - 1000); return C_MASK; } -- GitLab From 71c78cfba232de8f61a4b1bbb6e876424d133407 Mon Sep 17 00:00:00 2001 From: Philipp Reisner Date: Fri, 14 Jan 2011 19:20:34 +0100 Subject: [PATCH 0476/2822] drbd: Nothing should stop SyncSource -> Ahead transitions Signed-off-by: Philipp Reisner Signed-off-by: Lars Ellenberg --- drivers/block/drbd/drbd_req.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/block/drbd/drbd_req.c b/drivers/block/drbd/drbd_req.c index a3f6b04ebabad..6f9d1bfcca58c 100644 --- a/drivers/block/drbd/drbd_req.c +++ b/drivers/block/drbd/drbd_req.c @@ -1002,7 +1002,7 @@ allocate_barrier: congested = 1; } - if (congested && atomic_read(&mdev->rs_pending_cnt) == 0) { + if (congested) { /* rs_pending_cnt must be zero, otherwise the two peers might get different bitmaps. With sane configurations the resync stalls long before we might want to go into -- GitLab From 370a43e7982dd497822097e0ae6022947ac2e7d4 Mon Sep 17 00:00:00 2001 From: Philipp Reisner Date: Fri, 14 Jan 2011 16:03:11 +0100 Subject: [PATCH 0477/2822] drbd: Work on the Ahead -> SyncSource transition The test if rs_pending_cnt == 0 was too weak. Using Test for unacked_cnt == 0 instead. Moved that into the worker. Since unacked_cnt gets already increased when an P_RS_DATA_REQ comes in. Also using a timer to make Ahead -> SyncSource -> Ahead cycles slower... Signed-off-by: Philipp Reisner Signed-off-by: Lars Ellenberg --- drivers/block/drbd/drbd_int.h | 3 +++ drivers/block/drbd/drbd_main.c | 4 ++++ drivers/block/drbd/drbd_receiver.c | 8 +++----- drivers/block/drbd/drbd_worker.c | 16 +++++++++++++++- 4 files changed, 25 insertions(+), 6 deletions(-) diff --git a/drivers/block/drbd/drbd_int.h b/drivers/block/drbd/drbd_int.h index 3c8eecd9666d8..cfe7fff459e30 100644 --- a/drivers/block/drbd/drbd_int.h +++ b/drivers/block/drbd/drbd_int.h @@ -850,6 +850,7 @@ enum { GOT_PING_ACK, /* set when we receive a ping_ack packet, misc wait gets woken */ NEW_CUR_UUID, /* Create new current UUID when thawing IO */ AL_SUSPENDED, /* Activity logging is currently suspended. */ + AHEAD_TO_SYNC_SOURCE, /* Ahead -> SyncSource queued */ }; struct drbd_bitmap; /* opaque for drbd_conf */ @@ -961,6 +962,7 @@ struct drbd_conf { start_resync_work; struct timer_list resync_timer; struct timer_list md_sync_timer; + struct timer_list start_resync_timer; #ifdef DRBD_DEBUG_MD_SYNC struct { unsigned int line; @@ -1544,6 +1546,7 @@ extern int w_send_oos(struct drbd_conf *, struct drbd_work *, int); extern int w_start_resync(struct drbd_conf *, struct drbd_work *, int); extern void resync_timer_fn(unsigned long data); +extern void start_resync_timer_fn(unsigned long data); /* drbd_receiver.c */ extern int drbd_rs_should_slow_down(struct drbd_conf *mdev, sector_t sector); diff --git a/drivers/block/drbd/drbd_main.c b/drivers/block/drbd/drbd_main.c index b3b6d3190f652..8ec7c65988bef 100644 --- a/drivers/block/drbd/drbd_main.c +++ b/drivers/block/drbd/drbd_main.c @@ -2984,12 +2984,16 @@ void drbd_init_set_defaults(struct drbd_conf *mdev) mdev->go_diskless.cb = w_go_diskless; mdev->md_sync_work.cb = w_md_sync; mdev->bm_io_work.w.cb = w_bitmap_io; + mdev->start_resync_work.cb = w_start_resync; init_timer(&mdev->resync_timer); init_timer(&mdev->md_sync_timer); + init_timer(&mdev->start_resync_timer); mdev->resync_timer.function = resync_timer_fn; mdev->resync_timer.data = (unsigned long) mdev; mdev->md_sync_timer.function = md_sync_timer_fn; mdev->md_sync_timer.data = (unsigned long) mdev; + mdev->start_resync_timer.function = start_resync_timer_fn; + mdev->start_resync_timer.data = (unsigned long) mdev; init_waitqueue_head(&mdev->misc_wait); init_waitqueue_head(&mdev->state_wait); diff --git a/drivers/block/drbd/drbd_receiver.c b/drivers/block/drbd/drbd_receiver.c index 7991183749e38..18cb8b609fe48 100644 --- a/drivers/block/drbd/drbd_receiver.c +++ b/drivers/block/drbd/drbd_receiver.c @@ -4392,11 +4392,9 @@ static int got_BarrierAck(struct drbd_conf *mdev, struct p_header80 *h) if (mdev->state.conn == C_AHEAD && atomic_read(&mdev->ap_in_flight) == 0 && - atomic_read(&mdev->rs_pending_cnt) == 0 && - list_empty(&mdev->start_resync_work.list)) { - struct drbd_work *w = &mdev->start_resync_work; - w->cb = w_start_resync; - drbd_queue_work(&mdev->data.work, w); + !test_and_set_bit(AHEAD_TO_SYNC_SOURCE, &mdev->current_epoch->flags)) { + mdev->start_resync_timer.expires = jiffies + HZ; + add_timer(&mdev->start_resync_timer); } return true; diff --git a/drivers/block/drbd/drbd_worker.c b/drivers/block/drbd/drbd_worker.c index 147f76b268102..3a95b701b5d09 100644 --- a/drivers/block/drbd/drbd_worker.c +++ b/drivers/block/drbd/drbd_worker.c @@ -712,10 +712,24 @@ static int w_make_ov_request(struct drbd_conf *mdev, struct drbd_work *w, int ca } +void start_resync_timer_fn(unsigned long data) +{ + struct drbd_conf *mdev = (struct drbd_conf *) data; + + drbd_queue_work(&mdev->data.work, &mdev->start_resync_work); +} + int w_start_resync(struct drbd_conf *mdev, struct drbd_work *w, int cancel) { - drbd_start_resync(mdev, C_SYNC_SOURCE); + if (atomic_read(&mdev->unacked_cnt) || atomic_read(&mdev->rs_pending_cnt)) { + dev_warn(DEV, "w_start_resync later...\n"); + mdev->start_resync_timer.expires = jiffies + HZ/10; + add_timer(&mdev->start_resync_timer); + return 1; + } + drbd_start_resync(mdev, C_SYNC_SOURCE); + clear_bit(AHEAD_TO_SYNC_SOURCE, &mdev->current_epoch->flags); return 1; } -- GitLab From 148efa165e9464927887b03c83a52c33b80b4431 Mon Sep 17 00:00:00 2001 From: Philipp Reisner Date: Sat, 15 Jan 2011 00:21:15 +0100 Subject: [PATCH 0478/2822] drbd: Do not drop net config if sending in drbd_send_protocol() fails Signed-off-by: Philipp Reisner Signed-off-by: Lars Ellenberg --- drivers/block/drbd/drbd_main.c | 2 +- drivers/block/drbd/drbd_receiver.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/block/drbd/drbd_main.c b/drivers/block/drbd/drbd_main.c index 8ec7c65988bef..1061b9fff2b08 100644 --- a/drivers/block/drbd/drbd_main.c +++ b/drivers/block/drbd/drbd_main.c @@ -1967,7 +1967,7 @@ int drbd_send_protocol(struct drbd_conf *mdev) else { dev_err(DEV, "--dry-run is not supported by peer"); kfree(p); - return 0; + return -1; } } p->conn_flags = cpu_to_be32(cf); diff --git a/drivers/block/drbd/drbd_receiver.c b/drivers/block/drbd/drbd_receiver.c index 18cb8b609fe48..fb8e86153fd09 100644 --- a/drivers/block/drbd/drbd_receiver.c +++ b/drivers/block/drbd/drbd_receiver.c @@ -906,7 +906,7 @@ retry: put_ldev(mdev); } - if (!drbd_send_protocol(mdev)) + if (drbd_send_protocol(mdev) == -1) return -1; drbd_send_sync_param(mdev, &mdev->sync_conf); drbd_send_sizes(mdev, 0, 0); -- GitLab From 94f2b05f03fbc605f83ae501682c85ff4535bb6d Mon Sep 17 00:00:00 2001 From: Philipp Reisner Date: Mon, 17 Jan 2011 15:14:26 +0100 Subject: [PATCH 0479/2822] drbd: Killed an assert that is no longer valid The point is that drbd_disconnect() can be called with a cstate of WFConnection. That happens if the user issues "drbdsetup disconnect" while the drbd_connect() function executes. Then drbdd_init() will call drbdd(), which in turn will return without receiving any packets. Then drbdd_init() will end up calling drbd_disconnect() with a cstate of WFConnection. Bottom line: This assertion is wrong as it is, and we do not see value in fixing it. => Removing it. Signed-off-by: Philipp Reisner Signed-off-by: Lars Ellenberg --- drivers/block/drbd/drbd_receiver.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/block/drbd/drbd_receiver.c b/drivers/block/drbd/drbd_receiver.c index fb8e86153fd09..2207d2886f840 100644 --- a/drivers/block/drbd/drbd_receiver.c +++ b/drivers/block/drbd/drbd_receiver.c @@ -3763,9 +3763,6 @@ static void drbd_disconnect(struct drbd_conf *mdev) if (mdev->state.conn == C_STANDALONE) return; - if (mdev->state.conn >= C_WF_CONNECTION) - dev_err(DEV, "ASSERT FAILED cstate = %s, expected < WFConnection\n", - drbd_conn_str(mdev->state.conn)); /* asender does not clean up anything. it must not interfere, either */ drbd_thread_stop(&mdev->asender); -- GitLab From 2deb8336d04106f215c21ad1b029e78d12033d02 Mon Sep 17 00:00:00 2001 From: Philipp Reisner Date: Mon, 17 Jan 2011 18:39:18 +0100 Subject: [PATCH 0480/2822] drbd: Fixed P_NEG_ACK processing for protocol A and B Protocol A has no P_WRITE_ACKs, but has P_NEG_ACKs. The master bio might already be completed, therefore the request is no longer in the collision hash. => Do not try to validate block_id as request In Protocol B we might already have got a P_RECV_ACK but then get a P_NEG_ACK after wards. Signed-off-by: Philipp Reisner Signed-off-by: Lars Ellenberg --- drivers/block/drbd/drbd_receiver.c | 45 ++++++++++++++++++++++-------- 1 file changed, 33 insertions(+), 12 deletions(-) diff --git a/drivers/block/drbd/drbd_receiver.c b/drivers/block/drbd/drbd_receiver.c index 2207d2886f840..a7f5b6d134e3b 100644 --- a/drivers/block/drbd/drbd_receiver.c +++ b/drivers/block/drbd/drbd_receiver.c @@ -1633,9 +1633,6 @@ static int receive_Data(struct drbd_conf *mdev, enum drbd_packets cmd, unsigned u32 dp_flags; if (!get_ldev(mdev)) { - if (__ratelimit(&drbd_ratelimit_state)) - dev_err(DEV, "Can not write mirrored data block " - "to local disk.\n"); spin_lock(&mdev->peer_seq_lock); if (mdev->peer_seq+1 == be32_to_cpu(p->seq_num)) mdev->peer_seq++; @@ -4247,8 +4244,6 @@ static struct drbd_request *_ack_id_to_req(struct drbd_conf *mdev, return req; } } - dev_err(DEV, "_ack_id_to_req: failed to find req %p, sector %llus in list\n", - (void *)(unsigned long)id, (unsigned long long)sector); return NULL; } @@ -4266,7 +4261,9 @@ static int validate_req_change_req_state(struct drbd_conf *mdev, req = validator(mdev, id, sector); if (unlikely(!req)) { spin_unlock_irq(&mdev->req_lock); - dev_err(DEV, "%s: got a corrupt block_id/sector pair\n", func); + + dev_err(DEV, "%s: failed to find req %p, sector %llus\n", func, + (void *)(unsigned long)id, (unsigned long long)sector); return false; } __req_mod(req, what, &m); @@ -4321,20 +4318,44 @@ static int got_NegAck(struct drbd_conf *mdev, struct p_header80 *h) { struct p_block_ack *p = (struct p_block_ack *)h; sector_t sector = be64_to_cpu(p->sector); - - if (__ratelimit(&drbd_ratelimit_state)) - dev_warn(DEV, "Got NegAck packet. Peer is in troubles?\n"); + int size = be32_to_cpu(p->blksize); + struct drbd_request *req; + struct bio_and_error m; update_peer_seq(mdev, be32_to_cpu(p->seq_num)); if (is_syncer_block_id(p->block_id)) { - int size = be32_to_cpu(p->blksize); dec_rs_pending(mdev); drbd_rs_failed_io(mdev, sector, size); return true; } - return validate_req_change_req_state(mdev, p->block_id, sector, - _ack_id_to_req, __func__ , neg_acked); + + spin_lock_irq(&mdev->req_lock); + req = _ack_id_to_req(mdev, p->block_id, sector); + if (!req) { + spin_unlock_irq(&mdev->req_lock); + if (mdev->net_conf->wire_protocol == DRBD_PROT_A || + mdev->net_conf->wire_protocol == DRBD_PROT_B) { + /* Protocol A has no P_WRITE_ACKs, but has P_NEG_ACKs. + The master bio might already be completed, therefore the + request is no longer in the collision hash. + => Do not try to validate block_id as request. */ + /* In Protocol B we might already have got a P_RECV_ACK + but then get a P_NEG_ACK after wards. */ + drbd_set_out_of_sync(mdev, sector, size); + return true; + } else { + dev_err(DEV, "%s: failed to find req %p, sector %llus\n", __func__, + (void *)(unsigned long)p->block_id, (unsigned long long)sector); + return false; + } + } + __req_mod(req, neg_acked, &m); + spin_unlock_irq(&mdev->req_lock); + + if (m.bio) + complete_master_bio(mdev, &m); + return true; } static int got_NegDReply(struct drbd_conf *mdev, struct p_header80 *h) -- GitLab From 6a35c45f890dc18c5527ac501b308058118f20e7 Mon Sep 17 00:00:00 2001 From: Philipp Reisner Date: Mon, 17 Jan 2011 20:27:30 +0100 Subject: [PATCH 0481/2822] drbd: Ensure that an epoch contains only requests of one kind The assert in drbd_req.c:755 forces us to have only requests of one kind in an epoch. The two kinds we distinguish here are: local-only or mirrored. Signed-off-by: Philipp Reisner Signed-off-by: Lars Ellenberg --- drivers/block/drbd/drbd_main.c | 7 ++++++- drivers/block/drbd/drbd_req.c | 29 ++++------------------------- drivers/block/drbd/drbd_req.h | 18 ++++++++++++++++++ 3 files changed, 28 insertions(+), 26 deletions(-) diff --git a/drivers/block/drbd/drbd_main.c b/drivers/block/drbd/drbd_main.c index 1061b9fff2b08..34ee8e44a7514 100644 --- a/drivers/block/drbd/drbd_main.c +++ b/drivers/block/drbd/drbd_main.c @@ -1261,9 +1261,14 @@ __drbd_set_state(struct drbd_conf *mdev, union drbd_state ns, if (os.conn < C_CONNECTED && ns.conn >= C_CONNECTED) drbd_resume_al(mdev); - if (os.conn == C_AHEAD && ns.conn != C_AHEAD) + /* Start a new epoch in case we start to mirror write requests */ + if (!drbd_should_do_remote(os) && drbd_should_do_remote(ns)) tl_forget(mdev); + /* Do not add local-only requests to an epoch with mirrored requests */ + if (drbd_should_do_remote(os) && !drbd_should_do_remote(ns)) + set_bit(CREATE_BARRIER, &mdev->flags); + ascw = kmalloc(sizeof(*ascw), GFP_ATOMIC); if (ascw) { ascw->os = os; diff --git a/drivers/block/drbd/drbd_req.c b/drivers/block/drbd/drbd_req.c index 6f9d1bfcca58c..336937a14d3fc 100644 --- a/drivers/block/drbd/drbd_req.c +++ b/drivers/block/drbd/drbd_req.c @@ -762,27 +762,6 @@ static int drbd_may_do_local_read(struct drbd_conf *mdev, sector_t sector, int s return 0 == drbd_bm_count_bits(mdev, sbnr, ebnr); } -static bool drbd_should_do_remote(struct drbd_conf *mdev) -{ - union drbd_state s = mdev->state; - - return s.pdsk == D_UP_TO_DATE || - (s.pdsk >= D_INCONSISTENT && - s.conn >= C_WF_BITMAP_T && - s.conn < C_AHEAD); - /* Before proto 96 that was >= CONNECTED instead of >= C_WF_BITMAP_T. - That is equivalent since before 96 IO was frozen in the C_WF_BITMAP* - states. */ -} -static bool drbd_should_send_oos(struct drbd_conf *mdev) -{ - union drbd_state s = mdev->state; - - return s.conn == C_AHEAD || s.conn == C_WF_BITMAP_S; - /* pdsk = D_INCONSISTENT as a consequence. Protocol 96 check not necessary - since we enter state C_AHEAD only if proto >= 96 */ -} - static int drbd_make_request_common(struct drbd_conf *mdev, struct bio *bio, unsigned long start_time) { const int rw = bio_rw(bio); @@ -854,8 +833,8 @@ static int drbd_make_request_common(struct drbd_conf *mdev, struct bio *bio, uns drbd_al_begin_io(mdev, sector); } - remote = remote && drbd_should_do_remote(mdev); - send_oos = rw == WRITE && drbd_should_send_oos(mdev); + remote = remote && drbd_should_do_remote(mdev->state); + send_oos = rw == WRITE && drbd_should_send_oos(mdev->state); D_ASSERT(!(remote && send_oos)); if (!(local || remote) && !is_susp(mdev->state)) { @@ -896,8 +875,8 @@ allocate_barrier: } if (remote || send_oos) { - remote = drbd_should_do_remote(mdev); - send_oos = rw == WRITE && drbd_should_send_oos(mdev); + remote = drbd_should_do_remote(mdev->state); + send_oos = rw == WRITE && drbd_should_send_oos(mdev->state); D_ASSERT(!(remote && send_oos)); if (!(remote || send_oos)) diff --git a/drivers/block/drbd/drbd_req.h b/drivers/block/drbd/drbd_req.h index 077c47b1e9d78..32c1f2a312667 100644 --- a/drivers/block/drbd/drbd_req.h +++ b/drivers/block/drbd/drbd_req.h @@ -360,4 +360,22 @@ static inline int req_mod(struct drbd_request *req, return rv; } + +static inline bool drbd_should_do_remote(union drbd_state s) +{ + return s.pdsk == D_UP_TO_DATE || + (s.pdsk >= D_INCONSISTENT && + s.conn >= C_WF_BITMAP_T && + s.conn < C_AHEAD); + /* Before proto 96 that was >= CONNECTED instead of >= C_WF_BITMAP_T. + That is equivalent since before 96 IO was frozen in the C_WF_BITMAP* + states. */ +} +static inline bool drbd_should_send_oos(union drbd_state s) +{ + return s.conn == C_AHEAD || s.conn == C_WF_BITMAP_S; + /* pdsk = D_INCONSISTENT as a consequence. Protocol 96 check not necessary + since we enter state C_AHEAD only if proto >= 96 */ +} + #endif -- GitLab From 20ee639024e3d33111df0e343050b218c656bf16 Mon Sep 17 00:00:00 2001 From: Philipp Reisner Date: Tue, 18 Jan 2011 15:28:59 +0100 Subject: [PATCH 0482/2822] drbd: cleaned up __set_current_state() followed by schedule_timeout() calls Signed-off-by: Philipp Reisner Signed-off-by: Lars Ellenberg --- drivers/block/drbd/drbd_nl.c | 3 +-- drivers/block/drbd/drbd_receiver.c | 9 +++------ drivers/block/drbd/drbd_worker.c | 3 +-- 3 files changed, 5 insertions(+), 10 deletions(-) diff --git a/drivers/block/drbd/drbd_nl.c b/drivers/block/drbd/drbd_nl.c index a46bc0287e217..42e16e4edfa32 100644 --- a/drivers/block/drbd/drbd_nl.c +++ b/drivers/block/drbd/drbd_nl.c @@ -360,8 +360,7 @@ drbd_set_role(struct drbd_conf *mdev, enum drbd_role new_role, int force) if (rv == SS_TWO_PRIMARIES) { /* Maybe the peer is detected as dead very soon... retry at most once more in this case. */ - __set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout((mdev->net_conf->ping_timeo+1)*HZ/10); + schedule_timeout_interruptible((mdev->net_conf->ping_timeo+1)*HZ/10); if (try < max_tries) try = max_tries - 1; continue; diff --git a/drivers/block/drbd/drbd_receiver.c b/drivers/block/drbd/drbd_receiver.c index a7f5b6d134e3b..3ccc6c33a330d 100644 --- a/drivers/block/drbd/drbd_receiver.c +++ b/drivers/block/drbd/drbd_receiver.c @@ -768,8 +768,7 @@ static int drbd_connect(struct drbd_conf *mdev) if (s || ++try >= 3) break; /* give the other side time to call bind() & listen() */ - __set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(HZ / 10); + schedule_timeout_interruptible(HZ / 10); } if (s) { @@ -788,8 +787,7 @@ static int drbd_connect(struct drbd_conf *mdev) } if (sock && msock) { - __set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(HZ / 10); + schedule_timeout_interruptible(HZ / 10); ok = drbd_socket_okay(mdev, &sock); ok = drbd_socket_okay(mdev, &msock) && ok; if (ok) @@ -4142,8 +4140,7 @@ int drbdd_init(struct drbd_thread *thi) h = drbd_connect(mdev); if (h == 0) { drbd_disconnect(mdev); - __set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(HZ); + schedule_timeout_interruptible(HZ); } if (h == -1) { dev_warn(DEV, "Discarding network configuration.\n"); diff --git a/drivers/block/drbd/drbd_worker.c b/drivers/block/drbd/drbd_worker.c index 3a95b701b5d09..7b3d4dc4af84b 100644 --- a/drivers/block/drbd/drbd_worker.c +++ b/drivers/block/drbd/drbd_worker.c @@ -777,8 +777,7 @@ int drbd_resync_finished(struct drbd_conf *mdev) * queue (or even the read operations for those packets * is not finished by now). Retry in 100ms. */ - __set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(HZ / 10); + schedule_timeout_interruptible(HZ / 10); w = kmalloc(sizeof(struct drbd_work), GFP_ATOMIC); if (w) { w->cb = w_resync_finished; -- GitLab From 6c922ed543bee1bc6685ade07be59f3fa49a7288 Mon Sep 17 00:00:00 2001 From: Lars Ellenberg Date: Wed, 12 Jan 2011 11:51:13 +0100 Subject: [PATCH 0483/2822] drbd: only generate and send a new sync uuid after a successful state change Signed-off-by: Philipp Reisner Signed-off-by: Lars Ellenberg --- drivers/block/drbd/drbd_worker.c | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/drivers/block/drbd/drbd_worker.c b/drivers/block/drbd/drbd_worker.c index 7b3d4dc4af84b..ec42e04bb5177 100644 --- a/drivers/block/drbd/drbd_worker.c +++ b/drivers/block/drbd/drbd_worker.c @@ -1544,24 +1544,23 @@ void drbd_start_resync(struct drbd_conf *mdev, enum drbd_conns side) } write_unlock_irq(&global_state_lock); - if (side == C_SYNC_TARGET) - mdev->bm_resync_fo = 0; - - /* Since protocol 96, we must serialize drbd_gen_and_send_sync_uuid - * with w_send_oos, or the sync target will get confused as to - * how much bits to resync. We cannot do that always, because for an - * empty resync and protocol < 95, we need to do it here, as we call - * drbd_resync_finished from here in that case. - * We drbd_gen_and_send_sync_uuid here for protocol < 96, - * and from after_state_ch otherwise. */ - if (side == C_SYNC_SOURCE && mdev->agreed_pro_version < 96) - drbd_gen_and_send_sync_uuid(mdev); - if (r == SS_SUCCESS) { dev_info(DEV, "Began resync as %s (will sync %lu KB [%lu bits set]).\n", drbd_conn_str(ns.conn), (unsigned long) mdev->rs_total << (BM_BLOCK_SHIFT-10), (unsigned long) mdev->rs_total); + if (side == C_SYNC_TARGET) + mdev->bm_resync_fo = 0; + + /* Since protocol 96, we must serialize drbd_gen_and_send_sync_uuid + * with w_send_oos, or the sync target will get confused as to + * how much bits to resync. We cannot do that always, because for an + * empty resync and protocol < 95, we need to do it here, as we call + * drbd_resync_finished from here in that case. + * We drbd_gen_and_send_sync_uuid here for protocol < 96, + * and from after_state_ch otherwise. */ + if (side == C_SYNC_SOURCE && mdev->agreed_pro_version < 96) + drbd_gen_and_send_sync_uuid(mdev); if (mdev->agreed_pro_version < 95 && mdev->rs_total == 0) { /* This still has a race (about when exactly the peers -- GitLab From 194bfb32dba8345a7e0f83e9b1ee965e14d4b679 Mon Sep 17 00:00:00 2001 From: Lars Ellenberg Date: Tue, 18 Jan 2011 10:38:01 +0100 Subject: [PATCH 0484/2822] drbd: serialize admin requests for new resync with pending bitmap io Signed-off-by: Philipp Reisner Signed-off-by: Lars Ellenberg --- drivers/block/drbd/drbd_nl.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/drivers/block/drbd/drbd_nl.c b/drivers/block/drbd/drbd_nl.c index 42e16e4edfa32..434b621f76a9e 100644 --- a/drivers/block/drbd/drbd_nl.c +++ b/drivers/block/drbd/drbd_nl.c @@ -1873,6 +1873,10 @@ static int drbd_nl_invalidate(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nl { int retcode; + /* If there is still bitmap IO pending, probably because of a previous + * resync just being finished, wait for it before requesting a new resync. */ + wait_event(mdev->misc_wait, !test_bit(BITMAP_IO, &mdev->flags)); + retcode = _drbd_request_state(mdev, NS(conn, C_STARTING_SYNC_T), CS_ORDERED); if (retcode < SS_SUCCESS && retcode != SS_NEED_CONNECTION) @@ -1908,6 +1912,10 @@ static int drbd_nl_invalidate_peer(struct drbd_conf *mdev, struct drbd_nl_cfg_re { int retcode; + /* If there is still bitmap IO pending, probably because of a previous + * resync just being finished, wait for it before requesting a new resync. */ + wait_event(mdev->misc_wait, !test_bit(BITMAP_IO, &mdev->flags)); + retcode = _drbd_request_state(mdev, NS(conn, C_STARTING_SYNC_S), CS_ORDERED); if (retcode < SS_SUCCESS) { @@ -1916,7 +1924,6 @@ static int drbd_nl_invalidate_peer(struct drbd_conf *mdev, struct drbd_nl_cfg_re into a full resync. */ retcode = drbd_request_state(mdev, NS(pdsk, D_INCONSISTENT)); if (retcode >= SS_SUCCESS) { - /* open coded drbd_bitmap_io() */ if (drbd_bitmap_io(mdev, &drbd_bmio_set_susp_al, "set_n_write from invalidate_peer")) retcode = ERR_IO_MD_DISK; -- GitLab From 54b956abef2c1ab339fd01792e69e4a921a5e487 Mon Sep 17 00:00:00 2001 From: Lars Ellenberg Date: Thu, 20 Jan 2011 10:47:53 +0100 Subject: [PATCH 0485/2822] drbd: don't pointlessly queue bitmap send, if we lost connection This is a minor optimization and cleanup, and also considerably reduces some harmless (but noisy) race with the connection cleanup code. Signed-off-by: Philipp Reisner Signed-off-by: Lars Ellenberg --- drivers/block/drbd/drbd_main.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/block/drbd/drbd_main.c b/drivers/block/drbd/drbd_main.c index 34ee8e44a7514..1caced08a73e9 100644 --- a/drivers/block/drbd/drbd_main.c +++ b/drivers/block/drbd/drbd_main.c @@ -1428,8 +1428,13 @@ static void after_state_ch(struct drbd_conf *mdev, union drbd_state os, drbd_send_uuids(mdev); drbd_send_state(mdev); } - if (os.conn != C_WF_BITMAP_S && ns.conn == C_WF_BITMAP_S) - drbd_queue_bitmap_io(mdev, &drbd_send_bitmap, NULL, "send_bitmap (WFBitMapS)"); + /* No point in queuing send_bitmap if we don't have a connection + * anymore, so check also the _current_ state, not only the new state + * at the time this work was queued. */ + if (os.conn != C_WF_BITMAP_S && ns.conn == C_WF_BITMAP_S && + mdev->state.conn == C_WF_BITMAP_S) + drbd_queue_bitmap_io(mdev, &drbd_send_bitmap, NULL, + "send_bitmap (WFBitMapS)"); /* Lost contact to peer's copy of the data */ if ((os.pdsk >= D_INCONSISTENT && -- GitLab From 79a30d2d71f7be862de93228fe9b919ef664af52 Mon Sep 17 00:00:00 2001 From: Lars Ellenberg Date: Thu, 20 Jan 2011 10:32:05 +0100 Subject: [PATCH 0486/2822] drbd: queue bitmap writeout more intelligently The "lazy writeout" of cleared bitmap pages happens during resync, and should happen again once the resync finishes cleanly, or is aborted. If resync finished cleanly, or was aborted because of peer disk failure, we trigger the writeout from worker context in the after state change work. If resync was aborted because of connection failure, we should not immediately trigger bitmap writeout, but rather postpone the writeout to after the connection cleanup happened. We now do it in the receiver context from drbd_disconnect(). If resync was aborted because of local disk failure, well, there is nothing to write to anymore. Signed-off-by: Philipp Reisner Signed-off-by: Lars Ellenberg --- drivers/block/drbd/drbd_main.c | 12 +++++++++++- drivers/block/drbd/drbd_receiver.c | 1 + 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/drivers/block/drbd/drbd_main.c b/drivers/block/drbd/drbd_main.c index 1caced08a73e9..e0be4077d564b 100644 --- a/drivers/block/drbd/drbd_main.c +++ b/drivers/block/drbd/drbd_main.c @@ -1593,8 +1593,18 @@ static void after_state_ch(struct drbd_conf *mdev, union drbd_state os, if (os.disk < D_UP_TO_DATE && os.conn >= C_SYNC_SOURCE && ns.conn == C_CONNECTED) drbd_send_state(mdev); - if (os.conn > C_CONNECTED && ns.conn <= C_CONNECTED) + /* This triggers bitmap writeout of potentially still unwritten pages + * if the resync finished cleanly, or aborted because of peer disk + * failure. Resync aborted because of connection failure does bitmap + * writeout from drbd_disconnect. + * For resync aborted because of local disk failure, we cannot do + * any bitmap writeout anymore. + */ + if (os.conn > C_CONNECTED && ns.conn == C_CONNECTED && + mdev->state.conn == C_CONNECTED && get_ldev(mdev)) { drbd_queue_bitmap_io(mdev, &drbd_bm_write, NULL, "write from resync_finished"); + put_ldev(mdev); + } /* free tl_hash if we Got thawed and are C_STANDALONE */ if (ns.conn == C_STANDALONE && !is_susp(ns) && mdev->tl_hash) diff --git a/drivers/block/drbd/drbd_receiver.c b/drivers/block/drbd/drbd_receiver.c index 3ccc6c33a330d..432fe8f6b5d26 100644 --- a/drivers/block/drbd/drbd_receiver.c +++ b/drivers/block/drbd/drbd_receiver.c @@ -3811,6 +3811,7 @@ static void drbd_disconnect(struct drbd_conf *mdev) fp = FP_DONT_CARE; if (get_ldev(mdev)) { + drbd_bitmap_io(mdev, &drbd_bm_write, "write from disconnect"); fp = mdev->ldev->dc.fencing; put_ldev(mdev); } -- GitLab From cd88d030d41a9b0100fd5fee872024e6ebc8b276 Mon Sep 17 00:00:00 2001 From: Philipp Reisner Date: Thu, 20 Jan 2011 11:46:41 +0100 Subject: [PATCH 0487/2822] drbd: Provide hints with the error message when clearing the sync pause flag When the user clears the sync-pause flag, and sync stays in pause state, give hints to the user, why it still is in pause state. Signed-off-by: Philipp Reisner Signed-off-by: Lars Ellenberg --- drivers/block/drbd/drbd_nl.c | 12 ++++++++++-- include/linux/drbd.h | 2 ++ 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/drivers/block/drbd/drbd_nl.c b/drivers/block/drbd/drbd_nl.c index 434b621f76a9e..ffe3a97fef9b5 100644 --- a/drivers/block/drbd/drbd_nl.c +++ b/drivers/block/drbd/drbd_nl.c @@ -1952,9 +1952,17 @@ static int drbd_nl_resume_sync(struct drbd_conf *mdev, struct drbd_nl_cfg_req *n struct drbd_nl_cfg_reply *reply) { int retcode = NO_ERROR; + union drbd_state s; - if (drbd_request_state(mdev, NS(user_isp, 0)) == SS_NOTHING_TO_DO) - retcode = ERR_PAUSE_IS_CLEAR; + if (drbd_request_state(mdev, NS(user_isp, 0)) == SS_NOTHING_TO_DO) { + s = mdev->state; + if (s.conn == C_PAUSED_SYNC_S || s.conn == C_PAUSED_SYNC_T) { + retcode = s.aftr_isp ? ERR_PIC_AFTER_DEP : + s.peer_isp ? ERR_PIC_PEER_DEP : ERR_PAUSE_IS_CLEAR; + } else { + retcode = ERR_PAUSE_IS_CLEAR; + } + } reply->ret_code = retcode; return 0; diff --git a/include/linux/drbd.h b/include/linux/drbd.h index d10431fab0047..ba5c785d3f7de 100644 --- a/include/linux/drbd.h +++ b/include/linux/drbd.h @@ -153,6 +153,8 @@ enum drbd_ret_code { ERR_NEED_APV_93 = 153, ERR_STONITH_AND_PROT_A = 154, ERR_CONG_NOT_PROTO_A = 155, + ERR_PIC_AFTER_DEP = 156, + ERR_PIC_PEER_DEP = 157, /* insert new ones above this line */ AFTER_LAST_ERR_CODE -- GitLab From d07c9c10e5620c632aae9cac2b609033398f6139 Mon Sep 17 00:00:00 2001 From: Philipp Reisner Date: Thu, 20 Jan 2011 16:49:33 +0100 Subject: [PATCH 0488/2822] drbd: We can not process BIOs with a size of 0 Signed-off-by: Philipp Reisner Signed-off-by: Lars Ellenberg --- drivers/block/drbd/drbd_receiver.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/block/drbd/drbd_receiver.c b/drivers/block/drbd/drbd_receiver.c index 432fe8f6b5d26..e9354931eace6 100644 --- a/drivers/block/drbd/drbd_receiver.c +++ b/drivers/block/drbd/drbd_receiver.c @@ -1237,6 +1237,7 @@ read_in_block(struct drbd_conf *mdev, u64 id, sector_t sector, int data_size) __ data_size -= dgs; + ERR_IF(data_size == 0) return NULL; ERR_IF(data_size & 0x1ff) return NULL; ERR_IF(data_size > DRBD_MAX_BIO_SIZE) return NULL; -- GitLab From 62b0da3a244ac33d25a77861ef1cc0080103f2ff Mon Sep 17 00:00:00 2001 From: Lars Ellenberg Date: Thu, 20 Jan 2011 13:25:21 +0100 Subject: [PATCH 0489/2822] drbd: log UUIDs whenever they change All decisions about sync, sync direction, and wether or not to allow a connect or attach are based on our set of UUIDs to tag a data generation. Log changes to the UUIDs whenever they occur, logging "new current UUID P:Q:R:S" is more useful than "Creating new current UUID". Signed-off-by: Philipp Reisner Signed-off-by: Lars Ellenberg --- drivers/block/drbd/drbd_int.h | 6 ++- drivers/block/drbd/drbd_main.c | 71 ++++++++++++++---------------- drivers/block/drbd/drbd_nl.c | 1 + drivers/block/drbd/drbd_receiver.c | 11 +++-- drivers/block/drbd/drbd_worker.c | 20 +++++---- 5 files changed, 58 insertions(+), 51 deletions(-) diff --git a/drivers/block/drbd/drbd_int.h b/drivers/block/drbd/drbd_int.h index cfe7fff459e30..0a9059eb94dbb 100644 --- a/drivers/block/drbd/drbd_int.h +++ b/drivers/block/drbd/drbd_int.h @@ -1240,11 +1240,11 @@ extern int _drbd_send_bitmap(struct drbd_conf *mdev); extern int drbd_send_sr_reply(struct drbd_conf *mdev, enum drbd_state_rv retcode); extern void drbd_free_bc(struct drbd_backing_dev *ldev); extern void drbd_mdev_cleanup(struct drbd_conf *mdev); +void drbd_print_uuids(struct drbd_conf *mdev, const char *text); /* drbd_meta-data.c (still in drbd_main.c) */ extern void drbd_md_sync(struct drbd_conf *mdev); extern int drbd_md_read(struct drbd_conf *mdev, struct drbd_backing_dev *bdev); -/* maybe define them below as inline? */ extern void drbd_uuid_set(struct drbd_conf *mdev, int idx, u64 val) __must_hold(local); extern void _drbd_uuid_set(struct drbd_conf *mdev, int idx, u64 val) __must_hold(local); extern void drbd_uuid_new_current(struct drbd_conf *mdev) __must_hold(local); @@ -2360,9 +2360,11 @@ static inline void dec_ap_bio(struct drbd_conf *mdev) } } -static inline void drbd_set_ed_uuid(struct drbd_conf *mdev, u64 val) +static inline int drbd_set_ed_uuid(struct drbd_conf *mdev, u64 val) { + int changed = mdev->ed_uuid != val; mdev->ed_uuid = val; + return changed; } static inline int seq_cmp(u32 a, u32 b) diff --git a/drivers/block/drbd/drbd_main.c b/drivers/block/drbd/drbd_main.c index e0be4077d564b..b68332a0e73e0 100644 --- a/drivers/block/drbd/drbd_main.c +++ b/drivers/block/drbd/drbd_main.c @@ -1159,6 +1159,10 @@ __drbd_set_state(struct drbd_conf *mdev, union drbd_state ns, atomic_inc(&mdev->local_cnt); mdev->state = ns; + + if (os.disk == D_ATTACHING && ns.disk >= D_NEGOTIATING) + drbd_print_uuids(mdev, "attached to UUIDs"); + wake_up(&mdev->misc_wait); wake_up(&mdev->state_wait); @@ -2035,6 +2039,24 @@ int drbd_send_uuids_skip_initial_sync(struct drbd_conf *mdev) return _drbd_send_uuids(mdev, 8); } +void drbd_print_uuids(struct drbd_conf *mdev, const char *text) +{ + if (get_ldev_if_state(mdev, D_NEGOTIATING)) { + u64 *uuid = mdev->ldev->md.uuid; + dev_info(DEV, "%s %016llX:%016llX:%016llX:%016llX\n", + text, + (unsigned long long)uuid[UI_CURRENT], + (unsigned long long)uuid[UI_BITMAP], + (unsigned long long)uuid[UI_HISTORY_START], + (unsigned long long)uuid[UI_HISTORY_END]); + put_ldev(mdev); + } else { + dev_info(DEV, "%s effective data uuid: %016llX\n", + text, + (unsigned long long)mdev->ed_uuid); + } +} + int drbd_gen_and_send_sync_uuid(struct drbd_conf *mdev) { struct p_rs_uuid p; @@ -2044,6 +2066,7 @@ int drbd_gen_and_send_sync_uuid(struct drbd_conf *mdev) uuid = mdev->ldev->md.uuid[UI_BITMAP] + UUID_NEW_BM_OFFSET; drbd_uuid_set(mdev, UI_BITMAP, uuid); + drbd_print_uuids(mdev, "updated sync UUID"); drbd_md_sync(mdev); p.uuid = cpu_to_be64(uuid); @@ -3749,28 +3772,6 @@ int drbd_md_read(struct drbd_conf *mdev, struct drbd_backing_dev *bdev) return rv; } -static void debug_drbd_uuid(struct drbd_conf *mdev, enum drbd_uuid_index index) -{ - static char *uuid_str[UI_EXTENDED_SIZE] = { - [UI_CURRENT] = "CURRENT", - [UI_BITMAP] = "BITMAP", - [UI_HISTORY_START] = "HISTORY_START", - [UI_HISTORY_END] = "HISTORY_END", - [UI_SIZE] = "SIZE", - [UI_FLAGS] = "FLAGS", - }; - - if (index >= UI_EXTENDED_SIZE) { - dev_warn(DEV, " uuid_index >= EXTENDED_SIZE\n"); - return; - } - - dynamic_dev_dbg(DEV, " uuid[%s] now %016llX\n", - uuid_str[index], - (unsigned long long)mdev->ldev->md.uuid[index]); -} - - /** * drbd_md_mark_dirty() - Mark meta data super block as dirty * @mdev: DRBD device. @@ -3800,10 +3801,8 @@ static void drbd_uuid_move_history(struct drbd_conf *mdev) __must_hold(local) { int i; - for (i = UI_HISTORY_START; i < UI_HISTORY_END; i++) { + for (i = UI_HISTORY_START; i < UI_HISTORY_END; i++) mdev->ldev->md.uuid[i+1] = mdev->ldev->md.uuid[i]; - debug_drbd_uuid(mdev, i+1); - } } void _drbd_uuid_set(struct drbd_conf *mdev, int idx, u64 val) __must_hold(local) @@ -3818,7 +3817,6 @@ void _drbd_uuid_set(struct drbd_conf *mdev, int idx, u64 val) __must_hold(local) } mdev->ldev->md.uuid[idx] = val; - debug_drbd_uuid(mdev, idx); drbd_md_mark_dirty(mdev); } @@ -3828,7 +3826,6 @@ void drbd_uuid_set(struct drbd_conf *mdev, int idx, u64 val) __must_hold(local) if (mdev->ldev->md.uuid[idx]) { drbd_uuid_move_history(mdev); mdev->ldev->md.uuid[UI_HISTORY_START] = mdev->ldev->md.uuid[idx]; - debug_drbd_uuid(mdev, UI_HISTORY_START); } _drbd_uuid_set(mdev, idx, val); } @@ -3843,14 +3840,16 @@ void drbd_uuid_set(struct drbd_conf *mdev, int idx, u64 val) __must_hold(local) void drbd_uuid_new_current(struct drbd_conf *mdev) __must_hold(local) { u64 val; + unsigned long long bm_uuid = mdev->ldev->md.uuid[UI_BITMAP]; + + if (bm_uuid) + dev_warn(DEV, "bm UUID was already set: %llX\n", bm_uuid); - dev_info(DEV, "Creating new current UUID\n"); - D_ASSERT(mdev->ldev->md.uuid[UI_BITMAP] == 0); mdev->ldev->md.uuid[UI_BITMAP] = mdev->ldev->md.uuid[UI_CURRENT]; - debug_drbd_uuid(mdev, UI_BITMAP); get_random_bytes(&val, sizeof(u64)); _drbd_uuid_set(mdev, UI_CURRENT, val); + drbd_print_uuids(mdev, "new current UUID"); /* get it to stable storage _now_ */ drbd_md_sync(mdev); } @@ -3864,16 +3863,12 @@ void drbd_uuid_set_bm(struct drbd_conf *mdev, u64 val) __must_hold(local) drbd_uuid_move_history(mdev); mdev->ldev->md.uuid[UI_HISTORY_START] = mdev->ldev->md.uuid[UI_BITMAP]; mdev->ldev->md.uuid[UI_BITMAP] = 0; - debug_drbd_uuid(mdev, UI_HISTORY_START); - debug_drbd_uuid(mdev, UI_BITMAP); } else { - if (mdev->ldev->md.uuid[UI_BITMAP]) - dev_warn(DEV, "bm UUID already set"); - - mdev->ldev->md.uuid[UI_BITMAP] = val; - mdev->ldev->md.uuid[UI_BITMAP] &= ~((u64)1); + unsigned long long bm_uuid = mdev->ldev->md.uuid[UI_BITMAP]; + if (bm_uuid) + dev_warn(DEV, "bm UUID was already set: %llX\n", bm_uuid); - debug_drbd_uuid(mdev, UI_BITMAP); + mdev->ldev->md.uuid[UI_BITMAP] = val & ~((u64)1); } drbd_md_mark_dirty(mdev); } diff --git a/drivers/block/drbd/drbd_nl.c b/drivers/block/drbd/drbd_nl.c index ffe3a97fef9b5..ce6f2fe808528 100644 --- a/drivers/block/drbd/drbd_nl.c +++ b/drivers/block/drbd/drbd_nl.c @@ -2151,6 +2151,7 @@ static int drbd_nl_new_c_uuid(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nl if (skip_initial_sync) { drbd_send_uuids_skip_initial_sync(mdev); _drbd_uuid_set(mdev, UI_BITMAP, 0); + drbd_print_uuids(mdev, "cleared bitmap UUID"); spin_lock_irq(&mdev->req_lock); _drbd_set_state(_NS2(mdev, disk, D_UP_TO_DATE, pdsk, D_UP_TO_DATE), CS_VERBOSE, NULL); diff --git a/drivers/block/drbd/drbd_receiver.c b/drivers/block/drbd/drbd_receiver.c index e9354931eace6..e5686a81f42c0 100644 --- a/drivers/block/drbd/drbd_receiver.c +++ b/drivers/block/drbd/drbd_receiver.c @@ -3024,7 +3024,7 @@ static int receive_uuids(struct drbd_conf *mdev, enum drbd_packets cmd, unsigned { struct p_uuids *p = &mdev->data.rbuf.uuids; u64 *p_uuid; - int i; + int i, updated_uuids = 0; p_uuid = kmalloc(sizeof(u64)*UI_EXTENDED_SIZE, GFP_NOIO); @@ -3059,13 +3059,14 @@ static int receive_uuids(struct drbd_conf *mdev, enum drbd_packets cmd, unsigned _drbd_set_state(_NS2(mdev, disk, D_UP_TO_DATE, pdsk, D_UP_TO_DATE), CS_VERBOSE, NULL); drbd_md_sync(mdev); + updated_uuids = 1; } put_ldev(mdev); } else if (mdev->state.disk < D_INCONSISTENT && mdev->state.role == R_PRIMARY) { /* I am a diskless primary, the peer just created a new current UUID for me. */ - drbd_set_ed_uuid(mdev, p_uuid[UI_CURRENT]); + updated_uuids = drbd_set_ed_uuid(mdev, p_uuid[UI_CURRENT]); } /* Before we test for the disk state, we should wait until an eventually @@ -3074,7 +3075,10 @@ static int receive_uuids(struct drbd_conf *mdev, enum drbd_packets cmd, unsigned new disk state... */ wait_event(mdev->misc_wait, !test_bit(CLUSTER_ST_CHANGE, &mdev->flags)); if (mdev->state.conn >= C_CONNECTED && mdev->state.disk < D_INCONSISTENT) - drbd_set_ed_uuid(mdev, p_uuid[UI_CURRENT]); + updated_uuids |= drbd_set_ed_uuid(mdev, p_uuid[UI_CURRENT]); + + if (updated_uuids) + drbd_print_uuids(mdev, "receiver updated UUIDs to"); return true; } @@ -3305,6 +3309,7 @@ static int receive_sync_uuid(struct drbd_conf *mdev, enum drbd_packets cmd, unsi _drbd_uuid_set(mdev, UI_CURRENT, be64_to_cpu(p->uuid)); _drbd_uuid_set(mdev, UI_BITMAP, 0UL); + drbd_print_uuids(mdev, "updated sync uuid"); drbd_start_resync(mdev, C_SYNC_TARGET); put_ldev(mdev); diff --git a/drivers/block/drbd/drbd_worker.c b/drivers/block/drbd/drbd_worker.c index ec42e04bb5177..ff0eb308ee4ad 100644 --- a/drivers/block/drbd/drbd_worker.c +++ b/drivers/block/drbd/drbd_worker.c @@ -871,14 +871,18 @@ int drbd_resync_finished(struct drbd_conf *mdev) } } - drbd_uuid_set_bm(mdev, 0UL); - - if (mdev->p_uuid) { - /* Now the two UUID sets are equal, update what we - * know of the peer. */ - int i; - for (i = UI_CURRENT ; i <= UI_HISTORY_END ; i++) - mdev->p_uuid[i] = mdev->ldev->md.uuid[i]; + if (!(os.conn == C_VERIFY_S || os.conn == C_VERIFY_T)) { + /* for verify runs, we don't update uuids here, + * so there would be nothing to report. */ + drbd_uuid_set_bm(mdev, 0UL); + drbd_print_uuids(mdev, "updated UUIDs"); + if (mdev->p_uuid) { + /* Now the two UUID sets are equal, update what we + * know of the peer. */ + int i; + for (i = UI_CURRENT ; i <= UI_HISTORY_END ; i++) + mdev->p_uuid[i] = mdev->ldev->md.uuid[i]; + } } } -- GitLab From 20ceb2b22edaf51e59e76087efdc71a16a2858de Mon Sep 17 00:00:00 2001 From: Lars Ellenberg Date: Fri, 21 Jan 2011 10:56:44 +0100 Subject: [PATCH 0490/2822] drbd: describe bitmap locking for bulk operation in finer detail Now that we do no longer in-place endian-swap the bitmap, we allow selected bitmap operations (testing bits, sometimes even settting bits) during some bulk operations. This caused us to hit a lot of FIXME asserts similar to FIXME asender in drbd_bm_count_bits, bitmap locked for 'write from resync_finished' by worker Which now is nonsense: looking at the bitmap is perfectly legal as long as it is not being resized. This cosmetic patch defines some flags to describe expectations in finer detail, so the asserts in e.g. bm_change_bits_to() can be skipped if appropriate. Signed-off-by: Philipp Reisner Signed-off-by: Lars Ellenberg --- drivers/block/drbd/drbd_bitmap.c | 48 +++++++++++-------------- drivers/block/drbd/drbd_int.h | 36 ++++++++++++++++--- drivers/block/drbd/drbd_main.c | 58 +++++++++++++++++++----------- drivers/block/drbd/drbd_nl.c | 19 ++++++---- drivers/block/drbd/drbd_receiver.c | 17 ++++++--- 5 files changed, 115 insertions(+), 63 deletions(-) diff --git a/drivers/block/drbd/drbd_bitmap.c b/drivers/block/drbd/drbd_bitmap.c index 25428bc28476f..b62dd5f26c5d9 100644 --- a/drivers/block/drbd/drbd_bitmap.c +++ b/drivers/block/drbd/drbd_bitmap.c @@ -104,26 +104,16 @@ struct drbd_bitmap { wait_queue_head_t bm_io_wait; /* used to serialize IO of single pages */ - unsigned long bm_flags; + enum bm_flag bm_flags; /* debugging aid, in case we are still racy somewhere */ char *bm_why; struct task_struct *bm_task; }; -/* definition of bits in bm_flags */ -#define BM_LOCKED 0 -// #define BM_MD_IO_ERROR 1 unused now. -#define BM_P_VMALLOCED 2 - static int __bm_change_bits_to(struct drbd_conf *mdev, const unsigned long s, unsigned long e, int val, const enum km_type km); -static int bm_is_locked(struct drbd_bitmap *b) -{ - return test_bit(BM_LOCKED, &b->bm_flags); -} - #define bm_print_lock_info(m) __bm_print_lock_info(m, __func__) static void __bm_print_lock_info(struct drbd_conf *mdev, const char *func) { @@ -140,7 +130,7 @@ static void __bm_print_lock_info(struct drbd_conf *mdev, const char *func) b->bm_task == mdev->worker.task ? "worker" : "?"); } -void drbd_bm_lock(struct drbd_conf *mdev, char *why) +void drbd_bm_lock(struct drbd_conf *mdev, char *why, enum bm_flag flags) { struct drbd_bitmap *b = mdev->bitmap; int trylock_failed; @@ -163,8 +153,9 @@ void drbd_bm_lock(struct drbd_conf *mdev, char *why) b->bm_task == mdev->worker.task ? "worker" : "?"); mutex_lock(&b->bm_change); } - if (__test_and_set_bit(BM_LOCKED, &b->bm_flags)) + if (BM_LOCKED_MASK & b->bm_flags) dev_err(DEV, "FIXME bitmap already locked in bm_lock\n"); + b->bm_flags |= flags & BM_LOCKED_MASK; b->bm_why = why; b->bm_task = current; @@ -178,9 +169,10 @@ void drbd_bm_unlock(struct drbd_conf *mdev) return; } - if (!__test_and_clear_bit(BM_LOCKED, &mdev->bitmap->bm_flags)) + if (!(BM_LOCKED_MASK & mdev->bitmap->bm_flags)) dev_err(DEV, "FIXME bitmap not locked in bm_unlock\n"); + b->bm_flags &= ~BM_LOCKED_MASK; b->bm_why = NULL; b->bm_task = NULL; mutex_unlock(&b->bm_change); @@ -421,9 +413,9 @@ static struct page **bm_realloc_pages(struct drbd_bitmap *b, unsigned long want) } if (vmalloced) - set_bit(BM_P_VMALLOCED, &b->bm_flags); + b->bm_flags |= BM_P_VMALLOCED; else - clear_bit(BM_P_VMALLOCED, &b->bm_flags); + b->bm_flags &= ~BM_P_VMALLOCED; return new_pages; } @@ -460,7 +452,7 @@ void drbd_bm_cleanup(struct drbd_conf *mdev) { ERR_IF (!mdev->bitmap) return; bm_free_pages(mdev->bitmap->bm_pages, mdev->bitmap->bm_number_of_pages); - bm_vk_free(mdev->bitmap->bm_pages, test_bit(BM_P_VMALLOCED, &mdev->bitmap->bm_flags)); + bm_vk_free(mdev->bitmap->bm_pages, (BM_P_VMALLOCED & mdev->bitmap->bm_flags)); kfree(mdev->bitmap); mdev->bitmap = NULL; } @@ -623,7 +615,7 @@ int drbd_bm_resize(struct drbd_conf *mdev, sector_t capacity, int set_new_bits) ERR_IF(!b) return -ENOMEM; - drbd_bm_lock(mdev, "resize"); + drbd_bm_lock(mdev, "resize", BM_LOCKED_MASK); dev_info(DEV, "drbd_bm_resize called with capacity == %llu\n", (unsigned long long)capacity); @@ -631,7 +623,7 @@ int drbd_bm_resize(struct drbd_conf *mdev, sector_t capacity, int set_new_bits) if (capacity == b->bm_dev_capacity) goto out; - opages_vmalloced = test_bit(BM_P_VMALLOCED, &b->bm_flags); + opages_vmalloced = (BM_P_VMALLOCED & b->bm_flags); if (capacity == 0) { spin_lock_irq(&b->bm_lock); @@ -1030,7 +1022,7 @@ static int bm_rw(struct drbd_conf *mdev, int rw, unsigned lazy_writeout_upper_id * as we submit copies of pages anyways. */ if (!ctx.flags) - WARN_ON(!bm_is_locked(b)); + WARN_ON(!(BM_LOCKED_MASK & b->bm_flags)); num_pages = b->bm_number_of_pages; @@ -1220,7 +1212,7 @@ static unsigned long bm_find_next(struct drbd_conf *mdev, ERR_IF(!b->bm_pages) return i; spin_lock_irq(&b->bm_lock); - if (bm_is_locked(b)) + if (BM_DONT_TEST & b->bm_flags) bm_print_lock_info(mdev); i = __bm_find_next(mdev, bm_fo, find_zero_bit, KM_IRQ1); @@ -1246,13 +1238,13 @@ unsigned long drbd_bm_find_next_zero(struct drbd_conf *mdev, unsigned long bm_fo * you must take drbd_bm_lock() first */ unsigned long _drbd_bm_find_next(struct drbd_conf *mdev, unsigned long bm_fo) { - /* WARN_ON(!bm_is_locked(mdev)); */ + /* WARN_ON(!(BM_DONT_SET & mdev->b->bm_flags)); */ return __bm_find_next(mdev, bm_fo, 0, KM_USER1); } unsigned long _drbd_bm_find_next_zero(struct drbd_conf *mdev, unsigned long bm_fo) { - /* WARN_ON(!bm_is_locked(mdev)); */ + /* WARN_ON(!(BM_DONT_SET & mdev->b->bm_flags)); */ return __bm_find_next(mdev, bm_fo, 1, KM_USER1); } @@ -1322,7 +1314,7 @@ static int bm_change_bits_to(struct drbd_conf *mdev, const unsigned long s, ERR_IF(!b->bm_pages) return 0; spin_lock_irqsave(&b->bm_lock, flags); - if (bm_is_locked(b)) + if ((val ? BM_DONT_SET : BM_DONT_CLEAR) & b->bm_flags) bm_print_lock_info(mdev); c = __bm_change_bits_to(mdev, s, e, val, KM_IRQ1); @@ -1439,7 +1431,7 @@ int drbd_bm_test_bit(struct drbd_conf *mdev, const unsigned long bitnr) ERR_IF(!b->bm_pages) return 0; spin_lock_irqsave(&b->bm_lock, flags); - if (bm_is_locked(b)) + if (BM_DONT_TEST & b->bm_flags) bm_print_lock_info(mdev); if (bitnr < b->bm_bits) { p_addr = bm_map_pidx(b, bm_bit_to_page_idx(b, bitnr)); @@ -1474,7 +1466,7 @@ int drbd_bm_count_bits(struct drbd_conf *mdev, const unsigned long s, const unsi ERR_IF(!b->bm_pages) return 1; spin_lock_irqsave(&b->bm_lock, flags); - if (bm_is_locked(b)) + if (BM_DONT_TEST & b->bm_flags) bm_print_lock_info(mdev); for (bitnr = s; bitnr <= e; bitnr++) { unsigned int idx = bm_bit_to_page_idx(b, bitnr); @@ -1522,7 +1514,7 @@ int drbd_bm_e_weight(struct drbd_conf *mdev, unsigned long enr) ERR_IF(!b->bm_pages) return 0; spin_lock_irqsave(&b->bm_lock, flags); - if (bm_is_locked(b)) + if (BM_DONT_TEST & b->bm_flags) bm_print_lock_info(mdev); s = S2W(enr); @@ -1555,7 +1547,7 @@ unsigned long drbd_bm_ALe_set_all(struct drbd_conf *mdev, unsigned long al_enr) ERR_IF(!b->bm_pages) return 0; spin_lock_irq(&b->bm_lock); - if (bm_is_locked(b)) + if (BM_DONT_SET & b->bm_flags) bm_print_lock_info(mdev); weight = b->bm_set; diff --git a/drivers/block/drbd/drbd_int.h b/drivers/block/drbd/drbd_int.h index 0a9059eb94dbb..267d9897ca8c4 100644 --- a/drivers/block/drbd/drbd_int.h +++ b/drivers/block/drbd/drbd_int.h @@ -855,6 +855,32 @@ enum { struct drbd_bitmap; /* opaque for drbd_conf */ +/* definition of bits in bm_flags to be used in drbd_bm_lock + * and drbd_bitmap_io and friends. */ +enum bm_flag { + /* do we need to kfree, or vfree bm_pages? */ + BM_P_VMALLOCED = 0x10000, /* internal use only, will be masked out */ + + /* currently locked for bulk operation */ + BM_LOCKED_MASK = 0x7, + + /* in detail, that is: */ + BM_DONT_CLEAR = 0x1, + BM_DONT_SET = 0x2, + BM_DONT_TEST = 0x4, + + /* (test bit, count bit) allowed (common case) */ + BM_LOCKED_TEST_ALLOWED = 0x3, + + /* testing bits, as well as setting new bits allowed, but clearing bits + * would be unexpected. Used during bitmap receive. Setting new bits + * requires sending of "out-of-sync" information, though. */ + BM_LOCKED_SET_ALLOWED = 0x1, + + /* clear is not expected while bitmap is locked for bulk operation */ +}; + + /* TODO sort members for performance * MAYBE group them further */ @@ -920,6 +946,7 @@ struct drbd_md_io { struct bm_io_work { struct drbd_work w; char *why; + enum bm_flag flags; int (*io_fn)(struct drbd_conf *mdev); void (*done)(struct drbd_conf *mdev, int rv); }; @@ -1242,7 +1269,6 @@ extern void drbd_free_bc(struct drbd_backing_dev *ldev); extern void drbd_mdev_cleanup(struct drbd_conf *mdev); void drbd_print_uuids(struct drbd_conf *mdev, const char *text); -/* drbd_meta-data.c (still in drbd_main.c) */ extern void drbd_md_sync(struct drbd_conf *mdev); extern int drbd_md_read(struct drbd_conf *mdev, struct drbd_backing_dev *bdev); extern void drbd_uuid_set(struct drbd_conf *mdev, int idx, u64 val) __must_hold(local); @@ -1263,10 +1289,12 @@ extern void drbd_md_mark_dirty_(struct drbd_conf *mdev, extern void drbd_queue_bitmap_io(struct drbd_conf *mdev, int (*io_fn)(struct drbd_conf *), void (*done)(struct drbd_conf *, int), - char *why); + char *why, enum bm_flag flags); +extern int drbd_bitmap_io(struct drbd_conf *mdev, + int (*io_fn)(struct drbd_conf *), + char *why, enum bm_flag flags); extern int drbd_bmio_set_n_write(struct drbd_conf *mdev); extern int drbd_bmio_clear_n_write(struct drbd_conf *mdev); -extern int drbd_bitmap_io(struct drbd_conf *mdev, int (*io_fn)(struct drbd_conf *), char *why); extern void drbd_go_diskless(struct drbd_conf *mdev); extern void drbd_ldev_destroy(struct drbd_conf *mdev); @@ -1452,7 +1480,7 @@ extern void drbd_bm_merge_lel(struct drbd_conf *mdev, size_t offset, extern void drbd_bm_get_lel(struct drbd_conf *mdev, size_t offset, size_t number, unsigned long *buffer); -extern void drbd_bm_lock(struct drbd_conf *mdev, char *why); +extern void drbd_bm_lock(struct drbd_conf *mdev, char *why, enum bm_flag flags); extern void drbd_bm_unlock(struct drbd_conf *mdev); /* drbd_main.c */ diff --git a/drivers/block/drbd/drbd_main.c b/drivers/block/drbd/drbd_main.c index b68332a0e73e0..a9e9b496e73b7 100644 --- a/drivers/block/drbd/drbd_main.c +++ b/drivers/block/drbd/drbd_main.c @@ -1320,7 +1320,9 @@ static void abw_start_sync(struct drbd_conf *mdev, int rv) } } -int drbd_bitmap_io_from_worker(struct drbd_conf *mdev, int (*io_fn)(struct drbd_conf *), char *why) +int drbd_bitmap_io_from_worker(struct drbd_conf *mdev, + int (*io_fn)(struct drbd_conf *), + char *why, enum bm_flag flags) { int rv; @@ -1328,10 +1330,8 @@ int drbd_bitmap_io_from_worker(struct drbd_conf *mdev, int (*io_fn)(struct drbd_ /* open coded non-blocking drbd_suspend_io(mdev); */ set_bit(SUSPEND_IO, &mdev->flags); - if (!is_susp(mdev->state)) - D_ASSERT(atomic_read(&mdev->ap_bio_cnt) == 0); - drbd_bm_lock(mdev, why); + drbd_bm_lock(mdev, why, flags); rv = io_fn(mdev); drbd_bm_unlock(mdev); @@ -1438,7 +1438,8 @@ static void after_state_ch(struct drbd_conf *mdev, union drbd_state os, if (os.conn != C_WF_BITMAP_S && ns.conn == C_WF_BITMAP_S && mdev->state.conn == C_WF_BITMAP_S) drbd_queue_bitmap_io(mdev, &drbd_send_bitmap, NULL, - "send_bitmap (WFBitMapS)"); + "send_bitmap (WFBitMapS)", + BM_LOCKED_TEST_ALLOWED); /* Lost contact to peer's copy of the data */ if ((os.pdsk >= D_INCONSISTENT && @@ -1469,7 +1470,11 @@ static void after_state_ch(struct drbd_conf *mdev, union drbd_state os, /* D_DISKLESS Peer becomes secondary */ if (os.peer == R_PRIMARY && ns.peer == R_SECONDARY) - drbd_bitmap_io_from_worker(mdev, &drbd_bm_write, "demote diskless peer"); + /* We may still be Primary ourselves. + * No harm done if the bitmap still changes, + * redirtied pages will follow later. */ + drbd_bitmap_io_from_worker(mdev, &drbd_bm_write, + "demote diskless peer", BM_LOCKED_SET_ALLOWED); put_ldev(mdev); } @@ -1478,7 +1483,10 @@ static void after_state_ch(struct drbd_conf *mdev, union drbd_state os, * if there is a resync going on still */ if (os.role == R_PRIMARY && ns.role == R_SECONDARY && mdev->state.conn <= C_CONNECTED && get_ldev(mdev)) { - drbd_bitmap_io_from_worker(mdev, &drbd_bm_write, "demote"); + /* No changes to the bitmap expected this time, so assert that, + * even though no harm was done if it did change. */ + drbd_bitmap_io_from_worker(mdev, &drbd_bm_write, + "demote", BM_LOCKED_TEST_ALLOWED); put_ldev(mdev); } @@ -1512,12 +1520,17 @@ static void after_state_ch(struct drbd_conf *mdev, union drbd_state os, /* We are in the progress to start a full sync... */ if ((os.conn != C_STARTING_SYNC_T && ns.conn == C_STARTING_SYNC_T) || (os.conn != C_STARTING_SYNC_S && ns.conn == C_STARTING_SYNC_S)) - drbd_queue_bitmap_io(mdev, &drbd_bmio_set_n_write, &abw_start_sync, "set_n_write from StartingSync"); + /* no other bitmap changes expected during this phase */ + drbd_queue_bitmap_io(mdev, + &drbd_bmio_set_n_write, &abw_start_sync, + "set_n_write from StartingSync", BM_LOCKED_TEST_ALLOWED); /* We are invalidating our self... */ if (os.conn < C_CONNECTED && ns.conn < C_CONNECTED && os.disk > D_INCONSISTENT && ns.disk == D_INCONSISTENT) - drbd_queue_bitmap_io(mdev, &drbd_bmio_set_n_write, NULL, "set_n_write from invalidate"); + /* other bitmap operation expected during this phase */ + drbd_queue_bitmap_io(mdev, &drbd_bmio_set_n_write, NULL, + "set_n_write from invalidate", BM_LOCKED_MASK); /* first half of local IO error, failure to attach, * or administrative detach */ @@ -1599,14 +1612,14 @@ static void after_state_ch(struct drbd_conf *mdev, union drbd_state os, /* This triggers bitmap writeout of potentially still unwritten pages * if the resync finished cleanly, or aborted because of peer disk - * failure. Resync aborted because of connection failure does bitmap - * writeout from drbd_disconnect. + * failure, or because of connection loss. * For resync aborted because of local disk failure, we cannot do * any bitmap writeout anymore. + * No harm done if some bits change during this phase. */ - if (os.conn > C_CONNECTED && ns.conn == C_CONNECTED && - mdev->state.conn == C_CONNECTED && get_ldev(mdev)) { - drbd_queue_bitmap_io(mdev, &drbd_bm_write, NULL, "write from resync_finished"); + if (os.conn > C_CONNECTED && ns.conn <= C_CONNECTED && get_ldev(mdev)) { + drbd_queue_bitmap_io(mdev, &drbd_bm_write, NULL, + "write from resync_finished", BM_LOCKED_SET_ALLOWED); put_ldev(mdev); } @@ -3929,7 +3942,7 @@ static int w_bitmap_io(struct drbd_conf *mdev, struct drbd_work *w, int unused) D_ASSERT(atomic_read(&mdev->ap_bio_cnt) == 0); if (get_ldev(mdev)) { - drbd_bm_lock(mdev, work->why); + drbd_bm_lock(mdev, work->why, work->flags); rv = work->io_fn(mdev); drbd_bm_unlock(mdev); put_ldev(mdev); @@ -3944,6 +3957,7 @@ static int w_bitmap_io(struct drbd_conf *mdev, struct drbd_work *w, int unused) clear_bit(BITMAP_IO_QUEUED, &mdev->flags); work->why = NULL; + work->flags = 0; return 1; } @@ -3998,7 +4012,7 @@ void drbd_go_diskless(struct drbd_conf *mdev) void drbd_queue_bitmap_io(struct drbd_conf *mdev, int (*io_fn)(struct drbd_conf *), void (*done)(struct drbd_conf *, int), - char *why) + char *why, enum bm_flag flags) { D_ASSERT(current == mdev->worker.task); @@ -4012,6 +4026,7 @@ void drbd_queue_bitmap_io(struct drbd_conf *mdev, mdev->bm_io_work.io_fn = io_fn; mdev->bm_io_work.done = done; mdev->bm_io_work.why = why; + mdev->bm_io_work.flags = flags; spin_lock_irq(&mdev->req_lock); set_bit(BITMAP_IO, &mdev->flags); @@ -4031,19 +4046,22 @@ void drbd_queue_bitmap_io(struct drbd_conf *mdev, * freezes application IO while that the actual IO operations runs. This * functions MAY NOT be called from worker context. */ -int drbd_bitmap_io(struct drbd_conf *mdev, int (*io_fn)(struct drbd_conf *), char *why) +int drbd_bitmap_io(struct drbd_conf *mdev, int (*io_fn)(struct drbd_conf *), + char *why, enum bm_flag flags) { int rv; D_ASSERT(current != mdev->worker.task); - drbd_suspend_io(mdev); + if ((flags & BM_LOCKED_SET_ALLOWED) == 0) + drbd_suspend_io(mdev); - drbd_bm_lock(mdev, why); + drbd_bm_lock(mdev, why, flags); rv = io_fn(mdev); drbd_bm_unlock(mdev); - drbd_resume_io(mdev); + if ((flags & BM_LOCKED_SET_ALLOWED) == 0) + drbd_resume_io(mdev); return rv; } diff --git a/drivers/block/drbd/drbd_nl.c b/drivers/block/drbd/drbd_nl.c index ce6f2fe808528..bc0bcb964603c 100644 --- a/drivers/block/drbd/drbd_nl.c +++ b/drivers/block/drbd/drbd_nl.c @@ -648,7 +648,9 @@ enum determine_dev_size drbd_determin_dev_size(struct drbd_conf *mdev, enum dds_ dev_info(DEV, "Writing the whole bitmap, %s\n", la_size_changed && md_moved ? "size changed and md moved" : la_size_changed ? "size changed" : "md moved"); - err = drbd_bitmap_io(mdev, &drbd_bm_write, "size changed"); /* does drbd_resume_io() ! */ + /* next line implicitly does drbd_suspend_io()+drbd_resume_io() */ + err = drbd_bitmap_io(mdev, &drbd_bm_write, + "size changed", BM_LOCKED_MASK); if (err) { rv = dev_size_error; goto out; @@ -1160,12 +1162,14 @@ static int drbd_nl_disk_conf(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp if (drbd_md_test_flag(mdev->ldev, MDF_FULL_SYNC)) { dev_info(DEV, "Assuming that all blocks are out of sync " "(aka FullSync)\n"); - if (drbd_bitmap_io(mdev, &drbd_bmio_set_n_write, "set_n_write from attaching")) { + if (drbd_bitmap_io(mdev, &drbd_bmio_set_n_write, + "set_n_write from attaching", BM_LOCKED_MASK)) { retcode = ERR_IO_MD_DISK; goto force_diskless_dec; } } else { - if (drbd_bitmap_io(mdev, &drbd_bm_read, "read from attaching") < 0) { + if (drbd_bitmap_io(mdev, &drbd_bm_read, + "read from attaching", BM_LOCKED_MASK) < 0) { retcode = ERR_IO_MD_DISK; goto force_diskless_dec; } @@ -1173,7 +1177,8 @@ static int drbd_nl_disk_conf(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp if (cp_discovered) { drbd_al_apply_to_bm(mdev); - if (drbd_bitmap_io(mdev, &drbd_bm_write, "crashed primary apply AL")) { + if (drbd_bitmap_io(mdev, &drbd_bm_write, + "crashed primary apply AL", BM_LOCKED_MASK)) { retcode = ERR_IO_MD_DISK; goto force_diskless_dec; } @@ -1925,7 +1930,8 @@ static int drbd_nl_invalidate_peer(struct drbd_conf *mdev, struct drbd_nl_cfg_re retcode = drbd_request_state(mdev, NS(pdsk, D_INCONSISTENT)); if (retcode >= SS_SUCCESS) { if (drbd_bitmap_io(mdev, &drbd_bmio_set_susp_al, - "set_n_write from invalidate_peer")) + "set_n_write from invalidate_peer", + BM_LOCKED_SET_ALLOWED)) retcode = ERR_IO_MD_DISK; } } else @@ -2143,7 +2149,8 @@ static int drbd_nl_new_c_uuid(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nl drbd_uuid_new_current(mdev); /* New current, previous to UI_BITMAP */ if (args.clear_bm) { - err = drbd_bitmap_io(mdev, &drbd_bmio_clear_n_write, "clear_n_write from new_c_uuid"); + err = drbd_bitmap_io(mdev, &drbd_bmio_clear_n_write, + "clear_n_write from new_c_uuid", BM_LOCKED_MASK); if (err) { dev_err(DEV, "Writing bitmap failed with %d\n",err); retcode = ERR_IO_MD_DISK; diff --git a/drivers/block/drbd/drbd_receiver.c b/drivers/block/drbd/drbd_receiver.c index e5686a81f42c0..e13134f83faef 100644 --- a/drivers/block/drbd/drbd_receiver.c +++ b/drivers/block/drbd/drbd_receiver.c @@ -2599,7 +2599,8 @@ static enum drbd_conns drbd_sync_handshake(struct drbd_conf *mdev, enum drbd_rol if (abs(hg) >= 2) { dev_info(DEV, "Writing the whole bitmap, full sync required after drbd_sync_handshake.\n"); - if (drbd_bitmap_io(mdev, &drbd_bmio_set_n_write, "set_n_write from sync_handshake")) + if (drbd_bitmap_io(mdev, &drbd_bmio_set_n_write, "set_n_write from sync_handshake", + BM_LOCKED_SET_ALLOWED)) return C_MASK; } @@ -3053,7 +3054,8 @@ static int receive_uuids(struct drbd_conf *mdev, enum drbd_packets cmd, unsigned if (skip_initial_sync) { dev_info(DEV, "Accepted new current UUID, preparing to skip initial sync\n"); drbd_bitmap_io(mdev, &drbd_bmio_clear_n_write, - "clear_n_write from receive_uuids"); + "clear_n_write from receive_uuids", + BM_LOCKED_TEST_ALLOWED); _drbd_uuid_set(mdev, UI_CURRENT, p_uuid[UI_CURRENT]); _drbd_uuid_set(mdev, UI_BITMAP, 0); _drbd_set_state(_NS2(mdev, disk, D_UP_TO_DATE, pdsk, D_UP_TO_DATE), @@ -3494,7 +3496,9 @@ static int receive_bitmap(struct drbd_conf *mdev, enum drbd_packets cmd, unsigne int ok = false; struct p_header80 *h = &mdev->data.rbuf.header.h80; - /* drbd_bm_lock(mdev, "receive bitmap"); By intention no bm_lock */ + drbd_bm_lock(mdev, "receive bitmap", BM_LOCKED_SET_ALLOWED); + /* you are supposed to send additional out-of-sync information + * if you actually set bits during this phase */ /* maybe we should use some per thread scratch page, * and allocate that during initial device creation? */ @@ -3568,7 +3572,7 @@ static int receive_bitmap(struct drbd_conf *mdev, enum drbd_packets cmd, unsigne ok = true; out: - /* drbd_bm_unlock(mdev); by intention no lock */ + drbd_bm_unlock(mdev); if (ok && mdev->state.conn == C_WF_BITMAP_S) drbd_start_resync(mdev, C_SYNC_SOURCE); free_page((unsigned long) buffer); @@ -3817,7 +3821,6 @@ static void drbd_disconnect(struct drbd_conf *mdev) fp = FP_DONT_CARE; if (get_ldev(mdev)) { - drbd_bitmap_io(mdev, &drbd_bm_write, "write from disconnect"); fp = mdev->ldev->dc.fencing; put_ldev(mdev); } @@ -3846,6 +3849,10 @@ static void drbd_disconnect(struct drbd_conf *mdev) drbd_request_state(mdev, NS(conn, C_STANDALONE)); } + /* serialize with bitmap writeout triggered by the state change, + * if any. */ + wait_event(mdev->misc_wait, !test_bit(BITMAP_IO, &mdev->flags)); + /* tcp_close and release of sendpage pages can be deferred. I don't * want to use SO_LINGER, because apparently it can be deferred for * more than 20 seconds (longest time I checked). -- GitLab From 0ddc5549f88dfc4a4c919693e9a86095e89e080b Mon Sep 17 00:00:00 2001 From: Lars Ellenberg Date: Fri, 21 Jan 2011 12:35:15 +0100 Subject: [PATCH 0491/2822] drbd: silence some noisy log messages during disconnect If we fail to send the information that we lost our disk, we have no connection, and no disk: no access to data anymore. That is either expected (deconfiguration), or there will be so much noise in the logs that "Sending state failed" is not useful at all. Drop it. If the reason for a shorter than expected receive was a signal, which we sent because we already decided to disconnect, these additional log messages are confusing and useless. This patch follows this pattern: - dev_warn(DEV, "short read expecting header on sock: r=%d\n", r); + if (!signal_pending(current)) + dev_warn(DEV, "short read expecting header on sock: r=%d\n", r); Also make them all dev_warn for consistency. Signed-off-by: Philipp Reisner Signed-off-by: Lars Ellenberg --- drivers/block/drbd/drbd_main.c | 6 ++-- drivers/block/drbd/drbd_receiver.c | 45 +++++++++++++++++++----------- 2 files changed, 31 insertions(+), 20 deletions(-) diff --git a/drivers/block/drbd/drbd_main.c b/drivers/block/drbd/drbd_main.c index a9e9b496e73b7..c3760f33d52cf 100644 --- a/drivers/block/drbd/drbd_main.c +++ b/drivers/block/drbd/drbd_main.c @@ -1585,8 +1585,6 @@ static void after_state_ch(struct drbd_conf *mdev, union drbd_state os, if (drbd_send_state(mdev)) dev_warn(DEV, "Notified peer that I'm now diskless.\n"); - else - dev_err(DEV, "Sending state for being diskless failed\n"); /* corresponding get_ldev in __drbd_set_state * this may finaly trigger drbd_ldev_destroy. */ put_ldev(mdev); @@ -1868,8 +1866,8 @@ int _drbd_send_cmd(struct drbd_conf *mdev, struct socket *sock, sent = drbd_send(mdev, sock, h, size, msg_flags); ok = (sent == size); - if (!ok) - dev_err(DEV, "short sent %s size=%d sent=%d\n", + if (!ok && !signal_pending(current)) + dev_warn(DEV, "short sent %s size=%d sent=%d\n", cmdname(cmd), (int)size, sent); return ok; } diff --git a/drivers/block/drbd/drbd_receiver.c b/drivers/block/drbd/drbd_receiver.c index e13134f83faef..a56b107e01eb4 100644 --- a/drivers/block/drbd/drbd_receiver.c +++ b/drivers/block/drbd/drbd_receiver.c @@ -930,7 +930,8 @@ static int drbd_recv_header(struct drbd_conf *mdev, enum drbd_packets *cmd, unsi r = drbd_recv(mdev, h, sizeof(*h)); if (unlikely(r != sizeof(*h))) { - dev_err(DEV, "short read expecting header on sock: r=%d\n", r); + if (!signal_pending(current)) + dev_warn(DEV, "short read expecting header on sock: r=%d\n", r); return false; } @@ -1229,8 +1230,10 @@ read_in_block(struct drbd_conf *mdev, u64 id, sector_t sector, int data_size) __ if (dgs) { rr = drbd_recv(mdev, dig_in, dgs); if (rr != dgs) { - dev_warn(DEV, "short read receiving data digest: read %d expected %d\n", - rr, dgs); + if (!signal_pending(current)) + dev_warn(DEV, + "short read receiving data digest: read %d expected %d\n", + rr, dgs); return NULL; } } @@ -1270,8 +1273,9 @@ read_in_block(struct drbd_conf *mdev, u64 id, sector_t sector, int data_size) __ kunmap(page); if (rr != len) { drbd_free_ee(mdev, e); - dev_warn(DEV, "short read receiving data: read %d expected %d\n", - rr, len); + if (!signal_pending(current)) + dev_warn(DEV, "short read receiving data: read %d expected %d\n", + rr, len); return NULL; } ds -= rr; @@ -1311,8 +1315,10 @@ static int drbd_drain_block(struct drbd_conf *mdev, int data_size) rr = drbd_recv(mdev, data, min_t(int, data_size, PAGE_SIZE)); if (rr != min_t(int, data_size, PAGE_SIZE)) { rv = 0; - dev_warn(DEV, "short read receiving data: read %d expected %d\n", - rr, min_t(int, data_size, PAGE_SIZE)); + if (!signal_pending(current)) + dev_warn(DEV, + "short read receiving data: read %d expected %d\n", + rr, min_t(int, data_size, PAGE_SIZE)); break; } data_size -= rr; @@ -1337,8 +1343,10 @@ static int recv_dless_read(struct drbd_conf *mdev, struct drbd_request *req, if (dgs) { rr = drbd_recv(mdev, dig_in, dgs); if (rr != dgs) { - dev_warn(DEV, "short read receiving data reply digest: read %d expected %d\n", - rr, dgs); + if (!signal_pending(current)) + dev_warn(DEV, + "short read receiving data reply digest: read %d expected %d\n", + rr, dgs); return 0; } } @@ -1359,9 +1367,10 @@ static int recv_dless_read(struct drbd_conf *mdev, struct drbd_request *req, expect); kunmap(bvec->bv_page); if (rr != expect) { - dev_warn(DEV, "short read receiving data reply: " - "read %d expected %d\n", - rr, expect); + if (!signal_pending(current)) + dev_warn(DEV, "short read receiving data reply: " + "read %d expected %d\n", + rr, expect); return 0; } data_size -= rr; @@ -3696,7 +3705,8 @@ static void drbdd(struct drbd_conf *mdev) if (shs) { rv = drbd_recv(mdev, &header->h80.payload, shs); if (unlikely(rv != shs)) { - dev_err(DEV, "short read while reading sub header: rv=%d\n", rv); + if (!signal_pending(current)) + dev_warn(DEV, "short read while reading sub header: rv=%d\n", rv); goto err_out; } } @@ -3953,7 +3963,8 @@ static int drbd_do_handshake(struct drbd_conf *mdev) rv = drbd_recv(mdev, &p->head.payload, expect); if (rv != expect) { - dev_err(DEV, "short read receiving handshake packet: l=%u\n", rv); + if (!signal_pending(current)) + dev_warn(DEV, "short read receiving handshake packet: l=%u\n", rv); return 0; } @@ -4055,7 +4066,8 @@ static int drbd_do_auth(struct drbd_conf *mdev) rv = drbd_recv(mdev, peers_ch, length); if (rv != length) { - dev_err(DEV, "short read AuthChallenge: l=%u\n", rv); + if (!signal_pending(current)) + dev_warn(DEV, "short read AuthChallenge: l=%u\n", rv); rv = 0; goto fail; } @@ -4102,7 +4114,8 @@ static int drbd_do_auth(struct drbd_conf *mdev) rv = drbd_recv(mdev, response , resp_size); if (rv != resp_size) { - dev_err(DEV, "short read receiving AuthResponse: l=%u\n", rv); + if (!signal_pending(current)) + dev_warn(DEV, "short read receiving AuthResponse: l=%u\n", rv); rv = 0; goto fail; } -- GitLab From e636db5b956950b8b9bfbeb766a637f84bae1e3b Mon Sep 17 00:00:00 2001 From: Lars Ellenberg Date: Fri, 21 Jan 2011 17:10:37 +0100 Subject: [PATCH 0492/2822] drbd: fix potential imbalance of ap_in_flight When we receive a barrier ack, we walk the ring list of drbd requests in the transfer log of the respective epoch, do some housekeeping, and free those objects. We tried to keep epochs of mirrored and unmirrored drbd requests separate, and assert that no local-only requests are present in a barrier_acked epoch. It turns out that this has quite a number of corner cases and would add bloated code without functional benefit. We now revert the (insufficient) commits drbd: Fixed an issue with AHEAD -> SYNC_SOURCE transitions drbd: Ensure that an epoch contains only requests of one kind and instead fix the processing of barrier acks to cope with a mix of local-only and mirrored requests. Signed-off-by: Philipp Reisner Signed-off-by: Lars Ellenberg --- drivers/block/drbd/drbd_main.c | 25 ------------------------- drivers/block/drbd/drbd_req.c | 9 +++++---- 2 files changed, 5 insertions(+), 29 deletions(-) diff --git a/drivers/block/drbd/drbd_main.c b/drivers/block/drbd/drbd_main.c index c3760f33d52cf..9043772de4005 100644 --- a/drivers/block/drbd/drbd_main.c +++ b/drivers/block/drbd/drbd_main.c @@ -337,23 +337,6 @@ bail: } -/* In C_AHEAD mode only out_of_sync packets are sent for requests. Detach - * those requests from the newsest barrier when changing to an other cstate. - * - * That headless list vanishes when the last request finished its write or - * send out_of_sync packet. */ -static void tl_forget(struct drbd_conf *mdev) -{ - struct drbd_tl_epoch *b; - - if (test_bit(CREATE_BARRIER, &mdev->flags)) - return; - - b = mdev->newest_tle; - list_del(&b->requests); - _tl_add_barrier(mdev, b); -} - /** * _tl_restart() - Walks the transfer log, and applies an action to all requests * @mdev: DRBD device. @@ -1265,14 +1248,6 @@ __drbd_set_state(struct drbd_conf *mdev, union drbd_state ns, if (os.conn < C_CONNECTED && ns.conn >= C_CONNECTED) drbd_resume_al(mdev); - /* Start a new epoch in case we start to mirror write requests */ - if (!drbd_should_do_remote(os) && drbd_should_do_remote(ns)) - tl_forget(mdev); - - /* Do not add local-only requests to an epoch with mirrored requests */ - if (drbd_should_do_remote(os) && !drbd_should_do_remote(ns)) - set_bit(CREATE_BARRIER, &mdev->flags); - ascw = kmalloc(sizeof(*ascw), GFP_ATOMIC); if (ascw) { ascw->os = os; diff --git a/drivers/block/drbd/drbd_req.c b/drivers/block/drbd/drbd_req.c index 336937a14d3fc..c28be4e5e57c7 100644 --- a/drivers/block/drbd/drbd_req.c +++ b/drivers/block/drbd/drbd_req.c @@ -712,10 +712,11 @@ int __req_mod(struct drbd_request *req, enum drbd_req_event what, dev_err(DEV, "FIXME (barrier_acked but pending)\n"); list_move(&req->tl_requests, &mdev->out_of_sequence_requests); } - D_ASSERT(req->rq_state & RQ_NET_SENT); - req->rq_state |= RQ_NET_DONE; - if (mdev->net_conf->wire_protocol == DRBD_PROT_A) - atomic_sub(req->size>>9, &mdev->ap_in_flight); + if ((req->rq_state & RQ_NET_MASK) != 0) { + req->rq_state |= RQ_NET_DONE; + if (mdev->net_conf->wire_protocol == DRBD_PROT_A) + atomic_sub(req->size>>9, &mdev->ap_in_flight); + } _req_may_be_done(req, m); /* Allowed while state.susp */ break; -- GitLab From 873b0d5f98ab70e4df7a62b2ef0305373f88f330 Mon Sep 17 00:00:00 2001 From: Lars Ellenberg Date: Fri, 21 Jan 2011 22:53:48 +0100 Subject: [PATCH 0493/2822] drbd: serialize admin requests for new verify run with pending bitmap io This is an addendum to drbd: serialize admin requests for new resync with pending bitmap io It avoids a race that could trigger "FIXME" assert log messages. Signed-off-by: Philipp Reisner Signed-off-by: Lars Ellenberg --- drivers/block/drbd/drbd_nl.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/block/drbd/drbd_nl.c b/drivers/block/drbd/drbd_nl.c index bc0bcb964603c..87aaa7fc4d27d 100644 --- a/drivers/block/drbd/drbd_nl.c +++ b/drivers/block/drbd/drbd_nl.c @@ -2106,6 +2106,11 @@ static int drbd_nl_start_ov(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp, reply->ret_code = ERR_MANDATORY_TAG; return 0; } + + /* If there is still bitmap IO pending, e.g. previous resync or verify + * just being finished, wait for it before requesting a new resync. */ + wait_event(mdev->misc_wait, !test_bit(BITMAP_IO, &mdev->flags)); + /* w_make_ov_request expects position to be aligned */ mdev->ov_start_sector = args.start_sector & ~BM_SECT_PER_BIT; reply->ret_code = drbd_request_state(mdev,NS(conn,C_VERIFY_S)); -- GitLab From 039312b6481e2928f3be19fee94c83327d93e4c7 Mon Sep 17 00:00:00 2001 From: Philipp Reisner Date: Fri, 21 Jan 2011 14:13:22 +0100 Subject: [PATCH 0494/2822] drbd: Removed left over, now wrong comments Signed-off-by: Philipp Reisner Signed-off-by: Lars Ellenberg --- drivers/block/drbd/drbd_req.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/drivers/block/drbd/drbd_req.c b/drivers/block/drbd/drbd_req.c index c28be4e5e57c7..94fd5a2be559c 100644 --- a/drivers/block/drbd/drbd_req.c +++ b/drivers/block/drbd/drbd_req.c @@ -983,13 +983,7 @@ allocate_barrier: } if (congested) { - /* rs_pending_cnt must be zero, otherwise the two peers - might get different bitmaps. With sane configurations - the resync stalls long before we might want to go into - AHEAD mode. - We could force the resync into PAUSE mode here if - rs_pending_cnt is > 0 ... */ - queue_barrier(mdev); + queue_barrier(mdev); /* last barrier, after mirrored writes */ if (mdev->net_conf->on_congestion == OC_PULL_AHEAD) _drbd_set_state(_NS(mdev, conn, C_AHEAD), 0, NULL); -- GitLab From 10f6d9926cd17afff9dc03c967706419798b4929 Mon Sep 17 00:00:00 2001 From: Lars Ellenberg Date: Mon, 24 Jan 2011 14:47:09 +0100 Subject: [PATCH 0495/2822] drbd: don't BUG_ON, if bio_add_page of a single page to an empty bio fails Just deal with it more gracefully, if we fail to add even a single page to an empty bio. We used to BUG_ON() there, but it has been observed in some Xen deployment, so we need to handle that case more robustly now. Signed-off-by: Philipp Reisner Signed-off-by: Lars Ellenberg --- drivers/block/drbd/drbd_receiver.c | 45 ++++++++++++++++++++---------- drivers/block/drbd/drbd_worker.c | 7 +++-- 2 files changed, 34 insertions(+), 18 deletions(-) diff --git a/drivers/block/drbd/drbd_receiver.c b/drivers/block/drbd/drbd_receiver.c index a56b107e01eb4..9e9fc34131376 100644 --- a/drivers/block/drbd/drbd_receiver.c +++ b/drivers/block/drbd/drbd_receiver.c @@ -1073,6 +1073,16 @@ void drbd_bump_write_ordering(struct drbd_conf *mdev, enum write_ordering_e wo) * @mdev: DRBD device. * @e: epoch entry * @rw: flag field, see bio->bi_rw + * + * May spread the pages to multiple bios, + * depending on bio_add_page restrictions. + * + * Returns 0 if all bios have been submitted, + * -ENOMEM if we could not allocate enough bios, + * -ENOSPC (any better suggestion?) if we have not been able to bio_add_page a + * single page to an empty bio (which should never happen and likely indicates + * that the lower level IO stack is in some way broken). This has been observed + * on certain Xen deployments. */ /* TODO allocate from our own bio_set. */ int drbd_submit_ee(struct drbd_conf *mdev, struct drbd_epoch_entry *e, @@ -1085,6 +1095,7 @@ int drbd_submit_ee(struct drbd_conf *mdev, struct drbd_epoch_entry *e, unsigned ds = e->size; unsigned n_bios = 0; unsigned nr_pages = (ds + PAGE_SIZE -1) >> PAGE_SHIFT; + int err = -ENOMEM; /* In most cases, we will only need one bio. But in case the lower * level restrictions happen to be different at this offset on this @@ -1110,8 +1121,17 @@ next_bio: page_chain_for_each(page) { unsigned len = min_t(unsigned, ds, PAGE_SIZE); if (!bio_add_page(bio, page, len, 0)) { - /* a single page must always be possible! */ - BUG_ON(bio->bi_vcnt == 0); + /* A single page must always be possible! + * But in case it fails anyways, + * we deal with it, and complain (below). */ + if (bio->bi_vcnt == 0) { + dev_err(DEV, + "bio_add_page failed for len=%u, " + "bi_vcnt=0 (bi_sector=%llu)\n", + len, (unsigned long long)bio->bi_sector); + err = -ENOSPC; + goto fail; + } goto next_bio; } ds -= len; @@ -1137,7 +1157,7 @@ fail: bios = bios->bi_next; bio_put(bio); } - return -ENOMEM; + return err; } static int receive_Barrier(struct drbd_conf *mdev, enum drbd_packets cmd, unsigned int data_size) @@ -1436,9 +1456,8 @@ static int recv_resync_read(struct drbd_conf *mdev, sector_t sector, int data_si if (drbd_submit_ee(mdev, e, WRITE, DRBD_FAULT_RS_WR) == 0) return true; - /* drbd_submit_ee currently fails for one reason only: - * not being able to allocate enough bios. - * Is dropping the connection going to help? */ + /* don't care for the reason here */ + dev_err(DEV, "submit failed, triggering re-connect\n"); spin_lock_irq(&mdev->req_lock); list_del(&e->w.list); spin_unlock_irq(&mdev->req_lock); @@ -1837,9 +1856,8 @@ static int receive_Data(struct drbd_conf *mdev, enum drbd_packets cmd, unsigned if (drbd_submit_ee(mdev, e, rw, DRBD_FAULT_DT_WR) == 0) return true; - /* drbd_submit_ee currently fails for one reason only: - * not being able to allocate enough bios. - * Is dropping the connection going to help? */ + /* don't care for the reason here */ + dev_err(DEV, "submit failed, triggering re-connect\n"); spin_lock_irq(&mdev->req_lock); list_del(&e->w.list); hlist_del_init(&e->colision); @@ -1848,9 +1866,7 @@ static int receive_Data(struct drbd_conf *mdev, enum drbd_packets cmd, unsigned drbd_al_complete_io(mdev, e->sector); out_interrupted: - /* yes, the epoch_size now is imbalanced. - * but we drop the connection anyways, so we don't have a chance to - * receive a barrier... atomic_inc(&mdev->epoch_size); */ + drbd_may_finish_epoch(mdev, e->epoch, EV_PUT + EV_CLEANUP); put_ldev(mdev); drbd_free_ee(mdev, e); return false; @@ -2096,9 +2112,8 @@ submit: if (drbd_submit_ee(mdev, e, READ, fault_type) == 0) return true; - /* drbd_submit_ee currently fails for one reason only: - * not being able to allocate enough bios. - * Is dropping the connection going to help? */ + /* don't care for the reason here */ + dev_err(DEV, "submit failed, triggering re-connect\n"); spin_lock_irq(&mdev->req_lock); list_del(&e->w.list); spin_unlock_irq(&mdev->req_lock); diff --git a/drivers/block/drbd/drbd_worker.c b/drivers/block/drbd/drbd_worker.c index ff0eb308ee4ad..cfd324b9f95be 100644 --- a/drivers/block/drbd/drbd_worker.c +++ b/drivers/block/drbd/drbd_worker.c @@ -369,9 +369,10 @@ static int read_for_csum(struct drbd_conf *mdev, sector_t sector, int size) if (drbd_submit_ee(mdev, e, READ, DRBD_FAULT_RS_RD) == 0) return 0; - /* drbd_submit_ee currently fails for one reason only: - * not being able to allocate enough bios. - * Is dropping the connection going to help? */ + /* If it failed because of ENOMEM, retry should help. If it failed + * because bio_add_page failed (probably broken lower level driver), + * retry may or may not help. + * If it does not, you may need to force disconnect. */ spin_lock_irq(&mdev->req_lock); list_del(&e->w.list); spin_unlock_irq(&mdev->req_lock); -- GitLab From e99dc367b3aafb1ce2d5d92e94834d07b299e1d7 Mon Sep 17 00:00:00 2001 From: Lars Ellenberg Date: Mon, 24 Jan 2011 14:58:39 +0100 Subject: [PATCH 0496/2822] drbd: kill dead code This code became obsolete and unused last December with drbd: bitmap keep track of changes vs on-disk bitmap Signed-off-by: Philipp Reisner Signed-off-by: Lars Ellenberg --- drivers/block/drbd/drbd_actlog.c | 93 -------------------------------- 1 file changed, 93 deletions(-) diff --git a/drivers/block/drbd/drbd_actlog.c b/drivers/block/drbd/drbd_actlog.c index 090fc2ce0df48..a6050791401ba 100644 --- a/drivers/block/drbd/drbd_actlog.c +++ b/drivers/block/drbd/drbd_actlog.c @@ -569,99 +569,6 @@ static void atodb_endio(struct bio *bio, int error) put_ldev(mdev); } -/* sector to word */ -#define S2W(s) ((s)<<(BM_EXT_SHIFT-BM_BLOCK_SHIFT-LN2_BPL)) - -/* activity log to on disk bitmap -- prepare bio unless that sector - * is already covered by previously prepared bios */ -static int atodb_prepare_unless_covered(struct drbd_conf *mdev, - struct bio **bios, - unsigned int enr, - struct drbd_atodb_wait *wc) __must_hold(local) -{ - struct bio *bio; - struct page *page; - sector_t on_disk_sector; - unsigned int page_offset = PAGE_SIZE; - int offset; - int i = 0; - int err = -ENOMEM; - - /* We always write aligned, full 4k blocks, - * so we can ignore the logical_block_size (for now) */ - enr &= ~7U; - on_disk_sector = enr + mdev->ldev->md.md_offset - + mdev->ldev->md.bm_offset; - - D_ASSERT(!(on_disk_sector & 7U)); - - /* Check if that enr is already covered by an already created bio. - * Caution, bios[] is not NULL terminated, - * but only initialized to all NULL. - * For completely scattered activity log, - * the last invocation iterates over all bios, - * and finds the last NULL entry. - */ - while ((bio = bios[i])) { - if (bio->bi_sector == on_disk_sector) - return 0; - i++; - } - /* bios[i] == NULL, the next not yet used slot */ - - /* GFP_KERNEL, we are not in the write-out path */ - bio = bio_alloc(GFP_KERNEL, 1); - if (bio == NULL) - return -ENOMEM; - - if (i > 0) { - const struct bio_vec *prev_bv = bios[i-1]->bi_io_vec; - page_offset = prev_bv->bv_offset + prev_bv->bv_len; - page = prev_bv->bv_page; - } - if (page_offset == PAGE_SIZE) { - page = alloc_page(__GFP_HIGHMEM); - if (page == NULL) - goto out_bio_put; - page_offset = 0; - } else { - get_page(page); - } - - offset = S2W(enr); - drbd_bm_get_lel(mdev, offset, - min_t(size_t, S2W(8), drbd_bm_words(mdev) - offset), - kmap(page) + page_offset); - kunmap(page); - - bio->bi_private = wc; - bio->bi_end_io = atodb_endio; - bio->bi_bdev = mdev->ldev->md_bdev; - bio->bi_sector = on_disk_sector; - - if (bio_add_page(bio, page, 4096, page_offset) != 4096) - goto out_put_page; - - atomic_inc(&wc->count); - /* we already know that we may do this... - * get_ldev_if_state(mdev,D_ATTACHING); - * just get the extra reference, so that the local_cnt reflects - * the number of pending IO requests DRBD at its backing device. - */ - atomic_inc(&mdev->local_cnt); - - bios[i] = bio; - - return 0; - -out_put_page: - err = -EINVAL; - put_page(page); -out_bio_put: - bio_put(bio); - return err; -} - /** * drbd_al_apply_to_bm() - Sets the bitmap to diry(1) where covered ba active AL extents * @mdev: DRBD device. -- GitLab From fdda6544ad4d3284246e717b7108f7f497b45295 Mon Sep 17 00:00:00 2001 From: Lars Ellenberg Date: Mon, 24 Jan 2011 15:11:01 +0100 Subject: [PATCH 0497/2822] drbd: improve log message if received sector offset exceeds local capacity Signed-off-by: Philipp Reisner Signed-off-by: Lars Ellenberg --- drivers/block/drbd/drbd_receiver.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/block/drbd/drbd_receiver.c b/drivers/block/drbd/drbd_receiver.c index 9e9fc34131376..3d62ac7cdc4a1 100644 --- a/drivers/block/drbd/drbd_receiver.c +++ b/drivers/block/drbd/drbd_receiver.c @@ -1267,7 +1267,8 @@ read_in_block(struct drbd_conf *mdev, u64 id, sector_t sector, int data_size) __ /* even though we trust out peer, * we sometimes have to double check. */ if (sector + (data_size>>9) > capacity) { - dev_err(DEV, "capacity: %llus < sector: %llus + size: %u\n", + dev_err(DEV, "request from peer beyond end of local disk: " + "capacity: %llus < sector: %llus + size: %u\n", (unsigned long long)capacity, (unsigned long long)sector, data_size); return NULL; -- GitLab From c5a91619793d444e5103ec5841045bf878718398 Mon Sep 17 00:00:00 2001 From: Andreas Gruenbacher Date: Tue, 25 Jan 2011 17:33:38 +0100 Subject: [PATCH 0498/2822] drbd: Remove unused function atodb_endio() Signed-off-by: Philipp Reisner Signed-off-by: Lars Ellenberg --- drivers/block/drbd/drbd_actlog.c | 27 --------------------------- drivers/block/drbd/drbd_worker.c | 15 ++++++--------- include/linux/drbd.h | 2 +- 3 files changed, 7 insertions(+), 37 deletions(-) diff --git a/drivers/block/drbd/drbd_actlog.c b/drivers/block/drbd/drbd_actlog.c index a6050791401ba..2a1642bc451d6 100644 --- a/drivers/block/drbd/drbd_actlog.c +++ b/drivers/block/drbd/drbd_actlog.c @@ -542,33 +542,6 @@ cancel: return 1; } -static void atodb_endio(struct bio *bio, int error) -{ - struct drbd_atodb_wait *wc = bio->bi_private; - struct drbd_conf *mdev = wc->mdev; - struct page *page; - int uptodate = bio_flagged(bio, BIO_UPTODATE); - - /* strange behavior of some lower level drivers... - * fail the request by clearing the uptodate flag, - * but do not return any error?! */ - if (!error && !uptodate) - error = -EIO; - - drbd_chk_io_error(mdev, error, true); - if (error && wc->error == 0) - wc->error = error; - - if (atomic_dec_and_test(&wc->count)) - complete(&wc->io_done); - - page = bio->bi_io_vec[0].bv_page; - put_page(page); - bio_put(bio); - mdev->bm_writ_cnt++; - put_ldev(mdev); -} - /** * drbd_al_apply_to_bm() - Sets the bitmap to diry(1) where covered ba active AL extents * @mdev: DRBD device. diff --git a/drivers/block/drbd/drbd_worker.c b/drivers/block/drbd/drbd_worker.c index cfd324b9f95be..3d70d8d015d9a 100644 --- a/drivers/block/drbd/drbd_worker.c +++ b/drivers/block/drbd/drbd_worker.c @@ -44,15 +44,12 @@ static int w_make_resync_request(struct drbd_conf *mdev, -/* defined here: - drbd_md_io_complete - drbd_endio_sec - drbd_endio_pri - - * more endio handlers: - atodb_endio in drbd_actlog.c - drbd_bm_async_io_complete in drbd_bitmap.c - +/* endio handlers: + * drbd_md_io_complete (defined here) + * drbd_endio_pri (defined here) + * drbd_endio_sec (defined here) + * bm_async_io_complete (defined in drbd_bitmap.c) + * * For all these callbacks, note the following: * The callbacks will be called in irq context by the IDE drivers, * and in Softirqs/Tasklets/BH context by the SCSI drivers. diff --git a/include/linux/drbd.h b/include/linux/drbd.h index ba5c785d3f7de..d18d673ebc78e 100644 --- a/include/linux/drbd.h +++ b/include/linux/drbd.h @@ -53,7 +53,7 @@ extern const char *drbd_buildtag(void); -#define REL_VERSION "8.3.9" +#define REL_VERSION "8.3.10" #define API_VERSION 88 #define PRO_VERSION_MIN 86 #define PRO_VERSION_MAX 96 -- GitLab From 7fde2be93080c028c20078a2d6abec8a95891192 Mon Sep 17 00:00:00 2001 From: Philipp Reisner Date: Tue, 1 Mar 2011 11:08:28 +0100 Subject: [PATCH 0499/2822] drbd: Implemented real timeout checking for request processing time Signed-off-by: Philipp Reisner Signed-off-by: Lars Ellenberg --- drivers/block/drbd/drbd_int.h | 1 + drivers/block/drbd/drbd_main.c | 3 +++ drivers/block/drbd/drbd_receiver.c | 3 +++ drivers/block/drbd/drbd_req.c | 39 ++++++++++++++++++++++++++++++ drivers/block/drbd/drbd_req.h | 1 + 5 files changed, 47 insertions(+) diff --git a/drivers/block/drbd/drbd_int.h b/drivers/block/drbd/drbd_int.h index 267d9897ca8c4..81030d8d654b2 100644 --- a/drivers/block/drbd/drbd_int.h +++ b/drivers/block/drbd/drbd_int.h @@ -990,6 +990,7 @@ struct drbd_conf { struct timer_list resync_timer; struct timer_list md_sync_timer; struct timer_list start_resync_timer; + struct timer_list request_timer; #ifdef DRBD_DEBUG_MD_SYNC struct { unsigned int line; diff --git a/drivers/block/drbd/drbd_main.c b/drivers/block/drbd/drbd_main.c index 9043772de4005..dfc85f32d3177 100644 --- a/drivers/block/drbd/drbd_main.c +++ b/drivers/block/drbd/drbd_main.c @@ -3017,12 +3017,15 @@ void drbd_init_set_defaults(struct drbd_conf *mdev) init_timer(&mdev->resync_timer); init_timer(&mdev->md_sync_timer); init_timer(&mdev->start_resync_timer); + init_timer(&mdev->request_timer); mdev->resync_timer.function = resync_timer_fn; mdev->resync_timer.data = (unsigned long) mdev; mdev->md_sync_timer.function = md_sync_timer_fn; mdev->md_sync_timer.data = (unsigned long) mdev; mdev->start_resync_timer.function = start_resync_timer_fn; mdev->start_resync_timer.data = (unsigned long) mdev; + mdev->request_timer.function = request_timer_fn; + mdev->request_timer.data = (unsigned long) mdev; init_waitqueue_head(&mdev->misc_wait); init_waitqueue_head(&mdev->state_wait); diff --git a/drivers/block/drbd/drbd_receiver.c b/drivers/block/drbd/drbd_receiver.c index 3d62ac7cdc4a1..fe1564c7d8b6e 100644 --- a/drivers/block/drbd/drbd_receiver.c +++ b/drivers/block/drbd/drbd_receiver.c @@ -912,6 +912,7 @@ retry: drbd_send_state(mdev); clear_bit(USE_DEGR_WFC_T, &mdev->flags); clear_bit(RESIZE_PENDING, &mdev->flags); + mod_timer(&mdev->request_timer, jiffies + HZ); /* just start it here. */ return 1; @@ -3822,6 +3823,8 @@ static void drbd_disconnect(struct drbd_conf *mdev) atomic_set(&mdev->rs_pending_cnt, 0); wake_up(&mdev->misc_wait); + del_timer(&mdev->request_timer); + /* make sure syncer is stopped and w_resume_next_sg queued */ del_timer_sync(&mdev->resync_timer); resync_timer_fn((unsigned long)mdev); diff --git a/drivers/block/drbd/drbd_req.c b/drivers/block/drbd/drbd_req.c index 94fd5a2be559c..c2cc28a55907b 100644 --- a/drivers/block/drbd/drbd_req.c +++ b/drivers/block/drbd/drbd_req.c @@ -1194,3 +1194,42 @@ int drbd_merge_bvec(struct request_queue *q, struct bvec_merge_data *bvm, struct } return limit; } + +void request_timer_fn(unsigned long data) +{ + struct drbd_conf *mdev = (struct drbd_conf *) data; + struct drbd_request *req; /* oldest request */ + struct list_head *le; + unsigned long et = 0; /* effective timeout = ko_count * timeout */ + + if (get_net_conf(mdev)) { + et = mdev->net_conf->timeout*HZ/10 * mdev->net_conf->ko_count; + put_net_conf(mdev); + } + if (!et || mdev->state.conn < C_WF_REPORT_PARAMS) + return; /* Recurring timer stopped */ + + spin_lock_irq(&mdev->req_lock); + le = &mdev->oldest_tle->requests; + if (list_empty(le)) { + spin_unlock_irq(&mdev->req_lock); + mod_timer(&mdev->request_timer, jiffies + et); + return; + } + + le = le->prev; + req = list_entry(le, struct drbd_request, tl_requests); + if (time_is_before_eq_jiffies(req->start_time + et)) { + if (req->rq_state & RQ_NET_PENDING) { + dev_warn(DEV, "Remote failed to finish a request within ko-count * timeout\n"); + _drbd_set_state(_NS(mdev, conn, C_TIMEOUT), CS_VERBOSE, NULL); + } else { + dev_warn(DEV, "Local backing block device frozen?\n"); + mod_timer(&mdev->request_timer, jiffies + et); + } + } else { + mod_timer(&mdev->request_timer, req->start_time + et); + } + + spin_unlock_irq(&mdev->req_lock); +} diff --git a/drivers/block/drbd/drbd_req.h b/drivers/block/drbd/drbd_req.h index 32c1f2a312667..32e2c3e6a8134 100644 --- a/drivers/block/drbd/drbd_req.h +++ b/drivers/block/drbd/drbd_req.h @@ -322,6 +322,7 @@ extern int __req_mod(struct drbd_request *req, enum drbd_req_event what, struct bio_and_error *m); extern void complete_master_bio(struct drbd_conf *mdev, struct bio_and_error *m); +extern void request_timer_fn(unsigned long data); /* use this if you don't want to deal with calling complete_master_bio() * outside the spinlock, e.g. when walking some list on cleanup. */ -- GitLab From 8f21420ebd5ca5a751e2f606b49b0acd2a2af314 Mon Sep 17 00:00:00 2001 From: Philipp Reisner Date: Tue, 1 Mar 2011 15:52:35 +0100 Subject: [PATCH 0500/2822] drbd: Fixed handling of read errors on a 'VerifyT' node Signed-off-by: Philipp Reisner Signed-off-by: Lars Ellenberg --- drivers/block/drbd/drbd_worker.c | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/drivers/block/drbd/drbd_worker.c b/drivers/block/drbd/drbd_worker.c index 3d70d8d015d9a..7db29080f3639 100644 --- a/drivers/block/drbd/drbd_worker.c +++ b/drivers/block/drbd/drbd_worker.c @@ -1081,25 +1081,27 @@ int w_e_end_ov_req(struct drbd_conf *mdev, struct drbd_work *w, int cancel) if (unlikely(cancel)) goto out; - if (unlikely((e->flags & EE_WAS_ERROR) != 0)) - goto out; - digest_size = crypto_hash_digestsize(mdev->verify_tfm); - /* FIXME if this allocation fails, online verify will not terminate! */ digest = kmalloc(digest_size, GFP_NOIO); - if (digest) { - drbd_csum_ee(mdev, mdev->verify_tfm, e, digest); - inc_rs_pending(mdev); - ok = drbd_send_drequest_csum(mdev, e->sector, e->size, - digest, digest_size, P_OV_REPLY); - if (!ok) - dec_rs_pending(mdev); - kfree(digest); + if (!digest) { + ok = 0; /* terminate the connection in case the allocation failed */ + goto out; } + if (likely(!(e->flags & EE_WAS_ERROR))) + drbd_csum_ee(mdev, mdev->verify_tfm, e, digest); + else + memset(digest, 0, digest_size); + + inc_rs_pending(mdev); + ok = drbd_send_drequest_csum(mdev, e->sector, e->size, + digest, digest_size, P_OV_REPLY); + if (!ok) + dec_rs_pending(mdev); + kfree(digest); + out: drbd_free_ee(mdev, e); - dec_unacked(mdev); return ok; -- GitLab From 7961243b7bdd62d72b47eb2c0bee776c51a8a8e2 Mon Sep 17 00:00:00 2001 From: Philipp Reisner Date: Wed, 2 Mar 2011 23:14:44 +0100 Subject: [PATCH 0501/2822] drbd: Fixed handling of read errors on a 'VerifyS' node Signed-off-by: Philipp Reisner Signed-off-by: Lars Ellenberg --- drivers/block/drbd/drbd_worker.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/block/drbd/drbd_worker.c b/drivers/block/drbd/drbd_worker.c index 7db29080f3639..f7e6c92f8d03d 100644 --- a/drivers/block/drbd/drbd_worker.c +++ b/drivers/block/drbd/drbd_worker.c @@ -1151,10 +1151,6 @@ int w_e_end_ov_reply(struct drbd_conf *mdev, struct drbd_work *w, int cancel) eq = !memcmp(digest, di->digest, digest_size); kfree(digest); } - } else { - ok = drbd_send_ack(mdev, P_NEG_RS_DREPLY, e); - if (__ratelimit(&drbd_ratelimit_state)) - dev_err(DEV, "Sending NegDReply. I guess it gets messy.\n"); } dec_unacked(mdev); -- GitLab From 03567812d81dd87a810b2bd1e804f4001de03da5 Mon Sep 17 00:00:00 2001 From: Or Gerlitz Date: Thu, 13 Jan 2011 10:43:40 +0100 Subject: [PATCH 0502/2822] drbd: drop code present under #ifdef which is relevant to 2.6.28 and below Signed-off-by: Or Gerlitz Signed-off-by: Philipp Reisner Signed-off-by: Lars Ellenberg --- drivers/block/drbd/drbd_req.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/drivers/block/drbd/drbd_req.c b/drivers/block/drbd/drbd_req.c index c2cc28a55907b..5c0c8be1bb0ae 100644 --- a/drivers/block/drbd/drbd_req.c +++ b/drivers/block/drbd/drbd_req.c @@ -1127,11 +1127,7 @@ int drbd_make_request(struct request_queue *q, struct bio *bio) const int sps = 1 << HT_SHIFT; /* sectors per slot */ const int mask = sps - 1; const sector_t first_sectors = sps - (sect & mask); - bp = bio_split(bio, -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28) - bio_split_pool, -#endif - first_sectors); + bp = bio_split(bio, first_sectors); /* we need to get a "reference count" (ap_bio_cnt) * to avoid races with the disconnect/reconnect/suspend code. -- GitLab From a110f4ef810ee29d810876df725f41d66629733e Mon Sep 17 00:00:00 2001 From: Marek Belisko Date: Wed, 9 Mar 2011 21:46:20 +0100 Subject: [PATCH 0503/2822] ASoC: mini2440: Fix uda134x codec problem. ASoC audio for mini2440 platform in current kenrel doesn't work. First problem is samsung_asoc_dma device is missing in initialization. Next problem is with codec. Codec is initialized but never probed because no platform_device exist for codec driver. It leads to errors during codec binding to asoc dai. Next problem was platform data which was passed from board to asoc main driver but not passed to codec when called codec_soc_probe(). Following patch should fix issues. But not sure if in correct way. Please review. Signed-off-by: Marek Belisko Acked-by: Liam Girdwood Signed-off-by: Mark Brown Cc: stable@kernel.org --- arch/arm/mach-s3c2440/mach-mini2440.c | 7 +++++++ sound/soc/codecs/uda134x.c | 3 ++- sound/soc/samsung/s3c24xx_uda134x.c | 3 ++- 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/arch/arm/mach-s3c2440/mach-mini2440.c b/arch/arm/mach-s3c2440/mach-mini2440.c index f62bb4c793bdd..7c3fb071ddd69 100644 --- a/arch/arm/mach-s3c2440/mach-mini2440.c +++ b/arch/arm/mach-s3c2440/mach-mini2440.c @@ -506,6 +506,11 @@ static struct i2c_board_info mini2440_i2c_devs[] __initdata = { }, }; +static struct platform_device uda1340_codec = { + .name = "uda134x-codec", + .id = -1, +}; + static struct platform_device *mini2440_devices[] __initdata = { &s3c_device_ohci, &s3c_device_wdt, @@ -521,7 +526,9 @@ static struct platform_device *mini2440_devices[] __initdata = { &s3c_device_nand, &s3c_device_sdi, &s3c_device_iis, + &uda1340_codec, &mini2440_audio, + &samsung_asoc_dma, }; static void __init mini2440_map_io(void) diff --git a/sound/soc/codecs/uda134x.c b/sound/soc/codecs/uda134x.c index e76847a9438b0..48ffd406a71d1 100644 --- a/sound/soc/codecs/uda134x.c +++ b/sound/soc/codecs/uda134x.c @@ -486,7 +486,8 @@ static struct snd_soc_dai_driver uda134x_dai = { static int uda134x_soc_probe(struct snd_soc_codec *codec) { struct uda134x_priv *uda134x; - struct uda134x_platform_data *pd = dev_get_drvdata(codec->card->dev); + struct uda134x_platform_data *pd = codec->card->dev->platform_data; + int ret; printk(KERN_INFO "UDA134X SoC Audio Codec\n"); diff --git a/sound/soc/samsung/s3c24xx_uda134x.c b/sound/soc/samsung/s3c24xx_uda134x.c index 3cb7007510781..dc9d551f6788d 100644 --- a/sound/soc/samsung/s3c24xx_uda134x.c +++ b/sound/soc/samsung/s3c24xx_uda134x.c @@ -219,7 +219,7 @@ static struct snd_soc_ops s3c24xx_uda134x_ops = { static struct snd_soc_dai_link s3c24xx_uda134x_dai_link = { .name = "UDA134X", .stream_name = "UDA134X", - .codec_name = "uda134x-hifi", + .codec_name = "uda134x-codec", .codec_dai_name = "uda134x-hifi", .cpu_dai_name = "s3c24xx-iis", .ops = &s3c24xx_uda134x_ops, @@ -314,6 +314,7 @@ static int s3c24xx_uda134x_probe(struct platform_device *pdev) platform_set_drvdata(s3c24xx_uda134x_snd_device, &snd_soc_s3c24xx_uda134x); + platform_device_add_data(s3c24xx_uda134x_snd_device, &s3c24xx_uda134x, sizeof(s3c24xx_uda134x)); ret = platform_device_add(s3c24xx_uda134x_snd_device); if (ret) { printk(KERN_ERR "S3C24XX_UDA134X SoC Audio: Unable to add\n"); -- GitLab From e7a12b6406a478b5c9085091b5015cb3e1683958 Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Thu, 24 Feb 2011 09:02:28 +0200 Subject: [PATCH 0504/2822] OMAP: 3430SDP: Remove unused vdda_dac supply Remove extra vdda_dac supply definition. It was a leftover from conflict resolution. Signed-off-by: Tomi Valkeinen --- arch/arm/mach-omap2/board-3430sdp.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/arch/arm/mach-omap2/board-3430sdp.c b/arch/arm/mach-omap2/board-3430sdp.c index 5464bec156ada..e018472861e66 100644 --- a/arch/arm/mach-omap2/board-3430sdp.c +++ b/arch/arm/mach-omap2/board-3430sdp.c @@ -307,9 +307,6 @@ static struct omap_dss_board_info sdp3430_dss_data = { .default_device = &sdp3430_lcd_device, }; -static struct regulator_consumer_supply sdp3430_vdda_dac_supply = - REGULATOR_SUPPLY("vdda_dac", "omapdss"); - static struct omap_board_config_kernel sdp3430_config[] __initdata = { }; -- GitLab From 8ba775ca0d375ab42404ffd7a1a38326a7b21321 Mon Sep 17 00:00:00 2001 From: Sumit Semwal Date: Mon, 24 Jan 2011 06:21:48 +0000 Subject: [PATCH 0505/2822] OMAP2, 3: DSS2: remove forced clk-disable from omap_dss_remove As part of omap hwmod changes, DSS will not be the only controller of its clocks. hwmod initialization also enables the interface clocks, and manages them. So, when DSS is built as a module, omap_dss_remove doesn't try to disable all clocks that have a higher usecount. Reviewed-by: Kevin Hilman Tested-by: Kevin Hilman Signed-off-by: Sumit Semwal Signed-off-by: Tomi Valkeinen --- drivers/video/omap2/dss/core.c | 46 ++++++---------------------------- 1 file changed, 7 insertions(+), 39 deletions(-) diff --git a/drivers/video/omap2/dss/core.c b/drivers/video/omap2/dss/core.c index 8e89f60492809..ee56859c52ce0 100644 --- a/drivers/video/omap2/dss/core.c +++ b/drivers/video/omap2/dss/core.c @@ -623,7 +623,6 @@ static int omap_dss_remove(struct platform_device *pdev) { struct omap_dss_board_info *pdata = pdev->dev.platform_data; int i; - int c; dss_uninitialize_debugfs(); @@ -638,44 +637,13 @@ static int omap_dss_remove(struct platform_device *pdev) dss_exit(); - /* these should be removed at some point */ - c = core.dss_ick->usecount; - if (c > 0) { - DSSERR("warning: dss_ick usecount %d, disabling\n", c); - while (c-- > 0) - clk_disable(core.dss_ick); - } - - c = core.dss1_fck->usecount; - if (c > 0) { - DSSERR("warning: dss1_fck usecount %d, disabling\n", c); - while (c-- > 0) - clk_disable(core.dss1_fck); - } - - c = core.dss2_fck->usecount; - if (c > 0) { - DSSERR("warning: dss2_fck usecount %d, disabling\n", c); - while (c-- > 0) - clk_disable(core.dss2_fck); - } - - c = core.dss_54m_fck->usecount; - if (c > 0) { - DSSERR("warning: dss_54m_fck usecount %d, disabling\n", c); - while (c-- > 0) - clk_disable(core.dss_54m_fck); - } - - if (core.dss_96m_fck) { - c = core.dss_96m_fck->usecount; - if (c > 0) { - DSSERR("warning: dss_96m_fck usecount %d, disabling\n", - c); - while (c-- > 0) - clk_disable(core.dss_96m_fck); - } - } + /* + * As part of hwmod changes, DSS is not the only controller of dss + * clocks; hwmod framework itself will also enable clocks during hwmod + * init for dss, and autoidle is set in h/w for DSS. Hence, there's no + * need to disable clocks if their usecounts > 1. + */ + WARN_ON(core.num_clks_enabled > 0); dss_put_clocks(); -- GitLab From cf07f5316215972e987c63b0a75a922c89813781 Mon Sep 17 00:00:00 2001 From: Senthilvadivu Guruswamy Date: Mon, 24 Jan 2011 06:21:56 +0000 Subject: [PATCH 0506/2822] OMAP2,3: DSS2: Build omap_device for each DSS HWIP Looks up the hwmod database for each of the given DSS HW IP and builds omap_device which inturn does the platform device register for each of DSS HW IP Signed-off-by: Senthilvadivu Guruswamy Signed-off-by: Sumit Semwal Signed-off-by: Tomi Valkeinen --- arch/arm/mach-omap2/display.c | 52 +++++++++++++++++++++++ arch/arm/plat-omap/include/plat/display.h | 5 +++ 2 files changed, 57 insertions(+) diff --git a/arch/arm/mach-omap2/display.c b/arch/arm/mach-omap2/display.c index b18db84b03497..ee8303037d3df 100644 --- a/arch/arm/mach-omap2/display.c +++ b/arch/arm/mach-omap2/display.c @@ -23,6 +23,8 @@ #include #include +#include +#include static struct platform_device omap_display_device = { .name = "omapdss", @@ -32,9 +34,59 @@ static struct platform_device omap_display_device = { }, }; +static struct omap_device_pm_latency omap_dss_latency[] = { + [0] = { + .deactivate_func = omap_device_idle_hwmods, + .activate_func = omap_device_enable_hwmods, + .flags = OMAP_DEVICE_LATENCY_AUTO_ADJUST, + }, +}; + int __init omap_display_init(struct omap_dss_board_info *board_data) { int r = 0; + struct omap_hwmod *oh; + struct omap_device *od; + int i; + struct omap_display_platform_data pdata; + + /* + * omap: valid DSS hwmod names + * omap2,3: dss_core, dss_dispc, dss_rfbi, dss_venc + * omap3: dss_dsi1 + */ + char *oh_name[] = { "dss_core", "dss_dispc", "dss_rfbi", "dss_venc", + "dss_dsi1" }; + char *dev_name[] = { "omapdss_dss", "omapdss_dispc", "omapdss_rfbi", + "omapdss_venc", "omapdss_dsi1" }; + int oh_count; + + memset(&pdata, 0, sizeof(pdata)); + + if (cpu_is_omap24xx()) + oh_count = ARRAY_SIZE(oh_name) - 1; + /* last hwmod dev in oh_name is not available for omap2 */ + else + oh_count = ARRAY_SIZE(oh_name); + + pdata.board_data = board_data; + pdata.board_data->get_last_off_on_transaction_id = NULL; + + for (i = 0; i < oh_count; i++) { + oh = omap_hwmod_lookup(oh_name[i]); + if (!oh) { + pr_err("Could not look up %s\n", oh_name[i]); + return -ENODEV; + } + od = omap_device_build(dev_name[i], -1, oh, &pdata, + sizeof(struct omap_display_platform_data), + omap_dss_latency, + ARRAY_SIZE(omap_dss_latency), 0); + + if (WARN((IS_ERR(od)), "Could not build omap_device for %s\n", + oh_name[i])) + return -ENODEV; + } omap_display_device.dev.platform_data = board_data; r = platform_device_register(&omap_display_device); diff --git a/arch/arm/plat-omap/include/plat/display.h b/arch/arm/plat-omap/include/plat/display.h index 0f140ecedb01d..2fb057e1cb98b 100644 --- a/arch/arm/plat-omap/include/plat/display.h +++ b/arch/arm/plat-omap/include/plat/display.h @@ -237,6 +237,11 @@ static inline int omap_display_init(struct omap_dss_board_info *board_data) } #endif +struct omap_display_platform_data { + struct omap_dss_board_info *board_data; + /* TODO: Additional members to be added when PM is considered */ +}; + struct omap_video_timings { /* Unit: pixels */ u16 x_res; -- GitLab From 96c401bcb83a182a4f332f2f64ee6530ba35511a Mon Sep 17 00:00:00 2001 From: Senthilvadivu Guruswamy Date: Mon, 24 Jan 2011 06:21:57 +0000 Subject: [PATCH 0507/2822] OMAP2, 3: DSS2: DSS: create platform_driver, move init, exit to driver Hwmod adaptation design requires each of the DSS HW IP to be a platform driver. So a platform_driver of DSS is created and init exit methods are moved from core.c to its driver probe,remove. pdev member has to be maintained by its own drivers. DSS platform driver is registered from inside omap_dss_probe, in the order desired. Signed-off-by: Senthilvadivu Guruswamy Signed-off-by: Sumit Semwal Signed-off-by: Tomi Valkeinen --- drivers/video/omap2/dss/core.c | 19 ++++++------ drivers/video/omap2/dss/dss.c | 55 ++++++++++++++++++++++++++++++++-- drivers/video/omap2/dss/dss.h | 4 +-- 3 files changed, 64 insertions(+), 14 deletions(-) diff --git a/drivers/video/omap2/dss/core.c b/drivers/video/omap2/dss/core.c index ee56859c52ce0..e399ca22e514c 100644 --- a/drivers/video/omap2/dss/core.c +++ b/drivers/video/omap2/dss/core.c @@ -517,15 +517,9 @@ static int omap_dss_probe(struct platform_device *pdev) core.ctx_id = dss_get_ctx_id(); DSSDBG("initial ctx id %u\n", core.ctx_id); -#ifdef CONFIG_FB_OMAP_BOOTLOADER_INIT - /* DISPC_CONTROL */ - if (omap_readl(0x48050440) & 1) /* LCD enabled? */ - skip_init = 1; -#endif - - r = dss_init(skip_init); + r = dss_init_platform_driver(); if (r) { - DSSERR("Failed to initialize DSS\n"); + DSSERR("Failed to initialize DSS platform driver\n"); goto err_dss; } @@ -553,6 +547,11 @@ static int omap_dss_probe(struct platform_device *pdev) goto err_venc; } +#ifdef CONFIG_FB_OMAP_BOOTLOADER_INIT + /* DISPC_CONTROL */ + if (omap_readl(0x48050440) & 1) /* LCD enabled? */ + skip_init = 1; +#endif if (cpu_is_omap34xx()) { r = sdi_init(skip_init); if (r) { @@ -610,7 +609,7 @@ err_dispc: err_dpi: rfbi_exit(); err_rfbi: - dss_exit(); + dss_uninit_platform_driver(); err_dss: dss_clk_disable_all_no_ctx(); dss_put_clocks(); @@ -635,7 +634,7 @@ static int omap_dss_remove(struct platform_device *pdev) sdi_exit(); } - dss_exit(); + dss_uninit_platform_driver(); /* * As part of hwmod changes, DSS is not the only controller of dss diff --git a/drivers/video/omap2/dss/dss.c b/drivers/video/omap2/dss/dss.c index 77c3621c91718..01406f48f438e 100644 --- a/drivers/video/omap2/dss/dss.c +++ b/drivers/video/omap2/dss/dss.c @@ -59,6 +59,7 @@ struct dss_reg { dss_write_reg(idx, FLD_MOD(dss_read_reg(idx), val, start, end)) static struct { + struct platform_device *pdev; void __iomem *base; struct clk *dpll4_m4_ck; @@ -549,7 +550,7 @@ void dss_set_dac_pwrdn_bgz(bool enable) REG_FLD_MOD(DSS_CONTROL, enable, 5, 5); /* DAC Power-Down Control */ } -int dss_init(bool skip_init) +static int dss_init(bool skip_init) { int r; u32 rev; @@ -629,7 +630,7 @@ fail0: return r; } -void dss_exit(void) +static void dss_exit(void) { if (cpu_is_omap34xx()) clk_put(dss.dpll4_m4_ck); @@ -639,3 +640,53 @@ void dss_exit(void) iounmap(dss.base); } +/* DSS HW IP initialisation */ +static int omap_dsshw_probe(struct platform_device *pdev) +{ + int r; + int skip_init = 0; + + dss.pdev = pdev; + +#ifdef CONFIG_FB_OMAP_BOOTLOADER_INIT + /* DISPC_CONTROL */ + if (omap_readl(0x48050440) & 1) /* LCD enabled? */ + skip_init = 1; +#endif + + r = dss_init(skip_init); + if (r) { + DSSERR("Failed to initialize DSS\n"); + goto err_dss; + } + +err_dss: + + return r; +} + +static int omap_dsshw_remove(struct platform_device *pdev) +{ + dss_exit(); + + return 0; +} + +static struct platform_driver omap_dsshw_driver = { + .probe = omap_dsshw_probe, + .remove = omap_dsshw_remove, + .driver = { + .name = "omapdss_dss", + .owner = THIS_MODULE, + }, +}; + +int dss_init_platform_driver(void) +{ + return platform_driver_register(&omap_dsshw_driver); +} + +void dss_uninit_platform_driver(void) +{ + return platform_driver_unregister(&omap_dsshw_driver); +} diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h index b394951120ac3..37c4544e89072 100644 --- a/drivers/video/omap2/dss/dss.h +++ b/drivers/video/omap2/dss/dss.h @@ -214,8 +214,8 @@ void dss_overlay_setup_l4_manager(struct omap_overlay_manager *mgr); void dss_recheck_connections(struct omap_dss_device *dssdev, bool force); /* DSS */ -int dss_init(bool skip_init); -void dss_exit(void); +int dss_init_platform_driver(void); +void dss_uninit_platform_driver(void); void dss_save_context(void); void dss_restore_context(void); -- GitLab From 8b9cb3a8f39d0864c925c5cd5c2c54cfd85ad551 Mon Sep 17 00:00:00 2001 From: Senthilvadivu Guruswamy Date: Mon, 24 Jan 2011 06:21:58 +0000 Subject: [PATCH 0508/2822] OMAP2, 3: DSS2: Move clocks from core driver to dss driver All clock management is moved to dss platform driver. clk_get/put APIs use dss device instead of core platform device. Hwmod adaptation design requires each of the DSS HW IP to be a platform driver. So the device name is changed from omapdss to omapdss_dss in 2420, 2430, 3xxx clock database files. Now the core driver "omapdss" only takes care of panel registration with the custom bus. core driver also uses the clk_enable() / clk_disable() APIs exposed by DSS for clock management. DSS driver would do clock management of clocks needed by DISPC, RFBI, DSI, VENC TODO: The clock content would be adapted to omap_hwmod in a seperate series. Signed-off-by: Senthilvadivu Guruswamy Signed-off-by: Sumit Semwal Signed-off-by: Tomi Valkeinen --- arch/arm/mach-omap2/clock2420_data.c | 8 +- arch/arm/mach-omap2/clock2430_data.c | 8 +- arch/arm/mach-omap2/clock3xxx_data.c | 14 +- drivers/video/omap2/dss/core.c | 343 +-------------------------- drivers/video/omap2/dss/dss.c | 334 +++++++++++++++++++++++++- drivers/video/omap2/dss/dss.h | 13 +- 6 files changed, 360 insertions(+), 360 deletions(-) diff --git a/arch/arm/mach-omap2/clock2420_data.c b/arch/arm/mach-omap2/clock2420_data.c index 0a992bc8d0d89..9ece62a44a3f6 100644 --- a/arch/arm/mach-omap2/clock2420_data.c +++ b/arch/arm/mach-omap2/clock2420_data.c @@ -1786,10 +1786,10 @@ static struct omap_clk omap2420_clks[] = { CLK(NULL, "gfx_2d_fck", &gfx_2d_fck, CK_242X), CLK(NULL, "gfx_ick", &gfx_ick, CK_242X), /* DSS domain clocks */ - CLK("omapdss", "ick", &dss_ick, CK_242X), - CLK("omapdss", "dss1_fck", &dss1_fck, CK_242X), - CLK("omapdss", "dss2_fck", &dss2_fck, CK_242X), - CLK("omapdss", "tv_fck", &dss_54m_fck, CK_242X), + CLK("omapdss_dss", "ick", &dss_ick, CK_242X), + CLK("omapdss_dss", "dss1_fck", &dss1_fck, CK_242X), + CLK("omapdss_dss", "dss2_fck", &dss2_fck, CK_242X), + CLK("omapdss_dss", "tv_fck", &dss_54m_fck, CK_242X), /* L3 domain clocks */ CLK(NULL, "core_l3_ck", &core_l3_ck, CK_242X), CLK(NULL, "ssi_fck", &ssi_ssr_sst_fck, CK_242X), diff --git a/arch/arm/mach-omap2/clock2430_data.c b/arch/arm/mach-omap2/clock2430_data.c index 5c647ce05b042..61006ae7eac42 100644 --- a/arch/arm/mach-omap2/clock2430_data.c +++ b/arch/arm/mach-omap2/clock2430_data.c @@ -1890,10 +1890,10 @@ static struct omap_clk omap2430_clks[] = { CLK(NULL, "mdm_ick", &mdm_ick, CK_243X), CLK(NULL, "mdm_osc_ck", &mdm_osc_ck, CK_243X), /* DSS domain clocks */ - CLK("omapdss", "ick", &dss_ick, CK_243X), - CLK("omapdss", "dss1_fck", &dss1_fck, CK_243X), - CLK("omapdss", "dss2_fck", &dss2_fck, CK_243X), - CLK("omapdss", "tv_fck", &dss_54m_fck, CK_243X), + CLK("omapdss_dss", "ick", &dss_ick, CK_243X), + CLK("omapdss_dss", "dss1_fck", &dss1_fck, CK_243X), + CLK("omapdss_dss", "dss2_fck", &dss2_fck, CK_243X), + CLK("omapdss_dss", "tv_fck", &dss_54m_fck, CK_243X), /* L3 domain clocks */ CLK(NULL, "core_l3_ck", &core_l3_ck, CK_243X), CLK(NULL, "ssi_fck", &ssi_ssr_sst_fck, CK_243X), diff --git a/arch/arm/mach-omap2/clock3xxx_data.c b/arch/arm/mach-omap2/clock3xxx_data.c index 052ac329282f5..2e47d16fce77a 100644 --- a/arch/arm/mach-omap2/clock3xxx_data.c +++ b/arch/arm/mach-omap2/clock3xxx_data.c @@ -3357,13 +3357,13 @@ static struct omap_clk omap3xxx_clks[] = { CLK("omap_rng", "ick", &rng_ick, CK_34XX | CK_36XX), CLK(NULL, "sha11_ick", &sha11_ick, CK_34XX | CK_36XX), CLK(NULL, "des1_ick", &des1_ick, CK_34XX | CK_36XX), - CLK("omapdss", "dss1_fck", &dss1_alwon_fck_3430es1, CK_3430ES1), - CLK("omapdss", "dss1_fck", &dss1_alwon_fck_3430es2, CK_3430ES2PLUS | CK_AM35XX | CK_36XX), - CLK("omapdss", "tv_fck", &dss_tv_fck, CK_3XXX), - CLK("omapdss", "video_fck", &dss_96m_fck, CK_3XXX), - CLK("omapdss", "dss2_fck", &dss2_alwon_fck, CK_3XXX), - CLK("omapdss", "ick", &dss_ick_3430es1, CK_3430ES1), - CLK("omapdss", "ick", &dss_ick_3430es2, CK_3430ES2PLUS | CK_AM35XX | CK_36XX), + CLK("omapdss_dss", "dss1_fck", &dss1_alwon_fck_3430es1, CK_3430ES1), + CLK("omapdss_dss", "dss1_fck", &dss1_alwon_fck_3430es2, CK_3430ES2PLUS | CK_AM35XX | CK_36XX), + CLK("omapdss_dss", "tv_fck", &dss_tv_fck, CK_3XXX), + CLK("omapdss_dss", "video_fck", &dss_96m_fck, CK_3XXX), + CLK("omapdss_dss", "dss2_fck", &dss2_alwon_fck, CK_3XXX), + CLK("omapdss_dss", "ick", &dss_ick_3430es1, CK_3430ES1), + CLK("omapdss_dss", "ick", &dss_ick_3430es2, CK_3430ES2PLUS | CK_AM35XX | CK_36XX), CLK(NULL, "cam_mclk", &cam_mclk, CK_34XX | CK_36XX), CLK(NULL, "cam_ick", &cam_ick, CK_34XX | CK_36XX), CLK(NULL, "csi2_96m_fck", &csi2_96m_fck, CK_34XX | CK_36XX), diff --git a/drivers/video/omap2/dss/core.c b/drivers/video/omap2/dss/core.c index e399ca22e514c..255935541d0d3 100644 --- a/drivers/video/omap2/dss/core.c +++ b/drivers/video/omap2/dss/core.c @@ -34,32 +34,18 @@ #include #include -#include #include "dss.h" #include "dss_features.h" static struct { struct platform_device *pdev; - int ctx_id; - - struct clk *dss_ick; - struct clk *dss1_fck; - struct clk *dss2_fck; - struct clk *dss_54m_fck; - struct clk *dss_96m_fck; - unsigned num_clks_enabled; struct regulator *vdds_dsi_reg; struct regulator *vdds_sdi_reg; struct regulator *vdda_dac_reg; } core; -static void dss_clk_enable_all_no_ctx(void); -static void dss_clk_disable_all_no_ctx(void); -static void dss_clk_enable_no_ctx(enum dss_clock clks); -static void dss_clk_disable_no_ctx(enum dss_clock clks); - static char *def_disp_name; module_param_named(def_disp, def_disp_name, charp, 0); MODULE_PARM_DESC(def_disp_name, "default display name"); @@ -69,297 +55,6 @@ unsigned int dss_debug; module_param_named(debug, dss_debug, bool, 0644); #endif -/* CONTEXT */ -static int dss_get_ctx_id(void) -{ - struct omap_dss_board_info *pdata = core.pdev->dev.platform_data; - int r; - - if (!pdata->get_last_off_on_transaction_id) - return 0; - r = pdata->get_last_off_on_transaction_id(&core.pdev->dev); - if (r < 0) { - dev_err(&core.pdev->dev, "getting transaction ID failed, " - "will force context restore\n"); - r = -1; - } - return r; -} - -int dss_need_ctx_restore(void) -{ - int id = dss_get_ctx_id(); - - if (id < 0 || id != core.ctx_id) { - DSSDBG("ctx id %d -> id %d\n", - core.ctx_id, id); - core.ctx_id = id; - return 1; - } else { - return 0; - } -} - -static void save_all_ctx(void) -{ - DSSDBG("save context\n"); - - dss_clk_enable_no_ctx(DSS_CLK_ICK | DSS_CLK_FCK1); - - dss_save_context(); - dispc_save_context(); -#ifdef CONFIG_OMAP2_DSS_DSI - dsi_save_context(); -#endif - - dss_clk_disable_no_ctx(DSS_CLK_ICK | DSS_CLK_FCK1); -} - -static void restore_all_ctx(void) -{ - DSSDBG("restore context\n"); - - dss_clk_enable_all_no_ctx(); - - dss_restore_context(); - dispc_restore_context(); -#ifdef CONFIG_OMAP2_DSS_DSI - dsi_restore_context(); -#endif - - dss_clk_disable_all_no_ctx(); -} - -#if defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT) -/* CLOCKS */ -static void core_dump_clocks(struct seq_file *s) -{ - int i; - struct clk *clocks[5] = { - core.dss_ick, - core.dss1_fck, - core.dss2_fck, - core.dss_54m_fck, - core.dss_96m_fck - }; - - seq_printf(s, "- CORE -\n"); - - seq_printf(s, "internal clk count\t\t%u\n", core.num_clks_enabled); - - for (i = 0; i < 5; i++) { - if (!clocks[i]) - continue; - seq_printf(s, "%-15s\t%lu\t%d\n", - clocks[i]->name, - clk_get_rate(clocks[i]), - clocks[i]->usecount); - } -} -#endif /* defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT) */ - -static int dss_get_clock(struct clk **clock, const char *clk_name) -{ - struct clk *clk; - - clk = clk_get(&core.pdev->dev, clk_name); - - if (IS_ERR(clk)) { - DSSERR("can't get clock %s", clk_name); - return PTR_ERR(clk); - } - - *clock = clk; - - DSSDBG("clk %s, rate %ld\n", clk_name, clk_get_rate(clk)); - - return 0; -} - -static int dss_get_clocks(void) -{ - int r; - - core.dss_ick = NULL; - core.dss1_fck = NULL; - core.dss2_fck = NULL; - core.dss_54m_fck = NULL; - core.dss_96m_fck = NULL; - - r = dss_get_clock(&core.dss_ick, "ick"); - if (r) - goto err; - - r = dss_get_clock(&core.dss1_fck, "dss1_fck"); - if (r) - goto err; - - r = dss_get_clock(&core.dss2_fck, "dss2_fck"); - if (r) - goto err; - - r = dss_get_clock(&core.dss_54m_fck, "tv_fck"); - if (r) - goto err; - - r = dss_get_clock(&core.dss_96m_fck, "video_fck"); - if (r) - goto err; - - return 0; - -err: - if (core.dss_ick) - clk_put(core.dss_ick); - if (core.dss1_fck) - clk_put(core.dss1_fck); - if (core.dss2_fck) - clk_put(core.dss2_fck); - if (core.dss_54m_fck) - clk_put(core.dss_54m_fck); - if (core.dss_96m_fck) - clk_put(core.dss_96m_fck); - - return r; -} - -static void dss_put_clocks(void) -{ - if (core.dss_96m_fck) - clk_put(core.dss_96m_fck); - clk_put(core.dss_54m_fck); - clk_put(core.dss1_fck); - clk_put(core.dss2_fck); - clk_put(core.dss_ick); -} - -unsigned long dss_clk_get_rate(enum dss_clock clk) -{ - switch (clk) { - case DSS_CLK_ICK: - return clk_get_rate(core.dss_ick); - case DSS_CLK_FCK1: - return clk_get_rate(core.dss1_fck); - case DSS_CLK_FCK2: - return clk_get_rate(core.dss2_fck); - case DSS_CLK_54M: - return clk_get_rate(core.dss_54m_fck); - case DSS_CLK_96M: - return clk_get_rate(core.dss_96m_fck); - } - - BUG(); - return 0; -} - -static unsigned count_clk_bits(enum dss_clock clks) -{ - unsigned num_clks = 0; - - if (clks & DSS_CLK_ICK) - ++num_clks; - if (clks & DSS_CLK_FCK1) - ++num_clks; - if (clks & DSS_CLK_FCK2) - ++num_clks; - if (clks & DSS_CLK_54M) - ++num_clks; - if (clks & DSS_CLK_96M) - ++num_clks; - - return num_clks; -} - -static void dss_clk_enable_no_ctx(enum dss_clock clks) -{ - unsigned num_clks = count_clk_bits(clks); - - if (clks & DSS_CLK_ICK) - clk_enable(core.dss_ick); - if (clks & DSS_CLK_FCK1) - clk_enable(core.dss1_fck); - if (clks & DSS_CLK_FCK2) - clk_enable(core.dss2_fck); - if (clks & DSS_CLK_54M) - clk_enable(core.dss_54m_fck); - if (clks & DSS_CLK_96M) - clk_enable(core.dss_96m_fck); - - core.num_clks_enabled += num_clks; -} - -void dss_clk_enable(enum dss_clock clks) -{ - bool check_ctx = core.num_clks_enabled == 0; - - dss_clk_enable_no_ctx(clks); - - if (check_ctx && cpu_is_omap34xx() && dss_need_ctx_restore()) - restore_all_ctx(); -} - -static void dss_clk_disable_no_ctx(enum dss_clock clks) -{ - unsigned num_clks = count_clk_bits(clks); - - if (clks & DSS_CLK_ICK) - clk_disable(core.dss_ick); - if (clks & DSS_CLK_FCK1) - clk_disable(core.dss1_fck); - if (clks & DSS_CLK_FCK2) - clk_disable(core.dss2_fck); - if (clks & DSS_CLK_54M) - clk_disable(core.dss_54m_fck); - if (clks & DSS_CLK_96M) - clk_disable(core.dss_96m_fck); - - core.num_clks_enabled -= num_clks; -} - -void dss_clk_disable(enum dss_clock clks) -{ - if (cpu_is_omap34xx()) { - unsigned num_clks = count_clk_bits(clks); - - BUG_ON(core.num_clks_enabled < num_clks); - - if (core.num_clks_enabled == num_clks) - save_all_ctx(); - } - - dss_clk_disable_no_ctx(clks); -} - -static void dss_clk_enable_all_no_ctx(void) -{ - enum dss_clock clks; - - clks = DSS_CLK_ICK | DSS_CLK_FCK1 | DSS_CLK_FCK2 | DSS_CLK_54M; - if (cpu_is_omap34xx()) - clks |= DSS_CLK_96M; - dss_clk_enable_no_ctx(clks); -} - -static void dss_clk_disable_all_no_ctx(void) -{ - enum dss_clock clks; - - clks = DSS_CLK_ICK | DSS_CLK_FCK1 | DSS_CLK_FCK2 | DSS_CLK_54M; - if (cpu_is_omap34xx()) - clks |= DSS_CLK_96M; - dss_clk_disable_no_ctx(clks); -} - -static void dss_clk_disable_all(void) -{ - enum dss_clock clks; - - clks = DSS_CLK_ICK | DSS_CLK_FCK1 | DSS_CLK_FCK2 | DSS_CLK_54M; - if (cpu_is_omap34xx()) - clks |= DSS_CLK_96M; - dss_clk_disable(clks); -} - /* REGULATORS */ struct regulator *dss_get_vdds_dsi(void) @@ -404,18 +99,7 @@ struct regulator *dss_get_vdda_dac(void) return reg; } -/* DEBUGFS */ #if defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT) -static void dss_debug_dump_clocks(struct seq_file *s) -{ - core_dump_clocks(s); - dss_dump_clocks(s); - dispc_dump_clocks(s); -#ifdef CONFIG_OMAP2_DSS_DSI - dsi_dump_clocks(s); -#endif -} - static int dss_debug_show(struct seq_file *s, void *unused) { void (*func)(struct seq_file *) = s->private; @@ -508,21 +192,15 @@ static int omap_dss_probe(struct platform_device *pdev) dss_init_overlay_managers(pdev); dss_init_overlays(pdev); - r = dss_get_clocks(); - if (r) - goto err_clocks; - - dss_clk_enable_all_no_ctx(); - - core.ctx_id = dss_get_ctx_id(); - DSSDBG("initial ctx id %u\n", core.ctx_id); - r = dss_init_platform_driver(); if (r) { DSSERR("Failed to initialize DSS platform driver\n"); goto err_dss; } + /* keep clocks enabled to prevent context saves/restores during init */ + dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1); + r = rfbi_init(); if (r) { DSSERR("Failed to initialize rfbi\n"); @@ -588,7 +266,7 @@ static int omap_dss_probe(struct platform_device *pdev) pdata->default_device = dssdev; } - dss_clk_disable_all(); + dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1); return 0; @@ -611,9 +289,6 @@ err_dpi: err_rfbi: dss_uninit_platform_driver(); err_dss: - dss_clk_disable_all_no_ctx(); - dss_put_clocks(); -err_clocks: return r; } @@ -636,16 +311,6 @@ static int omap_dss_remove(struct platform_device *pdev) dss_uninit_platform_driver(); - /* - * As part of hwmod changes, DSS is not the only controller of dss - * clocks; hwmod framework itself will also enable clocks during hwmod - * init for dss, and autoidle is set in h/w for DSS. Hence, there's no - * need to disable clocks if their usecounts > 1. - */ - WARN_ON(core.num_clks_enabled > 0); - - dss_put_clocks(); - dss_uninit_overlays(pdev); dss_uninit_overlay_managers(pdev); diff --git a/drivers/video/omap2/dss/dss.c b/drivers/video/omap2/dss/dss.c index 01406f48f438e..72b395d69aaeb 100644 --- a/drivers/video/omap2/dss/dss.c +++ b/drivers/video/omap2/dss/dss.c @@ -31,6 +31,7 @@ #include #include +#include #include "dss.h" #define DSS_BASE 0x48050000 @@ -61,8 +62,15 @@ struct dss_reg { static struct { struct platform_device *pdev; void __iomem *base; + int ctx_id; struct clk *dpll4_m4_ck; + struct clk *dss_ick; + struct clk *dss1_fck; + struct clk *dss2_fck; + struct clk *dss_54m_fck; + struct clk *dss_96m_fck; + unsigned num_clks_enabled; unsigned long cache_req_pck; unsigned long cache_prate; @@ -75,6 +83,11 @@ static struct { u32 ctx[DSS_SZ_REGS / sizeof(u32)]; } dss; +static void dss_clk_enable_all_no_ctx(void); +static void dss_clk_disable_all_no_ctx(void); +static void dss_clk_enable_no_ctx(enum dss_clock clks); +static void dss_clk_disable_no_ctx(enum dss_clock clks); + static int _omap_dss_wait_reset(void); static inline void dss_write_reg(const struct dss_reg idx, u32 val) @@ -640,6 +653,301 @@ static void dss_exit(void) iounmap(dss.base); } +/* CONTEXT */ +static int dss_get_ctx_id(void) +{ + struct omap_display_platform_data *pdata = dss.pdev->dev.platform_data; + int r; + + if (!pdata->board_data->get_last_off_on_transaction_id) + return 0; + r = pdata->board_data->get_last_off_on_transaction_id(&dss.pdev->dev); + if (r < 0) { + dev_err(&dss.pdev->dev, "getting transaction ID failed, " + "will force context restore\n"); + r = -1; + } + return r; +} + +int dss_need_ctx_restore(void) +{ + int id = dss_get_ctx_id(); + + if (id < 0 || id != dss.ctx_id) { + DSSDBG("ctx id %d -> id %d\n", + dss.ctx_id, id); + dss.ctx_id = id; + return 1; + } else { + return 0; + } +} + +static void save_all_ctx(void) +{ + DSSDBG("save context\n"); + + dss_clk_enable_no_ctx(DSS_CLK_ICK | DSS_CLK_FCK1); + + dss_save_context(); + dispc_save_context(); +#ifdef CONFIG_OMAP2_DSS_DSI + dsi_save_context(); +#endif + + dss_clk_disable_no_ctx(DSS_CLK_ICK | DSS_CLK_FCK1); +} + +static void restore_all_ctx(void) +{ + DSSDBG("restore context\n"); + + dss_clk_enable_all_no_ctx(); + + dss_restore_context(); + dispc_restore_context(); +#ifdef CONFIG_OMAP2_DSS_DSI + dsi_restore_context(); +#endif + + dss_clk_disable_all_no_ctx(); +} + +static int dss_get_clock(struct clk **clock, const char *clk_name) +{ + struct clk *clk; + + clk = clk_get(&dss.pdev->dev, clk_name); + + if (IS_ERR(clk)) { + DSSERR("can't get clock %s", clk_name); + return PTR_ERR(clk); + } + + *clock = clk; + + DSSDBG("clk %s, rate %ld\n", clk_name, clk_get_rate(clk)); + + return 0; +} + +static int dss_get_clocks(void) +{ + int r; + + dss.dss_ick = NULL; + dss.dss1_fck = NULL; + dss.dss2_fck = NULL; + dss.dss_54m_fck = NULL; + dss.dss_96m_fck = NULL; + + r = dss_get_clock(&dss.dss_ick, "ick"); + if (r) + goto err; + + r = dss_get_clock(&dss.dss1_fck, "dss1_fck"); + if (r) + goto err; + + r = dss_get_clock(&dss.dss2_fck, "dss2_fck"); + if (r) + goto err; + + r = dss_get_clock(&dss.dss_54m_fck, "tv_fck"); + if (r) + goto err; + + r = dss_get_clock(&dss.dss_96m_fck, "video_fck"); + if (r) + goto err; + + return 0; + +err: + if (dss.dss_ick) + clk_put(dss.dss_ick); + if (dss.dss1_fck) + clk_put(dss.dss1_fck); + if (dss.dss2_fck) + clk_put(dss.dss2_fck); + if (dss.dss_54m_fck) + clk_put(dss.dss_54m_fck); + if (dss.dss_96m_fck) + clk_put(dss.dss_96m_fck); + + return r; +} + +static void dss_put_clocks(void) +{ + if (dss.dss_96m_fck) + clk_put(dss.dss_96m_fck); + clk_put(dss.dss_54m_fck); + clk_put(dss.dss1_fck); + clk_put(dss.dss2_fck); + clk_put(dss.dss_ick); +} + +unsigned long dss_clk_get_rate(enum dss_clock clk) +{ + switch (clk) { + case DSS_CLK_ICK: + return clk_get_rate(dss.dss_ick); + case DSS_CLK_FCK1: + return clk_get_rate(dss.dss1_fck); + case DSS_CLK_FCK2: + return clk_get_rate(dss.dss2_fck); + case DSS_CLK_54M: + return clk_get_rate(dss.dss_54m_fck); + case DSS_CLK_96M: + return clk_get_rate(dss.dss_96m_fck); + } + + BUG(); + return 0; +} + +static unsigned count_clk_bits(enum dss_clock clks) +{ + unsigned num_clks = 0; + + if (clks & DSS_CLK_ICK) + ++num_clks; + if (clks & DSS_CLK_FCK1) + ++num_clks; + if (clks & DSS_CLK_FCK2) + ++num_clks; + if (clks & DSS_CLK_54M) + ++num_clks; + if (clks & DSS_CLK_96M) + ++num_clks; + + return num_clks; +} + +static void dss_clk_enable_no_ctx(enum dss_clock clks) +{ + unsigned num_clks = count_clk_bits(clks); + + if (clks & DSS_CLK_ICK) + clk_enable(dss.dss_ick); + if (clks & DSS_CLK_FCK1) + clk_enable(dss.dss1_fck); + if (clks & DSS_CLK_FCK2) + clk_enable(dss.dss2_fck); + if (clks & DSS_CLK_54M) + clk_enable(dss.dss_54m_fck); + if (clks & DSS_CLK_96M) + clk_enable(dss.dss_96m_fck); + + dss.num_clks_enabled += num_clks; +} + +void dss_clk_enable(enum dss_clock clks) +{ + bool check_ctx = dss.num_clks_enabled == 0; + + dss_clk_enable_no_ctx(clks); + + if (check_ctx && cpu_is_omap34xx() && dss_need_ctx_restore()) + restore_all_ctx(); +} + +static void dss_clk_disable_no_ctx(enum dss_clock clks) +{ + unsigned num_clks = count_clk_bits(clks); + + if (clks & DSS_CLK_ICK) + clk_disable(dss.dss_ick); + if (clks & DSS_CLK_FCK1) + clk_disable(dss.dss1_fck); + if (clks & DSS_CLK_FCK2) + clk_disable(dss.dss2_fck); + if (clks & DSS_CLK_54M) + clk_disable(dss.dss_54m_fck); + if (clks & DSS_CLK_96M) + clk_disable(dss.dss_96m_fck); + + dss.num_clks_enabled -= num_clks; +} + +void dss_clk_disable(enum dss_clock clks) +{ + if (cpu_is_omap34xx()) { + unsigned num_clks = count_clk_bits(clks); + + BUG_ON(dss.num_clks_enabled < num_clks); + + if (dss.num_clks_enabled == num_clks) + save_all_ctx(); + } + + dss_clk_disable_no_ctx(clks); +} + +static void dss_clk_enable_all_no_ctx(void) +{ + enum dss_clock clks; + + clks = DSS_CLK_ICK | DSS_CLK_FCK1 | DSS_CLK_FCK2 | DSS_CLK_54M; + if (cpu_is_omap34xx()) + clks |= DSS_CLK_96M; + dss_clk_enable_no_ctx(clks); +} + +static void dss_clk_disable_all_no_ctx(void) +{ + enum dss_clock clks; + + clks = DSS_CLK_ICK | DSS_CLK_FCK1 | DSS_CLK_FCK2 | DSS_CLK_54M; + if (cpu_is_omap34xx()) + clks |= DSS_CLK_96M; + dss_clk_disable_no_ctx(clks); +} + +#if defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT) +/* CLOCKS */ +static void core_dump_clocks(struct seq_file *s) +{ + int i; + struct clk *clocks[5] = { + dss.dss_ick, + dss.dss1_fck, + dss.dss2_fck, + dss.dss_54m_fck, + dss.dss_96m_fck + }; + + seq_printf(s, "- CORE -\n"); + + seq_printf(s, "internal clk count\t\t%u\n", dss.num_clks_enabled); + + for (i = 0; i < 5; i++) { + if (!clocks[i]) + continue; + seq_printf(s, "%-15s\t%lu\t%d\n", + clocks[i]->name, + clk_get_rate(clocks[i]), + clocks[i]->usecount); + } +} +#endif /* defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT) */ + +/* DEBUGFS */ +#if defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT) +void dss_debug_dump_clocks(struct seq_file *s) +{ + core_dump_clocks(s); + dss_dump_clocks(s); + dispc_dump_clocks(s); +#ifdef CONFIG_OMAP2_DSS_DSI + dsi_dump_clocks(s); +#endif +} +#endif + + /* DSS HW IP initialisation */ static int omap_dsshw_probe(struct platform_device *pdev) { @@ -648,6 +956,15 @@ static int omap_dsshw_probe(struct platform_device *pdev) dss.pdev = pdev; + r = dss_get_clocks(); + if (r) + goto err_clocks; + + dss_clk_enable_all_no_ctx(); + + dss.ctx_id = dss_get_ctx_id(); + DSSDBG("initial ctx id %u\n", dss.ctx_id); + #ifdef CONFIG_FB_OMAP_BOOTLOADER_INIT /* DISPC_CONTROL */ if (omap_readl(0x48050440) & 1) /* LCD enabled? */ @@ -660,15 +977,30 @@ static int omap_dsshw_probe(struct platform_device *pdev) goto err_dss; } -err_dss: + dss_clk_disable_all_no_ctx(); + return 0; +err_dss: + dss_clk_disable_all_no_ctx(); + dss_put_clocks(); +err_clocks: return r; } static int omap_dsshw_remove(struct platform_device *pdev) { + dss_exit(); + /* + * As part of hwmod changes, DSS is not the only controller of dss + * clocks; hwmod framework itself will also enable clocks during hwmod + * init for dss, and autoidle is set in h/w for DSS. Hence, there's no + * need to disable clocks if their usecounts > 1. + */ + WARN_ON(dss.num_clks_enabled > 0); + + dss_put_clocks(); return 0; } diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h index 37c4544e89072..c535ee1db3ee4 100644 --- a/drivers/video/omap2/dss/dss.h +++ b/drivers/video/omap2/dss/dss.h @@ -169,11 +169,6 @@ struct seq_file; struct platform_device; /* core */ -void dss_clk_enable(enum dss_clock clks); -void dss_clk_disable(enum dss_clock clks); -unsigned long dss_clk_get_rate(enum dss_clock clk); -int dss_need_ctx_restore(void); -void dss_dump_clocks(struct seq_file *s); struct bus_type *dss_get_bus(void); struct regulator *dss_get_vdds_dsi(void); struct regulator *dss_get_vdds_sdi(void); @@ -219,8 +214,16 @@ void dss_uninit_platform_driver(void); void dss_save_context(void); void dss_restore_context(void); +void dss_clk_enable(enum dss_clock clks); +void dss_clk_disable(enum dss_clock clks); +unsigned long dss_clk_get_rate(enum dss_clock clk); +int dss_need_ctx_restore(void); +void dss_dump_clocks(struct seq_file *s); void dss_dump_regs(struct seq_file *s); +#if defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT) +void dss_debug_dump_clocks(struct seq_file *s); +#endif void dss_sdi_init(u8 datapairs); int dss_sdi_enable(void); -- GitLab From 3448d500f7002a5ee374ec92d954b1667cbf72a4 Mon Sep 17 00:00:00 2001 From: Senthilvadivu Guruswamy Date: Mon, 24 Jan 2011 06:21:59 +0000 Subject: [PATCH 0509/2822] OMAP2, 3: DSS2: RFBI: create platform_driver, move init, exit to driver Hwmod adaptation design requires each of the DSS HW IP to be a platform driver. So a platform_driver for RFBI is created and init exit methods are moved from core.c to its driver probe,remove. pdev member has to be maintained by its own drivers. RFBI platform driver is registered from inside omap_dss_probe, in the order desired. Signed-off-by: Senthilvadivu Guruswamy Signed-off-by: Sumit Semwal Signed-off-by: Tomi Valkeinen --- drivers/video/omap2/dss/core.c | 8 +-- drivers/video/omap2/dss/dss.h | 8 +-- drivers/video/omap2/dss/rfbi.c | 110 ++++++++++++++++++++------------- 3 files changed, 74 insertions(+), 52 deletions(-) diff --git a/drivers/video/omap2/dss/core.c b/drivers/video/omap2/dss/core.c index 255935541d0d3..8eef616fee037 100644 --- a/drivers/video/omap2/dss/core.c +++ b/drivers/video/omap2/dss/core.c @@ -201,9 +201,9 @@ static int omap_dss_probe(struct platform_device *pdev) /* keep clocks enabled to prevent context saves/restores during init */ dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1); - r = rfbi_init(); + r = rfbi_init_platform_driver(); if (r) { - DSSERR("Failed to initialize rfbi\n"); + DSSERR("Failed to initialize rfbi platform driver\n"); goto err_rfbi; } @@ -285,7 +285,7 @@ err_venc: err_dispc: dpi_exit(); err_dpi: - rfbi_exit(); + rfbi_uninit_platform_driver(); err_rfbi: dss_uninit_platform_driver(); err_dss: @@ -303,7 +303,7 @@ static int omap_dss_remove(struct platform_device *pdev) venc_exit(); dispc_exit(); dpi_exit(); - rfbi_exit(); + rfbi_uninit_platform_driver(); if (cpu_is_omap34xx()) { dsi_exit(); sdi_exit(); diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h index c535ee1db3ee4..0ba4bdbd6b01a 100644 --- a/drivers/video/omap2/dss/dss.h +++ b/drivers/video/omap2/dss/dss.h @@ -428,8 +428,8 @@ static inline void venc_exit(void) /* RFBI */ #ifdef CONFIG_OMAP2_DSS_RFBI -int rfbi_init(void); -void rfbi_exit(void); +int rfbi_init_platform_driver(void); +void rfbi_uninit_platform_driver(void); void rfbi_dump_regs(struct seq_file *s); int rfbi_configure(int rfbi_module, int bpp, int lines); @@ -440,11 +440,11 @@ void rfbi_set_timings(int rfbi_module, struct rfbi_timings *t); unsigned long rfbi_get_max_tx_rate(void); int rfbi_init_display(struct omap_dss_device *display); #else -static inline int rfbi_init(void) +static inline int rfbi_init_platform_driver(void) { return 0; } -static inline void rfbi_exit(void) +static inline void rfbi_uninit_platform_driver(void) { } #endif diff --git a/drivers/video/omap2/dss/rfbi.c b/drivers/video/omap2/dss/rfbi.c index 10a2ffe02882e..153f963e8e893 100644 --- a/drivers/video/omap2/dss/rfbi.c +++ b/drivers/video/omap2/dss/rfbi.c @@ -100,6 +100,7 @@ static int rfbi_convert_timings(struct rfbi_timings *t); static void rfbi_get_clk_info(u32 *clk_period, u32 *max_clk_div); static struct { + struct platform_device *pdev; void __iomem *base; unsigned long l4_khz; @@ -957,50 +958,6 @@ void rfbi_dump_regs(struct seq_file *s) #undef DUMPREG } -int rfbi_init(void) -{ - u32 rev; - u32 l; - - spin_lock_init(&rfbi.cmd_lock); - - init_completion(&rfbi.cmd_done); - atomic_set(&rfbi.cmd_fifo_full, 0); - atomic_set(&rfbi.cmd_pending, 0); - - rfbi.base = ioremap(RFBI_BASE, SZ_256); - if (!rfbi.base) { - DSSERR("can't ioremap RFBI\n"); - return -ENOMEM; - } - - rfbi_enable_clocks(1); - - msleep(10); - - rfbi.l4_khz = dss_clk_get_rate(DSS_CLK_ICK) / 1000; - - /* Enable autoidle and smart-idle */ - l = rfbi_read_reg(RFBI_SYSCONFIG); - l |= (1 << 0) | (2 << 3); - rfbi_write_reg(RFBI_SYSCONFIG, l); - - rev = rfbi_read_reg(RFBI_REVISION); - printk(KERN_INFO "OMAP RFBI rev %d.%d\n", - FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0)); - - rfbi_enable_clocks(0); - - return 0; -} - -void rfbi_exit(void) -{ - DSSDBG("rfbi_exit\n"); - - iounmap(rfbi.base); -} - int omapdss_rfbi_display_enable(struct omap_dss_device *dssdev) { int r; @@ -1056,3 +1013,68 @@ int rfbi_init_display(struct omap_dss_device *dssdev) dssdev->caps = OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE; return 0; } + +/* RFBI HW IP initialisation */ +static int omap_rfbihw_probe(struct platform_device *pdev) +{ + u32 rev; + u32 l; + + rfbi.pdev = pdev; + + spin_lock_init(&rfbi.cmd_lock); + + init_completion(&rfbi.cmd_done); + atomic_set(&rfbi.cmd_fifo_full, 0); + atomic_set(&rfbi.cmd_pending, 0); + + rfbi.base = ioremap(RFBI_BASE, SZ_256); + if (!rfbi.base) { + DSSERR("can't ioremap RFBI\n"); + return -ENOMEM; + } + + rfbi_enable_clocks(1); + + msleep(10); + + rfbi.l4_khz = dss_clk_get_rate(DSS_CLK_ICK) / 1000; + + /* Enable autoidle and smart-idle */ + l = rfbi_read_reg(RFBI_SYSCONFIG); + l |= (1 << 0) | (2 << 3); + rfbi_write_reg(RFBI_SYSCONFIG, l); + + rev = rfbi_read_reg(RFBI_REVISION); + printk(KERN_INFO "OMAP RFBI rev %d.%d\n", + FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0)); + + rfbi_enable_clocks(0); + + return 0; +} + +static int omap_rfbihw_remove(struct platform_device *pdev) +{ + iounmap(rfbi.base); + return 0; +} + +static struct platform_driver omap_rfbihw_driver = { + .probe = omap_rfbihw_probe, + .remove = omap_rfbihw_remove, + .driver = { + .name = "omapdss_rfbi", + .owner = THIS_MODULE, + }, +}; + +int rfbi_init_platform_driver(void) +{ + return platform_driver_register(&omap_rfbihw_driver); +} + +void rfbi_uninit_platform_driver(void) +{ + return platform_driver_unregister(&omap_rfbihw_driver); +} -- GitLab From 060b6d9cbab03f1379dbe00393ab26d6eb371ce2 Mon Sep 17 00:00:00 2001 From: Senthilvadivu Guruswamy Date: Mon, 24 Jan 2011 06:22:00 +0000 Subject: [PATCH 0510/2822] OMAP2, 3: DSS2: DISPC: create platform_driver, move init, exit to driver Hwmod adaptation design requires each of the DSS HW IP to be a platform driver. So a platform_driver for DISPC is created and init exit methods are moved from core.c to its driver probe,remove. pdev member has to be maintained by its own drivers. DISPC platform driver is registered from inside omap_dss_probe, in the order desired. Signed-off-by: Senthilvadivu Guruswamy Signed-off-by: Sumit Semwal Signed-off-by: Tomi Valkeinen --- drivers/video/omap2/dss/core.c | 8 +-- drivers/video/omap2/dss/dispc.c | 105 +++++++++++++++++++------------- drivers/video/omap2/dss/dss.h | 4 +- 3 files changed, 70 insertions(+), 47 deletions(-) diff --git a/drivers/video/omap2/dss/core.c b/drivers/video/omap2/dss/core.c index 8eef616fee037..8b7eab83e4124 100644 --- a/drivers/video/omap2/dss/core.c +++ b/drivers/video/omap2/dss/core.c @@ -213,9 +213,9 @@ static int omap_dss_probe(struct platform_device *pdev) goto err_dpi; } - r = dispc_init(); + r = dispc_init_platform_driver(); if (r) { - DSSERR("Failed to initialize dispc\n"); + DSSERR("Failed to initialize dispc platform driver\n"); goto err_dispc; } @@ -281,7 +281,7 @@ err_dsi: err_sdi: venc_exit(); err_venc: - dispc_exit(); + dispc_uninit_platform_driver(); err_dispc: dpi_exit(); err_dpi: @@ -301,7 +301,7 @@ static int omap_dss_remove(struct platform_device *pdev) dss_uninitialize_debugfs(); venc_exit(); - dispc_exit(); + dispc_uninit_platform_driver(); dpi_exit(); rfbi_uninit_platform_driver(); if (cpu_is_omap34xx()) { diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c index 9f8c69f16e619..28ad68b6be481 100644 --- a/drivers/video/omap2/dss/dispc.c +++ b/drivers/video/omap2/dss/dispc.c @@ -178,6 +178,7 @@ struct dispc_irq_stats { }; static struct { + struct platform_device *pdev; void __iomem *base; u32 fifo_size[3]; @@ -3269,47 +3270,6 @@ static void _omap_dispc_initial_config(void) dispc_read_plane_fifo_sizes(); } -int dispc_init(void) -{ - u32 rev; - - spin_lock_init(&dispc.irq_lock); - -#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS - spin_lock_init(&dispc.irq_stats_lock); - dispc.irq_stats.last_reset = jiffies; -#endif - - INIT_WORK(&dispc.error_work, dispc_error_worker); - - dispc.base = ioremap(DISPC_BASE, DISPC_SZ_REGS); - if (!dispc.base) { - DSSERR("can't ioremap DISPC\n"); - return -ENOMEM; - } - - enable_clocks(1); - - _omap_dispc_initial_config(); - - _omap_dispc_initialize_irq(); - - dispc_save_context(); - - rev = dispc_read_reg(DISPC_REVISION); - printk(KERN_INFO "OMAP DISPC rev %d.%d\n", - FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0)); - - enable_clocks(0); - - return 0; -} - -void dispc_exit(void) -{ - iounmap(dispc.base); -} - int dispc_enable_plane(enum omap_plane plane, bool enable) { DSSDBG("dispc_enable_plane %d, %d\n", plane, enable); @@ -3359,3 +3319,66 @@ int dispc_setup_plane(enum omap_plane plane, return r; } + +/* DISPC HW IP initialisation */ +static int omap_dispchw_probe(struct platform_device *pdev) +{ + u32 rev; + dispc.pdev = pdev; + + spin_lock_init(&dispc.irq_lock); + +#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS + spin_lock_init(&dispc.irq_stats_lock); + dispc.irq_stats.last_reset = jiffies; +#endif + + INIT_WORK(&dispc.error_work, dispc_error_worker); + + dispc.base = ioremap(DISPC_BASE, DISPC_SZ_REGS); + if (!dispc.base) { + DSSERR("can't ioremap DISPC\n"); + return -ENOMEM; + } + + enable_clocks(1); + + _omap_dispc_initial_config(); + + _omap_dispc_initialize_irq(); + + dispc_save_context(); + + rev = dispc_read_reg(DISPC_REVISION); + printk(KERN_INFO "OMAP DISPC rev %d.%d\n", + FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0)); + + enable_clocks(0); + + return 0; +} + +static int omap_dispchw_remove(struct platform_device *pdev) +{ + iounmap(dispc.base); + return 0; +} + +static struct platform_driver omap_dispchw_driver = { + .probe = omap_dispchw_probe, + .remove = omap_dispchw_remove, + .driver = { + .name = "omapdss_dispc", + .owner = THIS_MODULE, + }, +}; + +int dispc_init_platform_driver(void) +{ + return platform_driver_register(&omap_dispchw_driver); +} + +void dispc_uninit_platform_driver(void) +{ + return platform_driver_unregister(&omap_dispchw_driver); +} diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h index 0ba4bdbd6b01a..f4835c85db90e 100644 --- a/drivers/video/omap2/dss/dss.h +++ b/drivers/video/omap2/dss/dss.h @@ -319,8 +319,8 @@ static inline void dpi_exit(void) #endif /* DISPC */ -int dispc_init(void); -void dispc_exit(void); +int dispc_init_platform_driver(void); +void dispc_uninit_platform_driver(void); void dispc_dump_clocks(struct seq_file *s); void dispc_dump_irqs(struct seq_file *s); void dispc_dump_regs(struct seq_file *s); -- GitLab From 30ea50c9f5166a375b4dc0109d18a5d21bab5711 Mon Sep 17 00:00:00 2001 From: Senthilvadivu Guruswamy Date: Mon, 24 Jan 2011 06:22:01 +0000 Subject: [PATCH 0511/2822] OMAP2, 3: DSS2: VENC: create platform_driver, move init, exit to driver Hwmod adaptation design requires each of the DSS HW IP to be a platform driver. So a platform_driver for VENC is created and init exit methods are moved from core.c to its driver probe,remove. pdev member has to be maintained by its own drivers. Also, venc_vdda_dac reading is moved to venc.c. VENC platform driver is registered from inside omap_dss_probe, in the order desired. Signed-off-by: Senthilvadivu Guruswamy Signed-off-by: Sumit Semwal Signed-off-by: Tomi Valkeinen --- arch/arm/mach-omap2/board-3430sdp.c | 2 +- arch/arm/mach-omap2/board-cm-t35.c | 2 +- arch/arm/mach-omap2/board-devkit8000.c | 2 +- arch/arm/mach-omap2/board-omap3beagle.c | 2 +- arch/arm/mach-omap2/board-omap3evm.c | 2 +- arch/arm/mach-omap2/board-omap3pandora.c | 2 +- arch/arm/mach-omap2/board-omap3stalker.c | 2 +- arch/arm/mach-omap2/board-rx51-peripherals.c | 2 +- arch/arm/mach-omap2/board-zoom-peripherals.c | 2 +- drivers/video/omap2/dss/core.c | 28 +---- drivers/video/omap2/dss/dss.h | 9 +- drivers/video/omap2/dss/venc.c | 116 ++++++++++++------- 12 files changed, 93 insertions(+), 78 deletions(-) diff --git a/arch/arm/mach-omap2/board-3430sdp.c b/arch/arm/mach-omap2/board-3430sdp.c index e018472861e66..652e7c38c62ec 100644 --- a/arch/arm/mach-omap2/board-3430sdp.c +++ b/arch/arm/mach-omap2/board-3430sdp.c @@ -395,7 +395,7 @@ static struct regulator_consumer_supply sdp3430_vaux3_supplies[] = { }; static struct regulator_consumer_supply sdp3430_vdda_dac_supplies[] = { - REGULATOR_SUPPLY("vdda_dac", "omapdss"), + REGULATOR_SUPPLY("vdda_dac", "omapdss_venc"), }; /* VPLL2 for digital video outputs */ diff --git a/arch/arm/mach-omap2/board-cm-t35.c b/arch/arm/mach-omap2/board-cm-t35.c index 27bea540ccbb9..e55fde0a720dc 100644 --- a/arch/arm/mach-omap2/board-cm-t35.c +++ b/arch/arm/mach-omap2/board-cm-t35.c @@ -488,7 +488,7 @@ static struct regulator_consumer_supply cm_t35_vsim_supply = { }; static struct regulator_consumer_supply cm_t35_vdac_supply = - REGULATOR_SUPPLY("vdda_dac", "omapdss"); + REGULATOR_SUPPLY("vdda_dac", "omapdss_venc"); static struct regulator_consumer_supply cm_t35_vdvi_supply = REGULATOR_SUPPLY("vdvi", "omapdss"); diff --git a/arch/arm/mach-omap2/board-devkit8000.c b/arch/arm/mach-omap2/board-devkit8000.c index 728f27c5bcb1e..b64774b3d82c7 100644 --- a/arch/arm/mach-omap2/board-devkit8000.c +++ b/arch/arm/mach-omap2/board-devkit8000.c @@ -196,7 +196,7 @@ static struct omap_dss_board_info devkit8000_dss_data = { }; static struct regulator_consumer_supply devkit8000_vdda_dac_supply = - REGULATOR_SUPPLY("vdda_dac", "omapdss"); + REGULATOR_SUPPLY("vdda_dac", "omapdss_venc"); static uint32_t board_keymap[] = { KEY(0, 0, KEY_1), diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c index 20c5dbea89538..2fad38f9e6838 100644 --- a/arch/arm/mach-omap2/board-omap3beagle.c +++ b/arch/arm/mach-omap2/board-omap3beagle.c @@ -232,7 +232,7 @@ static struct omap_dss_board_info beagle_dss_data = { }; static struct regulator_consumer_supply beagle_vdac_supply = - REGULATOR_SUPPLY("vdda_dac", "omapdss"); + REGULATOR_SUPPLY("vdda_dac", "omapdss_venc"); static struct regulator_consumer_supply beagle_vdvi_supply = REGULATOR_SUPPLY("vdds_dsi", "omapdss"); diff --git a/arch/arm/mach-omap2/board-omap3evm.c b/arch/arm/mach-omap2/board-omap3evm.c index b65848c59e1d3..a6564b41b97af 100644 --- a/arch/arm/mach-omap2/board-omap3evm.c +++ b/arch/arm/mach-omap2/board-omap3evm.c @@ -542,7 +542,7 @@ static struct twl4030_codec_data omap3evm_codec_data = { }; static struct regulator_consumer_supply omap3_evm_vdda_dac_supply = - REGULATOR_SUPPLY("vdda_dac", "omapdss"); + REGULATOR_SUPPLY("vdda_dac", "omapdss_venc"); /* VDAC for DSS driving S-Video */ static struct regulator_init_data omap3_evm_vdac = { diff --git a/arch/arm/mach-omap2/board-omap3pandora.c b/arch/arm/mach-omap2/board-omap3pandora.c index 5386a8190ea13..37de418edd2a3 100644 --- a/arch/arm/mach-omap2/board-omap3pandora.c +++ b/arch/arm/mach-omap2/board-omap3pandora.c @@ -342,7 +342,7 @@ static struct regulator_consumer_supply pandora_vmmc3_supply = REGULATOR_SUPPLY("vmmc", "omap_hsmmc.2"); static struct regulator_consumer_supply pandora_vdda_dac_supply = - REGULATOR_SUPPLY("vdda_dac", "omapdss"); + REGULATOR_SUPPLY("vdda_dac", "omapdss_venc"); static struct regulator_consumer_supply pandora_vdds_supplies[] = { REGULATOR_SUPPLY("vdds_sdi", "omapdss"), diff --git a/arch/arm/mach-omap2/board-omap3stalker.c b/arch/arm/mach-omap2/board-omap3stalker.c index 15ede8b498150..bd0eed8580783 100644 --- a/arch/arm/mach-omap2/board-omap3stalker.c +++ b/arch/arm/mach-omap2/board-omap3stalker.c @@ -439,7 +439,7 @@ static struct twl4030_codec_data omap3stalker_codec_data = { }; static struct regulator_consumer_supply omap3_stalker_vdda_dac_supply = - REGULATOR_SUPPLY("vdda_dac", "omapdss"); + REGULATOR_SUPPLY("vdda_dac", "omapdss_venc"); /* VDAC for DSS driving S-Video */ static struct regulator_init_data omap3_stalker_vdac = { diff --git a/arch/arm/mach-omap2/board-rx51-peripherals.c b/arch/arm/mach-omap2/board-rx51-peripherals.c index 5f1900c532ec3..bbcb6775a6a30 100644 --- a/arch/arm/mach-omap2/board-rx51-peripherals.c +++ b/arch/arm/mach-omap2/board-rx51-peripherals.c @@ -372,7 +372,7 @@ static struct regulator_consumer_supply rx51_vaux1_consumers[] = { }; static struct regulator_consumer_supply rx51_vdac_supply[] = { - REGULATOR_SUPPLY("vdda_dac", "omapdss"), + REGULATOR_SUPPLY("vdda_dac", "omapdss_venc"), }; static struct regulator_init_data rx51_vaux1 = { diff --git a/arch/arm/mach-omap2/board-zoom-peripherals.c b/arch/arm/mach-omap2/board-zoom-peripherals.c index 448ab60195d5c..405400c4762b5 100644 --- a/arch/arm/mach-omap2/board-zoom-peripherals.c +++ b/arch/arm/mach-omap2/board-zoom-peripherals.c @@ -230,7 +230,7 @@ static struct regulator_consumer_supply zoom_vpll2_supply = REGULATOR_SUPPLY("vdds_dsi", "omapdss"); static struct regulator_consumer_supply zoom_vdda_dac_supply = - REGULATOR_SUPPLY("vdda_dac", "omapdss"); + REGULATOR_SUPPLY("vdda_dac", "omapdss_venc"); static struct regulator_init_data zoom_vpll2 = { .constraints = { diff --git a/drivers/video/omap2/dss/core.c b/drivers/video/omap2/dss/core.c index 8b7eab83e4124..57c6303cb1cda 100644 --- a/drivers/video/omap2/dss/core.c +++ b/drivers/video/omap2/dss/core.c @@ -43,7 +43,6 @@ static struct { struct regulator *vdds_dsi_reg; struct regulator *vdds_sdi_reg; - struct regulator *vdda_dac_reg; } core; static char *def_disp_name; @@ -85,20 +84,6 @@ struct regulator *dss_get_vdds_sdi(void) return reg; } -struct regulator *dss_get_vdda_dac(void) -{ - struct regulator *reg; - - if (core.vdda_dac_reg != NULL) - return core.vdda_dac_reg; - - reg = regulator_get(&core.pdev->dev, "vdda_dac"); - if (!IS_ERR(reg)) - core.vdda_dac_reg = reg; - - return reg; -} - #if defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT) static int dss_debug_show(struct seq_file *s, void *unused) { @@ -219,9 +204,9 @@ static int omap_dss_probe(struct platform_device *pdev) goto err_dispc; } - r = venc_init(pdev); + r = venc_init_platform_driver(); if (r) { - DSSERR("Failed to initialize venc\n"); + DSSERR("Failed to initialize venc platform driver\n"); goto err_venc; } @@ -279,7 +264,7 @@ err_dsi: if (cpu_is_omap34xx()) sdi_exit(); err_sdi: - venc_exit(); + venc_uninit_platform_driver(); err_venc: dispc_uninit_platform_driver(); err_dispc: @@ -300,7 +285,7 @@ static int omap_dss_remove(struct platform_device *pdev) dss_uninitialize_debugfs(); - venc_exit(); + venc_uninit_platform_driver(); dispc_uninit_platform_driver(); dpi_exit(); rfbi_uninit_platform_driver(); @@ -597,11 +582,6 @@ static void __exit omap_dss_exit(void) core.vdds_sdi_reg = NULL; } - if (core.vdda_dac_reg != NULL) { - regulator_put(core.vdda_dac_reg); - core.vdda_dac_reg = NULL; - } - platform_driver_unregister(&omap_dss_driver); omap_dss_bus_unregister(); diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h index f4835c85db90e..931385185dc61 100644 --- a/drivers/video/omap2/dss/dss.h +++ b/drivers/video/omap2/dss/dss.h @@ -172,7 +172,6 @@ struct platform_device; struct bus_type *dss_get_bus(void); struct regulator *dss_get_vdds_dsi(void); struct regulator *dss_get_vdds_sdi(void); -struct regulator *dss_get_vdda_dac(void); /* display */ int dss_suspend_all_devices(void); @@ -412,16 +411,16 @@ int dispc_get_clock_div(enum omap_channel channel, /* VENC */ #ifdef CONFIG_OMAP2_DSS_VENC -int venc_init(struct platform_device *pdev); -void venc_exit(void); +int venc_init_platform_driver(void); +void venc_uninit_platform_driver(void); void venc_dump_regs(struct seq_file *s); int venc_init_display(struct omap_dss_device *display); #else -static inline int venc_init(struct platform_device *pdev) +static inline int venc_init_platform_driver(void) { return 0; } -static inline void venc_exit(void) +static inline void venc_uninit_platform_driver(void) { } #endif diff --git a/drivers/video/omap2/dss/venc.c b/drivers/video/omap2/dss/venc.c index eff35050e28a6..765a4ac44ecdc 100644 --- a/drivers/video/omap2/dss/venc.c +++ b/drivers/video/omap2/dss/venc.c @@ -289,6 +289,7 @@ const struct omap_video_timings omap_dss_ntsc_timings = { EXPORT_SYMBOL(omap_dss_ntsc_timings); static struct { + struct platform_device *pdev; void __iomem *base; struct mutex venc_lock; u32 wss_data; @@ -306,6 +307,17 @@ static inline u32 venc_read_reg(int idx) return l; } +static struct regulator *venc_get_vdda_dac(void) +{ + struct regulator *reg; + + reg = regulator_get(&venc.pdev->dev, "vdda_dac"); + if (!IS_ERR(reg)) + venc.vdda_dac_reg = reg; + + return reg; +} + static void venc_write_config(const struct venc_config *config) { DSSDBG("write venc conf\n"); @@ -641,46 +653,6 @@ static struct omap_dss_driver venc_driver = { }; /* driver end */ - - -int venc_init(struct platform_device *pdev) -{ - u8 rev_id; - - mutex_init(&venc.venc_lock); - - venc.wss_data = 0; - - venc.base = ioremap(VENC_BASE, SZ_1K); - if (!venc.base) { - DSSERR("can't ioremap VENC\n"); - return -ENOMEM; - } - - venc.vdda_dac_reg = dss_get_vdda_dac(); - if (IS_ERR(venc.vdda_dac_reg)) { - iounmap(venc.base); - DSSERR("can't get VDDA_DAC regulator\n"); - return PTR_ERR(venc.vdda_dac_reg); - } - - venc_enable_clocks(1); - - rev_id = (u8)(venc_read_reg(VENC_REV_ID) & 0xff); - printk(KERN_INFO "OMAP VENC rev %d\n", rev_id); - - venc_enable_clocks(0); - - return omap_dss_register_driver(&venc_driver); -} - -void venc_exit(void) -{ - omap_dss_unregister_driver(&venc_driver); - - iounmap(venc.base); -} - int venc_init_display(struct omap_dss_device *dssdev) { DSSDBG("init_display\n"); @@ -740,3 +712,67 @@ void venc_dump_regs(struct seq_file *s) #undef DUMPREG } + +/* VENC HW IP initialisation */ +static int omap_venchw_probe(struct platform_device *pdev) +{ + u8 rev_id; + venc.pdev = pdev; + + mutex_init(&venc.venc_lock); + + venc.wss_data = 0; + + venc.base = ioremap(VENC_BASE, SZ_1K); + if (!venc.base) { + DSSERR("can't ioremap VENC\n"); + return -ENOMEM; + } + + venc.vdda_dac_reg = venc_get_vdda_dac(); + if (IS_ERR(venc.vdda_dac_reg)) { + iounmap(venc.base); + DSSERR("can't get VDDA_DAC regulator\n"); + return PTR_ERR(venc.vdda_dac_reg); + } + + venc_enable_clocks(1); + + rev_id = (u8)(venc_read_reg(VENC_REV_ID) & 0xff); + printk(KERN_INFO "OMAP VENC rev %d\n", rev_id); + + venc_enable_clocks(0); + + return omap_dss_register_driver(&venc_driver); +} + +static int omap_venchw_remove(struct platform_device *pdev) +{ + if (venc.vdda_dac_reg != NULL) { + regulator_put(venc.vdda_dac_reg); + venc.vdda_dac_reg = NULL; + } + omap_dss_unregister_driver(&venc_driver); + + iounmap(venc.base); + return 0; +} + +static struct platform_driver omap_venchw_driver = { + .probe = omap_venchw_probe, + .remove = omap_venchw_remove, + .driver = { + .name = "omapdss_venc", + .owner = THIS_MODULE, + }, +}; + +int venc_init_platform_driver(void) +{ + return platform_driver_register(&omap_venchw_driver); +} + +void venc_uninit_platform_driver(void) +{ + return platform_driver_unregister(&omap_venchw_driver); +} -- GitLab From c8aac01b7bd1109795586db11ea7f12ab1e2d163 Mon Sep 17 00:00:00 2001 From: Senthilvadivu Guruswamy Date: Mon, 24 Jan 2011 06:22:02 +0000 Subject: [PATCH 0512/2822] OMAP2, 3: DSS2: DSI: create platform_driver, move init, exit to driver Hwmod adaptation design requires each of the DSS HW IP to be a platform driver. So a platform_driver for DSI is created and init exit methods are moved from core.c to its driver probe,remove. pdev member has to be maintained by its own drivers. Also, vdds_dsi regulator handling is copied to dsi.c, since vdds_dsi regulator is needed by dpi_init() too. Board files are updated accordingly to add 2 instances of vdds_dsi regulator. DSI platform driver is registered from inside omap_dss_probe, in the order desired. Signed-off-by: Senthilvadivu Guruswamy Signed-off-by: Sumit Semwal Signed-off-by: Tomi Valkeinen --- arch/arm/mach-omap2/board-3430sdp.c | 1 + arch/arm/mach-omap2/board-devkit8000.c | 10 +-- arch/arm/mach-omap2/board-igep0020.c | 10 +-- arch/arm/mach-omap2/board-omap3beagle.c | 10 +-- arch/arm/mach-omap2/board-omap3evm.c | 10 +-- arch/arm/mach-omap2/board-omap3pandora.c | 1 + arch/arm/mach-omap2/board-omap3stalker.c | 10 +-- arch/arm/mach-omap2/board-zoom-peripherals.c | 10 +-- drivers/video/omap2/dss/core.c | 8 +-- drivers/video/omap2/dss/dsi.c | 64 +++++++++++++++++++- drivers/video/omap2/dss/dss.h | 8 +-- 11 files changed, 107 insertions(+), 35 deletions(-) diff --git a/arch/arm/mach-omap2/board-3430sdp.c b/arch/arm/mach-omap2/board-3430sdp.c index 652e7c38c62ec..75814ae4dd07d 100644 --- a/arch/arm/mach-omap2/board-3430sdp.c +++ b/arch/arm/mach-omap2/board-3430sdp.c @@ -401,6 +401,7 @@ static struct regulator_consumer_supply sdp3430_vdda_dac_supplies[] = { /* VPLL2 for digital video outputs */ static struct regulator_consumer_supply sdp3430_vpll2_supplies[] = { REGULATOR_SUPPLY("vdds_dsi", "omapdss"), + REGULATOR_SUPPLY("vdds_dsi", "omapdss_dsi1"), }; static struct regulator_consumer_supply sdp3430_vmmc1_supplies[] = { diff --git a/arch/arm/mach-omap2/board-devkit8000.c b/arch/arm/mach-omap2/board-devkit8000.c index b64774b3d82c7..e102e143afb1f 100644 --- a/arch/arm/mach-omap2/board-devkit8000.c +++ b/arch/arm/mach-omap2/board-devkit8000.c @@ -277,8 +277,10 @@ static struct twl4030_gpio_platform_data devkit8000_gpio_data = { .setup = devkit8000_twl_gpio_setup, }; -static struct regulator_consumer_supply devkit8000_vpll1_supply = - REGULATOR_SUPPLY("vdds_dsi", "omapdss"); +static struct regulator_consumer_supply devkit8000_vpll1_supplies[] = { + REGULATOR_SUPPLY("vdds_dsi", "omapdss"), + REGULATOR_SUPPLY("vdds_dsi", "omapdss_dsi1"), +}; /* VMMC1 for MMC1 pins CMD, CLK, DAT0..DAT3 (20 mA, plus card == max 220 mA) */ static struct regulator_init_data devkit8000_vmmc1 = { @@ -319,8 +321,8 @@ static struct regulator_init_data devkit8000_vpll1 = { .valid_ops_mask = REGULATOR_CHANGE_MODE | REGULATOR_CHANGE_STATUS, }, - .num_consumer_supplies = 1, - .consumer_supplies = &devkit8000_vpll1_supply, + .num_consumer_supplies = ARRAY_SIZE(devkit8000_vpll1_supplies), + .consumer_supplies = devkit8000_vpll1_supplies, }; /* VAUX4 for ads7846 and nubs */ diff --git a/arch/arm/mach-omap2/board-igep0020.c b/arch/arm/mach-omap2/board-igep0020.c index c4b3c1c47ec6f..12b3e41b6f78e 100644 --- a/arch/arm/mach-omap2/board-igep0020.c +++ b/arch/arm/mach-omap2/board-igep0020.c @@ -485,8 +485,10 @@ static struct omap_dss_board_info igep2_dss_data = { .default_device = &igep2_dvi_device, }; -static struct regulator_consumer_supply igep2_vpll2_supply = - REGULATOR_SUPPLY("vdds_dsi", "omapdss"); +static struct regulator_consumer_supply igep2_vpll2_supplies[] = { + REGULATOR_SUPPLY("vdds_dsi", "omapdss"), + REGULATOR_SUPPLY("vdds_dsi", "omapdss_dsi1"), +}; static struct regulator_init_data igep2_vpll2 = { .constraints = { @@ -499,8 +501,8 @@ static struct regulator_init_data igep2_vpll2 = { .valid_ops_mask = REGULATOR_CHANGE_MODE | REGULATOR_CHANGE_STATUS, }, - .num_consumer_supplies = 1, - .consumer_supplies = &igep2_vpll2_supply, + .num_consumer_supplies = ARRAY_SIZE(igep2_vpll2_supplies), + .consumer_supplies = igep2_vpll2_supplies, }; static void __init igep2_display_init(void) diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c index 2fad38f9e6838..e663c43fe039e 100644 --- a/arch/arm/mach-omap2/board-omap3beagle.c +++ b/arch/arm/mach-omap2/board-omap3beagle.c @@ -234,8 +234,10 @@ static struct omap_dss_board_info beagle_dss_data = { static struct regulator_consumer_supply beagle_vdac_supply = REGULATOR_SUPPLY("vdda_dac", "omapdss_venc"); -static struct regulator_consumer_supply beagle_vdvi_supply = - REGULATOR_SUPPLY("vdds_dsi", "omapdss"); +static struct regulator_consumer_supply beagle_vdvi_supplies[] = { + REGULATOR_SUPPLY("vdds_dsi", "omapdss"), + REGULATOR_SUPPLY("vdds_dsi", "omapdss_dsi1"), +}; static void __init beagle_display_init(void) { @@ -422,8 +424,8 @@ static struct regulator_init_data beagle_vpll2 = { .valid_ops_mask = REGULATOR_CHANGE_MODE | REGULATOR_CHANGE_STATUS, }, - .num_consumer_supplies = 1, - .consumer_supplies = &beagle_vdvi_supply, + .num_consumer_supplies = ARRAY_SIZE(beagle_vdvi_supplies), + .consumer_supplies = beagle_vdvi_supplies, }; static struct twl4030_usb_data beagle_usb_data = { diff --git a/arch/arm/mach-omap2/board-omap3evm.c b/arch/arm/mach-omap2/board-omap3evm.c index a6564b41b97af..5800db31e561f 100644 --- a/arch/arm/mach-omap2/board-omap3evm.c +++ b/arch/arm/mach-omap2/board-omap3evm.c @@ -560,8 +560,10 @@ static struct regulator_init_data omap3_evm_vdac = { }; /* VPLL2 for digital video outputs */ -static struct regulator_consumer_supply omap3_evm_vpll2_supply = - REGULATOR_SUPPLY("vdds_dsi", "omapdss"); +static struct regulator_consumer_supply omap3_evm_vpll2_supplies[] = { + REGULATOR_SUPPLY("vdds_dsi", "omapdss"), + REGULATOR_SUPPLY("vdds_dsi", "omapdss_dsi1"), +}; static struct regulator_init_data omap3_evm_vpll2 = { .constraints = { @@ -573,8 +575,8 @@ static struct regulator_init_data omap3_evm_vpll2 = { .valid_ops_mask = REGULATOR_CHANGE_MODE | REGULATOR_CHANGE_STATUS, }, - .num_consumer_supplies = 1, - .consumer_supplies = &omap3_evm_vpll2_supply, + .num_consumer_supplies = ARRAY_SIZE(omap3_evm_vpll2_supplies), + .consumer_supplies = omap3_evm_vpll2_supplies, }; /* ads7846 on SPI */ diff --git a/arch/arm/mach-omap2/board-omap3pandora.c b/arch/arm/mach-omap2/board-omap3pandora.c index 37de418edd2a3..131a58dd3c964 100644 --- a/arch/arm/mach-omap2/board-omap3pandora.c +++ b/arch/arm/mach-omap2/board-omap3pandora.c @@ -347,6 +347,7 @@ static struct regulator_consumer_supply pandora_vdda_dac_supply = static struct regulator_consumer_supply pandora_vdds_supplies[] = { REGULATOR_SUPPLY("vdds_sdi", "omapdss"), REGULATOR_SUPPLY("vdds_dsi", "omapdss"), + REGULATOR_SUPPLY("vdds_dsi", "omapdss_dsi1"), }; static struct regulator_consumer_supply pandora_vcc_lcd_supply = diff --git a/arch/arm/mach-omap2/board-omap3stalker.c b/arch/arm/mach-omap2/board-omap3stalker.c index bd0eed8580783..d1163a80f843f 100644 --- a/arch/arm/mach-omap2/board-omap3stalker.c +++ b/arch/arm/mach-omap2/board-omap3stalker.c @@ -457,8 +457,10 @@ static struct regulator_init_data omap3_stalker_vdac = { }; /* VPLL2 for digital video outputs */ -static struct regulator_consumer_supply omap3_stalker_vpll2_supply = - REGULATOR_SUPPLY("vdds_dsi", "omapdss"); +static struct regulator_consumer_supply omap3_stalker_vpll2_supplies[] = { + REGULATOR_SUPPLY("vdds_dsi", "omapdss"), + REGULATOR_SUPPLY("vdds_dsi", "omapdss_dsi1"), +}; static struct regulator_init_data omap3_stalker_vpll2 = { .constraints = { @@ -471,8 +473,8 @@ static struct regulator_init_data omap3_stalker_vpll2 = { .valid_ops_mask = REGULATOR_CHANGE_MODE | REGULATOR_CHANGE_STATUS, }, - .num_consumer_supplies = 1, - .consumer_supplies = &omap3_stalker_vpll2_supply, + .num_consumer_supplies = ARRAY_SIZE(omap3_stalker_vpll2_supplies), + .consumer_supplies = omap3_stalker_vpll2_supplies, }; static struct twl4030_platform_data omap3stalker_twldata = { diff --git a/arch/arm/mach-omap2/board-zoom-peripherals.c b/arch/arm/mach-omap2/board-zoom-peripherals.c index 405400c4762b5..8dee7549fbdf5 100644 --- a/arch/arm/mach-omap2/board-zoom-peripherals.c +++ b/arch/arm/mach-omap2/board-zoom-peripherals.c @@ -226,8 +226,10 @@ static struct omap2_hsmmc_info mmc[] = { {} /* Terminator */ }; -static struct regulator_consumer_supply zoom_vpll2_supply = - REGULATOR_SUPPLY("vdds_dsi", "omapdss"); +static struct regulator_consumer_supply zoom_vpll2_supplies[] = { + REGULATOR_SUPPLY("vdds_dsi", "omapdss"), + REGULATOR_SUPPLY("vdds_dsi", "omapdss_dsi1"), +}; static struct regulator_consumer_supply zoom_vdda_dac_supply = REGULATOR_SUPPLY("vdda_dac", "omapdss_venc"); @@ -241,8 +243,8 @@ static struct regulator_init_data zoom_vpll2 = { .valid_ops_mask = REGULATOR_CHANGE_MODE | REGULATOR_CHANGE_STATUS, }, - .num_consumer_supplies = 1, - .consumer_supplies = &zoom_vpll2_supply, + .num_consumer_supplies = ARRAY_SIZE(zoom_vpll2_supplies), + .consumer_supplies = zoom_vpll2_supplies, }; static struct regulator_init_data zoom_vdac = { diff --git a/drivers/video/omap2/dss/core.c b/drivers/video/omap2/dss/core.c index 57c6303cb1cda..3f7a5fcd1142c 100644 --- a/drivers/video/omap2/dss/core.c +++ b/drivers/video/omap2/dss/core.c @@ -222,9 +222,9 @@ static int omap_dss_probe(struct platform_device *pdev) goto err_sdi; } - r = dsi_init(pdev); + r = dsi_init_platform_driver(); if (r) { - DSSERR("Failed to initialize DSI\n"); + DSSERR("Failed to initialize DSI platform driver\n"); goto err_dsi; } } @@ -259,7 +259,7 @@ err_register: dss_uninitialize_debugfs(); err_debugfs: if (cpu_is_omap34xx()) - dsi_exit(); + dsi_uninit_platform_driver(); err_dsi: if (cpu_is_omap34xx()) sdi_exit(); @@ -290,7 +290,7 @@ static int omap_dss_remove(struct platform_device *pdev) dpi_exit(); rfbi_uninit_platform_driver(); if (cpu_is_omap34xx()) { - dsi_exit(); + dsi_uninit_platform_driver(); sdi_exit(); } diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c index ddf3a05608228..fa85f1adba2a4 100644 --- a/drivers/video/omap2/dss/dsi.c +++ b/drivers/video/omap2/dss/dsi.c @@ -222,6 +222,7 @@ struct dsi_irq_stats { static struct { + struct platform_device *pdev; void __iomem *base; struct dsi_clock_info current_cinfo; @@ -292,6 +293,20 @@ static inline u32 dsi_read_reg(const struct dsi_reg idx) return __raw_readl(dsi.base + idx.idx); } +static struct regulator *dsi_get_vdds_dsi(void) +{ + struct regulator *reg; + + if (dsi.vdds_dsi_reg != NULL) + return dsi.vdds_dsi_reg; + + reg = regulator_get(&dsi.pdev->dev, "vdds_dsi"); + if (!IS_ERR(reg)) + dsi.vdds_dsi_reg = reg; + + return reg; +} + void dsi_save_context(void) { @@ -3238,7 +3253,7 @@ void dsi_wait_dsi2_pll_active(void) DSSERR("DSI2 PLL clock not active\n"); } -int dsi_init(struct platform_device *pdev) +static int dsi_init(struct platform_device *pdev) { u32 rev; int r; @@ -3275,7 +3290,7 @@ int dsi_init(struct platform_device *pdev) goto err1; } - dsi.vdds_dsi_reg = dss_get_vdds_dsi(); + dsi.vdds_dsi_reg = dsi_get_vdds_dsi(); if (IS_ERR(dsi.vdds_dsi_reg)) { DSSERR("can't get VDDS_DSI regulator\n"); r = PTR_ERR(dsi.vdds_dsi_reg); @@ -3298,8 +3313,13 @@ err1: return r; } -void dsi_exit(void) +static void dsi_exit(void) { + if (dsi.vdds_dsi_reg != NULL) { + regulator_put(dsi.vdds_dsi_reg); + dsi.vdds_dsi_reg = NULL; + } + iounmap(dsi.base); destroy_workqueue(dsi.workqueue); @@ -3307,3 +3327,41 @@ void dsi_exit(void) DSSDBG("omap_dsi_exit\n"); } +/* DSI1 HW IP initialisation */ +static int omap_dsi1hw_probe(struct platform_device *pdev) +{ + int r; + dsi.pdev = pdev; + r = dsi_init(pdev); + if (r) { + DSSERR("Failed to initialize DSI\n"); + goto err_dsi; + } +err_dsi: + return r; +} + +static int omap_dsi1hw_remove(struct platform_device *pdev) +{ + dsi_exit(); + return 0; +} + +static struct platform_driver omap_dsi1hw_driver = { + .probe = omap_dsi1hw_probe, + .remove = omap_dsi1hw_remove, + .driver = { + .name = "omapdss_dsi1", + .owner = THIS_MODULE, + }, +}; + +int dsi_init_platform_driver(void) +{ + return platform_driver_register(&omap_dsi1hw_driver); +} + +void dsi_uninit_platform_driver(void) +{ + return platform_driver_unregister(&omap_dsi1hw_driver); +} diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h index 931385185dc61..981d247c30f27 100644 --- a/drivers/video/omap2/dss/dss.h +++ b/drivers/video/omap2/dss/dss.h @@ -261,8 +261,8 @@ static inline void sdi_exit(void) /* DSI */ #ifdef CONFIG_OMAP2_DSS_DSI -int dsi_init(struct platform_device *pdev); -void dsi_exit(void); +int dsi_init_platform_driver(void); +void dsi_uninit_platform_driver(void); void dsi_dump_clocks(struct seq_file *s); void dsi_dump_irqs(struct seq_file *s); @@ -287,11 +287,11 @@ void dsi_get_overlay_fifo_thresholds(enum omap_plane plane, void dsi_wait_dsi1_pll_active(void); void dsi_wait_dsi2_pll_active(void); #else -static inline int dsi_init(struct platform_device *pdev) +static inline int dsi_init_platform_driver(void) { return 0; } -static inline void dsi_exit(void) +static inline void dsi_uninit_platform_driver(void) { } static inline void dsi_wait_dsi1_pll_active(void) -- GitLab From a06b62f8004bd95c132fa312e8593c9a10f466ec Mon Sep 17 00:00:00 2001 From: Sumit Semwal Date: Mon, 24 Jan 2011 06:22:03 +0000 Subject: [PATCH 0513/2822] OMAP2,3: DSS2: replace printk with dev_dbg in init This patch replaces printk's in the init/probe functions to dev_dbg for boot time optimization. Reviewed-by: Kevin Hilman Tested-by: Kevin Hilman Signed-off-by: Sumit Semwal Signed-off-by: Tomi Valkeinen --- drivers/video/omap2/dss/dispc.c | 2 +- drivers/video/omap2/dss/dsi.c | 2 +- drivers/video/omap2/dss/rfbi.c | 2 +- drivers/video/omap2/dss/venc.c | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c index 28ad68b6be481..032e5dd19e098 100644 --- a/drivers/video/omap2/dss/dispc.c +++ b/drivers/video/omap2/dss/dispc.c @@ -3350,7 +3350,7 @@ static int omap_dispchw_probe(struct platform_device *pdev) dispc_save_context(); rev = dispc_read_reg(DISPC_REVISION); - printk(KERN_INFO "OMAP DISPC rev %d.%d\n", + dev_dbg(&pdev->dev, "OMAP DISPC rev %d.%d\n", FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0)); enable_clocks(0); diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c index fa85f1adba2a4..df246033b9403 100644 --- a/drivers/video/omap2/dss/dsi.c +++ b/drivers/video/omap2/dss/dsi.c @@ -3300,7 +3300,7 @@ static int dsi_init(struct platform_device *pdev) enable_clocks(1); rev = dsi_read_reg(DSI_REVISION); - printk(KERN_INFO "OMAP DSI rev %d.%d\n", + dev_dbg(&pdev->dev, "OMAP DSI rev %d.%d\n", FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0)); enable_clocks(0); diff --git a/drivers/video/omap2/dss/rfbi.c b/drivers/video/omap2/dss/rfbi.c index 153f963e8e893..5f186484984fb 100644 --- a/drivers/video/omap2/dss/rfbi.c +++ b/drivers/video/omap2/dss/rfbi.c @@ -1046,7 +1046,7 @@ static int omap_rfbihw_probe(struct platform_device *pdev) rfbi_write_reg(RFBI_SYSCONFIG, l); rev = rfbi_read_reg(RFBI_REVISION); - printk(KERN_INFO "OMAP RFBI rev %d.%d\n", + dev_dbg(&pdev->dev, "OMAP RFBI rev %d.%d\n", FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0)); rfbi_enable_clocks(0); diff --git a/drivers/video/omap2/dss/venc.c b/drivers/video/omap2/dss/venc.c index 765a4ac44ecdc..4a02f8eeb0d88 100644 --- a/drivers/video/omap2/dss/venc.c +++ b/drivers/video/omap2/dss/venc.c @@ -739,7 +739,7 @@ static int omap_venchw_probe(struct platform_device *pdev) venc_enable_clocks(1); rev_id = (u8)(venc_read_reg(VENC_REV_ID) & 0xff); - printk(KERN_INFO "OMAP VENC rev %d\n", rev_id); + dev_dbg(&pdev->dev, "OMAP VENC rev %d\n", rev_id); venc_enable_clocks(0); -- GitLab From ea9da36a304eed585fc5ef89c0f1c460eca61b48 Mon Sep 17 00:00:00 2001 From: Senthilvadivu Guruswamy Date: Mon, 24 Jan 2011 06:22:04 +0000 Subject: [PATCH 0514/2822] OMAP2,3: DSS2: Use platform device to get baseaddr DSS, DISPC, DSI, RFBI, VENC baseaddr can be obtained from platform_get_resource(). This API in turn picks the right silicon baseaddr from the hwmod database. So hardcoding of base addr could be removed. Reviewed-by: Paul Walmsley Reviewed-by: Kevin Hilman Tested-by: Kevin Hilman Signed-off-by: Sumit Semwal Signed-off-by: Senthilvadivu Guruswamy Signed-off-by: Tomi Valkeinen --- drivers/video/omap2/dss/dispc.c | 11 ++++++++--- drivers/video/omap2/dss/dsi.c | 11 ++++++++--- drivers/video/omap2/dss/dss.c | 11 ++++++++--- drivers/video/omap2/dss/rfbi.c | 10 +++++++--- drivers/video/omap2/dss/venc.c | 11 ++++++++--- 5 files changed, 39 insertions(+), 15 deletions(-) diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c index 032e5dd19e098..96e37f8e75dcd 100644 --- a/drivers/video/omap2/dss/dispc.c +++ b/drivers/video/omap2/dss/dispc.c @@ -42,8 +42,6 @@ #include "dss_features.h" /* DISPC */ -#define DISPC_BASE 0x48050400 - #define DISPC_SZ_REGS SZ_4K struct dispc_reg { u16 idx; }; @@ -3324,6 +3322,8 @@ int dispc_setup_plane(enum omap_plane plane, static int omap_dispchw_probe(struct platform_device *pdev) { u32 rev; + struct resource *dispc_mem; + dispc.pdev = pdev; spin_lock_init(&dispc.irq_lock); @@ -3335,7 +3335,12 @@ static int omap_dispchw_probe(struct platform_device *pdev) INIT_WORK(&dispc.error_work, dispc_error_worker); - dispc.base = ioremap(DISPC_BASE, DISPC_SZ_REGS); + dispc_mem = platform_get_resource(dispc.pdev, IORESOURCE_MEM, 0); + if (!dispc_mem) { + DSSERR("can't get IORESOURCE_MEM DISPC\n"); + return -EINVAL; + } + dispc.base = ioremap(dispc_mem->start, resource_size(dispc_mem)); if (!dispc.base) { DSSERR("can't ioremap DISPC\n"); return -ENOMEM; diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c index df246033b9403..c42acae10af01 100644 --- a/drivers/video/omap2/dss/dsi.c +++ b/drivers/video/omap2/dss/dsi.c @@ -42,8 +42,6 @@ /*#define VERBOSE_IRQ*/ #define DSI_CATCH_MISSING_TE -#define DSI_BASE 0x4804FC00 - struct dsi_reg { u16 idx; }; #define DSI_REG(idx) ((const struct dsi_reg) { idx }) @@ -3257,6 +3255,7 @@ static int dsi_init(struct platform_device *pdev) { u32 rev; int r; + struct resource *dsi_mem; spin_lock_init(&dsi.errors_lock); dsi.errors = 0; @@ -3283,7 +3282,13 @@ static int dsi_init(struct platform_device *pdev) dsi.te_timer.function = dsi_te_timeout; dsi.te_timer.data = 0; #endif - dsi.base = ioremap(DSI_BASE, DSI_SZ_REGS); + dsi_mem = platform_get_resource(dsi.pdev, IORESOURCE_MEM, 0); + if (!dsi_mem) { + DSSERR("can't get IORESOURCE_MEM DSI\n"); + r = -EINVAL; + goto err1; + } + dsi.base = ioremap(dsi_mem->start, resource_size(dsi_mem)); if (!dsi.base) { DSSERR("can't ioremap DSI\n"); r = -ENOMEM; diff --git a/drivers/video/omap2/dss/dss.c b/drivers/video/omap2/dss/dss.c index 72b395d69aaeb..ee9ce4af58b53 100644 --- a/drivers/video/omap2/dss/dss.c +++ b/drivers/video/omap2/dss/dss.c @@ -34,8 +34,6 @@ #include #include "dss.h" -#define DSS_BASE 0x48050000 - #define DSS_SZ_REGS SZ_512 struct dss_reg { @@ -567,8 +565,15 @@ static int dss_init(bool skip_init) { int r; u32 rev; + struct resource *dss_mem; - dss.base = ioremap(DSS_BASE, DSS_SZ_REGS); + dss_mem = platform_get_resource(dss.pdev, IORESOURCE_MEM, 0); + if (!dss_mem) { + DSSERR("can't get IORESOURCE_MEM DSS\n"); + r = -EINVAL; + goto fail0; + } + dss.base = ioremap(dss_mem->start, resource_size(dss_mem)); if (!dss.base) { DSSERR("can't ioremap DSS\n"); r = -ENOMEM; diff --git a/drivers/video/omap2/dss/rfbi.c b/drivers/video/omap2/dss/rfbi.c index 5f186484984fb..6dbb95d557f8b 100644 --- a/drivers/video/omap2/dss/rfbi.c +++ b/drivers/video/omap2/dss/rfbi.c @@ -36,8 +36,6 @@ #include #include "dss.h" -#define RFBI_BASE 0x48050800 - struct rfbi_reg { u16 idx; }; #define RFBI_REG(idx) ((const struct rfbi_reg) { idx }) @@ -1019,6 +1017,7 @@ static int omap_rfbihw_probe(struct platform_device *pdev) { u32 rev; u32 l; + struct resource *rfbi_mem; rfbi.pdev = pdev; @@ -1028,7 +1027,12 @@ static int omap_rfbihw_probe(struct platform_device *pdev) atomic_set(&rfbi.cmd_fifo_full, 0); atomic_set(&rfbi.cmd_pending, 0); - rfbi.base = ioremap(RFBI_BASE, SZ_256); + rfbi_mem = platform_get_resource(rfbi.pdev, IORESOURCE_MEM, 0); + if (!rfbi_mem) { + DSSERR("can't get IORESOURCE_MEM RFBI\n"); + return -EINVAL; + } + rfbi.base = ioremap(rfbi_mem->start, resource_size(rfbi_mem)); if (!rfbi.base) { DSSERR("can't ioremap RFBI\n"); return -ENOMEM; diff --git a/drivers/video/omap2/dss/venc.c b/drivers/video/omap2/dss/venc.c index 4a02f8eeb0d88..ef36811f6ac8b 100644 --- a/drivers/video/omap2/dss/venc.c +++ b/drivers/video/omap2/dss/venc.c @@ -39,8 +39,6 @@ #include "dss.h" -#define VENC_BASE 0x48050C00 - /* Venc registers */ #define VENC_REV_ID 0x00 #define VENC_STATUS 0x04 @@ -717,13 +715,20 @@ void venc_dump_regs(struct seq_file *s) static int omap_venchw_probe(struct platform_device *pdev) { u8 rev_id; + struct resource *venc_mem; + venc.pdev = pdev; mutex_init(&venc.venc_lock); venc.wss_data = 0; - venc.base = ioremap(VENC_BASE, SZ_1K); + venc_mem = platform_get_resource(venc.pdev, IORESOURCE_MEM, 0); + if (!venc_mem) { + DSSERR("can't get IORESOURCE_MEM VENC\n"); + return -EINVAL; + } + venc.base = ioremap(venc_mem->start, resource_size(venc_mem)); if (!venc.base) { DSSERR("can't ioremap VENC\n"); return -ENOMEM; -- GitLab From ef631f82500390b3dfc20b16214e53c443d675a4 Mon Sep 17 00:00:00 2001 From: Senthilvadivu Guruswamy Date: Tue, 15 Feb 2011 23:14:00 -0600 Subject: [PATCH 0515/2822] OMAP2,3: DSS2: Get DSS IRQ from platform device DSS IRQ number can be obtained from platform_get_irq(). This API in turn picks the right IRQ number belonging to HW IP from the hwmod database. So hardcoding of IRQ number could be removed. This IRQ is stored in dss_irq as part of dss structure, and freed it in dss_exit(). Reviewed-by: Paul Walmsley Reviewed-by: Kevin Hilman Tested-by: Kevin Hilman Signed-off-by: Senthilvadivu Guruswamy Signed-off-by: Sumit Semwal Signed-off-by: Tomi Valkeinen --- drivers/video/omap2/dss/dss.c | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/drivers/video/omap2/dss/dss.c b/drivers/video/omap2/dss/dss.c index ee9ce4af58b53..a00733d6436a5 100644 --- a/drivers/video/omap2/dss/dss.c +++ b/drivers/video/omap2/dss/dss.c @@ -79,6 +79,7 @@ static struct { enum dss_clk_source dispc_clk_source; u32 ctx[DSS_SZ_REGS / sizeof(u32)]; + int dss_irq; } dss; static void dss_clk_enable_all_no_ctx(void); @@ -609,11 +610,18 @@ static int dss_init(bool skip_init) REG_FLD_MOD(DSS_CONTROL, 0, 2, 2); /* venc clock mode = normal */ #endif - r = request_irq(INT_24XX_DSS_IRQ, - cpu_is_omap24xx() - ? dss_irq_handler_omap2 - : dss_irq_handler_omap3, - 0, "OMAP DSS", NULL); + dss.dss_irq = platform_get_irq(dss.pdev, 0); + if (dss.dss_irq < 0) { + DSSERR("omap2 dss: platform_get_irq failed\n"); + r = -ENODEV; + goto fail1; + } + + r = request_irq(dss.dss_irq, + cpu_is_omap24xx() + ? dss_irq_handler_omap2 + : dss_irq_handler_omap3, + 0, "OMAP DSS", NULL); if (r < 0) { DSSERR("omap2 dss: request_irq failed\n"); @@ -641,7 +649,7 @@ static int dss_init(bool skip_init) return 0; fail2: - free_irq(INT_24XX_DSS_IRQ, NULL); + free_irq(dss.dss_irq, NULL); fail1: iounmap(dss.base); fail0: @@ -653,7 +661,7 @@ static void dss_exit(void) if (cpu_is_omap34xx()) clk_put(dss.dpll4_m4_ck); - free_irq(INT_24XX_DSS_IRQ, NULL); + free_irq(dss.dss_irq, NULL); iounmap(dss.base); } -- GitLab From 872462cdfc74e7b93c09870128d9bb436d4e9804 Mon Sep 17 00:00:00 2001 From: Sumit Semwal Date: Mon, 31 Jan 2011 16:27:43 +0000 Subject: [PATCH 0516/2822] OMAP2PLUS: clocks: Align DSS clock names and roles Currently, clock database has tuples for DSS2. Because of this, the clock names are different across different OMAP platforms. This patch aligns the DSS2 clock names and roles across OMAP 2420, 2430, 3xxx, 44xx platforms in the clock databases, hwmod databases for opt-clocks, and DSS clock handling. This ensures that clk_get/put/enable/disable APIs in DSS can use uniform role names. Signed-off-by: Sumit Semwal Acked-by: Paul Walmsley Signed-off-by: Tomi Valkeinen --- arch/arm/mach-omap2/clock2420_data.c | 6 +++--- arch/arm/mach-omap2/clock2430_data.c | 6 +++--- arch/arm/mach-omap2/clock3xxx_data.c | 10 +++++----- arch/arm/mach-omap2/clock44xx_data.c | 10 +++++----- arch/arm/mach-omap2/omap_hwmod_3xxx_data.c | 2 +- drivers/video/omap2/dss/dss.c | 8 ++++---- 6 files changed, 21 insertions(+), 21 deletions(-) diff --git a/arch/arm/mach-omap2/clock2420_data.c b/arch/arm/mach-omap2/clock2420_data.c index 9ece62a44a3f6..26d89d5827c84 100644 --- a/arch/arm/mach-omap2/clock2420_data.c +++ b/arch/arm/mach-omap2/clock2420_data.c @@ -1787,9 +1787,9 @@ static struct omap_clk omap2420_clks[] = { CLK(NULL, "gfx_ick", &gfx_ick, CK_242X), /* DSS domain clocks */ CLK("omapdss_dss", "ick", &dss_ick, CK_242X), - CLK("omapdss_dss", "dss1_fck", &dss1_fck, CK_242X), - CLK("omapdss_dss", "dss2_fck", &dss2_fck, CK_242X), - CLK("omapdss_dss", "tv_fck", &dss_54m_fck, CK_242X), + CLK("omapdss_dss", "fck", &dss1_fck, CK_242X), + CLK("omapdss_dss", "sys_clk", &dss2_fck, CK_242X), + CLK("omapdss_dss", "tv_clk", &dss_54m_fck, CK_242X), /* L3 domain clocks */ CLK(NULL, "core_l3_ck", &core_l3_ck, CK_242X), CLK(NULL, "ssi_fck", &ssi_ssr_sst_fck, CK_242X), diff --git a/arch/arm/mach-omap2/clock2430_data.c b/arch/arm/mach-omap2/clock2430_data.c index 61006ae7eac42..0bfe4872b02b7 100644 --- a/arch/arm/mach-omap2/clock2430_data.c +++ b/arch/arm/mach-omap2/clock2430_data.c @@ -1891,9 +1891,9 @@ static struct omap_clk omap2430_clks[] = { CLK(NULL, "mdm_osc_ck", &mdm_osc_ck, CK_243X), /* DSS domain clocks */ CLK("omapdss_dss", "ick", &dss_ick, CK_243X), - CLK("omapdss_dss", "dss1_fck", &dss1_fck, CK_243X), - CLK("omapdss_dss", "dss2_fck", &dss2_fck, CK_243X), - CLK("omapdss_dss", "tv_fck", &dss_54m_fck, CK_243X), + CLK("omapdss_dss", "fck", &dss1_fck, CK_243X), + CLK("omapdss_dss", "sys_clk", &dss2_fck, CK_243X), + CLK("omapdss_dss", "tv_clk", &dss_54m_fck, CK_243X), /* L3 domain clocks */ CLK(NULL, "core_l3_ck", &core_l3_ck, CK_243X), CLK(NULL, "ssi_fck", &ssi_ssr_sst_fck, CK_243X), diff --git a/arch/arm/mach-omap2/clock3xxx_data.c b/arch/arm/mach-omap2/clock3xxx_data.c index 2e47d16fce77a..427f6c8d15853 100644 --- a/arch/arm/mach-omap2/clock3xxx_data.c +++ b/arch/arm/mach-omap2/clock3xxx_data.c @@ -3357,11 +3357,11 @@ static struct omap_clk omap3xxx_clks[] = { CLK("omap_rng", "ick", &rng_ick, CK_34XX | CK_36XX), CLK(NULL, "sha11_ick", &sha11_ick, CK_34XX | CK_36XX), CLK(NULL, "des1_ick", &des1_ick, CK_34XX | CK_36XX), - CLK("omapdss_dss", "dss1_fck", &dss1_alwon_fck_3430es1, CK_3430ES1), - CLK("omapdss_dss", "dss1_fck", &dss1_alwon_fck_3430es2, CK_3430ES2PLUS | CK_AM35XX | CK_36XX), - CLK("omapdss_dss", "tv_fck", &dss_tv_fck, CK_3XXX), - CLK("omapdss_dss", "video_fck", &dss_96m_fck, CK_3XXX), - CLK("omapdss_dss", "dss2_fck", &dss2_alwon_fck, CK_3XXX), + CLK("omapdss_dss", "fck", &dss1_alwon_fck_3430es1, CK_3430ES1), + CLK("omapdss_dss", "fck", &dss1_alwon_fck_3430es2, CK_3430ES2PLUS | CK_AM35XX | CK_36XX), + CLK("omapdss_dss", "tv_clk", &dss_tv_fck, CK_3XXX), + CLK("omapdss_dss", "video_clk", &dss_96m_fck, CK_3XXX), + CLK("omapdss_dss", "sys_clk", &dss2_alwon_fck, CK_3XXX), CLK("omapdss_dss", "ick", &dss_ick_3430es1, CK_3430ES1), CLK("omapdss_dss", "ick", &dss_ick_3430es2, CK_3430ES2PLUS | CK_AM35XX | CK_36XX), CLK(NULL, "cam_mclk", &cam_mclk, CK_34XX | CK_36XX), diff --git a/arch/arm/mach-omap2/clock44xx_data.c b/arch/arm/mach-omap2/clock44xx_data.c index fdbc0426b6f4e..6ba69b1158e64 100644 --- a/arch/arm/mach-omap2/clock44xx_data.c +++ b/arch/arm/mach-omap2/clock44xx_data.c @@ -3106,11 +3106,11 @@ static struct omap_clk omap44xx_clks[] = { CLK(NULL, "dmic_sync_mux_ck", &dmic_sync_mux_ck, CK_443X), CLK(NULL, "dmic_fck", &dmic_fck, CK_443X), CLK(NULL, "dsp_fck", &dsp_fck, CK_443X), - CLK(NULL, "dss_sys_clk", &dss_sys_clk, CK_443X), - CLK(NULL, "dss_tv_clk", &dss_tv_clk, CK_443X), - CLK(NULL, "dss_dss_clk", &dss_dss_clk, CK_443X), - CLK(NULL, "dss_48mhz_clk", &dss_48mhz_clk, CK_443X), - CLK(NULL, "dss_fck", &dss_fck, CK_443X), + CLK("omapdss_dss", "sys_clk", &dss_sys_clk, CK_443X), + CLK("omapdss_dss", "tv_clk", &dss_tv_clk, CK_443X), + CLK("omapdss_dss", "dss_clk", &dss_dss_clk, CK_443X), + CLK("omapdss_dss", "video_clk", &dss_48mhz_clk, CK_443X), + CLK("omapdss_dss", "fck", &dss_fck, CK_443X), CLK(NULL, "efuse_ctrl_cust_fck", &efuse_ctrl_cust_fck, CK_443X), CLK(NULL, "emif1_fck", &emif1_fck, CK_443X), CLK(NULL, "emif2_fck", &emif2_fck, CK_443X), diff --git a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c index c4ca005f8bb51..4ed48cab06fe2 100644 --- a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c @@ -1571,7 +1571,7 @@ static struct omap_hwmod_ocp_if *omap3xxx_dss_slaves[] = { static struct omap_hwmod_opt_clk dss_opt_clks[] = { { .role = "tv_clk", .clk = "dss_tv_fck" }, - { .role = "dssclk", .clk = "dss_96m_fck" }, + { .role = "video_clk", .clk = "dss_96m_fck" }, { .role = "sys_clk", .clk = "dss2_alwon_fck" }, }; diff --git a/drivers/video/omap2/dss/dss.c b/drivers/video/omap2/dss/dss.c index a00733d6436a5..56d37bfefd4d8 100644 --- a/drivers/video/omap2/dss/dss.c +++ b/drivers/video/omap2/dss/dss.c @@ -759,19 +759,19 @@ static int dss_get_clocks(void) if (r) goto err; - r = dss_get_clock(&dss.dss1_fck, "dss1_fck"); + r = dss_get_clock(&dss.dss1_fck, "fck"); if (r) goto err; - r = dss_get_clock(&dss.dss2_fck, "dss2_fck"); + r = dss_get_clock(&dss.dss2_fck, "sys_clk"); if (r) goto err; - r = dss_get_clock(&dss.dss_54m_fck, "tv_fck"); + r = dss_get_clock(&dss.dss_54m_fck, "tv_clk"); if (r) goto err; - r = dss_get_clock(&dss.dss_96m_fck, "video_fck"); + r = dss_get_clock(&dss.dss_96m_fck, "video_clk"); if (r) goto err; -- GitLab From 6af9cd1431db952a7f9f8931497c9989a48b07df Mon Sep 17 00:00:00 2001 From: Archit Taneja Date: Mon, 31 Jan 2011 16:27:44 +0000 Subject: [PATCH 0517/2822] OMAP2PLUS: DSS2: Generalize naming of PRCM related clock enums in DSS driver enum dss_clock structure is replaced with generic names that could be used across OMAP2420, 2430, 3xxx, 44xx platforms. Signed-off-by: Sumit Semwal Signed-off-by: Archit Taneja Signed-off-by: Tomi Valkeinen --- drivers/video/omap2/dss/core.c | 4 +- drivers/video/omap2/dss/dispc.c | 10 ++--- drivers/video/omap2/dss/dpi.c | 16 ++++---- drivers/video/omap2/dss/dsi.c | 18 ++++----- drivers/video/omap2/dss/dss.c | 62 +++++++++++++++---------------- drivers/video/omap2/dss/dss.h | 10 ++--- drivers/video/omap2/dss/manager.c | 4 +- drivers/video/omap2/dss/overlay.c | 4 +- drivers/video/omap2/dss/rfbi.c | 10 ++--- drivers/video/omap2/dss/sdi.c | 8 ++-- drivers/video/omap2/dss/venc.c | 8 ++-- 11 files changed, 77 insertions(+), 77 deletions(-) diff --git a/drivers/video/omap2/dss/core.c b/drivers/video/omap2/dss/core.c index 3f7a5fcd1142c..f56ee64f5b583 100644 --- a/drivers/video/omap2/dss/core.c +++ b/drivers/video/omap2/dss/core.c @@ -184,7 +184,7 @@ static int omap_dss_probe(struct platform_device *pdev) } /* keep clocks enabled to prevent context saves/restores during init */ - dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1); + dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK); r = rfbi_init_platform_driver(); if (r) { @@ -251,7 +251,7 @@ static int omap_dss_probe(struct platform_device *pdev) pdata->default_device = dssdev; } - dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1); + dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK); return 0; diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c index 96e37f8e75dcd..dc4518c4b0e4c 100644 --- a/drivers/video/omap2/dss/dispc.c +++ b/drivers/video/omap2/dss/dispc.c @@ -551,9 +551,9 @@ void dispc_restore_context(void) static inline void enable_clocks(bool enable) { if (enable) - dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1); + dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK); else - dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1); + dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK); } bool dispc_go_busy(enum omap_channel channel) @@ -2311,7 +2311,7 @@ unsigned long dispc_fclk_rate(void) unsigned long r = 0; if (dss_get_dispc_clk_source() == DSS_SRC_DSS1_ALWON_FCLK) - r = dss_clk_get_rate(DSS_CLK_FCK1); + r = dss_clk_get_rate(DSS_CLK_FCK); else #ifdef CONFIG_OMAP2_DSS_DSI r = dsi_get_dsi1_pll_rate(); @@ -2439,7 +2439,7 @@ void dispc_dump_regs(struct seq_file *s) { #define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, dispc_read_reg(r)) - dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1); + dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK); DUMPREG(DISPC_REVISION); DUMPREG(DISPC_SYSCONFIG); @@ -2596,7 +2596,7 @@ void dispc_dump_regs(struct seq_file *s) DUMPREG(DISPC_VID_PRELOAD(0)); DUMPREG(DISPC_VID_PRELOAD(1)); - dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1); + dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK); #undef DUMPREG } diff --git a/drivers/video/omap2/dss/dpi.c b/drivers/video/omap2/dss/dpi.c index 75fb0a5154304..746f1b6dd8970 100644 --- a/drivers/video/omap2/dss/dpi.c +++ b/drivers/video/omap2/dss/dpi.c @@ -107,7 +107,7 @@ static int dpi_set_mode(struct omap_dss_device *dssdev) bool is_tft; int r = 0; - dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1); + dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK); dispc_set_pol_freq(dssdev->manager->id, dssdev->panel.config, dssdev->panel.acbi, dssdev->panel.acb); @@ -137,7 +137,7 @@ static int dpi_set_mode(struct omap_dss_device *dssdev) dispc_set_lcd_timings(dssdev->manager->id, t); err0: - dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1); + dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK); return r; } @@ -173,14 +173,14 @@ int omapdss_dpi_display_enable(struct omap_dss_device *dssdev) goto err1; } - dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1); + dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK); r = dpi_basic_init(dssdev); if (r) goto err2; #ifdef CONFIG_OMAP2_DSS_USE_DSI_PLL - dss_clk_enable(DSS_CLK_FCK2); + dss_clk_enable(DSS_CLK_SYSCK); r = dsi_pll_init(dssdev, 0, 1); if (r) goto err3; @@ -199,10 +199,10 @@ err4: #ifdef CONFIG_OMAP2_DSS_USE_DSI_PLL dsi_pll_uninit(); err3: - dss_clk_disable(DSS_CLK_FCK2); + dss_clk_disable(DSS_CLK_SYSCK); #endif err2: - dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1); + dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK); if (cpu_is_omap34xx()) regulator_disable(dpi.vdds_dsi_reg); err1: @@ -219,10 +219,10 @@ void omapdss_dpi_display_disable(struct omap_dss_device *dssdev) #ifdef CONFIG_OMAP2_DSS_USE_DSI_PLL dss_select_dispc_clk_source(DSS_SRC_DSS1_ALWON_FCLK); dsi_pll_uninit(); - dss_clk_disable(DSS_CLK_FCK2); + dss_clk_disable(DSS_CLK_SYSCK); #endif - dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1); + dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK); if (cpu_is_omap34xx()) regulator_disable(dpi.vdds_dsi_reg); diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c index c42acae10af01..c7b5382e1a6b5 100644 --- a/drivers/video/omap2/dss/dsi.c +++ b/drivers/video/omap2/dss/dsi.c @@ -654,18 +654,18 @@ static void dsi_vc_disable_bta_irq(int channel) static inline void enable_clocks(bool enable) { if (enable) - dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1); + dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK); else - dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1); + dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK); } /* source clock for DSI PLL. this could also be PCLKFREE */ static inline void dsi_enable_pll_clock(bool enable) { if (enable) - dss_clk_enable(DSS_CLK_FCK2); + dss_clk_enable(DSS_CLK_SYSCK); else - dss_clk_disable(DSS_CLK_FCK2); + dss_clk_disable(DSS_CLK_SYSCK); if (enable && dsi.pll_locked) { if (wait_for_bit_change(DSI_PLL_STATUS, 1, 1) != 1) @@ -741,7 +741,7 @@ static unsigned long dsi_fclk_rate(void) if (dss_get_dsi_clk_source() == DSS_SRC_DSS1_ALWON_FCLK) { /* DSI FCLK source is DSS1_ALWON_FCK, which is dss1_fck */ - r = dss_clk_get_rate(DSS_CLK_FCK1); + r = dss_clk_get_rate(DSS_CLK_FCK); } else { /* DSI FCLK source is DSI2_PLL_FCLK */ r = dsi_get_dsi2_pll_rate(); @@ -821,7 +821,7 @@ static int dsi_calc_clock_rates(struct omap_dss_device *dssdev, return -EINVAL; if (cinfo->use_dss2_fck) { - cinfo->clkin = dss_clk_get_rate(DSS_CLK_FCK2); + cinfo->clkin = dss_clk_get_rate(DSS_CLK_SYSCK); /* XXX it is unclear if highfreq should be used * with DSS2_FCK source also */ cinfo->highfreq = 0; @@ -867,7 +867,7 @@ int dsi_pll_calc_clock_div_pck(bool is_tft, unsigned long req_pck, int match = 0; unsigned long dss_clk_fck2; - dss_clk_fck2 = dss_clk_get_rate(DSS_CLK_FCK2); + dss_clk_fck2 = dss_clk_get_rate(DSS_CLK_SYSCK); if (req_pck == dsi.cache_req_pck && dsi.cache_cinfo.clkin == dss_clk_fck2) { @@ -1319,7 +1319,7 @@ void dsi_dump_regs(struct seq_file *s) { #define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, dsi_read_reg(r)) - dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1); + dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK); DUMPREG(DSI_REVISION); DUMPREG(DSI_SYSCONFIG); @@ -1391,7 +1391,7 @@ void dsi_dump_regs(struct seq_file *s) DUMPREG(DSI_PLL_CONFIGURATION1); DUMPREG(DSI_PLL_CONFIGURATION2); - dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1); + dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK); #undef DUMPREG } diff --git a/drivers/video/omap2/dss/dss.c b/drivers/video/omap2/dss/dss.c index 56d37bfefd4d8..0372befbb692a 100644 --- a/drivers/video/omap2/dss/dss.c +++ b/drivers/video/omap2/dss/dss.c @@ -227,7 +227,7 @@ void dss_dump_clocks(struct seq_file *s) unsigned long dpll4_ck_rate; unsigned long dpll4_m4_ck_rate; - dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1); + dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK); dpll4_ck_rate = clk_get_rate(clk_get_parent(dss.dpll4_m4_ck)); dpll4_m4_ck_rate = clk_get_rate(dss.dpll4_m4_ck); @@ -240,21 +240,21 @@ void dss_dump_clocks(struct seq_file *s) seq_printf(s, "dss1_alwon_fclk = %lu / %lu = %lu\n", dpll4_ck_rate, dpll4_ck_rate / dpll4_m4_ck_rate, - dss_clk_get_rate(DSS_CLK_FCK1)); + dss_clk_get_rate(DSS_CLK_FCK)); else seq_printf(s, "dss1_alwon_fclk = %lu / %lu * 2 = %lu\n", dpll4_ck_rate, dpll4_ck_rate / dpll4_m4_ck_rate, - dss_clk_get_rate(DSS_CLK_FCK1)); + dss_clk_get_rate(DSS_CLK_FCK)); - dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1); + dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK); } void dss_dump_regs(struct seq_file *s) { #define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, dss_read_reg(r)) - dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1); + dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK); DUMPREG(DSS_REVISION); DUMPREG(DSS_SYSCONFIG); @@ -265,7 +265,7 @@ void dss_dump_regs(struct seq_file *s) DUMPREG(DSS_PLL_CONTROL); DUMPREG(DSS_SDI_STATUS); - dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1); + dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK); #undef DUMPREG } @@ -350,7 +350,7 @@ int dss_set_clock_div(struct dss_clock_info *cinfo) int dss_get_clock_div(struct dss_clock_info *cinfo) { - cinfo->fck = dss_clk_get_rate(DSS_CLK_FCK1); + cinfo->fck = dss_clk_get_rate(DSS_CLK_FCK); if (cpu_is_omap34xx()) { unsigned long prate; @@ -391,7 +391,7 @@ int dss_calc_clock_div(bool is_tft, unsigned long req_pck, prate = dss_get_dpll4_rate(); - fck = dss_clk_get_rate(DSS_CLK_FCK1); + fck = dss_clk_get_rate(DSS_CLK_FCK); if (req_pck == dss.cache_req_pck && ((cpu_is_omap34xx() && prate == dss.cache_prate) || dss.cache_dss_cinfo.fck == fck)) { @@ -418,7 +418,7 @@ retry: if (cpu_is_omap24xx()) { struct dispc_clock_info cur_dispc; /* XXX can we change the clock on omap2? */ - fck = dss_clk_get_rate(DSS_CLK_FCK1); + fck = dss_clk_get_rate(DSS_CLK_FCK); fck_div = 1; dispc_find_clk_divs(is_tft, req_pck, fck, &cur_dispc); @@ -701,7 +701,7 @@ static void save_all_ctx(void) { DSSDBG("save context\n"); - dss_clk_enable_no_ctx(DSS_CLK_ICK | DSS_CLK_FCK1); + dss_clk_enable_no_ctx(DSS_CLK_ICK | DSS_CLK_FCK); dss_save_context(); dispc_save_context(); @@ -709,7 +709,7 @@ static void save_all_ctx(void) dsi_save_context(); #endif - dss_clk_disable_no_ctx(DSS_CLK_ICK | DSS_CLK_FCK1); + dss_clk_disable_no_ctx(DSS_CLK_ICK | DSS_CLK_FCK); } static void restore_all_ctx(void) @@ -807,13 +807,13 @@ unsigned long dss_clk_get_rate(enum dss_clock clk) switch (clk) { case DSS_CLK_ICK: return clk_get_rate(dss.dss_ick); - case DSS_CLK_FCK1: + case DSS_CLK_FCK: return clk_get_rate(dss.dss1_fck); - case DSS_CLK_FCK2: + case DSS_CLK_SYSCK: return clk_get_rate(dss.dss2_fck); - case DSS_CLK_54M: + case DSS_CLK_TVFCK: return clk_get_rate(dss.dss_54m_fck); - case DSS_CLK_96M: + case DSS_CLK_VIDFCK: return clk_get_rate(dss.dss_96m_fck); } @@ -827,13 +827,13 @@ static unsigned count_clk_bits(enum dss_clock clks) if (clks & DSS_CLK_ICK) ++num_clks; - if (clks & DSS_CLK_FCK1) + if (clks & DSS_CLK_FCK) ++num_clks; - if (clks & DSS_CLK_FCK2) + if (clks & DSS_CLK_SYSCK) ++num_clks; - if (clks & DSS_CLK_54M) + if (clks & DSS_CLK_TVFCK) ++num_clks; - if (clks & DSS_CLK_96M) + if (clks & DSS_CLK_VIDFCK) ++num_clks; return num_clks; @@ -845,13 +845,13 @@ static void dss_clk_enable_no_ctx(enum dss_clock clks) if (clks & DSS_CLK_ICK) clk_enable(dss.dss_ick); - if (clks & DSS_CLK_FCK1) + if (clks & DSS_CLK_FCK) clk_enable(dss.dss1_fck); - if (clks & DSS_CLK_FCK2) + if (clks & DSS_CLK_SYSCK) clk_enable(dss.dss2_fck); - if (clks & DSS_CLK_54M) + if (clks & DSS_CLK_TVFCK) clk_enable(dss.dss_54m_fck); - if (clks & DSS_CLK_96M) + if (clks & DSS_CLK_VIDFCK) clk_enable(dss.dss_96m_fck); dss.num_clks_enabled += num_clks; @@ -873,13 +873,13 @@ static void dss_clk_disable_no_ctx(enum dss_clock clks) if (clks & DSS_CLK_ICK) clk_disable(dss.dss_ick); - if (clks & DSS_CLK_FCK1) + if (clks & DSS_CLK_FCK) clk_disable(dss.dss1_fck); - if (clks & DSS_CLK_FCK2) + if (clks & DSS_CLK_SYSCK) clk_disable(dss.dss2_fck); - if (clks & DSS_CLK_54M) + if (clks & DSS_CLK_TVFCK) clk_disable(dss.dss_54m_fck); - if (clks & DSS_CLK_96M) + if (clks & DSS_CLK_VIDFCK) clk_disable(dss.dss_96m_fck); dss.num_clks_enabled -= num_clks; @@ -903,9 +903,9 @@ static void dss_clk_enable_all_no_ctx(void) { enum dss_clock clks; - clks = DSS_CLK_ICK | DSS_CLK_FCK1 | DSS_CLK_FCK2 | DSS_CLK_54M; + clks = DSS_CLK_ICK | DSS_CLK_FCK | DSS_CLK_SYSCK | DSS_CLK_TVFCK; if (cpu_is_omap34xx()) - clks |= DSS_CLK_96M; + clks |= DSS_CLK_VIDFCK; dss_clk_enable_no_ctx(clks); } @@ -913,9 +913,9 @@ static void dss_clk_disable_all_no_ctx(void) { enum dss_clock clks; - clks = DSS_CLK_ICK | DSS_CLK_FCK1 | DSS_CLK_FCK2 | DSS_CLK_54M; + clks = DSS_CLK_ICK | DSS_CLK_FCK | DSS_CLK_SYSCK | DSS_CLK_TVFCK; if (cpu_is_omap34xx()) - clks |= DSS_CLK_96M; + clks |= DSS_CLK_VIDFCK; dss_clk_disable_no_ctx(clks); } diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h index 981d247c30f27..4b02e079f20e1 100644 --- a/drivers/video/omap2/dss/dss.h +++ b/drivers/video/omap2/dss/dss.h @@ -112,11 +112,11 @@ enum omap_parallel_interface_mode { }; enum dss_clock { - DSS_CLK_ICK = 1 << 0, - DSS_CLK_FCK1 = 1 << 1, - DSS_CLK_FCK2 = 1 << 2, - DSS_CLK_54M = 1 << 3, - DSS_CLK_96M = 1 << 4, + DSS_CLK_ICK = 1 << 0, /* DSS_L3_ICLK and DSS_L4_ICLK */ + DSS_CLK_FCK = 1 << 1, /* DSS1_ALWON_FCLK */ + DSS_CLK_SYSCK = 1 << 2, /* DSS2_ALWON_FCLK */ + DSS_CLK_TVFCK = 1 << 3, /* DSS_TV_FCLK */ + DSS_CLK_VIDFCK = 1 << 4, /* DSS_96M_FCLK*/ }; enum dss_clk_source { diff --git a/drivers/video/omap2/dss/manager.c b/drivers/video/omap2/dss/manager.c index 172d4e6973091..1f53bf20b6cb2 100644 --- a/drivers/video/omap2/dss/manager.c +++ b/drivers/video/omap2/dss/manager.c @@ -1394,7 +1394,7 @@ static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr) } r = 0; - dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1); + dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK); if (!dss_cache.irq_enabled) { u32 mask; @@ -1407,7 +1407,7 @@ static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr) dss_cache.irq_enabled = true; } configure_dispc(); - dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1); + dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK); spin_unlock_irqrestore(&dss_cache.lock, flags); diff --git a/drivers/video/omap2/dss/overlay.c b/drivers/video/omap2/dss/overlay.c index 456efef03c20c..996e9a4f6771e 100644 --- a/drivers/video/omap2/dss/overlay.c +++ b/drivers/video/omap2/dss/overlay.c @@ -490,7 +490,7 @@ static int omap_dss_set_manager(struct omap_overlay *ovl, ovl->manager = mgr; - dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1); + dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK); /* XXX: on manual update display, in auto update mode, a bug happens * here. When an overlay is first enabled on LCD, then it's disabled, * and the manager is changed to TV, we sometimes get SYNC_LOST_DIGIT @@ -499,7 +499,7 @@ static int omap_dss_set_manager(struct omap_overlay *ovl, * but I don't understand how or why. */ msleep(40); dispc_set_channel_out(ovl->id, mgr->id); - dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1); + dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK); return 0; } diff --git a/drivers/video/omap2/dss/rfbi.c b/drivers/video/omap2/dss/rfbi.c index 6dbb95d557f8b..5ea17f49c6110 100644 --- a/drivers/video/omap2/dss/rfbi.c +++ b/drivers/video/omap2/dss/rfbi.c @@ -141,9 +141,9 @@ static inline u32 rfbi_read_reg(const struct rfbi_reg idx) static void rfbi_enable_clocks(bool enable) { if (enable) - dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1); + dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK); else - dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1); + dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK); } void omap_rfbi_write_command(const void *buf, u32 len) @@ -496,7 +496,7 @@ unsigned long rfbi_get_max_tx_rate(void) }; l4_rate = rfbi.l4_khz / 1000; - dss1_rate = dss_clk_get_rate(DSS_CLK_FCK1) / 1000000; + dss1_rate = dss_clk_get_rate(DSS_CLK_FCK) / 1000000; for (i = 0; i < ARRAY_SIZE(ftab); i++) { /* Use a window instead of an exact match, to account @@ -921,7 +921,7 @@ void rfbi_dump_regs(struct seq_file *s) { #define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, rfbi_read_reg(r)) - dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1); + dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK); DUMPREG(RFBI_REVISION); DUMPREG(RFBI_SYSCONFIG); @@ -952,7 +952,7 @@ void rfbi_dump_regs(struct seq_file *s) DUMPREG(RFBI_VSYNC_WIDTH); DUMPREG(RFBI_HSYNC_WIDTH); - dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1); + dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK); #undef DUMPREG } diff --git a/drivers/video/omap2/dss/sdi.c b/drivers/video/omap2/dss/sdi.c index b64adf7dfc88b..8272fc1f32793 100644 --- a/drivers/video/omap2/dss/sdi.c +++ b/drivers/video/omap2/dss/sdi.c @@ -70,7 +70,7 @@ int omapdss_sdi_display_enable(struct omap_dss_device *dssdev) /* In case of skip_init sdi_init has already enabled the clocks */ if (!sdi.skip_init) - dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1); + dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK); sdi_basic_init(dssdev); @@ -130,7 +130,7 @@ int omapdss_sdi_display_enable(struct omap_dss_device *dssdev) return 0; err2: - dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1); + dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK); regulator_disable(sdi.vdds_sdi_reg); err1: omap_dss_stop_device(dssdev); @@ -145,7 +145,7 @@ void omapdss_sdi_display_disable(struct omap_dss_device *dssdev) dss_sdi_disable(); - dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1); + dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK); regulator_disable(sdi.vdds_sdi_reg); @@ -175,7 +175,7 @@ int sdi_init(bool skip_init) * of them until sdi_display_enable is called. */ if (skip_init) - dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1); + dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK); return 0; } diff --git a/drivers/video/omap2/dss/venc.c b/drivers/video/omap2/dss/venc.c index ef36811f6ac8b..1aadceb76e1d9 100644 --- a/drivers/video/omap2/dss/venc.c +++ b/drivers/video/omap2/dss/venc.c @@ -391,11 +391,11 @@ static void venc_reset(void) static void venc_enable_clocks(int enable) { if (enable) - dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1 | DSS_CLK_54M | - DSS_CLK_96M); + dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK | DSS_CLK_TVFCK | + DSS_CLK_VIDFCK); else - dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1 | DSS_CLK_54M | - DSS_CLK_96M); + dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK | DSS_CLK_TVFCK | + DSS_CLK_VIDFCK); } static const struct venc_config *venc_timings_to_config( -- GitLab From c7642f67e5bd71f91d165620f601f00c7c9802c9 Mon Sep 17 00:00:00 2001 From: Archit Taneja Date: Mon, 31 Jan 2011 16:27:45 +0000 Subject: [PATCH 0518/2822] OMAP2PLUS: DSS2: Generalize external clock names in struct dss of dss.c The dss struct in dss.c has omap2/3 specific clock names. Making them generic, to increase readability and extendability. Signed-off-by: Sumit Semwal Signed-off-by: Archit Taneja Signed-off-by: Tomi Valkeinen --- drivers/video/omap2/dss/dss.c | 82 +++++++++++++++++------------------ 1 file changed, 41 insertions(+), 41 deletions(-) diff --git a/drivers/video/omap2/dss/dss.c b/drivers/video/omap2/dss/dss.c index 0372befbb692a..ab82f79376751 100644 --- a/drivers/video/omap2/dss/dss.c +++ b/drivers/video/omap2/dss/dss.c @@ -64,10 +64,10 @@ static struct { struct clk *dpll4_m4_ck; struct clk *dss_ick; - struct clk *dss1_fck; - struct clk *dss2_fck; - struct clk *dss_54m_fck; - struct clk *dss_96m_fck; + struct clk *dss_fck; + struct clk *dss_sys_clk; + struct clk *dss_tv_fck; + struct clk *dss_video_fck; unsigned num_clks_enabled; unsigned long cache_req_pck; @@ -750,28 +750,28 @@ static int dss_get_clocks(void) int r; dss.dss_ick = NULL; - dss.dss1_fck = NULL; - dss.dss2_fck = NULL; - dss.dss_54m_fck = NULL; - dss.dss_96m_fck = NULL; + dss.dss_fck = NULL; + dss.dss_sys_clk = NULL; + dss.dss_tv_fck = NULL; + dss.dss_video_fck = NULL; r = dss_get_clock(&dss.dss_ick, "ick"); if (r) goto err; - r = dss_get_clock(&dss.dss1_fck, "fck"); + r = dss_get_clock(&dss.dss_fck, "fck"); if (r) goto err; - r = dss_get_clock(&dss.dss2_fck, "sys_clk"); + r = dss_get_clock(&dss.dss_sys_clk, "sys_clk"); if (r) goto err; - r = dss_get_clock(&dss.dss_54m_fck, "tv_clk"); + r = dss_get_clock(&dss.dss_tv_fck, "tv_clk"); if (r) goto err; - r = dss_get_clock(&dss.dss_96m_fck, "video_clk"); + r = dss_get_clock(&dss.dss_video_fck, "video_clk"); if (r) goto err; @@ -780,25 +780,25 @@ static int dss_get_clocks(void) err: if (dss.dss_ick) clk_put(dss.dss_ick); - if (dss.dss1_fck) - clk_put(dss.dss1_fck); - if (dss.dss2_fck) - clk_put(dss.dss2_fck); - if (dss.dss_54m_fck) - clk_put(dss.dss_54m_fck); - if (dss.dss_96m_fck) - clk_put(dss.dss_96m_fck); + if (dss.dss_fck) + clk_put(dss.dss_fck); + if (dss.dss_sys_clk) + clk_put(dss.dss_sys_clk); + if (dss.dss_tv_fck) + clk_put(dss.dss_tv_fck); + if (dss.dss_video_fck) + clk_put(dss.dss_video_fck); return r; } static void dss_put_clocks(void) { - if (dss.dss_96m_fck) - clk_put(dss.dss_96m_fck); - clk_put(dss.dss_54m_fck); - clk_put(dss.dss1_fck); - clk_put(dss.dss2_fck); + if (dss.dss_video_fck) + clk_put(dss.dss_video_fck); + clk_put(dss.dss_tv_fck); + clk_put(dss.dss_fck); + clk_put(dss.dss_sys_clk); clk_put(dss.dss_ick); } @@ -808,13 +808,13 @@ unsigned long dss_clk_get_rate(enum dss_clock clk) case DSS_CLK_ICK: return clk_get_rate(dss.dss_ick); case DSS_CLK_FCK: - return clk_get_rate(dss.dss1_fck); + return clk_get_rate(dss.dss_fck); case DSS_CLK_SYSCK: - return clk_get_rate(dss.dss2_fck); + return clk_get_rate(dss.dss_sys_clk); case DSS_CLK_TVFCK: - return clk_get_rate(dss.dss_54m_fck); + return clk_get_rate(dss.dss_tv_fck); case DSS_CLK_VIDFCK: - return clk_get_rate(dss.dss_96m_fck); + return clk_get_rate(dss.dss_video_fck); } BUG(); @@ -846,13 +846,13 @@ static void dss_clk_enable_no_ctx(enum dss_clock clks) if (clks & DSS_CLK_ICK) clk_enable(dss.dss_ick); if (clks & DSS_CLK_FCK) - clk_enable(dss.dss1_fck); + clk_enable(dss.dss_fck); if (clks & DSS_CLK_SYSCK) - clk_enable(dss.dss2_fck); + clk_enable(dss.dss_sys_clk); if (clks & DSS_CLK_TVFCK) - clk_enable(dss.dss_54m_fck); + clk_enable(dss.dss_tv_fck); if (clks & DSS_CLK_VIDFCK) - clk_enable(dss.dss_96m_fck); + clk_enable(dss.dss_video_fck); dss.num_clks_enabled += num_clks; } @@ -874,13 +874,13 @@ static void dss_clk_disable_no_ctx(enum dss_clock clks) if (clks & DSS_CLK_ICK) clk_disable(dss.dss_ick); if (clks & DSS_CLK_FCK) - clk_disable(dss.dss1_fck); + clk_disable(dss.dss_fck); if (clks & DSS_CLK_SYSCK) - clk_disable(dss.dss2_fck); + clk_disable(dss.dss_sys_clk); if (clks & DSS_CLK_TVFCK) - clk_disable(dss.dss_54m_fck); + clk_disable(dss.dss_tv_fck); if (clks & DSS_CLK_VIDFCK) - clk_disable(dss.dss_96m_fck); + clk_disable(dss.dss_video_fck); dss.num_clks_enabled -= num_clks; } @@ -926,10 +926,10 @@ static void core_dump_clocks(struct seq_file *s) int i; struct clk *clocks[5] = { dss.dss_ick, - dss.dss1_fck, - dss.dss2_fck, - dss.dss_54m_fck, - dss.dss_96m_fck + dss.dss_fck, + dss.dss_sys_clk, + dss.dss_tv_fck, + dss.dss_video_fck }; seq_printf(s, "- CORE -\n"); -- GitLab From f38190d61fe378d8eaf21b160c22e78b3b925747 Mon Sep 17 00:00:00 2001 From: Sumit Semwal Date: Mon, 31 Jan 2011 16:27:46 +0000 Subject: [PATCH 0519/2822] OMAP4: DSS2: clocks: Add ick as dummy clock DSS code uses ick as one of the clocks in clk_get/clk_put. OMAP4 clock database doesn't have ick for DSS, so adding ick as dummy clock. This is needed for backward compatibility with OMAP2/3. Once pm_runtime* APIs get introduced in DSS, this will be revisited. Signed-off-by: Sumit Semwal Signed-off-by: Tomi Valkeinen --- arch/arm/mach-omap2/clock44xx_data.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/arch/arm/mach-omap2/clock44xx_data.c b/arch/arm/mach-omap2/clock44xx_data.c index 6ba69b1158e64..5551013735956 100644 --- a/arch/arm/mach-omap2/clock44xx_data.c +++ b/arch/arm/mach-omap2/clock44xx_data.c @@ -3111,6 +3111,11 @@ static struct omap_clk omap44xx_clks[] = { CLK("omapdss_dss", "dss_clk", &dss_dss_clk, CK_443X), CLK("omapdss_dss", "video_clk", &dss_48mhz_clk, CK_443X), CLK("omapdss_dss", "fck", &dss_fck, CK_443X), + /* + * On OMAP4, DSS ick is a dummy clock; this is needed for compatibility + * with OMAP2/3. + */ + CLK("omapdss_dss", "ick", &dummy_ck, CK_443X), CLK(NULL, "efuse_ctrl_cust_fck", &efuse_ctrl_cust_fck, CK_443X), CLK(NULL, "emif1_fck", &emif1_fck, CK_443X), CLK(NULL, "emif2_fck", &emif2_fck, CK_443X), -- GitLab From 3f3aa06c46796cd2dc0f71d7d2f41bb75f7e97ff Mon Sep 17 00:00:00 2001 From: Mayuresh Janorkar Date: Tue, 15 Feb 2011 22:54:29 -0600 Subject: [PATCH 0520/2822] OMAP2PLUS: DSS2: Add OMAP4 Kconfig support Enable DSS2 and OMAPFB for OMAP4 in Kconfig Signed-off-by: Mayuresh Janorkar Signed-off-by: Tomi Valkeinen --- drivers/video/omap2/dss/Kconfig | 6 +++--- drivers/video/omap2/omapfb/Kconfig | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/video/omap2/dss/Kconfig b/drivers/video/omap2/dss/Kconfig index 43b64403eaa45..db01473c3307f 100644 --- a/drivers/video/omap2/dss/Kconfig +++ b/drivers/video/omap2/dss/Kconfig @@ -1,8 +1,8 @@ menuconfig OMAP2_DSS - tristate "OMAP2/3 Display Subsystem support (EXPERIMENTAL)" - depends on ARCH_OMAP2 || ARCH_OMAP3 + tristate "OMAP2+ Display Subsystem support (EXPERIMENTAL)" + depends on ARCH_OMAP2PLUS help - OMAP2/3 Display Subsystem support. + OMAP2+ Display Subsystem support. if OMAP2_DSS diff --git a/drivers/video/omap2/omapfb/Kconfig b/drivers/video/omap2/omapfb/Kconfig index 65149b22cf373..aa33386c81ff2 100644 --- a/drivers/video/omap2/omapfb/Kconfig +++ b/drivers/video/omap2/omapfb/Kconfig @@ -1,5 +1,5 @@ menuconfig FB_OMAP2 - tristate "OMAP2/3 frame buffer support (EXPERIMENTAL)" + tristate "OMAP2+ frame buffer support (EXPERIMENTAL)" depends on FB && OMAP2_DSS select OMAP2_VRAM @@ -8,10 +8,10 @@ menuconfig FB_OMAP2 select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT help - Frame buffer driver for OMAP2/3 based boards. + Frame buffer driver for OMAP2+ based boards. config FB_OMAP2_DEBUG_SUPPORT - bool "Debug support for OMAP2/3 FB" + bool "Debug support for OMAP2+ FB" default y depends on FB_OMAP2 help -- GitLab From 545376e734a6b0a4c66efb7616724ae4dbb2e57a Mon Sep 17 00:00:00 2001 From: Mayuresh Janorkar Date: Thu, 27 Jan 2011 11:17:04 +0000 Subject: [PATCH 0521/2822] OMAP4: DSS2: Add hwmod device names for OMAP4. Add hwmod device names for OMAP4; this enables device build for omap4 dss hwmod IPs. Signed-off-by: Sumit Semwal Signed-off-by: Mayuresh Janorkar Signed-off-by: Tomi Valkeinen --- arch/arm/mach-omap2/display.c | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/arch/arm/mach-omap2/display.c b/arch/arm/mach-omap2/display.c index ee8303037d3df..16d0db6718aee 100644 --- a/arch/arm/mach-omap2/display.c +++ b/arch/arm/mach-omap2/display.c @@ -52,22 +52,28 @@ int __init omap_display_init(struct omap_dss_board_info *board_data) /* * omap: valid DSS hwmod names - * omap2,3: dss_core, dss_dispc, dss_rfbi, dss_venc - * omap3: dss_dsi1 + * omap2,3,4: dss_core, dss_dispc, dss_rfbi, dss_venc + * omap3,4: dss_dsi1 + * omap4: dss_dsi2, dss_hdmi */ char *oh_name[] = { "dss_core", "dss_dispc", "dss_rfbi", "dss_venc", - "dss_dsi1" }; + "dss_dsi1", "dss_dsi2", "dss_hdmi" }; char *dev_name[] = { "omapdss_dss", "omapdss_dispc", "omapdss_rfbi", - "omapdss_venc", "omapdss_dsi1" }; + "omapdss_venc", "omapdss_dsi1", "omapdss_dsi2", + "omapdss_hdmi" }; int oh_count; memset(&pdata, 0, sizeof(pdata)); if (cpu_is_omap24xx()) - oh_count = ARRAY_SIZE(oh_name) - 1; - /* last hwmod dev in oh_name is not available for omap2 */ - else + oh_count = ARRAY_SIZE(oh_name) - 3; + /* last 3 hwmod dev in oh_name are not available for omap2 */ + else if (cpu_is_omap44xx()) oh_count = ARRAY_SIZE(oh_name); + else + oh_count = ARRAY_SIZE(oh_name) - 2; + /* last 2 hwmod dev in oh_name are not available for omap3 */ + pdata.board_data = board_data; pdata.board_data->get_last_off_on_transaction_id = NULL; -- GitLab From ac425ed5fb0b6564d4eeee9fb13ef0c1f6da8e8f Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Wed, 16 Feb 2011 04:53:44 -0600 Subject: [PATCH 0522/2822] OMAP: DSS2: Fix def_disp module param description MODULE_PARM_DESC() takes the name of the actual module parameter, not the name of the variable, as input. Fix the module parameter description for def_disp. Signed-off-by: Jani Nikula Signed-off-by: Tomi Valkeinen --- drivers/video/omap2/dss/core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/video/omap2/dss/core.c b/drivers/video/omap2/dss/core.c index f56ee64f5b583..bcf69a462b5f5 100644 --- a/drivers/video/omap2/dss/core.c +++ b/drivers/video/omap2/dss/core.c @@ -47,7 +47,7 @@ static struct { static char *def_disp_name; module_param_named(def_disp, def_disp_name, charp, 0); -MODULE_PARM_DESC(def_disp_name, "default display name"); +MODULE_PARM_DESC(def_disp, "default display name"); #ifdef DEBUG unsigned int dss_debug; -- GitLab From 5f42f2ce63f5ecbd9bc744b9c25d9786e9a8e3b4 Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Tue, 22 Feb 2011 15:53:46 +0200 Subject: [PATCH 0523/2822] OMAP: DSS2: Delay regulator_get() calls DSS submodules DPI/SDI/DSI/VENC require a regulator to function. However, if the board doesn't use, say, SDI, the board shouldn't need to configure vdds_sdi regulator required by the SDI module. Currently the regulators are acquired when the DSS driver is loaded. This means that if the kernel is configured with SDI, vdds_sdi regulator is needed for all boards. This patch changes the DSS driver to acquire the regulators only when a display of particular type is initialized. For example, vdds_sdi is acquired when sdi_init_display() is called. Signed-off-by: Tomi Valkeinen --- drivers/video/omap2/dss/dpi.c | 21 ++++++++++++-------- drivers/video/omap2/dss/dsi.c | 36 ++++++++++++---------------------- drivers/video/omap2/dss/sdi.c | 18 ++++++++++++----- drivers/video/omap2/dss/venc.c | 31 ++++++++++++----------------- 4 files changed, 52 insertions(+), 54 deletions(-) diff --git a/drivers/video/omap2/dss/dpi.c b/drivers/video/omap2/dss/dpi.c index 746f1b6dd8970..026702b921e5a 100644 --- a/drivers/video/omap2/dss/dpi.c +++ b/drivers/video/omap2/dss/dpi.c @@ -303,22 +303,27 @@ int dpi_init_display(struct omap_dss_device *dssdev) { DSSDBG("init_display\n"); - return 0; -} + if (cpu_is_omap34xx() && dpi.vdds_dsi_reg == NULL) { + struct regulator *vdds_dsi; -int dpi_init(struct platform_device *pdev) -{ - if (cpu_is_omap34xx()) { - dpi.vdds_dsi_reg = dss_get_vdds_dsi(); - if (IS_ERR(dpi.vdds_dsi_reg)) { + vdds_dsi = dss_get_vdds_dsi(); + + if (IS_ERR(vdds_dsi)) { DSSERR("can't get VDDS_DSI regulator\n"); - return PTR_ERR(dpi.vdds_dsi_reg); + return PTR_ERR(vdds_dsi); } + + dpi.vdds_dsi_reg = vdds_dsi; } return 0; } +int dpi_init(struct platform_device *pdev) +{ + return 0; +} + void dpi_exit(void) { } diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c index c7b5382e1a6b5..2928cddeb3fc4 100644 --- a/drivers/video/omap2/dss/dsi.c +++ b/drivers/video/omap2/dss/dsi.c @@ -291,20 +291,6 @@ static inline u32 dsi_read_reg(const struct dsi_reg idx) return __raw_readl(dsi.base + idx.idx); } -static struct regulator *dsi_get_vdds_dsi(void) -{ - struct regulator *reg; - - if (dsi.vdds_dsi_reg != NULL) - return dsi.vdds_dsi_reg; - - reg = regulator_get(&dsi.pdev->dev, "vdds_dsi"); - if (!IS_ERR(reg)) - dsi.vdds_dsi_reg = reg; - - return reg; -} - void dsi_save_context(void) { @@ -3236,6 +3222,19 @@ int dsi_init_display(struct omap_dss_device *dssdev) dsi.vc[0].dssdev = dssdev; dsi.vc[1].dssdev = dssdev; + if (dsi.vdds_dsi_reg == NULL) { + struct regulator *vdds_dsi; + + vdds_dsi = regulator_get(&dsi.pdev->dev, "vdds_dsi"); + + if (IS_ERR(vdds_dsi)) { + DSSERR("can't get VDDS_DSI regulator\n"); + return PTR_ERR(vdds_dsi); + } + + dsi.vdds_dsi_reg = vdds_dsi; + } + return 0; } @@ -3295,13 +3294,6 @@ static int dsi_init(struct platform_device *pdev) goto err1; } - dsi.vdds_dsi_reg = dsi_get_vdds_dsi(); - if (IS_ERR(dsi.vdds_dsi_reg)) { - DSSERR("can't get VDDS_DSI regulator\n"); - r = PTR_ERR(dsi.vdds_dsi_reg); - goto err2; - } - enable_clocks(1); rev = dsi_read_reg(DSI_REVISION); @@ -3311,8 +3303,6 @@ static int dsi_init(struct platform_device *pdev) enable_clocks(0); return 0; -err2: - iounmap(dsi.base); err1: destroy_workqueue(dsi.workqueue); return r; diff --git a/drivers/video/omap2/dss/sdi.c b/drivers/video/omap2/dss/sdi.c index 8272fc1f32793..9f10a0d9e7609 100644 --- a/drivers/video/omap2/dss/sdi.c +++ b/drivers/video/omap2/dss/sdi.c @@ -157,6 +157,19 @@ int sdi_init_display(struct omap_dss_device *dssdev) { DSSDBG("SDI init\n"); + if (sdi.vdds_sdi_reg == NULL) { + struct regulator *vdds_sdi; + + vdds_sdi = dss_get_vdds_sdi(); + + if (IS_ERR(vdds_sdi)) { + DSSERR("can't get VDDS_SDI regulator\n"); + return PTR_ERR(vdds_sdi); + } + + sdi.vdds_sdi_reg = vdds_sdi; + } + return 0; } @@ -165,11 +178,6 @@ int sdi_init(bool skip_init) /* we store this for first display enable, then clear it */ sdi.skip_init = skip_init; - sdi.vdds_sdi_reg = dss_get_vdds_sdi(); - if (IS_ERR(sdi.vdds_sdi_reg)) { - DSSERR("can't get VDDS_SDI regulator\n"); - return PTR_ERR(sdi.vdds_sdi_reg); - } /* * Enable clocks already here, otherwise there would be a toggle * of them until sdi_display_enable is called. diff --git a/drivers/video/omap2/dss/venc.c b/drivers/video/omap2/dss/venc.c index 1aadceb76e1d9..43009e57cd3e1 100644 --- a/drivers/video/omap2/dss/venc.c +++ b/drivers/video/omap2/dss/venc.c @@ -305,17 +305,6 @@ static inline u32 venc_read_reg(int idx) return l; } -static struct regulator *venc_get_vdda_dac(void) -{ - struct regulator *reg; - - reg = regulator_get(&venc.pdev->dev, "vdda_dac"); - if (!IS_ERR(reg)) - venc.vdda_dac_reg = reg; - - return reg; -} - static void venc_write_config(const struct venc_config *config) { DSSDBG("write venc conf\n"); @@ -655,6 +644,19 @@ int venc_init_display(struct omap_dss_device *dssdev) { DSSDBG("init_display\n"); + if (venc.vdda_dac_reg == NULL) { + struct regulator *vdda_dac; + + vdda_dac = regulator_get(&venc.pdev->dev, "vdda_dac"); + + if (IS_ERR(vdda_dac)) { + DSSERR("can't get VDDA_DAC regulator\n"); + return PTR_ERR(vdda_dac); + } + + venc.vdda_dac_reg = vdda_dac; + } + return 0; } @@ -734,13 +736,6 @@ static int omap_venchw_probe(struct platform_device *pdev) return -ENOMEM; } - venc.vdda_dac_reg = venc_get_vdda_dac(); - if (IS_ERR(venc.vdda_dac_reg)) { - iounmap(venc.base); - DSSERR("can't get VDDA_DAC regulator\n"); - return PTR_ERR(venc.vdda_dac_reg); - } - venc_enable_clocks(1); rev_id = (u8)(venc_read_reg(VENC_REV_ID) & 0xff); -- GitLab From 09dc89cb3123d102e1615fab9e3d65a70402d061 Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Tue, 22 Feb 2011 16:39:47 +0200 Subject: [PATCH 0524/2822] OMAP: DSS2: Support for Samsung LTE430WQ-F0C Add support for Samsung LTE430WQ-F0C to panel-generic-dpi. Signed-off-by: Tomi Valkeinen --- .../video/omap2/displays/panel-generic-dpi.c | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/drivers/video/omap2/displays/panel-generic-dpi.c b/drivers/video/omap2/displays/panel-generic-dpi.c index 07eb30ee59c87..4a9b9ff59467f 100644 --- a/drivers/video/omap2/displays/panel-generic-dpi.c +++ b/drivers/video/omap2/displays/panel-generic-dpi.c @@ -156,6 +156,31 @@ static struct panel_config generic_dpi_panels[] = { .power_off_delay = 0, .name = "toppoly_tdo35s", }, + + /* Samsung LTE430WQ-F0C */ + { + { + .x_res = 480, + .y_res = 272, + + .pixel_clock = 9200, + + .hfp = 8, + .hsw = 41, + .hbp = 45 - 41, + + .vfp = 4, + .vsw = 10, + .vbp = 12 - 10, + }, + .acbi = 0x0, + .acb = 0x0, + .config = OMAP_DSS_LCD_TFT | OMAP_DSS_LCD_IVS | + OMAP_DSS_LCD_IHS, + .power_on_delay = 0, + .power_off_delay = 0, + .name = "samsung_lte430wq_f0c", + }, }; struct panel_drv_data { -- GitLab From 371e2081447ce2bc6a25c20b513b9ba33cf5769e Mon Sep 17 00:00:00 2001 From: "Janorkar, Mayuresh" Date: Tue, 22 Feb 2011 07:35:13 -0600 Subject: [PATCH 0525/2822] OMAPFB: Adding a check for timings in set_def_mode When omapfb.mode is passed through bootargs, when omapfb is setting mode, it would check if timings passed are fine for panel attached to it. It makes use of check_timing API provided by the panel. In current code if check_timing API is not available for attached panel, OMAPFB would return -EINVAL and BPP sent via bootargs will not have any effect. In case of panels like TAAL panel, omapfb or any other driver should not be allowed to change the timings. So bpps sent via bootargs will not have an effect. In such case we can check only the x_res and y_res with the panels resolution and if they match go ahead and set the bpps. The bpp value sent via bootarg would have an effect. Signed-off-by: Mayuresh Janorkar Signed-off-by: Tomi Valkeinen --- drivers/video/omap2/omapfb/omapfb-main.c | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/drivers/video/omap2/omapfb/omapfb-main.c b/drivers/video/omap2/omapfb/omapfb-main.c index 4fdab8e9c4963..505ec66720490 100644 --- a/drivers/video/omap2/omapfb/omapfb-main.c +++ b/drivers/video/omap2/omapfb/omapfb-main.c @@ -2090,7 +2090,7 @@ static int omapfb_set_def_mode(struct omapfb2_device *fbdev, { int r; u8 bpp; - struct omap_video_timings timings; + struct omap_video_timings timings, temp_timings; r = omapfb_mode_to_timings(mode_str, &timings, &bpp); if (r) @@ -2100,14 +2100,23 @@ static int omapfb_set_def_mode(struct omapfb2_device *fbdev, fbdev->bpp_overrides[fbdev->num_bpp_overrides].bpp = bpp; ++fbdev->num_bpp_overrides; - if (!display->driver->check_timings || !display->driver->set_timings) - return -EINVAL; + if (display->driver->check_timings) { + r = display->driver->check_timings(display, &timings); + if (r) + return r; + } else { + /* If check_timings is not present compare xres and yres */ + if (display->driver->get_timings) { + display->driver->get_timings(display, &temp_timings); - r = display->driver->check_timings(display, &timings); - if (r) - return r; + if (temp_timings.x_res != timings.x_res || + temp_timings.y_res != timings.y_res) + return -EINVAL; + } + } - display->driver->set_timings(display, &timings); + if (display->driver->set_timings) + display->driver->set_timings(display, &timings); return 0; } -- GitLab From affe360d13e54b415cde2f11cee02369b4ed54bd Mon Sep 17 00:00:00 2001 From: archit taneja Date: Wed, 23 Feb 2011 08:41:03 +0000 Subject: [PATCH 0526/2822] OMAP: DSS2: Have separate irq handlers for DISPC and DSI Currently, the core DSS platform device requests for an irq line for OMAP2 and OMAP3. Make DISPC and DSI platform devices request for a shared IRQ line. On OMAP3, the logical OR of DSI and DISPC interrupt lines goes to the MPU. There is a register DSS_IRQSTATUS which tells if the interrupt came from DISPC or DSI. On OMAP2, there is no DSI, only DISPC interrupts goto the MPU. There is no DSS_IRQSTATUS register. Hence, it makes more sense to have separate irq handlers corresponding to the DSS sub modules instead of having a common handler. Since on OMAP3 the logical OR of the lines goes to MPU, the irq line is shared among the IRQ handlers. The hwmod irq info has been removed for DSS to DISPC and DSI for OMAP2 and OMAP3 hwmod databases. The Probes of DISPC and DSI now request for irq handlers. Signed-off-by: Archit Taneja Signed-off-by: Tomi Valkeinen --- arch/arm/mach-omap2/omap_hwmod_2420_data.c | 13 +++--- arch/arm/mach-omap2/omap_hwmod_2430_data.c | 12 ++--- arch/arm/mach-omap2/omap_hwmod_3xxx_data.c | 21 +++++---- drivers/video/omap2/dss/dispc.c | 40 +++++++++++++++-- drivers/video/omap2/dss/dsi.c | 25 ++++++++++- drivers/video/omap2/dss/dss.c | 51 +--------------------- 6 files changed, 84 insertions(+), 78 deletions(-) diff --git a/arch/arm/mach-omap2/omap_hwmod_2420_data.c b/arch/arm/mach-omap2/omap_hwmod_2420_data.c index 61e58bd27aec3..3a1ad00749787 100644 --- a/arch/arm/mach-omap2/omap_hwmod_2420_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_2420_data.c @@ -1168,11 +1168,6 @@ static struct omap_hwmod_class omap2420_dss_hwmod_class = { .sysc = &omap2420_dss_sysc, }; -/* dss */ -static struct omap_hwmod_irq_info omap2420_dss_irqs[] = { - { .irq = 25 }, -}; - static struct omap_hwmod_dma_info omap2420_dss_sdma_chs[] = { { .name = "dispc", .dma_req = 5 }, }; @@ -1221,8 +1216,6 @@ static struct omap_hwmod omap2420_dss_core_hwmod = { .name = "dss_core", .class = &omap2420_dss_hwmod_class, .main_clk = "dss1_fck", /* instead of dss_fck */ - .mpu_irqs = omap2420_dss_irqs, - .mpu_irqs_cnt = ARRAY_SIZE(omap2420_dss_irqs), .sdma_reqs = omap2420_dss_sdma_chs, .sdma_reqs_cnt = ARRAY_SIZE(omap2420_dss_sdma_chs), .prcm = { @@ -1265,6 +1258,10 @@ static struct omap_hwmod_class omap2420_dispc_hwmod_class = { .sysc = &omap2420_dispc_sysc, }; +static struct omap_hwmod_irq_info omap2420_dispc_irqs[] = { + { .irq = 25 }, +}; + static struct omap_hwmod_addr_space omap2420_dss_dispc_addrs[] = { { .pa_start = 0x48050400, @@ -1297,6 +1294,8 @@ static struct omap_hwmod_ocp_if *omap2420_dss_dispc_slaves[] = { static struct omap_hwmod omap2420_dss_dispc_hwmod = { .name = "dss_dispc", .class = &omap2420_dispc_hwmod_class, + .mpu_irqs = omap2420_dispc_irqs, + .mpu_irqs_cnt = ARRAY_SIZE(omap2420_dispc_irqs), .main_clk = "dss1_fck", .prcm = { .omap2 = { diff --git a/arch/arm/mach-omap2/omap_hwmod_2430_data.c b/arch/arm/mach-omap2/omap_hwmod_2430_data.c index 490789a6bed0d..c905c1bf90c42 100644 --- a/arch/arm/mach-omap2/omap_hwmod_2430_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_2430_data.c @@ -1268,10 +1268,6 @@ static struct omap_hwmod_class omap2430_dss_hwmod_class = { .sysc = &omap2430_dss_sysc, }; -/* dss */ -static struct omap_hwmod_irq_info omap2430_dss_irqs[] = { - { .irq = 25 }, -}; static struct omap_hwmod_dma_info omap2430_dss_sdma_chs[] = { { .name = "dispc", .dma_req = 5 }, }; @@ -1314,8 +1310,6 @@ static struct omap_hwmod omap2430_dss_core_hwmod = { .name = "dss_core", .class = &omap2430_dss_hwmod_class, .main_clk = "dss1_fck", /* instead of dss_fck */ - .mpu_irqs = omap2430_dss_irqs, - .mpu_irqs_cnt = ARRAY_SIZE(omap2430_dss_irqs), .sdma_reqs = omap2430_dss_sdma_chs, .sdma_reqs_cnt = ARRAY_SIZE(omap2430_dss_sdma_chs), .prcm = { @@ -1358,6 +1352,10 @@ static struct omap_hwmod_class omap2430_dispc_hwmod_class = { .sysc = &omap2430_dispc_sysc, }; +static struct omap_hwmod_irq_info omap2430_dispc_irqs[] = { + { .irq = 25 }, +}; + static struct omap_hwmod_addr_space omap2430_dss_dispc_addrs[] = { { .pa_start = 0x48050400, @@ -1384,6 +1382,8 @@ static struct omap_hwmod_ocp_if *omap2430_dss_dispc_slaves[] = { static struct omap_hwmod omap2430_dss_dispc_hwmod = { .name = "dss_dispc", .class = &omap2430_dispc_hwmod_class, + .mpu_irqs = omap2430_dispc_irqs, + .mpu_irqs_cnt = ARRAY_SIZE(omap2430_dispc_irqs), .main_clk = "dss1_fck", .prcm = { .omap2 = { diff --git a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c index 4ed48cab06fe2..f997b0e9759d6 100644 --- a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c @@ -1503,11 +1503,6 @@ static struct omap_hwmod_class omap3xxx_dss_hwmod_class = { .sysc = &omap3xxx_dss_sysc, }; -/* dss */ -static struct omap_hwmod_irq_info omap3xxx_dss_irqs[] = { - { .irq = 25 }, -}; - static struct omap_hwmod_dma_info omap3xxx_dss_sdma_chs[] = { { .name = "dispc", .dma_req = 5 }, { .name = "dsi1", .dma_req = 74 }, @@ -1579,8 +1574,6 @@ static struct omap_hwmod omap3430es1_dss_core_hwmod = { .name = "dss_core", .class = &omap3xxx_dss_hwmod_class, .main_clk = "dss1_alwon_fck", /* instead of dss_fck */ - .mpu_irqs = omap3xxx_dss_irqs, - .mpu_irqs_cnt = ARRAY_SIZE(omap3xxx_dss_irqs), .sdma_reqs = omap3xxx_dss_sdma_chs, .sdma_reqs_cnt = ARRAY_SIZE(omap3xxx_dss_sdma_chs), @@ -1607,8 +1600,6 @@ static struct omap_hwmod omap3xxx_dss_core_hwmod = { .name = "dss_core", .class = &omap3xxx_dss_hwmod_class, .main_clk = "dss1_alwon_fck", /* instead of dss_fck */ - .mpu_irqs = omap3xxx_dss_irqs, - .mpu_irqs_cnt = ARRAY_SIZE(omap3xxx_dss_irqs), .sdma_reqs = omap3xxx_dss_sdma_chs, .sdma_reqs_cnt = ARRAY_SIZE(omap3xxx_dss_sdma_chs), @@ -1654,6 +1645,10 @@ static struct omap_hwmod_class omap3xxx_dispc_hwmod_class = { .sysc = &omap3xxx_dispc_sysc, }; +static struct omap_hwmod_irq_info omap3xxx_dispc_irqs[] = { + { .irq = 25 }, +}; + static struct omap_hwmod_addr_space omap3xxx_dss_dispc_addrs[] = { { .pa_start = 0x48050400, @@ -1687,6 +1682,8 @@ static struct omap_hwmod_ocp_if *omap3xxx_dss_dispc_slaves[] = { static struct omap_hwmod omap3xxx_dss_dispc_hwmod = { .name = "dss_dispc", .class = &omap3xxx_dispc_hwmod_class, + .mpu_irqs = omap3xxx_dispc_irqs, + .mpu_irqs_cnt = ARRAY_SIZE(omap3xxx_dispc_irqs), .main_clk = "dss1_alwon_fck", .prcm = { .omap2 = { @@ -1712,6 +1709,10 @@ static struct omap_hwmod_class omap3xxx_dsi_hwmod_class = { .name = "dsi", }; +static struct omap_hwmod_irq_info omap3xxx_dsi1_irqs[] = { + { .irq = 25 }, +}; + /* dss_dsi1 */ static struct omap_hwmod_addr_space omap3xxx_dss_dsi1_addrs[] = { { @@ -1745,6 +1746,8 @@ static struct omap_hwmod_ocp_if *omap3xxx_dss_dsi1_slaves[] = { static struct omap_hwmod omap3xxx_dss_dsi1_hwmod = { .name = "dss_dsi1", .class = &omap3xxx_dsi_hwmod_class, + .mpu_irqs = omap3xxx_dsi1_irqs, + .mpu_irqs_cnt = ARRAY_SIZE(omap3xxx_dsi1_irqs), .main_clk = "dss1_alwon_fck", .prcm = { .omap2 = { diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c index dc4518c4b0e4c..43f7091c71cb8 100644 --- a/drivers/video/omap2/dss/dispc.c +++ b/drivers/video/omap2/dss/dispc.c @@ -32,6 +32,7 @@ #include #include #include +#include #include #include @@ -178,6 +179,7 @@ struct dispc_irq_stats { static struct { struct platform_device *pdev; void __iomem *base; + int irq; u32 fifo_size[3]; @@ -2865,10 +2867,10 @@ static void print_irq_status(u32 status) * but we presume they are on because we got an IRQ. However, * an irq handler may turn the clocks off, so we may not have * clock later in the function. */ -void dispc_irq_handler(void) +static irqreturn_t omap_dispc_irq_handler(int irq, void *arg) { int i; - u32 irqstatus; + u32 irqstatus, irqenable; u32 handledirqs = 0; u32 unhandled_errors; struct omap_dispc_isr_data *isr_data; @@ -2877,6 +2879,13 @@ void dispc_irq_handler(void) spin_lock(&dispc.irq_lock); irqstatus = dispc_read_reg(DISPC_IRQSTATUS); + irqenable = dispc_read_reg(DISPC_IRQENABLE); + + /* IRQ is not for us */ + if (!(irqstatus & irqenable)) { + spin_unlock(&dispc.irq_lock); + return IRQ_NONE; + } #ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS spin_lock(&dispc.irq_stats_lock); @@ -2928,6 +2937,8 @@ void dispc_irq_handler(void) } spin_unlock(&dispc.irq_lock); + + return IRQ_HANDLED; } static void dispc_error_worker(struct work_struct *work) @@ -3322,6 +3333,7 @@ int dispc_setup_plane(enum omap_plane plane, static int omap_dispchw_probe(struct platform_device *pdev) { u32 rev; + int r = 0; struct resource *dispc_mem; dispc.pdev = pdev; @@ -3338,12 +3350,27 @@ static int omap_dispchw_probe(struct platform_device *pdev) dispc_mem = platform_get_resource(dispc.pdev, IORESOURCE_MEM, 0); if (!dispc_mem) { DSSERR("can't get IORESOURCE_MEM DISPC\n"); - return -EINVAL; + r = -EINVAL; + goto fail0; } dispc.base = ioremap(dispc_mem->start, resource_size(dispc_mem)); if (!dispc.base) { DSSERR("can't ioremap DISPC\n"); - return -ENOMEM; + r = -ENOMEM; + goto fail0; + } + dispc.irq = platform_get_irq(dispc.pdev, 0); + if (dispc.irq < 0) { + DSSERR("platform_get_irq failed\n"); + r = -ENODEV; + goto fail1; + } + + r = request_irq(dispc.irq, omap_dispc_irq_handler, IRQF_SHARED, + "OMAP DISPC", dispc.pdev); + if (r < 0) { + DSSERR("request_irq failed\n"); + goto fail1; } enable_clocks(1); @@ -3361,10 +3388,15 @@ static int omap_dispchw_probe(struct platform_device *pdev) enable_clocks(0); return 0; +fail1: + iounmap(dispc.base); +fail0: + return r; } static int omap_dispchw_remove(struct platform_device *pdev) { + free_irq(dispc.irq, dispc.pdev); iounmap(dispc.base); return 0; } diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c index 2928cddeb3fc4..2f7d9491cd024 100644 --- a/drivers/video/omap2/dss/dsi.c +++ b/drivers/video/omap2/dss/dsi.c @@ -222,6 +222,7 @@ static struct { struct platform_device *pdev; void __iomem *base; + int irq; struct dsi_clock_info current_cinfo; @@ -480,13 +481,17 @@ static void print_irq_status_cio(u32 status) static int debug_irq; /* called from dss */ -void dsi_irq_handler(void) +static irqreturn_t omap_dsi_irq_handler(int irq, void *arg) { u32 irqstatus, vcstatus, ciostatus; int i; irqstatus = dsi_read_reg(DSI_IRQSTATUS); + /* IRQ is not for us */ + if (!irqstatus) + return IRQ_NONE; + #ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS spin_lock(&dsi.irq_stats_lock); dsi.irq_stats.irq_count++; @@ -564,9 +569,9 @@ void dsi_irq_handler(void) #ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS spin_unlock(&dsi.irq_stats_lock); #endif + return IRQ_HANDLED; } - static void _dsi_initialize_irq(void) { u32 l; @@ -3293,6 +3298,19 @@ static int dsi_init(struct platform_device *pdev) r = -ENOMEM; goto err1; } + dsi.irq = platform_get_irq(dsi.pdev, 0); + if (dsi.irq < 0) { + DSSERR("platform_get_irq failed\n"); + r = -ENODEV; + goto err2; + } + + r = request_irq(dsi.irq, omap_dsi_irq_handler, IRQF_SHARED, + "OMAP DSI1", dsi.pdev); + if (r < 0) { + DSSERR("request_irq failed\n"); + goto err2; + } enable_clocks(1); @@ -3303,6 +3321,8 @@ static int dsi_init(struct platform_device *pdev) enable_clocks(0); return 0; +err2: + iounmap(dsi.base); err1: destroy_workqueue(dsi.workqueue); return r; @@ -3315,6 +3335,7 @@ static void dsi_exit(void) dsi.vdds_dsi_reg = NULL; } + free_irq(dsi.irq, dsi.pdev); iounmap(dsi.base); destroy_workqueue(dsi.workqueue); diff --git a/drivers/video/omap2/dss/dss.c b/drivers/video/omap2/dss/dss.c index ab82f79376751..dc57100cc43dc 100644 --- a/drivers/video/omap2/dss/dss.c +++ b/drivers/video/omap2/dss/dss.c @@ -26,7 +26,6 @@ #include #include #include -#include #include #include @@ -79,7 +78,6 @@ static struct { enum dss_clk_source dispc_clk_source; u32 ctx[DSS_SZ_REGS / sizeof(u32)]; - int dss_irq; } dss; static void dss_clk_enable_all_no_ctx(void); @@ -495,31 +493,6 @@ found: return 0; } - - -static irqreturn_t dss_irq_handler_omap2(int irq, void *arg) -{ - dispc_irq_handler(); - - return IRQ_HANDLED; -} - -static irqreturn_t dss_irq_handler_omap3(int irq, void *arg) -{ - u32 irqstatus; - - irqstatus = dss_read_reg(DSS_IRQSTATUS); - - if (irqstatus & (1<<0)) /* DISPC_IRQ */ - dispc_irq_handler(); -#ifdef CONFIG_OMAP2_DSS_DSI - if (irqstatus & (1<<1)) /* DSI_IRQ */ - dsi_irq_handler(); -#endif - - return IRQ_HANDLED; -} - static int _omap_dss_wait_reset(void) { int t = 0; @@ -610,30 +583,12 @@ static int dss_init(bool skip_init) REG_FLD_MOD(DSS_CONTROL, 0, 2, 2); /* venc clock mode = normal */ #endif - dss.dss_irq = platform_get_irq(dss.pdev, 0); - if (dss.dss_irq < 0) { - DSSERR("omap2 dss: platform_get_irq failed\n"); - r = -ENODEV; - goto fail1; - } - - r = request_irq(dss.dss_irq, - cpu_is_omap24xx() - ? dss_irq_handler_omap2 - : dss_irq_handler_omap3, - 0, "OMAP DSS", NULL); - - if (r < 0) { - DSSERR("omap2 dss: request_irq failed\n"); - goto fail1; - } - if (cpu_is_omap34xx()) { dss.dpll4_m4_ck = clk_get(NULL, "dpll4_m4_ck"); if (IS_ERR(dss.dpll4_m4_ck)) { DSSERR("Failed to get dpll4_m4_ck\n"); r = PTR_ERR(dss.dpll4_m4_ck); - goto fail2; + goto fail1; } } @@ -648,8 +603,6 @@ static int dss_init(bool skip_init) return 0; -fail2: - free_irq(dss.dss_irq, NULL); fail1: iounmap(dss.base); fail0: @@ -661,8 +614,6 @@ static void dss_exit(void) if (cpu_is_omap34xx()) clk_put(dss.dpll4_m4_ck); - free_irq(dss.dss_irq, NULL); - iounmap(dss.base); } -- GitLab From 830e6384e100dc758392c41f68c807c002945928 Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Wed, 23 Feb 2011 16:34:17 +0200 Subject: [PATCH 0527/2822] MAINTAINERS: Update OMAP DSS maintainer Signed-off-by: Tomi Valkeinen --- MAINTAINERS | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/MAINTAINERS b/MAINTAINERS index 939e852ef74d3..ee484254dcb5c 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -4514,14 +4514,14 @@ S: Maintained F: sound/soc/omap/ OMAP FRAMEBUFFER SUPPORT -M: Tomi Valkeinen +M: Tomi Valkeinen L: linux-fbdev@vger.kernel.org L: linux-omap@vger.kernel.org S: Maintained F: drivers/video/omap/ OMAP DISPLAY SUBSYSTEM and FRAMEBUFFER SUPPORT (DSS2) -M: Tomi Valkeinen +M: Tomi Valkeinen L: linux-omap@vger.kernel.org L: linux-fbdev@vger.kernel.org S: Maintained -- GitLab From d0030452b5057570db47e953433f689e4a5475b5 Mon Sep 17 00:00:00 2001 From: Samreen Date: Thu, 24 Feb 2011 06:26:40 +0000 Subject: [PATCH 0528/2822] OMAP2/3/4: DSS2: Enable Display SubSystem as modules Enabling all the display interface options to be built as module And enabling all the display panels to be built as modules. Signed-off-by: Samreen Acked-by: Tony Lindgren Signed-off-by: Tomi Valkeinen --- arch/arm/configs/omap2plus_defconfig | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/arch/arm/configs/omap2plus_defconfig b/arch/arm/configs/omap2plus_defconfig index 019fb7c67dc36..076db52ff6723 100644 --- a/arch/arm/configs/omap2plus_defconfig +++ b/arch/arm/configs/omap2plus_defconfig @@ -193,6 +193,17 @@ CONFIG_FIRMWARE_EDID=y CONFIG_FB_MODE_HELPERS=y CONFIG_FB_TILEBLITTING=y CONFIG_FB_OMAP_LCD_VGA=y +CONFIG_OMAP2_DSS=m +CONFIG_OMAP2_DSS_RFBI=y +CONFIG_OMAP2_DSS_SDI=y +CONFIG_OMAP2_DSS_DSI=y +CONFIG_FB_OMAP2=m +CONFIG_PANEL_GENERIC_DPI=m +CONFIG_PANEL_SHARP_LS037V7DW01=m +CONFIG_PANEL_NEC_NL8048HL11_01B=m +CONFIG_PANEL_TAAL=m +CONFIG_PANEL_TPO_TD043MTEA1=m +CONFIG_PANEL_ACX565AKM=m CONFIG_BACKLIGHT_LCD_SUPPORT=y CONFIG_LCD_CLASS_DEVICE=y CONFIG_LCD_PLATFORM=y -- GitLab From e528e3a8b4e005e6e2c9e50fdee1ab7e84cf1e27 Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Thu, 24 Feb 2011 13:59:13 +0200 Subject: [PATCH 0529/2822] OMAP: DSS2: Clean up a switch-case Support for the display interface was checked in a separate switch-case. There's no reason for that, and this patch handles the fail code path in the same switch-case where the display initialization is done. Signed-off-by: Tomi Valkeinen --- drivers/video/omap2/dss/display.c | 27 +++------------------------ 1 file changed, 3 insertions(+), 24 deletions(-) diff --git a/drivers/video/omap2/dss/display.c b/drivers/video/omap2/dss/display.c index 22dd7a474f79b..3f4fa0b08460e 100644 --- a/drivers/video/omap2/dss/display.c +++ b/drivers/video/omap2/dss/display.c @@ -393,29 +393,6 @@ void dss_init_device(struct platform_device *pdev, int i; int r; - switch (dssdev->type) { -#ifdef CONFIG_OMAP2_DSS_DPI - case OMAP_DISPLAY_TYPE_DPI: -#endif -#ifdef CONFIG_OMAP2_DSS_RFBI - case OMAP_DISPLAY_TYPE_DBI: -#endif -#ifdef CONFIG_OMAP2_DSS_SDI - case OMAP_DISPLAY_TYPE_SDI: -#endif -#ifdef CONFIG_OMAP2_DSS_DSI - case OMAP_DISPLAY_TYPE_DSI: -#endif -#ifdef CONFIG_OMAP2_DSS_VENC - case OMAP_DISPLAY_TYPE_VENC: -#endif - break; - default: - DSSERR("Support for display '%s' not compiled in.\n", - dssdev->name); - return; - } - switch (dssdev->type) { #ifdef CONFIG_OMAP2_DSS_DPI case OMAP_DISPLAY_TYPE_DPI: @@ -443,7 +420,9 @@ void dss_init_device(struct platform_device *pdev, break; #endif default: - BUG(); + DSSERR("Support for display '%s' not compiled in.\n", + dssdev->name); + return; } if (r) { -- GitLab From 4e777dd765b7c10eb66532330cf3fe6ae0b477b0 Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Thu, 24 Feb 2011 14:20:31 +0200 Subject: [PATCH 0530/2822] OMAP: DSS2: FEATURES: Remove SDI from 3630 displays OMAP 3630 does not support SDI. Split omap3_dss_supported_displays into 3430 and 3630 entries, and remove the SDI from 3630 entry. Signed-off-by: Tomi Valkeinen --- drivers/video/omap2/dss/dss_features.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/drivers/video/omap2/dss/dss_features.c b/drivers/video/omap2/dss/dss_features.c index cf3ef696e141e..f4367f6564a28 100644 --- a/drivers/video/omap2/dss/dss_features.c +++ b/drivers/video/omap2/dss/dss_features.c @@ -73,7 +73,7 @@ static const enum omap_display_type omap2_dss_supported_displays[] = { OMAP_DISPLAY_TYPE_VENC, }; -static const enum omap_display_type omap3_dss_supported_displays[] = { +static const enum omap_display_type omap3430_dss_supported_displays[] = { /* OMAP_DSS_CHANNEL_LCD */ OMAP_DISPLAY_TYPE_DPI | OMAP_DISPLAY_TYPE_DBI | OMAP_DISPLAY_TYPE_SDI | OMAP_DISPLAY_TYPE_DSI, @@ -82,6 +82,15 @@ static const enum omap_display_type omap3_dss_supported_displays[] = { OMAP_DISPLAY_TYPE_VENC, }; +static const enum omap_display_type omap3630_dss_supported_displays[] = { + /* OMAP_DSS_CHANNEL_LCD */ + OMAP_DISPLAY_TYPE_DPI | OMAP_DISPLAY_TYPE_DBI | + OMAP_DISPLAY_TYPE_DSI, + + /* OMAP_DSS_CHANNEL_DIGIT */ + OMAP_DISPLAY_TYPE_VENC, +}; + static const enum omap_display_type omap4_dss_supported_displays[] = { /* OMAP_DSS_CHANNEL_LCD */ OMAP_DISPLAY_TYPE_DBI | OMAP_DISPLAY_TYPE_DSI, @@ -161,7 +170,7 @@ static struct omap_dss_features omap3430_dss_features = { .num_mgrs = 2, .num_ovls = 3, - .supported_displays = omap3_dss_supported_displays, + .supported_displays = omap3430_dss_supported_displays, .supported_color_modes = omap3_dss_supported_color_modes, }; @@ -176,7 +185,7 @@ static struct omap_dss_features omap3630_dss_features = { .num_mgrs = 2, .num_ovls = 3, - .supported_displays = omap3_dss_supported_displays, + .supported_displays = omap3630_dss_supported_displays, .supported_color_modes = omap3_dss_supported_color_modes, }; -- GitLab From f8df01f1a47ea6e503f5ba8d782fc6fb53bb40e8 Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Thu, 24 Feb 2011 14:21:25 +0200 Subject: [PATCH 0531/2822] OMAP: DSS2: FEATURES: Remove DSI & SDI from OMAP2 OMAP2 doesn't support SDI or DSI. Remove them from omap2_dss_supported_displays. Signed-off-by: Tomi Valkeinen --- drivers/video/omap2/dss/dss_features.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/video/omap2/dss/dss_features.c b/drivers/video/omap2/dss/dss_features.c index f4367f6564a28..fe22d11068bdb 100644 --- a/drivers/video/omap2/dss/dss_features.c +++ b/drivers/video/omap2/dss/dss_features.c @@ -66,8 +66,7 @@ static const struct dss_reg_field omap3_dss_reg_fields[] = { static const enum omap_display_type omap2_dss_supported_displays[] = { /* OMAP_DSS_CHANNEL_LCD */ - OMAP_DISPLAY_TYPE_DPI | OMAP_DISPLAY_TYPE_DBI | - OMAP_DISPLAY_TYPE_SDI | OMAP_DISPLAY_TYPE_DSI, + OMAP_DISPLAY_TYPE_DPI | OMAP_DISPLAY_TYPE_DBI, /* OMAP_DSS_CHANNEL_DIGIT */ OMAP_DISPLAY_TYPE_VENC, -- GitLab From 6ec549e50b192105ede7bb289a31da6f6e1a61e9 Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Thu, 24 Feb 2011 14:18:50 +0200 Subject: [PATCH 0532/2822] OMAP: DSS2: Check for SDI HW before accessing SDI registers Only OMAP 3430 hardware has SDI support. The availability of SDI HW can be found out by checking if the LCD channel supports SDI displays. This patch checks for SDI HW support before accessing SDI registers, which fixes a crash on OMAP4 when SDI SW support is compiled in. Signed-off-by: Tomi Valkeinen --- drivers/video/omap2/dss/dss.c | 29 ++++++++++++++++++----------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/drivers/video/omap2/dss/dss.c b/drivers/video/omap2/dss/dss.c index dc57100cc43dc..50c18677684d3 100644 --- a/drivers/video/omap2/dss/dss.c +++ b/drivers/video/omap2/dss/dss.c @@ -32,6 +32,7 @@ #include #include #include "dss.h" +#include "dss_features.h" #define DSS_SZ_REGS SZ_512 @@ -110,10 +111,11 @@ void dss_save_context(void) SR(SYSCONFIG); SR(CONTROL); -#ifdef CONFIG_OMAP2_DSS_SDI - SR(SDI_CONTROL); - SR(PLL_CONTROL); -#endif + if (dss_feat_get_supported_displays(OMAP_DSS_CHANNEL_LCD) & + OMAP_DISPLAY_TYPE_SDI) { + SR(SDI_CONTROL); + SR(PLL_CONTROL); + } } void dss_restore_context(void) @@ -124,10 +126,11 @@ void dss_restore_context(void) RR(SYSCONFIG); RR(CONTROL); -#ifdef CONFIG_OMAP2_DSS_SDI - RR(SDI_CONTROL); - RR(PLL_CONTROL); -#endif + if (dss_feat_get_supported_displays(OMAP_DSS_CHANNEL_LCD) & + OMAP_DISPLAY_TYPE_SDI) { + RR(SDI_CONTROL); + RR(PLL_CONTROL); + } } #undef SR @@ -259,9 +262,13 @@ void dss_dump_regs(struct seq_file *s) DUMPREG(DSS_SYSSTATUS); DUMPREG(DSS_IRQSTATUS); DUMPREG(DSS_CONTROL); - DUMPREG(DSS_SDI_CONTROL); - DUMPREG(DSS_PLL_CONTROL); - DUMPREG(DSS_SDI_STATUS); + + if (dss_feat_get_supported_displays(OMAP_DSS_CHANNEL_LCD) & + OMAP_DISPLAY_TYPE_SDI) { + DUMPREG(DSS_SDI_CONTROL); + DUMPREG(DSS_PLL_CONTROL); + DUMPREG(DSS_SDI_STATUS); + } dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK); #undef DUMPREG -- GitLab From 0897cc21036c4da0337d8ebcbe7d4b7bb81cf2ca Mon Sep 17 00:00:00 2001 From: "Janorkar, Mayuresh" Date: Thu, 24 Feb 2011 03:39:17 -0600 Subject: [PATCH 0533/2822] OMAP: OMAPFB: Adding help for FB_OMAP_LCD_VGA option CONFIG_FB_OMAP_LCD_VGA option is present in drivers/video/omap There is no explaination about what this flag does. Lets add information about it. FB_OMAP_LCD_VGA flag sets resolution of display to VGA (640 X 480). The default resolution of 3430 LDP is 320 X 240. Signed-off-by: Mayuresh Janorkar Signed-off-by: Tomi Valkeinen --- drivers/video/omap/Kconfig | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/video/omap/Kconfig b/drivers/video/omap/Kconfig index 083c8fe53e241..ff7049b2cc8ff 100644 --- a/drivers/video/omap/Kconfig +++ b/drivers/video/omap/Kconfig @@ -11,7 +11,11 @@ config FB_OMAP config FB_OMAP_LCD_VGA bool "Use LCD in VGA mode" depends on MACH_OMAP_3430SDP || MACH_OMAP_LDP - + help + Set LCD resolution as VGA (640 X 480). + Default resolution without this option is QVGA(320 X 240). + Please take a look at drivers/video/omap/lcd_ldp.c file + for lcd driver code. choice depends on FB_OMAP && MACH_OVERO prompt "Screen resolution" -- GitLab From 4a0ab8df3e35da4d12df0631b2daae683dafe46c Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Thu, 28 Oct 2010 15:29:33 +0300 Subject: [PATCH 0534/2822] OMAP: DSS2: Remove unused list There was an unused list defined in display.c. Remove it. Signed-off-by: Tomi Valkeinen --- drivers/video/omap2/dss/display.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/video/omap2/dss/display.c b/drivers/video/omap2/dss/display.c index 3f4fa0b08460e..7d96b724c9926 100644 --- a/drivers/video/omap2/dss/display.c +++ b/drivers/video/omap2/dss/display.c @@ -25,14 +25,11 @@ #include #include #include -#include #include #include #include "dss.h" -static LIST_HEAD(display_list); - static ssize_t display_enabled_show(struct device *dev, struct device_attribute *attr, char *buf) { -- GitLab From 4b6b7fa2d3677d1d86780c73fe2284147713e3b1 Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Wed, 2 Jun 2010 15:09:37 +0300 Subject: [PATCH 0535/2822] OMAP: DSS2: DSI: remove unused function dsi_reset_tx_fifo() was not used. Furthermore, OMAP errata states that TX FIFO flush is not functional, so the function wouldn't even have worked. Signed-off-by: Tomi Valkeinen --- drivers/video/omap2/dss/dsi.c | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c index 2f7d9491cd024..c3019d95618d3 100644 --- a/drivers/video/omap2/dss/dsi.c +++ b/drivers/video/omap2/dss/dsi.c @@ -1626,20 +1626,6 @@ static int _dsi_reset(void) return _dsi_wait_reset(); } -static void dsi_reset_tx_fifo(int channel) -{ - u32 mask; - u32 l; - - /* set fifosize of the channel to 0, then return the old size */ - l = dsi_read_reg(DSI_TX_FIFO_VC_SIZE); - - mask = FLD_MASK((8 * channel) + 7, (8 * channel) + 4); - dsi_write_reg(DSI_TX_FIFO_VC_SIZE, l & ~mask); - - dsi_write_reg(DSI_TX_FIFO_VC_SIZE, l); -} - static void dsi_config_tx_fifo(enum fifo_size size1, enum fifo_size size2, enum fifo_size size3, enum fifo_size size4) { -- GitLab From fd4b34f60736a20c5acd81cbb3083a0c60ae058e Mon Sep 17 00:00:00 2001 From: "Semwal, Sumit" Date: Tue, 1 Mar 2011 02:42:13 -0600 Subject: [PATCH 0536/2822] OMAP2PLUS:DSS2: add opt_clock_available in pdata Provide a function in pdata to allow dss submodules to check if a given clock is available on a platform as an optional clock. Signed-off-by: Senthilvadivu Guruswamy (based on implementation from Senthil) Signed-off-by: Sumit Semwal Signed-off-by: Tomi Valkeinen --- arch/arm/mach-omap2/display.c | 22 ++++++++++++++++++++++ arch/arm/plat-omap/include/plat/display.h | 2 ++ 2 files changed, 24 insertions(+) diff --git a/arch/arm/mach-omap2/display.c b/arch/arm/mach-omap2/display.c index 16d0db6718aee..256d23fb79aba 100644 --- a/arch/arm/mach-omap2/display.c +++ b/arch/arm/mach-omap2/display.c @@ -42,6 +42,20 @@ static struct omap_device_pm_latency omap_dss_latency[] = { }, }; +/* oh_core is used for getting opt-clocks */ +static struct omap_hwmod *oh_core; + +static bool opt_clock_available(const char *clk_role) +{ + int i; + + for (i = 0; i < oh_core->opt_clks_cnt; i++) { + if (!strcmp(oh_core->opt_clks[i].role, clk_role)) + return true; + } + return false; +} + int __init omap_display_init(struct omap_dss_board_info *board_data) { int r = 0; @@ -74,9 +88,16 @@ int __init omap_display_init(struct omap_dss_board_info *board_data) oh_count = ARRAY_SIZE(oh_name) - 2; /* last 2 hwmod dev in oh_name are not available for omap3 */ + /* opt_clks are always associated with dss hwmod */ + oh_core = omap_hwmod_lookup("dss_core"); + if (!oh_core) { + pr_err("Could not look up dss_core.\n"); + return -ENODEV; + } pdata.board_data = board_data; pdata.board_data->get_last_off_on_transaction_id = NULL; + pdata.opt_clock_available = opt_clock_available; for (i = 0; i < oh_count; i++) { oh = omap_hwmod_lookup(oh_name[i]); @@ -84,6 +105,7 @@ int __init omap_display_init(struct omap_dss_board_info *board_data) pr_err("Could not look up %s\n", oh_name[i]); return -ENODEV; } + od = omap_device_build(dev_name[i], -1, oh, &pdata, sizeof(struct omap_display_platform_data), omap_dss_latency, diff --git a/arch/arm/plat-omap/include/plat/display.h b/arch/arm/plat-omap/include/plat/display.h index 2fb057e1cb98b..4101bcd2133e8 100644 --- a/arch/arm/plat-omap/include/plat/display.h +++ b/arch/arm/plat-omap/include/plat/display.h @@ -240,6 +240,8 @@ static inline int omap_display_init(struct omap_dss_board_info *board_data) struct omap_display_platform_data { struct omap_dss_board_info *board_data; /* TODO: Additional members to be added when PM is considered */ + + bool (*opt_clock_available)(const char *clk_role); }; struct omap_video_timings { -- GitLab From a1a0dccaea9e036200dc0b1070af1bfae06690fb Mon Sep 17 00:00:00 2001 From: "Semwal, Sumit" Date: Tue, 1 Mar 2011 02:42:14 -0600 Subject: [PATCH 0537/2822] OMAP2PLUS:DSS2: Use opt_clock_available from pdata hwmod databases provide information about which optional clocks are available for a given platform. This is available via a function pointer opt_clock_enable in pdata. Use this information during get/enable/disable/put of clocks. Signed-off-by: Sumit Semwal Signed-off-by: Tomi Valkeinen --- drivers/video/omap2/dss/dss.c | 46 +++++++++++++++++++++++------------ 1 file changed, 30 insertions(+), 16 deletions(-) diff --git a/drivers/video/omap2/dss/dss.c b/drivers/video/omap2/dss/dss.c index 50c18677684d3..0cf5f8bd1c8a0 100644 --- a/drivers/video/omap2/dss/dss.c +++ b/drivers/video/omap2/dss/dss.c @@ -706,6 +706,7 @@ static int dss_get_clock(struct clk **clock, const char *clk_name) static int dss_get_clocks(void) { int r; + struct omap_display_platform_data *pdata = dss.pdev->dev.platform_data; dss.dss_ick = NULL; dss.dss_fck = NULL; @@ -721,17 +722,28 @@ static int dss_get_clocks(void) if (r) goto err; - r = dss_get_clock(&dss.dss_sys_clk, "sys_clk"); - if (r) + if (!pdata->opt_clock_available) { + r = -ENODEV; goto err; + } - r = dss_get_clock(&dss.dss_tv_fck, "tv_clk"); - if (r) - goto err; + if (pdata->opt_clock_available("sys_clk")) { + r = dss_get_clock(&dss.dss_sys_clk, "sys_clk"); + if (r) + goto err; + } - r = dss_get_clock(&dss.dss_video_fck, "video_clk"); - if (r) - goto err; + if (pdata->opt_clock_available("tv_clk")) { + r = dss_get_clock(&dss.dss_tv_fck, "tv_clk"); + if (r) + goto err; + } + + if (pdata->opt_clock_available("video_clk")) { + r = dss_get_clock(&dss.dss_video_fck, "video_clk"); + if (r) + goto err; + } return 0; @@ -754,9 +766,11 @@ static void dss_put_clocks(void) { if (dss.dss_video_fck) clk_put(dss.dss_video_fck); - clk_put(dss.dss_tv_fck); + if (dss.dss_tv_fck) + clk_put(dss.dss_tv_fck); + if (dss.dss_sys_clk) + clk_put(dss.dss_sys_clk); clk_put(dss.dss_fck); - clk_put(dss.dss_sys_clk); clk_put(dss.dss_ick); } @@ -805,11 +819,11 @@ static void dss_clk_enable_no_ctx(enum dss_clock clks) clk_enable(dss.dss_ick); if (clks & DSS_CLK_FCK) clk_enable(dss.dss_fck); - if (clks & DSS_CLK_SYSCK) + if ((clks & DSS_CLK_SYSCK) && dss.dss_sys_clk) clk_enable(dss.dss_sys_clk); - if (clks & DSS_CLK_TVFCK) + if ((clks & DSS_CLK_TVFCK) && dss.dss_tv_fck) clk_enable(dss.dss_tv_fck); - if (clks & DSS_CLK_VIDFCK) + if ((clks & DSS_CLK_VIDFCK) && dss.dss_video_fck) clk_enable(dss.dss_video_fck); dss.num_clks_enabled += num_clks; @@ -833,11 +847,11 @@ static void dss_clk_disable_no_ctx(enum dss_clock clks) clk_disable(dss.dss_ick); if (clks & DSS_CLK_FCK) clk_disable(dss.dss_fck); - if (clks & DSS_CLK_SYSCK) + if ((clks & DSS_CLK_SYSCK) && dss.dss_sys_clk) clk_disable(dss.dss_sys_clk); - if (clks & DSS_CLK_TVFCK) + if ((clks & DSS_CLK_TVFCK) && dss.dss_tv_fck) clk_disable(dss.dss_tv_fck); - if (clks & DSS_CLK_VIDFCK) + if ((clks & DSS_CLK_VIDFCK) && dss.dss_video_fck) clk_disable(dss.dss_video_fck); dss.num_clks_enabled -= num_clks; -- GitLab From 08a0a657949e723f0cbb6a33b1c706134d5a6d78 Mon Sep 17 00:00:00 2001 From: Jarkko Nikula Date: Tue, 1 Mar 2011 02:40:37 -0600 Subject: [PATCH 0538/2822] omapfb: Fix linker error in drivers/video/omap/lcd_2430sdp.c There is a linker error from lcd_2430sdp.c if CONFIG_TWL4030_CORE is not set. This can be triggered on OMAP2 builds when OMAP3 or OMAP4 are not set. drivers/built-in.o: In function `sdp2430_panel_disable': drivers/video/omap/lcd_2430sdp.c:123: undefined reference to `twl_i2c_write_u8' drivers/video/omap/lcd_2430sdp.c:124: undefined reference to `twl_i2c_write_u8' drivers/built-in.o: In function `sdp2430_panel_enable': drivers/video/omap/lcd_2430sdp.c:110: undefined reference to `twl_i2c_write_u8' drivers/video/omap/lcd_2430sdp.c:112: undefined reference to `twl_i2c_write_u8' Fix this by selecting the TWL4030_CORE for MACH_OMAP_2430SDP when building with CONFIG_FB_OMAP as there is no own Kconfig entry for lcd_2430 and it is compiled always when both MACH_OMAP_2430SDP and FB_OMAP are set. Signed-off-by: Jarkko Nikula Signed-off-by: Tomi Valkeinen --- drivers/video/omap/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/video/omap/Kconfig b/drivers/video/omap/Kconfig index ff7049b2cc8ff..15e7f1912af9b 100644 --- a/drivers/video/omap/Kconfig +++ b/drivers/video/omap/Kconfig @@ -5,6 +5,7 @@ config FB_OMAP select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT + select TWL4030_CORE if MACH_OMAP_2430SDP help Frame buffer driver for OMAP based boards. -- GitLab From 87a7484b6a9ceaa9e7a9a238154b02ed4495f26a Mon Sep 17 00:00:00 2001 From: Archit Taneja Date: Wed, 2 Mar 2011 11:19:50 +0530 Subject: [PATCH 0539/2822] OMAP2PLUS: DSS2: FEATURES: DISPC overlay code cleanup Add dss_features and register fields to incorporate changes in DISPC pipelines between OMAP3 and OMAP4. Register fields added: FEAT_REG_HORIZONTALACCU, FEAT_REG_VERTICALACCU DSS Features added: FEAT_LINEBUFFERSPLIT, FEAT_ROWREPEATENABLE, FEAT_RESIZECONF _dispc_set_scaling() and _dispc_set_rotation_attrs() have been cleaned up. Signed-off-by: Archit Taneja Signed-off-by: Tomi Valkeinen --- drivers/video/omap2/dss/dispc.c | 52 ++++++++++++++++++-------- drivers/video/omap2/dss/dss_features.c | 30 ++++++++++++--- drivers/video/omap2/dss/dss_features.h | 5 +++ 3 files changed, 66 insertions(+), 21 deletions(-) diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c index 43f7091c71cb8..aa6479712d4c6 100644 --- a/drivers/video/omap2/dss/dispc.c +++ b/drivers/video/omap2/dss/dispc.c @@ -1130,10 +1130,16 @@ static void _dispc_set_vid_accu0(enum omap_plane plane, int haccu, int vaccu) u32 val; const struct dispc_reg ac0_reg[] = { DISPC_VID_ACCU0(0), DISPC_VID_ACCU0(1) }; + u8 hor_start, hor_end, vert_start, vert_end; BUG_ON(plane == OMAP_DSS_GFX); - val = FLD_VAL(vaccu, 25, 16) | FLD_VAL(haccu, 9, 0); + dss_feat_get_reg_field(FEAT_REG_HORIZONTALACCU, &hor_start, &hor_end); + dss_feat_get_reg_field(FEAT_REG_VERTICALACCU, &vert_start, &vert_end); + + val = FLD_VAL(vaccu, vert_start, vert_end) | + FLD_VAL(haccu, hor_start, hor_end); + dispc_write_reg(ac0_reg[plane-1], val); } @@ -1142,10 +1148,16 @@ static void _dispc_set_vid_accu1(enum omap_plane plane, int haccu, int vaccu) u32 val; const struct dispc_reg ac1_reg[] = { DISPC_VID_ACCU1(0), DISPC_VID_ACCU1(1) }; + u8 hor_start, hor_end, vert_start, vert_end; BUG_ON(plane == OMAP_DSS_GFX); - val = FLD_VAL(vaccu, 25, 16) | FLD_VAL(haccu, 9, 0); + dss_feat_get_reg_field(FEAT_REG_HORIZONTALACCU, &hor_start, &hor_end); + dss_feat_get_reg_field(FEAT_REG_VERTICALACCU, &vert_start, &vert_end); + + val = FLD_VAL(vaccu, vert_start, vert_end) | + FLD_VAL(haccu, hor_start, hor_end); + dispc_write_reg(ac1_reg[plane-1], val); } @@ -1183,16 +1195,25 @@ static void _dispc_set_scaling(enum omap_plane plane, _dispc_set_fir(plane, fir_hinc, fir_vinc); l = dispc_read_reg(dispc_reg_att[plane]); - l &= ~((0x0f << 5) | (0x3 << 21)); + /* RESIZEENABLE and VERTICALTAPS */ + l &= ~((0x3 << 5) | (0x1 << 21)); l |= fir_hinc ? (1 << 5) : 0; l |= fir_vinc ? (1 << 6) : 0; + l |= five_taps ? (1 << 21) : 0; - l |= hscaleup ? 0 : (1 << 7); - l |= vscaleup ? 0 : (1 << 8); + /* VRESIZECONF and HRESIZECONF */ + if (dss_has_feature(FEAT_RESIZECONF)) { + l &= ~(0x3 << 7); + l |= hscaleup ? 0 : (1 << 7); + l |= vscaleup ? 0 : (1 << 8); + } - l |= five_taps ? (1 << 21) : 0; - l |= five_taps ? (1 << 22) : 0; + /* LINEBUFFERSPLIT */ + if (dss_has_feature(FEAT_LINEBUFFERSPLIT)) { + l &= ~(0x1 << 22); + l |= five_taps ? (1 << 22) : 0; + } dispc_write_reg(dispc_reg_att[plane], l); @@ -1216,9 +1237,11 @@ static void _dispc_set_scaling(enum omap_plane plane, static void _dispc_set_rotation_attrs(enum omap_plane plane, u8 rotation, bool mirroring, enum omap_color_mode color_mode) { + bool row_repeat = false; + int vidrot = 0; + if (color_mode == OMAP_DSS_COLOR_YUV2 || color_mode == OMAP_DSS_COLOR_UYVY) { - int vidrot = 0; if (mirroring) { switch (rotation) { @@ -1252,16 +1275,15 @@ static void _dispc_set_rotation_attrs(enum omap_plane plane, u8 rotation, } } - REG_FLD_MOD(dispc_reg_att[plane], vidrot, 13, 12); - if (rotation == OMAP_DSS_ROT_90 || rotation == OMAP_DSS_ROT_270) - REG_FLD_MOD(dispc_reg_att[plane], 0x1, 18, 18); + row_repeat = true; else - REG_FLD_MOD(dispc_reg_att[plane], 0x0, 18, 18); - } else { - REG_FLD_MOD(dispc_reg_att[plane], 0, 13, 12); - REG_FLD_MOD(dispc_reg_att[plane], 0, 18, 18); + row_repeat = false; } + + REG_FLD_MOD(dispc_reg_att[plane], vidrot, 13, 12); + if (dss_has_feature(FEAT_ROWREPEATENABLE)) + REG_FLD_MOD(dispc_reg_att[plane], row_repeat ? 1 : 0, 18, 18); } static int color_mode_to_bpp(enum omap_color_mode color_mode) diff --git a/drivers/video/omap2/dss/dss_features.c b/drivers/video/omap2/dss/dss_features.c index fe22d11068bdb..679be14b73a84 100644 --- a/drivers/video/omap2/dss/dss_features.c +++ b/drivers/video/omap2/dss/dss_features.c @@ -54,6 +54,8 @@ static const struct dss_reg_field omap2_dss_reg_fields[] = { { FEAT_REG_FIFOLOWTHRESHOLD, 8, 0 }, { FEAT_REG_FIFOHIGHTHRESHOLD, 24, 16 }, { FEAT_REG_FIFOSIZE, 8, 0 }, + { FEAT_REG_HORIZONTALACCU, 9, 0 }, + { FEAT_REG_VERTICALACCU, 25, 16 }, }; static const struct dss_reg_field omap3_dss_reg_fields[] = { @@ -62,6 +64,18 @@ static const struct dss_reg_field omap3_dss_reg_fields[] = { { FEAT_REG_FIFOLOWTHRESHOLD, 11, 0 }, { FEAT_REG_FIFOHIGHTHRESHOLD, 27, 16 }, { FEAT_REG_FIFOSIZE, 10, 0 }, + { FEAT_REG_HORIZONTALACCU, 9, 0 }, + { FEAT_REG_VERTICALACCU, 25, 16 }, +}; + +static const struct dss_reg_field omap4_dss_reg_fields[] = { + { FEAT_REG_FIRHINC, 12, 0 }, + { FEAT_REG_FIRVINC, 28, 16 }, + { FEAT_REG_FIFOLOWTHRESHOLD, 15, 0 }, + { FEAT_REG_FIFOHIGHTHRESHOLD, 31, 16 }, + { FEAT_REG_FIFOSIZE, 15, 0 }, + { FEAT_REG_HORIZONTALACCU, 10, 0 }, + { FEAT_REG_VERTICALACCU, 26, 16 }, }; static const enum omap_display_type omap2_dss_supported_displays[] = { @@ -149,7 +163,8 @@ static struct omap_dss_features omap2_dss_features = { .has_feature = FEAT_LCDENABLEPOL | FEAT_LCDENABLESIGNAL | - FEAT_PCKFREEENABLE | FEAT_FUNCGATED, + FEAT_PCKFREEENABLE | FEAT_FUNCGATED | + FEAT_ROWREPEATENABLE | FEAT_RESIZECONF, .num_mgrs = 2, .num_ovls = 3, @@ -165,7 +180,8 @@ static struct omap_dss_features omap3430_dss_features = { .has_feature = FEAT_GLOBAL_ALPHA | FEAT_LCDENABLEPOL | FEAT_LCDENABLESIGNAL | FEAT_PCKFREEENABLE | - FEAT_FUNCGATED, + FEAT_FUNCGATED | FEAT_ROWREPEATENABLE | + FEAT_LINEBUFFERSPLIT | FEAT_RESIZECONF, .num_mgrs = 2, .num_ovls = 3, @@ -180,7 +196,9 @@ static struct omap_dss_features omap3630_dss_features = { .has_feature = FEAT_GLOBAL_ALPHA | FEAT_LCDENABLEPOL | FEAT_LCDENABLESIGNAL | FEAT_PCKFREEENABLE | - FEAT_PRE_MULT_ALPHA | FEAT_FUNCGATED, + FEAT_PRE_MULT_ALPHA | FEAT_FUNCGATED | + FEAT_ROWREPEATENABLE | FEAT_LINEBUFFERSPLIT | + FEAT_RESIZECONF, .num_mgrs = 2, .num_ovls = 3, @@ -190,12 +208,12 @@ static struct omap_dss_features omap3630_dss_features = { /* OMAP4 DSS Features */ static struct omap_dss_features omap4_dss_features = { - .reg_fields = omap3_dss_reg_fields, - .num_reg_fields = ARRAY_SIZE(omap3_dss_reg_fields), + .reg_fields = omap4_dss_reg_fields, + .num_reg_fields = ARRAY_SIZE(omap4_dss_reg_fields), .has_feature = FEAT_GLOBAL_ALPHA | FEAT_PRE_MULT_ALPHA | - FEAT_MGR_LCD2, + FEAT_MGR_LCD2 | FEAT_GLOBAL_ALPHA_VID1, .num_mgrs = 3, .num_ovls = 3, diff --git a/drivers/video/omap2/dss/dss_features.h b/drivers/video/omap2/dss/dss_features.h index b9c70be925887..b3f81415507ce 100644 --- a/drivers/video/omap2/dss/dss_features.h +++ b/drivers/video/omap2/dss/dss_features.h @@ -33,6 +33,9 @@ enum dss_feat_id { FEAT_PCKFREEENABLE = 1 << 5, FEAT_FUNCGATED = 1 << 6, FEAT_MGR_LCD2 = 1 << 7, + FEAT_LINEBUFFERSPLIT = 1 << 8, + FEAT_ROWREPEATENABLE = 1 << 9, + FEAT_RESIZECONF = 1 << 10, }; /* DSS register field id */ @@ -42,6 +45,8 @@ enum dss_feat_reg_field { FEAT_REG_FIFOHIGHTHRESHOLD, FEAT_REG_FIFOLOWTHRESHOLD, FEAT_REG_FIFOSIZE, + FEAT_REG_HORIZONTALACCU, + FEAT_REG_VERTICALACCU, }; /* DSS Feature Functions */ -- GitLab From 819d807c59af10cce1dcbb13539c2fb100953fcd Mon Sep 17 00:00:00 2001 From: Archit Taneja Date: Tue, 1 Mar 2011 11:54:00 +0530 Subject: [PATCH 0540/2822] OMAP2PLUS: DSS2: FEATURES: Function to Provide the max fck supported The maximum supported frequency for DSS has increased from 173 to 186 Mhz on OMAP4. Introduce a dss feature function to get the max_fck to replace DISPC_MAX_FCK macro. Signed-off-by: Archit Taneja Signed-off-by: Tomi Valkeinen --- drivers/video/omap2/dss/dsi.c | 9 ++++++--- drivers/video/omap2/dss/dss.c | 8 +++++--- drivers/video/omap2/dss/dss.h | 2 -- drivers/video/omap2/dss/dss_features.c | 11 +++++++++++ drivers/video/omap2/dss/dss_features.h | 1 + 5 files changed, 23 insertions(+), 8 deletions(-) diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c index c3019d95618d3..705599ad3166e 100644 --- a/drivers/video/omap2/dss/dsi.c +++ b/drivers/video/omap2/dss/dsi.c @@ -38,6 +38,7 @@ #include #include "dss.h" +#include "dss_features.h" /*#define VERBOSE_IRQ*/ #define DSI_CATCH_MISSING_TE @@ -856,10 +857,12 @@ int dsi_pll_calc_clock_div_pck(bool is_tft, unsigned long req_pck, struct dispc_clock_info best_dispc; int min_fck_per_pck; int match = 0; - unsigned long dss_clk_fck2; + unsigned long dss_clk_fck2, max_dss_fck; dss_clk_fck2 = dss_clk_get_rate(DSS_CLK_SYSCK); + max_dss_fck = dss_feat_get_max_dss_fck(); + if (req_pck == dsi.cache_req_pck && dsi.cache_cinfo.clkin == dss_clk_fck2) { DSSDBG("DSI clock info found from cache\n"); @@ -872,7 +875,7 @@ int dsi_pll_calc_clock_div_pck(bool is_tft, unsigned long req_pck, min_fck_per_pck = CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK; if (min_fck_per_pck && - req_pck * min_fck_per_pck > DISPC_MAX_FCK) { + req_pck * min_fck_per_pck > max_dss_fck) { DSSERR("Requested pixel clock not possible with the current " "OMAP2_DSS_MIN_FCK_PER_PCK setting. Turning " "the constraint off.\n"); @@ -925,7 +928,7 @@ retry: if (cur.dsi1_pll_fclk < req_pck) break; - if (cur.dsi1_pll_fclk > DISPC_MAX_FCK) + if (cur.dsi1_pll_fclk > max_dss_fck) continue; if (min_fck_per_pck && diff --git a/drivers/video/omap2/dss/dss.c b/drivers/video/omap2/dss/dss.c index 0cf5f8bd1c8a0..01be82a4f42fa 100644 --- a/drivers/video/omap2/dss/dss.c +++ b/drivers/video/omap2/dss/dss.c @@ -387,7 +387,7 @@ int dss_calc_clock_div(bool is_tft, unsigned long req_pck, struct dss_clock_info best_dss; struct dispc_clock_info best_dispc; - unsigned long fck; + unsigned long fck, max_dss_fck; u16 fck_div; @@ -396,6 +396,8 @@ int dss_calc_clock_div(bool is_tft, unsigned long req_pck, prate = dss_get_dpll4_rate(); + max_dss_fck = dss_feat_get_max_dss_fck(); + fck = dss_clk_get_rate(DSS_CLK_FCK); if (req_pck == dss.cache_req_pck && ((cpu_is_omap34xx() && prate == dss.cache_prate) || @@ -409,7 +411,7 @@ int dss_calc_clock_div(bool is_tft, unsigned long req_pck, min_fck_per_pck = CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK; if (min_fck_per_pck && - req_pck * min_fck_per_pck > DISPC_MAX_FCK) { + req_pck * min_fck_per_pck > max_dss_fck) { DSSERR("Requested pixel clock not possible with the current " "OMAP2_DSS_MIN_FCK_PER_PCK setting. Turning " "the constraint off.\n"); @@ -445,7 +447,7 @@ retry: else fck = prate / fck_div * 2; - if (fck > DISPC_MAX_FCK) + if (fck > max_dss_fck) continue; if (min_fck_per_pck && diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h index 4b02e079f20e1..7fe32d1647f9b 100644 --- a/drivers/video/omap2/dss/dss.h +++ b/drivers/video/omap2/dss/dss.h @@ -97,8 +97,6 @@ extern unsigned int dss_debug; #define FLD_MOD(orig, val, start, end) \ (((orig) & ~FLD_MASK(start, end)) | FLD_VAL(val, start, end)) -#define DISPC_MAX_FCK 173000000 - enum omap_burst_size { OMAP_DSS_BURST_4x32 = 0, OMAP_DSS_BURST_8x32 = 1, diff --git a/drivers/video/omap2/dss/dss_features.c b/drivers/video/omap2/dss/dss_features.c index 679be14b73a84..3ebe0d91afd2c 100644 --- a/drivers/video/omap2/dss/dss_features.c +++ b/drivers/video/omap2/dss/dss_features.c @@ -41,6 +41,7 @@ struct omap_dss_features { const int num_mgrs; const int num_ovls; + const unsigned long max_dss_fck; const enum omap_display_type *supported_displays; const enum omap_color_mode *supported_color_modes; }; @@ -168,6 +169,7 @@ static struct omap_dss_features omap2_dss_features = { .num_mgrs = 2, .num_ovls = 3, + .max_dss_fck = 173000000, .supported_displays = omap2_dss_supported_displays, .supported_color_modes = omap2_dss_supported_color_modes, }; @@ -185,6 +187,7 @@ static struct omap_dss_features omap3430_dss_features = { .num_mgrs = 2, .num_ovls = 3, + .max_dss_fck = 173000000, .supported_displays = omap3430_dss_supported_displays, .supported_color_modes = omap3_dss_supported_color_modes, }; @@ -202,6 +205,7 @@ static struct omap_dss_features omap3630_dss_features = { .num_mgrs = 2, .num_ovls = 3, + .max_dss_fck = 173000000, .supported_displays = omap3630_dss_supported_displays, .supported_color_modes = omap3_dss_supported_color_modes, }; @@ -217,6 +221,7 @@ static struct omap_dss_features omap4_dss_features = { .num_mgrs = 3, .num_ovls = 3, + .max_dss_fck = 186000000, .supported_displays = omap4_dss_supported_displays, .supported_color_modes = omap3_dss_supported_color_modes, }; @@ -232,6 +237,12 @@ int dss_feat_get_num_ovls(void) return omap_current_dss_features->num_ovls; } +/* Max supported DSS FCK in Hz */ +unsigned long dss_feat_get_max_dss_fck(void) +{ + return omap_current_dss_features->max_dss_fck; +} + enum omap_display_type dss_feat_get_supported_displays(enum omap_channel channel) { return omap_current_dss_features->supported_displays[channel]; diff --git a/drivers/video/omap2/dss/dss_features.h b/drivers/video/omap2/dss/dss_features.h index b3f81415507ce..18ab195158178 100644 --- a/drivers/video/omap2/dss/dss_features.h +++ b/drivers/video/omap2/dss/dss_features.h @@ -52,6 +52,7 @@ enum dss_feat_reg_field { /* DSS Feature Functions */ int dss_feat_get_num_mgrs(void); int dss_feat_get_num_ovls(void); +unsigned long dss_feat_get_max_dss_fck(void); enum omap_display_type dss_feat_get_supported_displays(enum omap_channel channel); enum omap_color_mode dss_feat_get_supported_color_modes(enum omap_plane plane); bool dss_feat_color_mode_supported(enum omap_plane plane, -- GitLab From 88134fa138b90518819b750891ffecc13f5f4886 Mon Sep 17 00:00:00 2001 From: Archit Taneja Date: Thu, 6 Jan 2011 10:44:10 +0530 Subject: [PATCH 0541/2822] OMAP2PLUS: DSS2: Make members of dss_clk_source generic The enum members of 'dss_clk_source' have clock source names specific to OMAP2/3. Change the names to more generic terms such that they now describe where the clocks come from and what they are used for. Also, change the enum member names to have "DSS_CLK_SRC" instead of "DSS_SRC" for more clarity. Signed-off-by: Archit Taneja Signed-off-by: Tomi Valkeinen --- drivers/video/omap2/dss/dispc.c | 4 ++-- drivers/video/omap2/dss/dpi.c | 4 ++-- drivers/video/omap2/dss/dsi.c | 20 ++++++++++---------- drivers/video/omap2/dss/dss.c | 20 ++++++++++---------- drivers/video/omap2/dss/dss.h | 6 +++--- 5 files changed, 27 insertions(+), 27 deletions(-) diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c index aa6479712d4c6..a06b2ea41e988 100644 --- a/drivers/video/omap2/dss/dispc.c +++ b/drivers/video/omap2/dss/dispc.c @@ -2334,7 +2334,7 @@ unsigned long dispc_fclk_rate(void) { unsigned long r = 0; - if (dss_get_dispc_clk_source() == DSS_SRC_DSS1_ALWON_FCLK) + if (dss_get_dispc_clk_source() == DSS_CLK_SRC_FCK) r = dss_clk_get_rate(DSS_CLK_FCK); else #ifdef CONFIG_OMAP2_DSS_DSI @@ -2385,7 +2385,7 @@ void dispc_dump_clocks(struct seq_file *s) seq_printf(s, "- DISPC -\n"); seq_printf(s, "dispc fclk source = %s\n", - dss_get_dispc_clk_source() == DSS_SRC_DSS1_ALWON_FCLK ? + dss_get_dispc_clk_source() == DSS_CLK_SRC_FCK ? "dss1_alwon_fclk" : "dsi1_pll_fclk"); seq_printf(s, "fck\t\t%-16lu\n", dispc_fclk_rate()); diff --git a/drivers/video/omap2/dss/dpi.c b/drivers/video/omap2/dss/dpi.c index 026702b921e5a..1b2867dfeeb93 100644 --- a/drivers/video/omap2/dss/dpi.c +++ b/drivers/video/omap2/dss/dpi.c @@ -57,7 +57,7 @@ static int dpi_set_dsi_clk(struct omap_dss_device *dssdev, bool is_tft, if (r) return r; - dss_select_dispc_clk_source(DSS_SRC_DSI1_PLL_FCLK); + dss_select_dispc_clk_source(DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC); r = dispc_set_clock_div(dssdev->manager->id, &dispc_cinfo); if (r) @@ -217,7 +217,7 @@ void omapdss_dpi_display_disable(struct omap_dss_device *dssdev) dssdev->manager->disable(dssdev->manager); #ifdef CONFIG_OMAP2_DSS_USE_DSI_PLL - dss_select_dispc_clk_source(DSS_SRC_DSS1_ALWON_FCLK); + dss_select_dispc_clk_source(DSS_CLK_SRC_FCK); dsi_pll_uninit(); dss_clk_disable(DSS_CLK_SYSCK); #endif diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c index 705599ad3166e..df35aed828da9 100644 --- a/drivers/video/omap2/dss/dsi.c +++ b/drivers/video/omap2/dss/dsi.c @@ -731,7 +731,7 @@ static unsigned long dsi_fclk_rate(void) { unsigned long r; - if (dss_get_dsi_clk_source() == DSS_SRC_DSS1_ALWON_FCLK) { + if (dss_get_dsi_clk_source() == DSS_CLK_SRC_FCK) { /* DSI FCLK source is DSS1_ALWON_FCK, which is dss1_fck */ r = dss_clk_get_rate(DSS_CLK_FCK); } else { @@ -1188,19 +1188,19 @@ void dsi_dump_clocks(struct seq_file *s) seq_printf(s, "dsi1_pll_fck\t%-16luregm3 %u\t(%s)\n", cinfo->dsi1_pll_fclk, cinfo->regm3, - dss_get_dispc_clk_source() == DSS_SRC_DSS1_ALWON_FCLK ? + dss_get_dispc_clk_source() == DSS_CLK_SRC_FCK ? "off" : "on"); seq_printf(s, "dsi2_pll_fck\t%-16luregm4 %u\t(%s)\n", cinfo->dsi2_pll_fclk, cinfo->regm4, - dss_get_dsi_clk_source() == DSS_SRC_DSS1_ALWON_FCLK ? + dss_get_dsi_clk_source() == DSS_CLK_SRC_FCK ? "off" : "on"); seq_printf(s, "- DSI -\n"); seq_printf(s, "dsi fclk source = %s\n", - dss_get_dsi_clk_source() == DSS_SRC_DSS1_ALWON_FCLK ? + dss_get_dsi_clk_source() == DSS_CLK_SRC_FCK ? "dss1_alwon_fclk" : "dsi2_pll_fclk"); seq_printf(s, "DSI_FCLK\t%lu\n", dsi_fclk_rate()); @@ -3038,8 +3038,8 @@ static int dsi_display_init_dsi(struct omap_dss_device *dssdev) if (r) goto err1; - dss_select_dispc_clk_source(DSS_SRC_DSI1_PLL_FCLK); - dss_select_dsi_clk_source(DSS_SRC_DSI2_PLL_FCLK); + dss_select_dispc_clk_source(DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC); + dss_select_dsi_clk_source(DSS_CLK_SRC_DSI_PLL_HSDIV_DSI); DSSDBG("PLL OK\n"); @@ -3075,8 +3075,8 @@ static int dsi_display_init_dsi(struct omap_dss_device *dssdev) err3: dsi_complexio_uninit(); err2: - dss_select_dispc_clk_source(DSS_SRC_DSS1_ALWON_FCLK); - dss_select_dsi_clk_source(DSS_SRC_DSS1_ALWON_FCLK); + dss_select_dispc_clk_source(DSS_CLK_SRC_FCK); + dss_select_dsi_clk_source(DSS_CLK_SRC_FCK); err1: dsi_pll_uninit(); err0: @@ -3092,8 +3092,8 @@ static void dsi_display_uninit_dsi(struct omap_dss_device *dssdev) dsi_vc_enable(2, 0); dsi_vc_enable(3, 0); - dss_select_dispc_clk_source(DSS_SRC_DSS1_ALWON_FCLK); - dss_select_dsi_clk_source(DSS_SRC_DSS1_ALWON_FCLK); + dss_select_dispc_clk_source(DSS_CLK_SRC_FCK); + dss_select_dsi_clk_source(DSS_CLK_SRC_FCK); dsi_complexio_uninit(); dsi_pll_uninit(); } diff --git a/drivers/video/omap2/dss/dss.c b/drivers/video/omap2/dss/dss.c index 01be82a4f42fa..998c188c8823f 100644 --- a/drivers/video/omap2/dss/dss.c +++ b/drivers/video/omap2/dss/dss.c @@ -278,12 +278,12 @@ void dss_select_dispc_clk_source(enum dss_clk_source clk_src) { int b; - BUG_ON(clk_src != DSS_SRC_DSI1_PLL_FCLK && - clk_src != DSS_SRC_DSS1_ALWON_FCLK); + BUG_ON(clk_src != DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC && + clk_src != DSS_CLK_SRC_FCK); - b = clk_src == DSS_SRC_DSS1_ALWON_FCLK ? 0 : 1; + b = clk_src == DSS_CLK_SRC_FCK ? 0 : 1; - if (clk_src == DSS_SRC_DSI1_PLL_FCLK) + if (clk_src == DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC) dsi_wait_dsi1_pll_active(); REG_FLD_MOD(DSS_CONTROL, b, 0, 0); /* DISPC_CLK_SWITCH */ @@ -295,12 +295,12 @@ void dss_select_dsi_clk_source(enum dss_clk_source clk_src) { int b; - BUG_ON(clk_src != DSS_SRC_DSI2_PLL_FCLK && - clk_src != DSS_SRC_DSS1_ALWON_FCLK); + BUG_ON(clk_src != DSS_CLK_SRC_DSI_PLL_HSDIV_DSI && + clk_src != DSS_CLK_SRC_FCK); - b = clk_src == DSS_SRC_DSS1_ALWON_FCLK ? 0 : 1; + b = clk_src == DSS_CLK_SRC_FCK ? 0 : 1; - if (clk_src == DSS_SRC_DSI2_PLL_FCLK) + if (clk_src == DSS_CLK_SRC_DSI_PLL_HSDIV_DSI) dsi_wait_dsi2_pll_active(); REG_FLD_MOD(DSS_CONTROL, b, 1, 1); /* DSI_CLK_SWITCH */ @@ -601,8 +601,8 @@ static int dss_init(bool skip_init) } } - dss.dsi_clk_source = DSS_SRC_DSS1_ALWON_FCLK; - dss.dispc_clk_source = DSS_SRC_DSS1_ALWON_FCLK; + dss.dsi_clk_source = DSS_CLK_SRC_FCK; + dss.dispc_clk_source = DSS_CLK_SRC_FCK; dss_save_context(); diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h index 7fe32d1647f9b..a166ff36ec90b 100644 --- a/drivers/video/omap2/dss/dss.h +++ b/drivers/video/omap2/dss/dss.h @@ -118,9 +118,9 @@ enum dss_clock { }; enum dss_clk_source { - DSS_SRC_DSI1_PLL_FCLK, - DSS_SRC_DSI2_PLL_FCLK, - DSS_SRC_DSS1_ALWON_FCLK, + DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC, /* DSI1_PLL_FCLK */ + DSS_CLK_SRC_DSI_PLL_HSDIV_DSI, /* DSI2_PLL_FCLK */ + DSS_CLK_SRC_FCK, /* DSS1_ALWON_FCLK */ }; struct dss_clock_info { -- GitLab From 067a57e48e302863eb2d5ac0900ae9ae65dbc8c3 Mon Sep 17 00:00:00 2001 From: Archit Taneja Date: Wed, 2 Mar 2011 11:57:25 +0530 Subject: [PATCH 0542/2822] OMAP2PLUS: DSS2: Use dss features to get clock source names of current OMAP Clock source names vary across OMAP2/3 and OMAP4, the clock source enum names have been made generic in the driver, but for purposes of debugging and dumping clock sources, it is better to preserve the actual TRM name of the clock. Introduce a dss feature function 'dss_feat_get_clk_source_name()' which returns a string with the TRM clock name for the current OMAP in use. The OMAP specific name is printed along the generic name within brackets. Signed-off-by: Archit Taneja Signed-off-by: Tomi Valkeinen --- drivers/video/omap2/dss/dispc.c | 7 +++-- drivers/video/omap2/dss/dsi.c | 42 ++++++++++++++++++-------- drivers/video/omap2/dss/dss.c | 19 ++++++++++-- drivers/video/omap2/dss/dss.h | 7 +++++ drivers/video/omap2/dss/dss_features.c | 23 ++++++++++++++ drivers/video/omap2/dss/dss_features.h | 1 + 6 files changed, 81 insertions(+), 18 deletions(-) diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c index a06b2ea41e988..2c82d9a3df4b1 100644 --- a/drivers/video/omap2/dss/dispc.c +++ b/drivers/video/omap2/dss/dispc.c @@ -2379,14 +2379,15 @@ unsigned long dispc_pclk_rate(enum omap_channel channel) void dispc_dump_clocks(struct seq_file *s) { int lcd, pcd; + enum dss_clk_source dispc_clk_src = dss_get_dispc_clk_source(); enable_clocks(1); seq_printf(s, "- DISPC -\n"); - seq_printf(s, "dispc fclk source = %s\n", - dss_get_dispc_clk_source() == DSS_CLK_SRC_FCK ? - "dss1_alwon_fclk" : "dsi1_pll_fclk"); + seq_printf(s, "dispc fclk source = %s (%s)\n", + dss_get_generic_clk_source_name(dispc_clk_src), + dss_feat_get_clk_source_name(dispc_clk_src)); seq_printf(s, "fck\t\t%-16lu\n", dispc_fclk_rate()); diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c index df35aed828da9..3ef94227bbe74 100644 --- a/drivers/video/omap2/dss/dsi.c +++ b/drivers/video/omap2/dss/dsi.c @@ -1022,10 +1022,14 @@ int dsi_pll_set_clock_div(struct dsi_clock_info *cinfo) DSSDBG("Clock lane freq %ld Hz\n", cinfo->clkin4ddr / 4); - DSSDBG("regm3 = %d, dsi1_pll_fclk = %lu\n", - cinfo->regm3, cinfo->dsi1_pll_fclk); - DSSDBG("regm4 = %d, dsi2_pll_fclk = %lu\n", - cinfo->regm4, cinfo->dsi2_pll_fclk); + DSSDBG("regm3 = %d, %s (%s) = %lu\n", cinfo->regm3, + dss_get_generic_clk_source_name(DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC), + dss_feat_get_clk_source_name(DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC), + cinfo->dsi1_pll_fclk); + DSSDBG("regm4 = %d, %s (%s) = %lu\n", cinfo->regm4, + dss_get_generic_clk_source_name(DSS_CLK_SRC_DSI_PLL_HSDIV_DSI), + dss_feat_get_clk_source_name(DSS_CLK_SRC_DSI_PLL_HSDIV_DSI), + cinfo->dsi2_pll_fclk); REG_FLD_MOD(DSI_PLL_CONTROL, 0, 0, 0); /* DSI_PLL_AUTOMODE = manual */ @@ -1169,6 +1173,10 @@ void dsi_dump_clocks(struct seq_file *s) { int clksel; struct dsi_clock_info *cinfo = &dsi.current_cinfo; + enum dss_clk_source dispc_clk_src, dsi_clk_src; + + dispc_clk_src = dss_get_dispc_clk_source(); + dsi_clk_src = dss_get_dsi_clk_source(); enable_clocks(1); @@ -1185,23 +1193,27 @@ void dsi_dump_clocks(struct seq_file *s) seq_printf(s, "CLKIN4DDR\t%-16luregm %u\n", cinfo->clkin4ddr, cinfo->regm); - seq_printf(s, "dsi1_pll_fck\t%-16luregm3 %u\t(%s)\n", + seq_printf(s, "%s (%s)\t%-16luregm3 %u\t(%s)\n", + dss_get_generic_clk_source_name(dispc_clk_src), + dss_feat_get_clk_source_name(dispc_clk_src), cinfo->dsi1_pll_fclk, cinfo->regm3, - dss_get_dispc_clk_source() == DSS_CLK_SRC_FCK ? + dispc_clk_src == DSS_CLK_SRC_FCK ? "off" : "on"); - seq_printf(s, "dsi2_pll_fck\t%-16luregm4 %u\t(%s)\n", + seq_printf(s, "%s (%s)\t%-16luregm4 %u\t(%s)\n", + dss_get_generic_clk_source_name(dsi_clk_src), + dss_feat_get_clk_source_name(dsi_clk_src), cinfo->dsi2_pll_fclk, cinfo->regm4, - dss_get_dsi_clk_source() == DSS_CLK_SRC_FCK ? + dsi_clk_src == DSS_CLK_SRC_FCK ? "off" : "on"); seq_printf(s, "- DSI -\n"); - seq_printf(s, "dsi fclk source = %s\n", - dss_get_dsi_clk_source() == DSS_CLK_SRC_FCK ? - "dss1_alwon_fclk" : "dsi2_pll_fclk"); + seq_printf(s, "dsi fclk source = %s (%s)\n", + dss_get_generic_clk_source_name(dsi_clk_src), + dss_feat_get_clk_source_name(dsi_clk_src)); seq_printf(s, "DSI_FCLK\t%lu\n", dsi_fclk_rate()); @@ -3235,13 +3247,17 @@ int dsi_init_display(struct omap_dss_device *dssdev) void dsi_wait_dsi1_pll_active(void) { if (wait_for_bit_change(DSI_PLL_STATUS, 7, 1) != 1) - DSSERR("DSI1 PLL clock not active\n"); + DSSERR("%s (%s) not active\n", + dss_get_generic_clk_source_name(DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC), + dss_feat_get_clk_source_name(DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC)); } void dsi_wait_dsi2_pll_active(void) { if (wait_for_bit_change(DSI_PLL_STATUS, 8, 1) != 1) - DSSERR("DSI2 PLL clock not active\n"); + DSSERR("%s (%s) not active\n", + dss_get_generic_clk_source_name(DSS_CLK_SRC_DSI_PLL_HSDIV_DSI), + dss_feat_get_clk_source_name(DSS_CLK_SRC_DSI_PLL_HSDIV_DSI)); } static int dsi_init(struct platform_device *pdev) diff --git a/drivers/video/omap2/dss/dss.c b/drivers/video/omap2/dss/dss.c index 998c188c8823f..d049598bb4124 100644 --- a/drivers/video/omap2/dss/dss.c +++ b/drivers/video/omap2/dss/dss.c @@ -81,6 +81,12 @@ static struct { u32 ctx[DSS_SZ_REGS / sizeof(u32)]; } dss; +static const struct dss_clk_source_name dss_generic_clk_source_names[] = { + { DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC, "DSI_PLL_HSDIV_DISPC" }, + { DSS_CLK_SRC_DSI_PLL_HSDIV_DSI, "DSI_PLL_HSDIV_DSI" }, + { DSS_CLK_SRC_FCK, "DSS_FCK" }, +}; + static void dss_clk_enable_all_no_ctx(void); static void dss_clk_disable_all_no_ctx(void); static void dss_clk_enable_no_ctx(enum dss_clock clks); @@ -223,6 +229,11 @@ void dss_sdi_disable(void) REG_FLD_MOD(DSS_PLL_CONTROL, 0, 18, 18); /* SDI_PLL_SYSRESET */ } +const char *dss_get_generic_clk_source_name(enum dss_clk_source clk_src) +{ + return dss_generic_clk_source_names[clk_src].clksrc_name; +} + void dss_dump_clocks(struct seq_file *s) { unsigned long dpll4_ck_rate; @@ -238,12 +249,16 @@ void dss_dump_clocks(struct seq_file *s) seq_printf(s, "dpll4_ck %lu\n", dpll4_ck_rate); if (cpu_is_omap3630()) - seq_printf(s, "dss1_alwon_fclk = %lu / %lu = %lu\n", + seq_printf(s, "%s (%s) = %lu / %lu = %lu\n", + dss_get_generic_clk_source_name(DSS_CLK_SRC_FCK), + dss_feat_get_clk_source_name(DSS_CLK_SRC_FCK), dpll4_ck_rate, dpll4_ck_rate / dpll4_m4_ck_rate, dss_clk_get_rate(DSS_CLK_FCK)); else - seq_printf(s, "dss1_alwon_fclk = %lu / %lu * 2 = %lu\n", + seq_printf(s, "%s (%s) = %lu / %lu * 2 = %lu\n", + dss_get_generic_clk_source_name(DSS_CLK_SRC_FCK), + dss_feat_get_clk_source_name(DSS_CLK_SRC_FCK), dpll4_ck_rate, dpll4_ck_rate / dpll4_m4_ck_rate, dss_clk_get_rate(DSS_CLK_FCK)); diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h index a166ff36ec90b..42ca70f2bfd54 100644 --- a/drivers/video/omap2/dss/dss.h +++ b/drivers/video/omap2/dss/dss.h @@ -123,6 +123,12 @@ enum dss_clk_source { DSS_CLK_SRC_FCK, /* DSS1_ALWON_FCLK */ }; +/* Correlates clock source name and dss_clk_source member */ +struct dss_clk_source_name { + enum dss_clk_source clksrc; + const char *clksrc_name; +}; + struct dss_clock_info { /* rates that we get with dividers below */ unsigned long fck; @@ -215,6 +221,7 @@ void dss_clk_enable(enum dss_clock clks); void dss_clk_disable(enum dss_clock clks); unsigned long dss_clk_get_rate(enum dss_clock clk); int dss_need_ctx_restore(void); +const char *dss_get_generic_clk_source_name(enum dss_clk_source clk_src); void dss_dump_clocks(struct seq_file *s); void dss_dump_regs(struct seq_file *s); diff --git a/drivers/video/omap2/dss/dss_features.c b/drivers/video/omap2/dss/dss_features.c index 3ebe0d91afd2c..ccae57b34f5ca 100644 --- a/drivers/video/omap2/dss/dss_features.c +++ b/drivers/video/omap2/dss/dss_features.c @@ -25,6 +25,7 @@ #include #include +#include "dss.h" #include "dss_features.h" /* Defines a generic omap register field */ @@ -44,6 +45,7 @@ struct omap_dss_features { const unsigned long max_dss_fck; const enum omap_display_type *supported_displays; const enum omap_color_mode *supported_color_modes; + const struct dss_clk_source_name *clksrc_names; }; /* This struct is assigned to one of the below during initialization */ @@ -157,6 +159,18 @@ static const enum omap_color_mode omap3_dss_supported_color_modes[] = { OMAP_DSS_COLOR_RGBA32 | OMAP_DSS_COLOR_RGBX32, }; +static const struct dss_clk_source_name omap2_dss_clk_source_names[] = { + { DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC, "N/A" }, + { DSS_CLK_SRC_DSI_PLL_HSDIV_DSI, "N/A" }, + { DSS_CLK_SRC_FCK, "DSS_FCLK1" }, +}; + +static const struct dss_clk_source_name omap3_dss_clk_source_names[] = { + { DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC, "DSI1_PLL_FCLK" }, + { DSS_CLK_SRC_DSI_PLL_HSDIV_DSI, "DSI2_PLL_FCLK" }, + { DSS_CLK_SRC_FCK, "DSS1_ALWON_FCLK" }, +}; + /* OMAP2 DSS Features */ static struct omap_dss_features omap2_dss_features = { .reg_fields = omap2_dss_reg_fields, @@ -172,6 +186,7 @@ static struct omap_dss_features omap2_dss_features = { .max_dss_fck = 173000000, .supported_displays = omap2_dss_supported_displays, .supported_color_modes = omap2_dss_supported_color_modes, + .clksrc_names = omap2_dss_clk_source_names, }; /* OMAP3 DSS Features */ @@ -190,6 +205,7 @@ static struct omap_dss_features omap3430_dss_features = { .max_dss_fck = 173000000, .supported_displays = omap3430_dss_supported_displays, .supported_color_modes = omap3_dss_supported_color_modes, + .clksrc_names = omap3_dss_clk_source_names, }; static struct omap_dss_features omap3630_dss_features = { @@ -208,6 +224,7 @@ static struct omap_dss_features omap3630_dss_features = { .max_dss_fck = 173000000, .supported_displays = omap3630_dss_supported_displays, .supported_color_modes = omap3_dss_supported_color_modes, + .clksrc_names = omap3_dss_clk_source_names, }; /* OMAP4 DSS Features */ @@ -224,6 +241,7 @@ static struct omap_dss_features omap4_dss_features = { .max_dss_fck = 186000000, .supported_displays = omap4_dss_supported_displays, .supported_color_modes = omap3_dss_supported_color_modes, + .clksrc_names = omap3_dss_clk_source_names, }; /* Functions returning values related to a DSS feature */ @@ -260,6 +278,11 @@ bool dss_feat_color_mode_supported(enum omap_plane plane, color_mode; } +const char *dss_feat_get_clk_source_name(enum dss_clk_source id) +{ + return omap_current_dss_features->clksrc_names[id].clksrc_name; +} + /* DSS has_feature check */ bool dss_has_feature(enum dss_feat_id id) { diff --git a/drivers/video/omap2/dss/dss_features.h b/drivers/video/omap2/dss/dss_features.h index 18ab195158178..65d6de7e0feb7 100644 --- a/drivers/video/omap2/dss/dss_features.h +++ b/drivers/video/omap2/dss/dss_features.h @@ -57,6 +57,7 @@ enum omap_display_type dss_feat_get_supported_displays(enum omap_channel channel enum omap_color_mode dss_feat_get_supported_color_modes(enum omap_plane plane); bool dss_feat_color_mode_supported(enum omap_plane plane, enum omap_color_mode color_mode); +const char *dss_feat_get_clk_source_name(enum dss_clk_source id); bool dss_has_feature(enum dss_feat_id id); void dss_feat_get_reg_field(enum dss_feat_reg_field id, u8 *start, u8 *end); -- GitLab From 1bb478350670fadf708d3cbd6137c32dfbe3fd5f Mon Sep 17 00:00:00 2001 From: Archit Taneja Date: Thu, 24 Feb 2011 14:17:30 +0530 Subject: [PATCH 0543/2822] OMAP2PLUS: DSS2: DSI: Generalize DSI PLL Clock Naming DSI PLL output clock names have been made more generic. The clock name describes what the source of the clock and what clock is used for. Some of DSI PLL parameters like dividers and DSI PLL source have also been made more generic. dsi1_pll_fclk and dsi2_pll_fclk have been changed as dsi_pll_hsdiv_dispc_clk and dsi_pll_hsdiv_dsi_clk respectively. Also, the hsdividers are now named regm_dispc and regm_dsi instead of regm3 and regm4. Functions and macros named on the basis of these clock names have also been made generic. Signed-off-by: Archit Taneja Signed-off-by: Tomi Valkeinen --- arch/arm/plat-omap/include/plat/display.h | 4 +- drivers/video/omap2/dss/dispc.c | 2 +- drivers/video/omap2/dss/dpi.c | 4 +- drivers/video/omap2/dss/dsi.c | 134 +++++++++++----------- drivers/video/omap2/dss/dss.c | 4 +- drivers/video/omap2/dss/dss.h | 20 ++-- 6 files changed, 87 insertions(+), 81 deletions(-) diff --git a/arch/arm/plat-omap/include/plat/display.h b/arch/arm/plat-omap/include/plat/display.h index 4101bcd2133e8..37658249e4834 100644 --- a/arch/arm/plat-omap/include/plat/display.h +++ b/arch/arm/plat-omap/include/plat/display.h @@ -403,8 +403,8 @@ struct omap_dss_device { struct { u16 regn; u16 regm; - u16 regm3; - u16 regm4; + u16 regm_dispc; + u16 regm_dsi; u16 lp_clk_div; diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c index 2c82d9a3df4b1..9fb11c17623f5 100644 --- a/drivers/video/omap2/dss/dispc.c +++ b/drivers/video/omap2/dss/dispc.c @@ -2338,7 +2338,7 @@ unsigned long dispc_fclk_rate(void) r = dss_clk_get_rate(DSS_CLK_FCK); else #ifdef CONFIG_OMAP2_DSS_DSI - r = dsi_get_dsi1_pll_rate(); + r = dsi_get_pll_hsdiv_dispc_rate(); #else BUG(); #endif diff --git a/drivers/video/omap2/dss/dpi.c b/drivers/video/omap2/dss/dpi.c index 1b2867dfeeb93..08fed3080c0a6 100644 --- a/drivers/video/omap2/dss/dpi.c +++ b/drivers/video/omap2/dss/dpi.c @@ -63,7 +63,7 @@ static int dpi_set_dsi_clk(struct omap_dss_device *dssdev, bool is_tft, if (r) return r; - *fck = dsi_cinfo.dsi1_pll_fclk; + *fck = dsi_cinfo.dsi_pll_hsdiv_dispc_clk; *lck_div = dispc_cinfo.lck_div; *pck_div = dispc_cinfo.pck_div; @@ -271,7 +271,7 @@ int dpi_check_timings(struct omap_dss_device *dssdev, if (r) return r; - fck = dsi_cinfo.dsi1_pll_fclk; + fck = dsi_cinfo.dsi_pll_hsdiv_dispc_clk; lck_div = dispc_cinfo.lck_div; pck_div = dispc_cinfo.pck_div; } diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c index 3ef94227bbe74..37ffbb6ecf691 100644 --- a/drivers/video/omap2/dss/dsi.c +++ b/drivers/video/omap2/dss/dsi.c @@ -189,8 +189,8 @@ struct dsi_reg { u16 idx; }; #define FINT_MIN 750000 #define REGN_MAX (1 << 7) #define REGM_MAX ((1 << 11) - 1) -#define REGM3_MAX (1 << 4) -#define REGM4_MAX (1 << 4) +#define REGM_DISPC_MAX (1 << 4) +#define REGM_DSI_MAX (1 << 4) #define LP_DIV_MAX ((1 << 13) - 1) enum fifo_size { @@ -642,7 +642,7 @@ static void dsi_vc_disable_bta_irq(int channel) dsi_write_reg(DSI_VC_IRQENABLE(channel), l); } -/* DSI func clock. this could also be DSI2_PLL_FCLK */ +/* DSI func clock. this could also be dsi_pll_hsdiv_dsi_clk */ static inline void enable_clocks(bool enable) { if (enable) @@ -712,14 +712,14 @@ static inline int dsi_if_enable(bool enable) return 0; } -unsigned long dsi_get_dsi1_pll_rate(void) +unsigned long dsi_get_pll_hsdiv_dispc_rate(void) { - return dsi.current_cinfo.dsi1_pll_fclk; + return dsi.current_cinfo.dsi_pll_hsdiv_dispc_clk; } -static unsigned long dsi_get_dsi2_pll_rate(void) +static unsigned long dsi_get_pll_hsdiv_dsi_rate(void) { - return dsi.current_cinfo.dsi2_pll_fclk; + return dsi.current_cinfo.dsi_pll_hsdiv_dsi_clk; } static unsigned long dsi_get_txbyteclkhs(void) @@ -732,11 +732,11 @@ static unsigned long dsi_fclk_rate(void) unsigned long r; if (dss_get_dsi_clk_source() == DSS_CLK_SRC_FCK) { - /* DSI FCLK source is DSS1_ALWON_FCK, which is dss1_fck */ + /* DSI FCLK source is DSS_CLK_FCK */ r = dss_clk_get_rate(DSS_CLK_FCK); } else { - /* DSI FCLK source is DSI2_PLL_FCLK */ - r = dsi_get_dsi2_pll_rate(); + /* DSI FCLK source is dsi_pll_hsdiv_dsi_clk */ + r = dsi_get_pll_hsdiv_dsi_rate(); } return r; @@ -806,16 +806,16 @@ static int dsi_calc_clock_rates(struct omap_dss_device *dssdev, if (cinfo->regm == 0 || cinfo->regm > REGM_MAX) return -EINVAL; - if (cinfo->regm3 > REGM3_MAX) + if (cinfo->regm_dispc > REGM_DISPC_MAX) return -EINVAL; - if (cinfo->regm4 > REGM4_MAX) + if (cinfo->regm_dsi > REGM_DSI_MAX) return -EINVAL; - if (cinfo->use_dss2_fck) { + if (cinfo->use_sys_clk) { cinfo->clkin = dss_clk_get_rate(DSS_CLK_SYSCK); /* XXX it is unclear if highfreq should be used - * with DSS2_FCK source also */ + * with DSS_SYS_CLK source also */ cinfo->highfreq = 0; } else { cinfo->clkin = dispc_pclk_rate(dssdev->manager->id); @@ -836,15 +836,17 @@ static int dsi_calc_clock_rates(struct omap_dss_device *dssdev, if (cinfo->clkin4ddr > 1800 * 1000 * 1000) return -EINVAL; - if (cinfo->regm3 > 0) - cinfo->dsi1_pll_fclk = cinfo->clkin4ddr / cinfo->regm3; + if (cinfo->regm_dispc > 0) + cinfo->dsi_pll_hsdiv_dispc_clk = + cinfo->clkin4ddr / cinfo->regm_dispc; else - cinfo->dsi1_pll_fclk = 0; + cinfo->dsi_pll_hsdiv_dispc_clk = 0; - if (cinfo->regm4 > 0) - cinfo->dsi2_pll_fclk = cinfo->clkin4ddr / cinfo->regm4; + if (cinfo->regm_dsi > 0) + cinfo->dsi_pll_hsdiv_dsi_clk = + cinfo->clkin4ddr / cinfo->regm_dsi; else - cinfo->dsi2_pll_fclk = 0; + cinfo->dsi_pll_hsdiv_dsi_clk = 0; return 0; } @@ -857,18 +859,18 @@ int dsi_pll_calc_clock_div_pck(bool is_tft, unsigned long req_pck, struct dispc_clock_info best_dispc; int min_fck_per_pck; int match = 0; - unsigned long dss_clk_fck2, max_dss_fck; + unsigned long dss_sys_clk, max_dss_fck; - dss_clk_fck2 = dss_clk_get_rate(DSS_CLK_SYSCK); + dss_sys_clk = dss_clk_get_rate(DSS_CLK_SYSCK); max_dss_fck = dss_feat_get_max_dss_fck(); if (req_pck == dsi.cache_req_pck && - dsi.cache_cinfo.clkin == dss_clk_fck2) { + dsi.cache_cinfo.clkin == dss_sys_clk) { DSSDBG("DSI clock info found from cache\n"); *dsi_cinfo = dsi.cache_cinfo; - dispc_find_clk_divs(is_tft, req_pck, dsi_cinfo->dsi1_pll_fclk, - dispc_cinfo); + dispc_find_clk_divs(is_tft, req_pck, + dsi_cinfo->dsi_pll_hsdiv_dispc_clk, dispc_cinfo); return 0; } @@ -889,8 +891,8 @@ retry: memset(&best_dispc, 0, sizeof(best_dispc)); memset(&cur, 0, sizeof(cur)); - cur.clkin = dss_clk_fck2; - cur.use_dss2_fck = 1; + cur.clkin = dss_sys_clk; + cur.use_sys_clk = 1; cur.highfreq = 0; /* no highfreq: 0.75MHz < Fint = clkin / regn < 2.1MHz */ @@ -916,30 +918,32 @@ retry: if (cur.clkin4ddr > 1800 * 1000 * 1000) break; - /* DSI1_PLL_FCLK(MHz) = DSIPHY(MHz) / regm3 < 173MHz */ - for (cur.regm3 = 1; cur.regm3 < REGM3_MAX; - ++cur.regm3) { + /* dsi_pll_hsdiv_dispc_clk(MHz) = + * DSIPHY(MHz) / regm_dispc < 173MHz/186Mhz */ + for (cur.regm_dispc = 1; cur.regm_dispc < REGM_DISPC_MAX; + ++cur.regm_dispc) { struct dispc_clock_info cur_dispc; - cur.dsi1_pll_fclk = cur.clkin4ddr / cur.regm3; + cur.dsi_pll_hsdiv_dispc_clk = + cur.clkin4ddr / cur.regm_dispc; /* this will narrow down the search a bit, * but still give pixclocks below what was * requested */ - if (cur.dsi1_pll_fclk < req_pck) + if (cur.dsi_pll_hsdiv_dispc_clk < req_pck) break; - if (cur.dsi1_pll_fclk > max_dss_fck) + if (cur.dsi_pll_hsdiv_dispc_clk > max_dss_fck) continue; if (min_fck_per_pck && - cur.dsi1_pll_fclk < + cur.dsi_pll_hsdiv_dispc_clk < req_pck * min_fck_per_pck) continue; match = 1; dispc_find_clk_divs(is_tft, req_pck, - cur.dsi1_pll_fclk, + cur.dsi_pll_hsdiv_dispc_clk, &cur_dispc); if (abs(cur_dispc.pck - req_pck) < @@ -968,9 +972,9 @@ found: return -EINVAL; } - /* DSI2_PLL_FCLK (regm4) is not used */ - best.regm4 = 0; - best.dsi2_pll_fclk = 0; + /* dsi_pll_hsdiv_dsi_clk (regm_dsi) is not used */ + best.regm_dsi = 0; + best.dsi_pll_hsdiv_dsi_clk = 0; if (dsi_cinfo) *dsi_cinfo = best; @@ -994,18 +998,20 @@ int dsi_pll_set_clock_div(struct dsi_clock_info *cinfo) dsi.current_cinfo.fint = cinfo->fint; dsi.current_cinfo.clkin4ddr = cinfo->clkin4ddr; - dsi.current_cinfo.dsi1_pll_fclk = cinfo->dsi1_pll_fclk; - dsi.current_cinfo.dsi2_pll_fclk = cinfo->dsi2_pll_fclk; + dsi.current_cinfo.dsi_pll_hsdiv_dispc_clk = + cinfo->dsi_pll_hsdiv_dispc_clk; + dsi.current_cinfo.dsi_pll_hsdiv_dsi_clk = + cinfo->dsi_pll_hsdiv_dsi_clk; dsi.current_cinfo.regn = cinfo->regn; dsi.current_cinfo.regm = cinfo->regm; - dsi.current_cinfo.regm3 = cinfo->regm3; - dsi.current_cinfo.regm4 = cinfo->regm4; + dsi.current_cinfo.regm_dispc = cinfo->regm_dispc; + dsi.current_cinfo.regm_dsi = cinfo->regm_dsi; DSSDBG("DSI Fint %ld\n", cinfo->fint); DSSDBG("clkin (%s) rate %ld, highfreq %d\n", - cinfo->use_dss2_fck ? "dss2_fck" : "pclkfree", + cinfo->use_sys_clk ? "dss_sys_clk" : "pclkfree", cinfo->clkin, cinfo->highfreq); @@ -1022,14 +1028,14 @@ int dsi_pll_set_clock_div(struct dsi_clock_info *cinfo) DSSDBG("Clock lane freq %ld Hz\n", cinfo->clkin4ddr / 4); - DSSDBG("regm3 = %d, %s (%s) = %lu\n", cinfo->regm3, + DSSDBG("regm_dispc = %d, %s (%s) = %lu\n", cinfo->regm_dispc, dss_get_generic_clk_source_name(DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC), dss_feat_get_clk_source_name(DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC), - cinfo->dsi1_pll_fclk); - DSSDBG("regm4 = %d, %s (%s) = %lu\n", cinfo->regm4, + cinfo->dsi_pll_hsdiv_dispc_clk); + DSSDBG("regm_dsi = %d, %s (%s) = %lu\n", cinfo->regm_dsi, dss_get_generic_clk_source_name(DSS_CLK_SRC_DSI_PLL_HSDIV_DSI), dss_feat_get_clk_source_name(DSS_CLK_SRC_DSI_PLL_HSDIV_DSI), - cinfo->dsi2_pll_fclk); + cinfo->dsi_pll_hsdiv_dsi_clk); REG_FLD_MOD(DSI_PLL_CONTROL, 0, 0, 0); /* DSI_PLL_AUTOMODE = manual */ @@ -1037,9 +1043,9 @@ int dsi_pll_set_clock_div(struct dsi_clock_info *cinfo) l = FLD_MOD(l, 1, 0, 0); /* DSI_PLL_STOPMODE */ l = FLD_MOD(l, cinfo->regn - 1, 7, 1); /* DSI_PLL_REGN */ l = FLD_MOD(l, cinfo->regm, 18, 8); /* DSI_PLL_REGM */ - l = FLD_MOD(l, cinfo->regm3 > 0 ? cinfo->regm3 - 1 : 0, + l = FLD_MOD(l, cinfo->regm_dispc > 0 ? cinfo->regm_dispc - 1 : 0, 22, 19); /* DSI_CLOCK_DIV */ - l = FLD_MOD(l, cinfo->regm4 > 0 ? cinfo->regm4 - 1 : 0, + l = FLD_MOD(l, cinfo->regm_dsi > 0 ? cinfo->regm_dsi - 1 : 0, 26, 23); /* DSIPROTO_CLOCK_DIV */ dsi_write_reg(DSI_PLL_CONFIGURATION1, l); @@ -1057,7 +1063,7 @@ int dsi_pll_set_clock_div(struct dsi_clock_info *cinfo) l = dsi_read_reg(DSI_PLL_CONFIGURATION2); l = FLD_MOD(l, f, 4, 1); /* DSI_PLL_FREQSEL */ - l = FLD_MOD(l, cinfo->use_dss2_fck ? 0 : 1, + l = FLD_MOD(l, cinfo->use_sys_clk ? 0 : 1, 11, 11); /* DSI_PLL_CLKSEL */ l = FLD_MOD(l, cinfo->highfreq, 12, 12); /* DSI_PLL_HIGHFREQ */ @@ -1186,26 +1192,26 @@ void dsi_dump_clocks(struct seq_file *s) seq_printf(s, "dsi pll source = %s\n", clksel == 0 ? - "dss2_alwon_fclk" : "pclkfree"); + "dss_sys_clk" : "pclkfree"); seq_printf(s, "Fint\t\t%-16luregn %u\n", cinfo->fint, cinfo->regn); seq_printf(s, "CLKIN4DDR\t%-16luregm %u\n", cinfo->clkin4ddr, cinfo->regm); - seq_printf(s, "%s (%s)\t%-16luregm3 %u\t(%s)\n", + seq_printf(s, "%s (%s)\t%-16luregm_dispc %u\t(%s)\n", dss_get_generic_clk_source_name(dispc_clk_src), dss_feat_get_clk_source_name(dispc_clk_src), - cinfo->dsi1_pll_fclk, - cinfo->regm3, + cinfo->dsi_pll_hsdiv_dispc_clk, + cinfo->regm_dispc, dispc_clk_src == DSS_CLK_SRC_FCK ? "off" : "on"); - seq_printf(s, "%s (%s)\t%-16luregm4 %u\t(%s)\n", + seq_printf(s, "%s (%s)\t%-16luregm_dsi %u\t(%s)\n", dss_get_generic_clk_source_name(dsi_clk_src), dss_feat_get_clk_source_name(dsi_clk_src), - cinfo->dsi2_pll_fclk, - cinfo->regm4, + cinfo->dsi_pll_hsdiv_dsi_clk, + cinfo->regm_dsi, dsi_clk_src == DSS_CLK_SRC_FCK ? "off" : "on"); @@ -2989,12 +2995,12 @@ static int dsi_configure_dsi_clocks(struct omap_dss_device *dssdev) struct dsi_clock_info cinfo; int r; - /* we always use DSS2_FCK as input clock */ - cinfo.use_dss2_fck = true; + /* we always use DSS_CLK_SYSCK as input clock */ + cinfo.use_sys_clk = true; cinfo.regn = dssdev->phy.dsi.div.regn; cinfo.regm = dssdev->phy.dsi.div.regm; - cinfo.regm3 = dssdev->phy.dsi.div.regm3; - cinfo.regm4 = dssdev->phy.dsi.div.regm4; + cinfo.regm_dispc = dssdev->phy.dsi.div.regm_dispc; + cinfo.regm_dsi = dssdev->phy.dsi.div.regm_dsi; r = dsi_calc_clock_rates(dssdev, &cinfo); if (r) { DSSERR("Failed to calc dsi clocks\n"); @@ -3016,7 +3022,7 @@ static int dsi_configure_dispc_clocks(struct omap_dss_device *dssdev) int r; unsigned long long fck; - fck = dsi_get_dsi1_pll_rate(); + fck = dsi_get_pll_hsdiv_dispc_rate(); dispc_cinfo.lck_div = dssdev->phy.dsi.div.lck_div; dispc_cinfo.pck_div = dssdev->phy.dsi.div.pck_div; @@ -3244,7 +3250,7 @@ int dsi_init_display(struct omap_dss_device *dssdev) return 0; } -void dsi_wait_dsi1_pll_active(void) +void dsi_wait_pll_hsdiv_dispc_active(void) { if (wait_for_bit_change(DSI_PLL_STATUS, 7, 1) != 1) DSSERR("%s (%s) not active\n", @@ -3252,7 +3258,7 @@ void dsi_wait_dsi1_pll_active(void) dss_feat_get_clk_source_name(DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC)); } -void dsi_wait_dsi2_pll_active(void) +void dsi_wait_pll_hsdiv_dsi_active(void) { if (wait_for_bit_change(DSI_PLL_STATUS, 8, 1) != 1) DSSERR("%s (%s) not active\n", diff --git a/drivers/video/omap2/dss/dss.c b/drivers/video/omap2/dss/dss.c index d049598bb4124..5c6805b3362d1 100644 --- a/drivers/video/omap2/dss/dss.c +++ b/drivers/video/omap2/dss/dss.c @@ -299,7 +299,7 @@ void dss_select_dispc_clk_source(enum dss_clk_source clk_src) b = clk_src == DSS_CLK_SRC_FCK ? 0 : 1; if (clk_src == DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC) - dsi_wait_dsi1_pll_active(); + dsi_wait_pll_hsdiv_dispc_active(); REG_FLD_MOD(DSS_CONTROL, b, 0, 0); /* DISPC_CLK_SWITCH */ @@ -316,7 +316,7 @@ void dss_select_dsi_clk_source(enum dss_clk_source clk_src) b = clk_src == DSS_CLK_SRC_FCK ? 0 : 1; if (clk_src == DSS_CLK_SRC_DSI_PLL_HSDIV_DSI) - dsi_wait_dsi2_pll_active(); + dsi_wait_pll_hsdiv_dsi_active(); REG_FLD_MOD(DSS_CONTROL, b, 1, 1); /* DSI_CLK_SWITCH */ diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h index 42ca70f2bfd54..20590fb53c91b 100644 --- a/drivers/video/omap2/dss/dss.h +++ b/drivers/video/omap2/dss/dss.h @@ -152,21 +152,21 @@ struct dsi_clock_info { unsigned long fint; unsigned long clkin4ddr; unsigned long clkin; - unsigned long dsi1_pll_fclk; - unsigned long dsi2_pll_fclk; + unsigned long dsi_pll_hsdiv_dispc_clk; /* DSI1_PLL_CLK */ + unsigned long dsi_pll_hsdiv_dsi_clk; /* DSI2_PLL_CLK */ unsigned long lp_clk; /* dividers */ u16 regn; u16 regm; - u16 regm3; - u16 regm4; + u16 regm_dispc; /* REGM3 */ + u16 regm_dsi; /* REGM4 */ u16 lp_clk_div; u8 highfreq; - bool use_dss2_fck; + bool use_sys_clk; }; struct seq_file; @@ -278,7 +278,7 @@ void dsi_restore_context(void); int dsi_init_display(struct omap_dss_device *display); void dsi_irq_handler(void); -unsigned long dsi_get_dsi1_pll_rate(void); +unsigned long dsi_get_pll_hsdiv_dispc_rate(void); int dsi_pll_set_clock_div(struct dsi_clock_info *cinfo); int dsi_pll_calc_clock_div_pck(bool is_tft, unsigned long req_pck, struct dsi_clock_info *cinfo, @@ -289,8 +289,8 @@ void dsi_pll_uninit(void); void dsi_get_overlay_fifo_thresholds(enum omap_plane plane, u32 fifo_size, enum omap_burst_size *burst_size, u32 *fifo_low, u32 *fifo_high); -void dsi_wait_dsi1_pll_active(void); -void dsi_wait_dsi2_pll_active(void); +void dsi_wait_pll_hsdiv_dispc_active(void); +void dsi_wait_pll_hsdiv_dsi_active(void); #else static inline int dsi_init_platform_driver(void) { @@ -299,10 +299,10 @@ static inline int dsi_init_platform_driver(void) static inline void dsi_uninit_platform_driver(void) { } -static inline void dsi_wait_dsi1_pll_active(void) +static inline void dsi_wait_pll_hsdiv_dispc_active(void) { } -static inline void dsi_wait_dsi2_pll_active(void) +static inline void dsi_wait_pll_hsdiv_dsi_active(void) { } #endif -- GitLab From 42c9dee82129d965bc8ca02170150817317c0135 Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Wed, 2 Mar 2011 12:29:27 +0200 Subject: [PATCH 0544/2822] OMAP: DSS2: Remove FB_OMAP_BOOTLOADER_INIT support FB_OMAP_BOOTLOADER_INIT does not work, and it was only partially implemented for SDI. This patch removes support for FB_OMAP_BOOTLOADER_INIT to clean up the code and to remove any assumptions that FB_OMAP_BOOTLOADER_INIT would work. Proper implementation is much more complex, requiring early boot time register and clock handling to keep the DSS running. Signed-off-by: Tomi Valkeinen --- drivers/video/omap2/dss/core.c | 8 +------ drivers/video/omap2/dss/dss.c | 41 +++++++++++++--------------------- drivers/video/omap2/dss/dss.h | 4 ++-- drivers/video/omap2/dss/sdi.c | 40 ++++++++------------------------- 4 files changed, 28 insertions(+), 65 deletions(-) diff --git a/drivers/video/omap2/dss/core.c b/drivers/video/omap2/dss/core.c index bcf69a462b5f5..02db5f1269eed 100644 --- a/drivers/video/omap2/dss/core.c +++ b/drivers/video/omap2/dss/core.c @@ -166,7 +166,6 @@ static inline void dss_uninitialize_debugfs(void) static int omap_dss_probe(struct platform_device *pdev) { struct omap_dss_board_info *pdata = pdev->dev.platform_data; - int skip_init = 0; int r; int i; @@ -210,13 +209,8 @@ static int omap_dss_probe(struct platform_device *pdev) goto err_venc; } -#ifdef CONFIG_FB_OMAP_BOOTLOADER_INIT - /* DISPC_CONTROL */ - if (omap_readl(0x48050440) & 1) /* LCD enabled? */ - skip_init = 1; -#endif if (cpu_is_omap34xx()) { - r = sdi_init(skip_init); + r = sdi_init(); if (r) { DSSERR("Failed to initialize SDI\n"); goto err_sdi; diff --git a/drivers/video/omap2/dss/dss.c b/drivers/video/omap2/dss/dss.c index 5c6805b3362d1..4025a14c5bc12 100644 --- a/drivers/video/omap2/dss/dss.c +++ b/drivers/video/omap2/dss/dss.c @@ -559,7 +559,7 @@ void dss_set_dac_pwrdn_bgz(bool enable) REG_FLD_MOD(DSS_CONTROL, enable, 5, 5); /* DAC Power-Down Control */ } -static int dss_init(bool skip_init) +static int dss_init(void) { int r; u32 rev; @@ -578,22 +578,20 @@ static int dss_init(bool skip_init) goto fail0; } - if (!skip_init) { - /* disable LCD and DIGIT output. This seems to fix the synclost - * problem that we get, if the bootloader starts the DSS and - * the kernel resets it */ - omap_writel(omap_readl(0x48050440) & ~0x3, 0x48050440); - - /* We need to wait here a bit, otherwise we sometimes start to - * get synclost errors, and after that only power cycle will - * restore DSS functionality. I have no idea why this happens. - * And we have to wait _before_ resetting the DSS, but after - * enabling clocks. - */ - msleep(50); - - _omap_dss_reset(); - } + /* disable LCD and DIGIT output. This seems to fix the synclost + * problem that we get, if the bootloader starts the DSS and + * the kernel resets it */ + omap_writel(omap_readl(0x48050440) & ~0x3, 0x48050440); + + /* We need to wait here a bit, otherwise we sometimes start to + * get synclost errors, and after that only power cycle will + * restore DSS functionality. I have no idea why this happens. + * And we have to wait _before_ resetting the DSS, but after + * enabling clocks. + */ + msleep(50); + + _omap_dss_reset(); /* autoidle */ REG_FLD_MOD(DSS_SYSCONFIG, 1, 0, 0); @@ -954,7 +952,6 @@ void dss_debug_dump_clocks(struct seq_file *s) static int omap_dsshw_probe(struct platform_device *pdev) { int r; - int skip_init = 0; dss.pdev = pdev; @@ -967,13 +964,7 @@ static int omap_dsshw_probe(struct platform_device *pdev) dss.ctx_id = dss_get_ctx_id(); DSSDBG("initial ctx id %u\n", dss.ctx_id); -#ifdef CONFIG_FB_OMAP_BOOTLOADER_INIT - /* DISPC_CONTROL */ - if (omap_readl(0x48050440) & 1) /* LCD enabled? */ - skip_init = 1; -#endif - - r = dss_init(skip_init); + r = dss_init(); if (r) { DSSERR("Failed to initialize DSS\n"); goto err_dss; diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h index 20590fb53c91b..069fcc72331c1 100644 --- a/drivers/video/omap2/dss/dss.h +++ b/drivers/video/omap2/dss/dss.h @@ -251,11 +251,11 @@ int dss_calc_clock_div(bool is_tft, unsigned long req_pck, /* SDI */ #ifdef CONFIG_OMAP2_DSS_SDI -int sdi_init(bool skip_init); +int sdi_init(void); void sdi_exit(void); int sdi_init_display(struct omap_dss_device *display); #else -static inline int sdi_init(bool skip_init) +static inline int sdi_init(void) { return 0; } diff --git a/drivers/video/omap2/dss/sdi.c b/drivers/video/omap2/dss/sdi.c index 9f10a0d9e7609..54a53e648180e 100644 --- a/drivers/video/omap2/dss/sdi.c +++ b/drivers/video/omap2/dss/sdi.c @@ -30,7 +30,6 @@ #include "dss.h" static struct { - bool skip_init; bool update_enabled; struct regulator *vdds_sdi_reg; } sdi; @@ -68,9 +67,7 @@ int omapdss_sdi_display_enable(struct omap_dss_device *dssdev) if (r) goto err1; - /* In case of skip_init sdi_init has already enabled the clocks */ - if (!sdi.skip_init) - dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK); + dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK); sdi_basic_init(dssdev); @@ -80,14 +77,8 @@ int omapdss_sdi_display_enable(struct omap_dss_device *dssdev) dispc_set_pol_freq(dssdev->manager->id, dssdev->panel.config, dssdev->panel.acbi, dssdev->panel.acb); - if (!sdi.skip_init) { - r = dss_calc_clock_div(1, t->pixel_clock * 1000, - &dss_cinfo, &dispc_cinfo); - } else { - r = dss_get_clock_div(&dss_cinfo); - r = dispc_get_clock_div(dssdev->manager->id, &dispc_cinfo); - } - + r = dss_calc_clock_div(1, t->pixel_clock * 1000, + &dss_cinfo, &dispc_cinfo); if (r) goto err2; @@ -116,18 +107,14 @@ int omapdss_sdi_display_enable(struct omap_dss_device *dssdev) if (r) goto err2; - if (!sdi.skip_init) { - dss_sdi_init(dssdev->phy.sdi.datapairs); - r = dss_sdi_enable(); - if (r) - goto err1; - mdelay(2); - } + dss_sdi_init(dssdev->phy.sdi.datapairs); + r = dss_sdi_enable(); + if (r) + goto err1; + mdelay(2); dssdev->manager->enable(dssdev->manager); - sdi.skip_init = 0; - return 0; err2: dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK); @@ -173,17 +160,8 @@ int sdi_init_display(struct omap_dss_device *dssdev) return 0; } -int sdi_init(bool skip_init) +int sdi_init(void) { - /* we store this for first display enable, then clear it */ - sdi.skip_init = skip_init; - - /* - * Enable clocks already here, otherwise there would be a toggle - * of them until sdi_display_enable is called. - */ - if (skip_init) - dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK); return 0; } -- GitLab From 277b2881c3c0d97e214487fbd677b0590fb4acf3 Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Wed, 2 Mar 2011 12:32:48 +0200 Subject: [PATCH 0545/2822] OMAP: DSS2: Remove pdev argument from dpi_init dpi_init() does not use the pdev argument for anything. Remove it. Signed-off-by: Tomi Valkeinen --- drivers/video/omap2/dss/core.c | 2 +- drivers/video/omap2/dss/dpi.c | 2 +- drivers/video/omap2/dss/dss.h | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/video/omap2/dss/core.c b/drivers/video/omap2/dss/core.c index 02db5f1269eed..acefe50209fc7 100644 --- a/drivers/video/omap2/dss/core.c +++ b/drivers/video/omap2/dss/core.c @@ -191,7 +191,7 @@ static int omap_dss_probe(struct platform_device *pdev) goto err_rfbi; } - r = dpi_init(pdev); + r = dpi_init(); if (r) { DSSERR("Failed to initialize dpi\n"); goto err_dpi; diff --git a/drivers/video/omap2/dss/dpi.c b/drivers/video/omap2/dss/dpi.c index 08fed3080c0a6..2d3ca4ca4a05b 100644 --- a/drivers/video/omap2/dss/dpi.c +++ b/drivers/video/omap2/dss/dpi.c @@ -319,7 +319,7 @@ int dpi_init_display(struct omap_dss_device *dssdev) return 0; } -int dpi_init(struct platform_device *pdev) +int dpi_init(void) { return 0; } diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h index 069fcc72331c1..85d4141689c14 100644 --- a/drivers/video/omap2/dss/dss.h +++ b/drivers/video/omap2/dss/dss.h @@ -309,11 +309,11 @@ static inline void dsi_wait_pll_hsdiv_dsi_active(void) /* DPI */ #ifdef CONFIG_OMAP2_DSS_DPI -int dpi_init(struct platform_device *pdev); +int dpi_init(void); void dpi_exit(void); int dpi_init_display(struct omap_dss_device *dssdev); #else -static inline int dpi_init(struct platform_device *pdev) +static inline int dpi_init(void) { return 0; } -- GitLab From 587b5e8269fab583e4e9d2d6bbdc77b289ac78a7 Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Wed, 2 Mar 2011 12:47:54 +0200 Subject: [PATCH 0546/2822] OMAP: DSS2: Move DPI & SDI init into DSS plat driver DPI and SDI are different from the other interfaces as they are not hwmods and there is not platform driver for them. They could be said to be a part of DSS or DISPC modules, although it's not a clear definition. This patch moves DPI and SDI initialization into DSS platform driver, making the code more consistent: omap_dss_probe() only initializes platform drivers now. Signed-off-by: Tomi Valkeinen --- drivers/video/omap2/dss/core.c | 19 ------------------- drivers/video/omap2/dss/dss.c | 17 ++++++++++++++++- 2 files changed, 16 insertions(+), 20 deletions(-) diff --git a/drivers/video/omap2/dss/core.c b/drivers/video/omap2/dss/core.c index acefe50209fc7..8cfedae982110 100644 --- a/drivers/video/omap2/dss/core.c +++ b/drivers/video/omap2/dss/core.c @@ -191,12 +191,6 @@ static int omap_dss_probe(struct platform_device *pdev) goto err_rfbi; } - r = dpi_init(); - if (r) { - DSSERR("Failed to initialize dpi\n"); - goto err_dpi; - } - r = dispc_init_platform_driver(); if (r) { DSSERR("Failed to initialize dispc platform driver\n"); @@ -210,12 +204,6 @@ static int omap_dss_probe(struct platform_device *pdev) } if (cpu_is_omap34xx()) { - r = sdi_init(); - if (r) { - DSSERR("Failed to initialize SDI\n"); - goto err_sdi; - } - r = dsi_init_platform_driver(); if (r) { DSSERR("Failed to initialize DSI platform driver\n"); @@ -255,15 +243,10 @@ err_debugfs: if (cpu_is_omap34xx()) dsi_uninit_platform_driver(); err_dsi: - if (cpu_is_omap34xx()) - sdi_exit(); -err_sdi: venc_uninit_platform_driver(); err_venc: dispc_uninit_platform_driver(); err_dispc: - dpi_exit(); -err_dpi: rfbi_uninit_platform_driver(); err_rfbi: dss_uninit_platform_driver(); @@ -281,11 +264,9 @@ static int omap_dss_remove(struct platform_device *pdev) venc_uninit_platform_driver(); dispc_uninit_platform_driver(); - dpi_exit(); rfbi_uninit_platform_driver(); if (cpu_is_omap34xx()) { dsi_uninit_platform_driver(); - sdi_exit(); } dss_uninit_platform_driver(); diff --git a/drivers/video/omap2/dss/dss.c b/drivers/video/omap2/dss/dss.c index 4025a14c5bc12..e5da050bcf857 100644 --- a/drivers/video/omap2/dss/dss.c +++ b/drivers/video/omap2/dss/dss.c @@ -970,9 +970,24 @@ static int omap_dsshw_probe(struct platform_device *pdev) goto err_dss; } + r = dpi_init(); + if (r) { + DSSERR("Failed to initialize DPI\n"); + goto err_dpi; + } + + r = sdi_init(); + if (r) { + DSSERR("Failed to initialize SDI\n"); + goto err_sdi; + } + dss_clk_disable_all_no_ctx(); return 0; - +err_sdi: + dpi_exit(); +err_dpi: + dss_exit(); err_dss: dss_clk_disable_all_no_ctx(); dss_put_clocks(); -- GitLab From 0a5835185420160f4fe8a6e1d1e42cd7efa07dc7 Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Wed, 2 Mar 2011 12:48:35 +0200 Subject: [PATCH 0547/2822] OMAP: DSS2: Remove unneeded cpu_is_xxx checks cpu_is_omapxxx() was used previously to select the supported interfaces. Now that the interfaces are platform devices, we no longer need to do the check when registering the driver. Thus we can just remove the checks. Signed-off-by: Tomi Valkeinen --- drivers/video/omap2/dss/core.c | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/drivers/video/omap2/dss/core.c b/drivers/video/omap2/dss/core.c index 8cfedae982110..c2f930bf2844a 100644 --- a/drivers/video/omap2/dss/core.c +++ b/drivers/video/omap2/dss/core.c @@ -203,12 +203,10 @@ static int omap_dss_probe(struct platform_device *pdev) goto err_venc; } - if (cpu_is_omap34xx()) { - r = dsi_init_platform_driver(); - if (r) { - DSSERR("Failed to initialize DSI platform driver\n"); - goto err_dsi; - } + r = dsi_init_platform_driver(); + if (r) { + DSSERR("Failed to initialize DSI platform driver\n"); + goto err_dsi; } r = dss_initialize_debugfs(); @@ -240,8 +238,7 @@ static int omap_dss_probe(struct platform_device *pdev) err_register: dss_uninitialize_debugfs(); err_debugfs: - if (cpu_is_omap34xx()) - dsi_uninit_platform_driver(); + dsi_uninit_platform_driver(); err_dsi: venc_uninit_platform_driver(); err_venc: @@ -265,10 +262,7 @@ static int omap_dss_remove(struct platform_device *pdev) venc_uninit_platform_driver(); dispc_uninit_platform_driver(); rfbi_uninit_platform_driver(); - if (cpu_is_omap34xx()) { - dsi_uninit_platform_driver(); - } - + dsi_uninit_platform_driver(); dss_uninit_platform_driver(); dss_uninit_overlays(pdev); -- GitLab From 5ee3c1445dd89342ca8498c14afef82d0f76c794 Mon Sep 17 00:00:00 2001 From: Archit Taneja Date: Wed, 2 Mar 2011 12:35:53 +0530 Subject: [PATCH 0548/2822] OMAP: DSS2: Functions to request/release DSI VCs Introduce functions which request and release VC's. This will be used in panel drivers in their probes. omap_dsi_request_vc() takes in the pointer to the omap_dss_device, the VC_ID parameter which goes into the header of the DSI packets, and returns a Virtual channel number (or virtual channel register set) which it can use. omap_dsi_set_vc_id() takes the omap_dss_device pointer, the Virtual Channel number and the VC_ID that needs to be set for the specifed Virtual Channel. omap_dsi_release_vc() takes the omap_dss_device pointer and the Virtual Channel number that needs to be made free. Initialisation of VC parameters is done in dsi_init(). Signed-off-by: Archit Taneja Signed-off-by: Tomi Valkeinen --- arch/arm/plat-omap/include/plat/display.h | 3 + drivers/video/omap2/dss/dsi.c | 67 +++++++++++++++++++++-- 2 files changed, 65 insertions(+), 5 deletions(-) diff --git a/arch/arm/plat-omap/include/plat/display.h b/arch/arm/plat-omap/include/plat/display.h index 37658249e4834..e81ca66dfbb46 100644 --- a/arch/arm/plat-omap/include/plat/display.h +++ b/arch/arm/plat-omap/include/plat/display.h @@ -562,6 +562,9 @@ int omap_dsi_update(struct omap_dss_device *dssdev, int channel, u16 x, u16 y, u16 w, u16 h, void (*callback)(int, void *), void *data); +int omap_dsi_request_vc(struct omap_dss_device *dssdev, int *channel); +int omap_dsi_set_vc_id(struct omap_dss_device *dssdev, int channel, int vc_id); +void omap_dsi_release_vc(struct omap_dss_device *dssdev, int channel); int omapdss_dsi_display_enable(struct omap_dss_device *dssdev); void omapdss_dsi_display_disable(struct omap_dss_device *dssdev); diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c index 37ffbb6ecf691..fe3578bbff7dc 100644 --- a/drivers/video/omap2/dss/dsi.c +++ b/drivers/video/omap2/dss/dsi.c @@ -233,6 +233,7 @@ static struct enum dsi_vc_mode mode; struct omap_dss_device *dssdev; enum fifo_size fifo_size; + int vc_id; } vc[4]; struct mutex lock; @@ -1764,8 +1765,6 @@ static void dsi_vc_initial_config(int channel) r = FLD_MOD(r, 4, 23, 21); /* DMA_TX_REQ_NB = no dma */ dsi_write_reg(DSI_VC_CTRL(channel), r); - - dsi.vc[channel].mode = DSI_VC_MODE_L4; } static int dsi_vc_config_l4(int channel) @@ -1972,7 +1971,7 @@ static inline void dsi_vc_write_long_header(int channel, u8 data_type, WARN_ON(!dsi_bus_is_locked()); - data_id = data_type | channel << 6; + data_id = data_type | dsi.vc[channel].vc_id << 6; val = FLD_VAL(data_id, 7, 0) | FLD_VAL(len, 23, 8) | FLD_VAL(ecc, 31, 24); @@ -2075,7 +2074,7 @@ static int dsi_vc_send_short(int channel, u8 data_type, u16 data, u8 ecc) return -EINVAL; } - data_id = data_type | channel << 6; + data_id = data_type | dsi.vc[channel].vc_id << 6; r = (data_id << 0) | (data << 8) | (ecc << 24); @@ -3250,6 +3249,57 @@ int dsi_init_display(struct omap_dss_device *dssdev) return 0; } +int omap_dsi_request_vc(struct omap_dss_device *dssdev, int *channel) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(dsi.vc); i++) { + if (!dsi.vc[i].dssdev) { + dsi.vc[i].dssdev = dssdev; + *channel = i; + return 0; + } + } + + DSSERR("cannot get VC for display %s", dssdev->name); + return -ENOSPC; +} +EXPORT_SYMBOL(omap_dsi_request_vc); + +int omap_dsi_set_vc_id(struct omap_dss_device *dssdev, int channel, int vc_id) +{ + if (vc_id < 0 || vc_id > 3) { + DSSERR("VC ID out of range\n"); + return -EINVAL; + } + + if (channel < 0 || channel > 3) { + DSSERR("Virtual Channel out of range\n"); + return -EINVAL; + } + + if (dsi.vc[channel].dssdev != dssdev) { + DSSERR("Virtual Channel not allocated to display %s\n", + dssdev->name); + return -EINVAL; + } + + dsi.vc[channel].vc_id = vc_id; + + return 0; +} +EXPORT_SYMBOL(omap_dsi_set_vc_id); + +void omap_dsi_release_vc(struct omap_dss_device *dssdev, int channel) +{ + if ((channel >= 0 && channel <= 3) && + dsi.vc[channel].dssdev == dssdev) { + dsi.vc[channel].dssdev = NULL; + dsi.vc[channel].vc_id = 0; + } +} +EXPORT_SYMBOL(omap_dsi_release_vc); + void dsi_wait_pll_hsdiv_dispc_active(void) { if (wait_for_bit_change(DSI_PLL_STATUS, 7, 1) != 1) @@ -3269,7 +3319,7 @@ void dsi_wait_pll_hsdiv_dsi_active(void) static int dsi_init(struct platform_device *pdev) { u32 rev; - int r; + int r, i; struct resource *dsi_mem; spin_lock_init(&dsi.errors_lock); @@ -3323,6 +3373,13 @@ static int dsi_init(struct platform_device *pdev) goto err2; } + /* DSI VCs initialization */ + for (i = 0; i < ARRAY_SIZE(dsi.vc); i++) { + dsi.vc[i].mode = DSI_VC_MODE_L4; + dsi.vc[i].dssdev = NULL; + dsi.vc[i].vc_id = 0; + } + enable_clocks(1); rev = dsi_read_reg(DSI_REVISION); -- GitLab From bc6d4b1d3d9b7568fe88f5bb80d0266a7ef624cc Mon Sep 17 00:00:00 2001 From: Archit Taneja Date: Tue, 1 Mar 2011 13:59:46 +0530 Subject: [PATCH 0549/2822] OMAP: DSS2: Use request / release calls in Taal for DSI Virtual Channels. Taal driver used to take a hard coded Macro for Virtual Channel and the VC_ID. The Taal panel driver now requests for a Virtual channel through the omap_dsi_request_vc() call in taal_probe(). The channel number returned by the request_vc() call is used for sending command and data to the Panel. The DSI driver automatically configures the Virtual Channel's source to either Video Port or L4 Slave port based on what the panel driver is using it for. The driver uses omap_dsi_release_vc() to free the VC specified by the panel. taal_remove() or when a request_vc() call fails. Signed-off-by: Archit Taneja Signed-off-by: Tomi Valkeinen --- drivers/video/omap2/displays/panel-taal.c | 123 +++++++++++++--------- drivers/video/omap2/dss/dsi.c | 3 - 2 files changed, 71 insertions(+), 55 deletions(-) diff --git a/drivers/video/omap2/displays/panel-taal.c b/drivers/video/omap2/displays/panel-taal.c index 61026f96ad20a..abdfdd81001fd 100644 --- a/drivers/video/omap2/displays/panel-taal.c +++ b/drivers/video/omap2/displays/panel-taal.c @@ -218,6 +218,8 @@ struct taal_data { u16 w; u16 h; } update_region; + int channel; + struct delayed_work te_timeout_work; bool use_dsi_bl; @@ -257,12 +259,12 @@ static void hw_guard_wait(struct taal_data *td) } } -static int taal_dcs_read_1(u8 dcs_cmd, u8 *data) +static int taal_dcs_read_1(struct taal_data *td, u8 dcs_cmd, u8 *data) { int r; u8 buf[1]; - r = dsi_vc_dcs_read(TCH, dcs_cmd, buf, 1); + r = dsi_vc_dcs_read(td->channel, dcs_cmd, buf, 1); if (r < 0) return r; @@ -272,17 +274,17 @@ static int taal_dcs_read_1(u8 dcs_cmd, u8 *data) return 0; } -static int taal_dcs_write_0(u8 dcs_cmd) +static int taal_dcs_write_0(struct taal_data *td, u8 dcs_cmd) { - return dsi_vc_dcs_write(TCH, &dcs_cmd, 1); + return dsi_vc_dcs_write(td->channel, &dcs_cmd, 1); } -static int taal_dcs_write_1(u8 dcs_cmd, u8 param) +static int taal_dcs_write_1(struct taal_data *td, u8 dcs_cmd, u8 param) { u8 buf[2]; buf[0] = dcs_cmd; buf[1] = param; - return dsi_vc_dcs_write(TCH, buf, 2); + return dsi_vc_dcs_write(td->channel, buf, 2); } static int taal_sleep_in(struct taal_data *td) @@ -294,7 +296,7 @@ static int taal_sleep_in(struct taal_data *td) hw_guard_wait(td); cmd = DCS_SLEEP_IN; - r = dsi_vc_dcs_write_nosync(TCH, &cmd, 1); + r = dsi_vc_dcs_write_nosync(td->channel, &cmd, 1); if (r) return r; @@ -312,7 +314,7 @@ static int taal_sleep_out(struct taal_data *td) hw_guard_wait(td); - r = taal_dcs_write_0(DCS_SLEEP_OUT); + r = taal_dcs_write_0(td, DCS_SLEEP_OUT); if (r) return r; @@ -324,30 +326,30 @@ static int taal_sleep_out(struct taal_data *td) return 0; } -static int taal_get_id(u8 *id1, u8 *id2, u8 *id3) +static int taal_get_id(struct taal_data *td, u8 *id1, u8 *id2, u8 *id3) { int r; - r = taal_dcs_read_1(DCS_GET_ID1, id1); + r = taal_dcs_read_1(td, DCS_GET_ID1, id1); if (r) return r; - r = taal_dcs_read_1(DCS_GET_ID2, id2); + r = taal_dcs_read_1(td, DCS_GET_ID2, id2); if (r) return r; - r = taal_dcs_read_1(DCS_GET_ID3, id3); + r = taal_dcs_read_1(td, DCS_GET_ID3, id3); if (r) return r; return 0; } -static int taal_set_addr_mode(u8 rotate, bool mirror) +static int taal_set_addr_mode(struct taal_data *td, u8 rotate, bool mirror) { int r; u8 mode; int b5, b6, b7; - r = taal_dcs_read_1(DCS_READ_MADCTL, &mode); + r = taal_dcs_read_1(td, DCS_READ_MADCTL, &mode); if (r) return r; @@ -381,10 +383,11 @@ static int taal_set_addr_mode(u8 rotate, bool mirror) mode &= ~((1<<7) | (1<<6) | (1<<5)); mode |= (b7 << 7) | (b6 << 6) | (b5 << 5); - return taal_dcs_write_1(DCS_MEM_ACC_CTRL, mode); + return taal_dcs_write_1(td, DCS_MEM_ACC_CTRL, mode); } -static int taal_set_update_window(u16 x, u16 y, u16 w, u16 h) +static int taal_set_update_window(struct taal_data *td, + u16 x, u16 y, u16 w, u16 h) { int r; u16 x1 = x; @@ -399,7 +402,7 @@ static int taal_set_update_window(u16 x, u16 y, u16 w, u16 h) buf[3] = (x2 >> 8) & 0xff; buf[4] = (x2 >> 0) & 0xff; - r = dsi_vc_dcs_write_nosync(TCH, buf, sizeof(buf)); + r = dsi_vc_dcs_write_nosync(td->channel, buf, sizeof(buf)); if (r) return r; @@ -409,11 +412,11 @@ static int taal_set_update_window(u16 x, u16 y, u16 w, u16 h) buf[3] = (y2 >> 8) & 0xff; buf[4] = (y2 >> 0) & 0xff; - r = dsi_vc_dcs_write_nosync(TCH, buf, sizeof(buf)); + r = dsi_vc_dcs_write_nosync(td->channel, buf, sizeof(buf)); if (r) return r; - dsi_vc_send_bta_sync(TCH); + dsi_vc_send_bta_sync(td->channel); return r; } @@ -439,7 +442,7 @@ static int taal_bl_update_status(struct backlight_device *dev) if (td->use_dsi_bl) { if (td->enabled) { dsi_bus_lock(); - r = taal_dcs_write_1(DCS_BRIGHTNESS, level); + r = taal_dcs_write_1(td, DCS_BRIGHTNESS, level); dsi_bus_unlock(); } else { r = 0; @@ -502,7 +505,7 @@ static ssize_t taal_num_errors_show(struct device *dev, if (td->enabled) { dsi_bus_lock(); - r = taal_dcs_read_1(DCS_READ_NUM_ERRORS, &errors); + r = taal_dcs_read_1(td, DCS_READ_NUM_ERRORS, &errors); dsi_bus_unlock(); } else { r = -ENODEV; @@ -528,7 +531,7 @@ static ssize_t taal_hw_revision_show(struct device *dev, if (td->enabled) { dsi_bus_lock(); - r = taal_get_id(&id1, &id2, &id3); + r = taal_get_id(td, &id1, &id2, &id3); dsi_bus_unlock(); } else { r = -ENODEV; @@ -590,7 +593,7 @@ static ssize_t store_cabc_mode(struct device *dev, if (td->enabled) { dsi_bus_lock(); if (!td->cabc_broken) - taal_dcs_write_1(DCS_WRITE_CABC, i); + taal_dcs_write_1(td, DCS_WRITE_CABC, i); dsi_bus_unlock(); } @@ -774,14 +777,29 @@ static int taal_probe(struct omap_dss_device *dssdev) dev_dbg(&dssdev->dev, "Using GPIO TE\n"); } + r = omap_dsi_request_vc(dssdev, &td->channel); + if (r) { + dev_err(&dssdev->dev, "failed to get virtual channel\n"); + goto err_req_vc; + } + + r = omap_dsi_set_vc_id(dssdev, td->channel, TCH); + if (r) { + dev_err(&dssdev->dev, "failed to set VC_ID\n"); + goto err_vc_id; + } + r = sysfs_create_group(&dssdev->dev.kobj, &taal_attr_group); if (r) { dev_err(&dssdev->dev, "failed to create sysfs files\n"); - goto err_sysfs; + goto err_vc_id; } return 0; -err_sysfs: + +err_vc_id: + omap_dsi_release_vc(dssdev, td->channel); +err_req_vc: if (panel_data->use_ext_te) free_irq(gpio_to_irq(panel_data->ext_te_gpio), dssdev); err_irq: @@ -808,6 +826,7 @@ static void taal_remove(struct omap_dss_device *dssdev) dev_dbg(&dssdev->dev, "remove\n"); sysfs_remove_group(&dssdev->dev.kobj, &taal_attr_group); + omap_dsi_release_vc(dssdev, td->channel); if (panel_data->use_ext_te) { int gpio = panel_data->ext_te_gpio; @@ -846,13 +865,13 @@ static int taal_power_on(struct omap_dss_device *dssdev) taal_hw_reset(dssdev); - omapdss_dsi_vc_enable_hs(TCH, false); + omapdss_dsi_vc_enable_hs(td->channel, false); r = taal_sleep_out(td); if (r) goto err; - r = taal_get_id(&id1, &id2, &id3); + r = taal_get_id(td, &id1, &id2, &id3); if (r) goto err; @@ -861,30 +880,30 @@ static int taal_power_on(struct omap_dss_device *dssdev) (id2 == 0x00 || id2 == 0xff || id2 == 0x81)) td->cabc_broken = true; - r = taal_dcs_write_1(DCS_BRIGHTNESS, 0xff); + r = taal_dcs_write_1(td, DCS_BRIGHTNESS, 0xff); if (r) goto err; - r = taal_dcs_write_1(DCS_CTRL_DISPLAY, + r = taal_dcs_write_1(td, DCS_CTRL_DISPLAY, (1<<2) | (1<<5)); /* BL | BCTRL */ if (r) goto err; - r = taal_dcs_write_1(DCS_PIXEL_FORMAT, 0x7); /* 24bit/pixel */ + r = taal_dcs_write_1(td, DCS_PIXEL_FORMAT, 0x7); /* 24bit/pixel */ if (r) goto err; - r = taal_set_addr_mode(td->rotate, td->mirror); + r = taal_set_addr_mode(td, td->rotate, td->mirror); if (r) goto err; if (!td->cabc_broken) { - r = taal_dcs_write_1(DCS_WRITE_CABC, td->cabc_mode); + r = taal_dcs_write_1(td, DCS_WRITE_CABC, td->cabc_mode); if (r) goto err; } - r = taal_dcs_write_0(DCS_DISPLAY_ON); + r = taal_dcs_write_0(td, DCS_DISPLAY_ON); if (r) goto err; @@ -903,7 +922,7 @@ static int taal_power_on(struct omap_dss_device *dssdev) td->intro_printed = true; } - omapdss_dsi_vc_enable_hs(TCH, true); + omapdss_dsi_vc_enable_hs(td->channel, true); return 0; err: @@ -921,7 +940,7 @@ static void taal_power_off(struct omap_dss_device *dssdev) struct taal_data *td = dev_get_drvdata(&dssdev->dev); int r; - r = taal_dcs_write_0(DCS_DISPLAY_OFF); + r = taal_dcs_write_0(td, DCS_DISPLAY_OFF); if (!r) { r = taal_sleep_in(td); /* HACK: wait a bit so that the message goes through */ @@ -1089,7 +1108,7 @@ static irqreturn_t taal_te_isr(int irq, void *data) if (old) { cancel_delayed_work(&td->te_timeout_work); - r = omap_dsi_update(dssdev, TCH, + r = omap_dsi_update(dssdev, td->channel, td->update_region.x, td->update_region.y, td->update_region.w, @@ -1139,7 +1158,7 @@ static int taal_update(struct omap_dss_device *dssdev, if (r) goto err; - r = taal_set_update_window(x, y, w, h); + r = taal_set_update_window(td, x, y, w, h); if (r) goto err; @@ -1153,7 +1172,7 @@ static int taal_update(struct omap_dss_device *dssdev, msecs_to_jiffies(250)); atomic_set(&td->do_update, 1); } else { - r = omap_dsi_update(dssdev, TCH, x, y, w, h, + r = omap_dsi_update(dssdev, td->channel, x, y, w, h, taal_framedone_cb, dssdev); if (r) goto err; @@ -1191,9 +1210,9 @@ static int _taal_enable_te(struct omap_dss_device *dssdev, bool enable) int r; if (enable) - r = taal_dcs_write_1(DCS_TEAR_ON, 0); + r = taal_dcs_write_1(td, DCS_TEAR_ON, 0); else - r = taal_dcs_write_0(DCS_TEAR_OFF); + r = taal_dcs_write_0(td, DCS_TEAR_OFF); if (!panel_data->use_ext_te) omapdss_dsi_enable_te(dssdev, enable); @@ -1263,7 +1282,7 @@ static int taal_rotate(struct omap_dss_device *dssdev, u8 rotate) dsi_bus_lock(); if (td->enabled) { - r = taal_set_addr_mode(rotate, td->mirror); + r = taal_set_addr_mode(td, rotate, td->mirror); if (r) goto err; } @@ -1306,7 +1325,7 @@ static int taal_mirror(struct omap_dss_device *dssdev, bool enable) dsi_bus_lock(); if (td->enabled) { - r = taal_set_addr_mode(td->rotate, enable); + r = taal_set_addr_mode(td, td->rotate, enable); if (r) goto err; } @@ -1350,13 +1369,13 @@ static int taal_run_test(struct omap_dss_device *dssdev, int test_num) dsi_bus_lock(); - r = taal_dcs_read_1(DCS_GET_ID1, &id1); + r = taal_dcs_read_1(td, DCS_GET_ID1, &id1); if (r) goto err2; - r = taal_dcs_read_1(DCS_GET_ID2, &id2); + r = taal_dcs_read_1(td, DCS_GET_ID2, &id2); if (r) goto err2; - r = taal_dcs_read_1(DCS_GET_ID3, &id3); + r = taal_dcs_read_1(td, DCS_GET_ID3, &id3); if (r) goto err2; @@ -1404,9 +1423,9 @@ static int taal_memory_read(struct omap_dss_device *dssdev, else plen = 2; - taal_set_update_window(x, y, w, h); + taal_set_update_window(td, x, y, w, h); - r = dsi_vc_set_max_rx_packet_size(TCH, plen); + r = dsi_vc_set_max_rx_packet_size(td->channel, plen); if (r) goto err2; @@ -1414,7 +1433,7 @@ static int taal_memory_read(struct omap_dss_device *dssdev, u8 dcs_cmd = first ? 0x2e : 0x3e; first = 0; - r = dsi_vc_dcs_read(TCH, dcs_cmd, + r = dsi_vc_dcs_read(td->channel, dcs_cmd, buf + buf_used, size - buf_used); if (r < 0) { @@ -1440,7 +1459,7 @@ static int taal_memory_read(struct omap_dss_device *dssdev, r = buf_used; err3: - dsi_vc_set_max_rx_packet_size(TCH, 1); + dsi_vc_set_max_rx_packet_size(td->channel, 1); err2: dsi_bus_unlock(); err1: @@ -1466,7 +1485,7 @@ static void taal_esd_work(struct work_struct *work) dsi_bus_lock(); - r = taal_dcs_read_1(DCS_RDDSDR, &state1); + r = taal_dcs_read_1(td, DCS_RDDSDR, &state1); if (r) { dev_err(&dssdev->dev, "failed to read Taal status\n"); goto err; @@ -1479,7 +1498,7 @@ static void taal_esd_work(struct work_struct *work) goto err; } - r = taal_dcs_read_1(DCS_RDDSDR, &state2); + r = taal_dcs_read_1(td, DCS_RDDSDR, &state2); if (r) { dev_err(&dssdev->dev, "failed to read Taal status\n"); goto err; @@ -1495,7 +1514,7 @@ static void taal_esd_work(struct work_struct *work) /* Self-diagnostics result is also shown on TE GPIO line. We need * to re-enable TE after self diagnostics */ if (td->te_enabled && panel_data->use_ext_te) { - r = taal_dcs_write_1(DCS_TEAR_ON, 0); + r = taal_dcs_write_1(td, DCS_TEAR_ON, 0); if (r) goto err; } diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c index fe3578bbff7dc..44b667b55ab80 100644 --- a/drivers/video/omap2/dss/dsi.c +++ b/drivers/video/omap2/dss/dsi.c @@ -3230,9 +3230,6 @@ int dsi_init_display(struct omap_dss_device *dssdev) dssdev->caps = OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE | OMAP_DSS_DISPLAY_CAP_TEAR_ELIM; - dsi.vc[0].dssdev = dssdev; - dsi.vc[1].dssdev = dssdev; - if (dsi.vdds_dsi_reg == NULL) { struct regulator *vdds_dsi; -- GitLab From f2988ab9f4a2bf5e24f37d20eab1aad6862953d3 Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Wed, 2 Mar 2011 10:06:48 +0200 Subject: [PATCH 0550/2822] HACK: OMAP: DSS2: Fix OMAP2_DSS_USE_DSI_PLL When using OMAP2_DSS_USE_DSI_PLL, which selects DSI PLL as source clock for DISPC, the DSI needs the vdds_dsi regulator. Latest regulator changes broke this, causing the the code to not acquire the regulator when using OMAP2_DSS_USE_DSI_PLL. This patch acquires the vdds_dsi regulator in dsi_pll_init(), fixing the issue. This is is just a quick hack to get the OMAP2_DSS_USE_DSI_PLL option working. There shouldn't be any other downside in this solution than some extra lines of code. OMAP2_DSS_USE_DSI_PLL is itself a big hack, and should be removed, and the feature itself should be implemented in a more sane way. However, the solution is not trivial, and people are using DSI PLL to get more exact pixel clocks, so this hack is an acceptable temporary solution for the time being. Signed-off-by: Tomi Valkeinen --- drivers/video/omap2/dss/dsi.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c index 44b667b55ab80..be7694ff7ca7d 100644 --- a/drivers/video/omap2/dss/dsi.c +++ b/drivers/video/omap2/dss/dsi.c @@ -1119,6 +1119,26 @@ int dsi_pll_init(struct omap_dss_device *dssdev, bool enable_hsclk, DSSDBG("PLL init\n"); +#ifdef CONFIG_OMAP2_DSS_USE_DSI_PLL + /* + * HACK: this is just a quick hack to get the USE_DSI_PLL + * option working. USE_DSI_PLL is itself a big hack, and + * should be removed. + */ + if (dsi.vdds_dsi_reg == NULL) { + struct regulator *vdds_dsi; + + vdds_dsi = regulator_get(&dsi.pdev->dev, "vdds_dsi"); + + if (IS_ERR(vdds_dsi)) { + DSSERR("can't get VDDS_DSI regulator\n"); + return PTR_ERR(vdds_dsi); + } + + dsi.vdds_dsi_reg = vdds_dsi; + } +#endif + enable_clocks(1); dsi_enable_pll_clock(1); -- GitLab From 85604b0a247615157cedfec46b9cbfde2884f80f Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Thu, 3 Mar 2011 13:16:23 +0200 Subject: [PATCH 0551/2822] HACK: OMAP: DSS2: add delay after enabling clocks On omap4 the registers may not be accessible right after enabling the clocks. At some point this will be handled by pm_runtime, but, for the time begin, adding a small delay after clk_enable() should make things work. Signed-off-by: Tomi Valkeinen --- drivers/video/omap2/dss/dss.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/video/omap2/dss/dss.c b/drivers/video/omap2/dss/dss.c index e5da050bcf857..2be4d03ece437 100644 --- a/drivers/video/omap2/dss/dss.c +++ b/drivers/video/omap2/dss/dss.c @@ -850,6 +850,14 @@ void dss_clk_enable(enum dss_clock clks) dss_clk_enable_no_ctx(clks); + /* + * HACK: On omap4 the registers may not be accessible right after + * enabling the clocks. At some point this will be handled by + * pm_runtime, but for the time begin this should make things work. + */ + if (cpu_is_omap44xx() && check_ctx) + udelay(10); + if (check_ctx && cpu_is_omap34xx() && dss_need_ctx_restore()) restore_all_ctx(); } -- GitLab From 5c6366e14d9d4466ae34a1ccbc08dd8738909c1f Mon Sep 17 00:00:00 2001 From: "Murthy, Raghuveer" Date: Thu, 3 Mar 2011 09:27:58 -0600 Subject: [PATCH 0552/2822] OMAP: DSS2: Adding dss_features for independent core clk divider In OMAP3xxx DISPC_DIVISOR register has a logical clock divisor (lcd_div) field. The lcd_div is common, for deciding the DISPC core functional clock frequency, and the final pixel clock frequency for LCD display. In OMAP4, there are 2 LCD channels, hence two divisor registers, DISPC_DIVISOR1 and DISPC_DIVISOR2. Also, there is a third register DISPC_DIVISOR. The DISPC_DIVISOR in OMAP4 is used to configure lcd_div exclusively for core functional clock configuration. For pixel clock configuration of primary and secondary LCDs, lcd_div of DISPC_DIVISOR1 and DISPC_DIVISOR2 are used respectively Signed-off-by: Archit Taneja Signed-off-by: Raghuveer Murthy Signed-off-by: Tomi Valkeinen --- drivers/video/omap2/dss/dss_features.c | 3 ++- drivers/video/omap2/dss/dss_features.h | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/video/omap2/dss/dss_features.c b/drivers/video/omap2/dss/dss_features.c index ccae57b34f5ca..dc170ad079f2b 100644 --- a/drivers/video/omap2/dss/dss_features.c +++ b/drivers/video/omap2/dss/dss_features.c @@ -234,7 +234,8 @@ static struct omap_dss_features omap4_dss_features = { .has_feature = FEAT_GLOBAL_ALPHA | FEAT_PRE_MULT_ALPHA | - FEAT_MGR_LCD2 | FEAT_GLOBAL_ALPHA_VID1, + FEAT_MGR_LCD2 | FEAT_GLOBAL_ALPHA_VID1 | + FEAT_CORE_CLK_DIV, .num_mgrs = 3, .num_ovls = 3, diff --git a/drivers/video/omap2/dss/dss_features.h b/drivers/video/omap2/dss/dss_features.h index 65d6de7e0feb7..569d1b295edda 100644 --- a/drivers/video/omap2/dss/dss_features.h +++ b/drivers/video/omap2/dss/dss_features.h @@ -36,6 +36,8 @@ enum dss_feat_id { FEAT_LINEBUFFERSPLIT = 1 << 8, FEAT_ROWREPEATENABLE = 1 << 9, FEAT_RESIZECONF = 1 << 10, + /* Independent core clk divider */ + FEAT_CORE_CLK_DIV = 1 << 11, }; /* DSS register field id */ -- GitLab From ce7fa5eb1e815e79e4dd5db42d0d1f8c9d96925b Mon Sep 17 00:00:00 2001 From: "Murthy, Raghuveer" Date: Thu, 3 Mar 2011 09:27:59 -0600 Subject: [PATCH 0553/2822] OMAP: DSS2: Renaming register macro DISPC_DIVISOR(ch) The OMAP4 DISPC_DIVISOR1 is backward compatible to OMAP3xxx DISPC_DIVISOR. However DISPC_DIVISOR is also provided in OMAP4, to control DISPC_CORE_CLK independent of Primary and Secondary display clocks. Renamed DISPC_DIVISOR(ch) to DISPC_DIVISORo(ch), to facilitate introduction of DISPC_DIVISOR register, which is specific for OMAP4. OMAP4 has 3 registers DISPC_DIVISOR, DISPC_DIVISOR1 and DISPC_DIVISOR2. Also updated, all the usages of DISPC_DIVISOR(ch) to DISPC_DIVISORo(ch). Use DISPC_DIVISORo(ch) when DISPC_DIVISOR1 or DISPC_DIVISOR2 has to be configured OMAP4 TRM uses DISPC_DIVISORo generically to refer to DISPC_DIVISOR1 and DISPC_DIVISOR2 Signed-off-by: Raghuveer Murthy Signed-off-by: Tomi Valkeinen --- drivers/video/omap2/dss/dispc.c | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c index 9fb11c17623f5..a3dff5ffdcbb4 100644 --- a/drivers/video/omap2/dss/dispc.c +++ b/drivers/video/omap2/dss/dispc.c @@ -73,7 +73,7 @@ struct dispc_reg { u16 idx; }; #define DISPC_TIMING_H(ch) DISPC_REG(ch != 2 ? 0x0064 : 0x0400) #define DISPC_TIMING_V(ch) DISPC_REG(ch != 2 ? 0x0068 : 0x0404) #define DISPC_POL_FREQ(ch) DISPC_REG(ch != 2 ? 0x006C : 0x0408) -#define DISPC_DIVISOR(ch) DISPC_REG(ch != 2 ? 0x0070 : 0x040C) +#define DISPC_DIVISORo(ch) DISPC_REG(ch != 2 ? 0x0070 : 0x040C) #define DISPC_GLOBAL_ALPHA DISPC_REG(0x0074) #define DISPC_SIZE_DIG DISPC_REG(0x0078) #define DISPC_SIZE_LCD(ch) DISPC_REG(ch != 2 ? 0x007C : 0x03CC) @@ -128,6 +128,7 @@ struct dispc_reg { u16 idx; }; #define DISPC_VID_PRELOAD(n) DISPC_REG(0x230 + (n)*0x04) +#define DISPC_DIVISOR DISPC_REG(0x0804) #define DISPC_IRQ_MASK_ERROR (DISPC_IRQ_GFX_FIFO_UNDERFLOW | \ DISPC_IRQ_OCP_ERR | \ @@ -231,7 +232,7 @@ void dispc_save_context(void) SR(TIMING_H(0)); SR(TIMING_V(0)); SR(POL_FREQ(0)); - SR(DIVISOR(0)); + SR(DIVISORo(0)); SR(GLOBAL_ALPHA); SR(SIZE_DIG); SR(SIZE_LCD(0)); @@ -243,7 +244,7 @@ void dispc_save_context(void) SR(TIMING_H(2)); SR(TIMING_V(2)); SR(POL_FREQ(2)); - SR(DIVISOR(2)); + SR(DIVISORo(2)); SR(CONFIG2); } @@ -390,7 +391,7 @@ void dispc_restore_context(void) RR(TIMING_H(0)); RR(TIMING_V(0)); RR(POL_FREQ(0)); - RR(DIVISOR(0)); + RR(DIVISORo(0)); RR(GLOBAL_ALPHA); RR(SIZE_DIG); RR(SIZE_LCD(0)); @@ -401,7 +402,7 @@ void dispc_restore_context(void) RR(TIMING_H(2)); RR(TIMING_V(2)); RR(POL_FREQ(2)); - RR(DIVISOR(2)); + RR(DIVISORo(2)); RR(CONFIG2); } @@ -2316,7 +2317,7 @@ static void dispc_set_lcd_divisor(enum omap_channel channel, u16 lck_div, BUG_ON(pck_div < 2); enable_clocks(1); - dispc_write_reg(DISPC_DIVISOR(channel), + dispc_write_reg(DISPC_DIVISORo(channel), FLD_VAL(lck_div, 23, 16) | FLD_VAL(pck_div, 7, 0)); enable_clocks(0); } @@ -2325,7 +2326,7 @@ static void dispc_get_lcd_divisor(enum omap_channel channel, int *lck_div, int *pck_div) { u32 l; - l = dispc_read_reg(DISPC_DIVISOR(channel)); + l = dispc_read_reg(DISPC_DIVISORo(channel)); *lck_div = FLD_GET(l, 23, 16); *pck_div = FLD_GET(l, 7, 0); } @@ -2351,7 +2352,7 @@ unsigned long dispc_lclk_rate(enum omap_channel channel) unsigned long r; u32 l; - l = dispc_read_reg(DISPC_DIVISOR(channel)); + l = dispc_read_reg(DISPC_DIVISORo(channel)); lcd = FLD_GET(l, 23, 16); @@ -2366,7 +2367,7 @@ unsigned long dispc_pclk_rate(enum omap_channel channel) unsigned long r; u32 l; - l = dispc_read_reg(DISPC_DIVISOR(channel)); + l = dispc_read_reg(DISPC_DIVISORo(channel)); lcd = FLD_GET(l, 23, 16); pcd = FLD_GET(l, 7, 0); @@ -2483,7 +2484,7 @@ void dispc_dump_regs(struct seq_file *s) DUMPREG(DISPC_TIMING_H(0)); DUMPREG(DISPC_TIMING_V(0)); DUMPREG(DISPC_POL_FREQ(0)); - DUMPREG(DISPC_DIVISOR(0)); + DUMPREG(DISPC_DIVISORo(0)); DUMPREG(DISPC_GLOBAL_ALPHA); DUMPREG(DISPC_SIZE_DIG); DUMPREG(DISPC_SIZE_LCD(0)); @@ -2495,7 +2496,7 @@ void dispc_dump_regs(struct seq_file *s) DUMPREG(DISPC_TIMING_H(2)); DUMPREG(DISPC_TIMING_V(2)); DUMPREG(DISPC_POL_FREQ(2)); - DUMPREG(DISPC_DIVISOR(2)); + DUMPREG(DISPC_DIVISORo(2)); DUMPREG(DISPC_SIZE_LCD(2)); } @@ -2737,8 +2738,8 @@ int dispc_get_clock_div(enum omap_channel channel, fck = dispc_fclk_rate(); - cinfo->lck_div = REG_GET(DISPC_DIVISOR(channel), 23, 16); - cinfo->pck_div = REG_GET(DISPC_DIVISOR(channel), 7, 0); + cinfo->lck_div = REG_GET(DISPC_DIVISORo(channel), 23, 16); + cinfo->pck_div = REG_GET(DISPC_DIVISORo(channel), 7, 0); cinfo->lck = fck / cinfo->lck_div; cinfo->pck = cinfo->lck / cinfo->pck_div; -- GitLab From 0cf35df353e8c36d4be0da2d7483896de599f397 Mon Sep 17 00:00:00 2001 From: "Murthy, Raghuveer" Date: Thu, 3 Mar 2011 09:28:00 -0600 Subject: [PATCH 0554/2822] OMAP4: DSS2: Using dss_features to set independent core clock divider Using dss_features to select independent core clock divider and setting it. Added the register used, to DISPC context save and restore group ----------------------------------------------------------------------- In OMAP4, the minimum DISPC_CORE_CLK required can be expressed as: DISPC_CORE_CLK >= max(PCLK1*HSCALE1, PCLK2*HSCALE2, ...) Where PCLKi is the pixel clock generated by MANAGERi and HSCALEi is the maximum horizontal downscaling done through MANAGERi Based on the usecase, core clk can be increased or decreased at runtime to save power. Such mechanism are not yet implemented. Hence, we set the core clock divisor to 1, to support maximum range of resolutions ------------------------------------------------------------------------ Signed-off-by: Raghuveer Murthy Signed-off-by: Tomi Valkeinen --- drivers/video/omap2/dss/dispc.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c index a3dff5ffdcbb4..dae9686fb437f 100644 --- a/drivers/video/omap2/dss/dispc.c +++ b/drivers/video/omap2/dss/dispc.c @@ -375,6 +375,9 @@ void dispc_save_context(void) SR(VID_FIR_COEF_V(1, 7)); SR(VID_PRELOAD(1)); + + if (dss_has_feature(FEAT_CORE_CLK_DIV)) + SR(DIVISOR); } void dispc_restore_context(void) @@ -534,6 +537,9 @@ void dispc_restore_context(void) RR(VID_PRELOAD(1)); + if (dss_has_feature(FEAT_CORE_CLK_DIV)) + RR(DIVISOR); + /* enable last, because LCD & DIGIT enable are here */ RR(CONTROL); if (dss_has_feature(FEAT_MGR_LCD2)) @@ -2380,6 +2386,7 @@ unsigned long dispc_pclk_rate(enum omap_channel channel) void dispc_dump_clocks(struct seq_file *s) { int lcd, pcd; + u32 l; enum dss_clk_source dispc_clk_src = dss_get_dispc_clk_source(); enable_clocks(1); @@ -2392,6 +2399,14 @@ void dispc_dump_clocks(struct seq_file *s) seq_printf(s, "fck\t\t%-16lu\n", dispc_fclk_rate()); + if (dss_has_feature(FEAT_CORE_CLK_DIV)) { + seq_printf(s, "- DISPC-CORE-CLK -\n"); + l = dispc_read_reg(DISPC_DIVISOR); + lcd = FLD_GET(l, 23, 16); + + seq_printf(s, "lck\t\t%-16lulck div\t%u\n", + (dispc_fclk_rate()/lcd), lcd); + } seq_printf(s, "- LCD1 -\n"); dispc_get_lcd_divisor(OMAP_DSS_CHANNEL_LCD, &lcd, &pcd); @@ -3287,6 +3302,15 @@ static void _omap_dispc_initial_config(void) l = FLD_MOD(l, 1, 0, 0); /* AUTOIDLE */ dispc_write_reg(DISPC_SYSCONFIG, l); + /* Exclusively enable DISPC_CORE_CLK and set divider to 1 */ + if (dss_has_feature(FEAT_CORE_CLK_DIV)) { + l = dispc_read_reg(DISPC_DIVISOR); + /* Use DISPC_DIVISOR.LCD, instead of DISPC_DIVISOR1.LCD */ + l = FLD_MOD(l, 1, 0, 0); + l = FLD_MOD(l, 1, 23, 16); + dispc_write_reg(DISPC_DIVISOR, l); + } + /* FUNCGATED */ if (dss_has_feature(FEAT_FUNCGATED)) REG_FLD_MOD(DISPC_CONFIG, 1, 9, 9); -- GitLab From b9cb0984a6e6a09a4bcdc11ebc9f0eb71e5b6c85 Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Fri, 4 Mar 2011 18:19:54 +0200 Subject: [PATCH 0555/2822] OMAP: DSS2: fix omap_dispc_register_isr() fail path Fix handling of error in omap_dispc_register_isr() in case there are no free isr slots available. Reported-by: Ben Tucker Signed-off-by: Tomi Valkeinen --- drivers/video/omap2/dss/dispc.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c index dae9686fb437f..4a368c47700e9 100644 --- a/drivers/video/omap2/dss/dispc.c +++ b/drivers/video/omap2/dss/dispc.c @@ -2831,6 +2831,9 @@ int omap_dispc_register_isr(omap_dispc_isr_t isr, void *arg, u32 mask) break; } + if (ret) + goto err; + _omap_dispc_set_irqs(); spin_unlock_irqrestore(&dispc.irq_lock, flags); -- GitLab From 7654b4d3f4d2e2bc5b60990fc121891b95b33be5 Mon Sep 17 00:00:00 2001 From: Steve Sakoman Date: Sat, 5 Mar 2011 07:58:38 -0600 Subject: [PATCH 0556/2822] OMAP: DSS2: Add support for LG Philips LB035Q02 panel This patch adds support for the Gumstix Palo35 expansion board which utilizes the 320 x 240 pixel LG.Philips LB035Q02 LCD Panel Signed-off-by: Steve Sakoman Signed-off-by: Tomi Valkeinen --- drivers/video/omap2/displays/Kconfig | 6 + drivers/video/omap2/displays/Makefile | 1 + .../omap2/displays/panel-lgphilips-lb035q02.c | 279 ++++++++++++++++++ 3 files changed, 286 insertions(+) create mode 100644 drivers/video/omap2/displays/panel-lgphilips-lb035q02.c diff --git a/drivers/video/omap2/displays/Kconfig b/drivers/video/omap2/displays/Kconfig index 940cab394c2e6..d18ad6b2372af 100644 --- a/drivers/video/omap2/displays/Kconfig +++ b/drivers/video/omap2/displays/Kconfig @@ -9,6 +9,12 @@ config PANEL_GENERIC_DPI Supports LCD Panel used in TI SDP3430 and EVM boards, OMAP3517 EVM boards and CM-T35. +config PANEL_LGPHILIPS_LB035Q02 + tristate "LG.Philips LB035Q02 LCD Panel" + depends on OMAP2_DSS && SPI + help + LCD Panel used on the Gumstix Overo Palo35 + config PANEL_SHARP_LS037V7DW01 tristate "Sharp LS037V7DW01 LCD Panel" depends on OMAP2_DSS diff --git a/drivers/video/omap2/displays/Makefile b/drivers/video/omap2/displays/Makefile index 861f0255ec6ba..0f601ab3abf49 100644 --- a/drivers/video/omap2/displays/Makefile +++ b/drivers/video/omap2/displays/Makefile @@ -1,4 +1,5 @@ obj-$(CONFIG_PANEL_GENERIC_DPI) += panel-generic-dpi.o +obj-$(CONFIG_PANEL_LGPHILIPS_LB035Q02) += panel-lgphilips-lb035q02.o obj-$(CONFIG_PANEL_SHARP_LS037V7DW01) += panel-sharp-ls037v7dw01.o obj-$(CONFIG_PANEL_NEC_NL8048HL11_01B) += panel-nec-nl8048hl11-01b.o diff --git a/drivers/video/omap2/displays/panel-lgphilips-lb035q02.c b/drivers/video/omap2/displays/panel-lgphilips-lb035q02.c new file mode 100644 index 0000000000000..271324db24366 --- /dev/null +++ b/drivers/video/omap2/displays/panel-lgphilips-lb035q02.c @@ -0,0 +1,279 @@ +/* + * LCD panel driver for LG.Philips LB035Q02 + * + * Author: Steve Sakoman + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published by + * the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see . + */ + +#include +#include +#include +#include + +#include + +struct lb035q02_data { + struct mutex lock; +}; + +static struct omap_video_timings lb035q02_timings = { + .x_res = 320, + .y_res = 240, + + .pixel_clock = 6500, + + .hsw = 2, + .hfp = 20, + .hbp = 68, + + .vsw = 2, + .vfp = 4, + .vbp = 18, +}; + +static int lb035q02_panel_power_on(struct omap_dss_device *dssdev) +{ + int r; + + if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) + return 0; + + r = omapdss_dpi_display_enable(dssdev); + if (r) + goto err0; + + if (dssdev->platform_enable) { + r = dssdev->platform_enable(dssdev); + if (r) + goto err1; + } + + return 0; +err1: + omapdss_dpi_display_disable(dssdev); +err0: + return r; +} + +static void lb035q02_panel_power_off(struct omap_dss_device *dssdev) +{ + if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) + return; + + if (dssdev->platform_disable) + dssdev->platform_disable(dssdev); + + omapdss_dpi_display_disable(dssdev); +} + +static int lb035q02_panel_probe(struct omap_dss_device *dssdev) +{ + struct lb035q02_data *ld; + int r; + + dssdev->panel.config = OMAP_DSS_LCD_TFT | OMAP_DSS_LCD_IVS | + OMAP_DSS_LCD_IHS; + dssdev->panel.timings = lb035q02_timings; + + ld = kzalloc(sizeof(*ld), GFP_KERNEL); + if (!ld) { + r = -ENOMEM; + goto err; + } + mutex_init(&ld->lock); + dev_set_drvdata(&dssdev->dev, ld); + return 0; +err: + return r; +} + +static void lb035q02_panel_remove(struct omap_dss_device *dssdev) +{ + struct lb035q02_data *ld = dev_get_drvdata(&dssdev->dev); + + kfree(ld); +} + +static int lb035q02_panel_enable(struct omap_dss_device *dssdev) +{ + struct lb035q02_data *ld = dev_get_drvdata(&dssdev->dev); + int r; + + mutex_lock(&ld->lock); + + r = lb035q02_panel_power_on(dssdev); + if (r) + goto err; + dssdev->state = OMAP_DSS_DISPLAY_ACTIVE; + + mutex_unlock(&ld->lock); + return 0; +err: + mutex_unlock(&ld->lock); + return r; +} + +static void lb035q02_panel_disable(struct omap_dss_device *dssdev) +{ + struct lb035q02_data *ld = dev_get_drvdata(&dssdev->dev); + + mutex_lock(&ld->lock); + + lb035q02_panel_power_off(dssdev); + dssdev->state = OMAP_DSS_DISPLAY_DISABLED; + + mutex_unlock(&ld->lock); +} + +static int lb035q02_panel_suspend(struct omap_dss_device *dssdev) +{ + struct lb035q02_data *ld = dev_get_drvdata(&dssdev->dev); + + mutex_lock(&ld->lock); + + lb035q02_panel_power_off(dssdev); + dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED; + + mutex_unlock(&ld->lock); + return 0; +} + +static int lb035q02_panel_resume(struct omap_dss_device *dssdev) +{ + struct lb035q02_data *ld = dev_get_drvdata(&dssdev->dev); + int r; + + mutex_lock(&ld->lock); + + r = lb035q02_panel_power_on(dssdev); + if (r) + goto err; + dssdev->state = OMAP_DSS_DISPLAY_ACTIVE; + + mutex_unlock(&ld->lock); + return 0; +err: + mutex_unlock(&ld->lock); + return r; +} + +static struct omap_dss_driver lb035q02_driver = { + .probe = lb035q02_panel_probe, + .remove = lb035q02_panel_remove, + + .enable = lb035q02_panel_enable, + .disable = lb035q02_panel_disable, + .suspend = lb035q02_panel_suspend, + .resume = lb035q02_panel_resume, + + .driver = { + .name = "lgphilips_lb035q02_panel", + .owner = THIS_MODULE, + }, +}; + +static int lb035q02_write_reg(struct spi_device *spi, u8 reg, u16 val) +{ + struct spi_message msg; + struct spi_transfer index_xfer = { + .len = 3, + .cs_change = 1, + }; + struct spi_transfer value_xfer = { + .len = 3, + }; + u8 buffer[16]; + + spi_message_init(&msg); + + /* register index */ + buffer[0] = 0x70; + buffer[1] = 0x00; + buffer[2] = reg & 0x7f; + index_xfer.tx_buf = buffer; + spi_message_add_tail(&index_xfer, &msg); + + /* register value */ + buffer[4] = 0x72; + buffer[5] = val >> 8; + buffer[6] = val; + value_xfer.tx_buf = buffer + 4; + spi_message_add_tail(&value_xfer, &msg); + + return spi_sync(spi, &msg); +} + +static void init_lb035q02_panel(struct spi_device *spi) +{ + /* Init sequence from page 28 of the lb035q02 spec */ + lb035q02_write_reg(spi, 0x01, 0x6300); + lb035q02_write_reg(spi, 0x02, 0x0200); + lb035q02_write_reg(spi, 0x03, 0x0177); + lb035q02_write_reg(spi, 0x04, 0x04c7); + lb035q02_write_reg(spi, 0x05, 0xffc0); + lb035q02_write_reg(spi, 0x06, 0xe806); + lb035q02_write_reg(spi, 0x0a, 0x4008); + lb035q02_write_reg(spi, 0x0b, 0x0000); + lb035q02_write_reg(spi, 0x0d, 0x0030); + lb035q02_write_reg(spi, 0x0e, 0x2800); + lb035q02_write_reg(spi, 0x0f, 0x0000); + lb035q02_write_reg(spi, 0x16, 0x9f80); + lb035q02_write_reg(spi, 0x17, 0x0a0f); + lb035q02_write_reg(spi, 0x1e, 0x00c1); + lb035q02_write_reg(spi, 0x30, 0x0300); + lb035q02_write_reg(spi, 0x31, 0x0007); + lb035q02_write_reg(spi, 0x32, 0x0000); + lb035q02_write_reg(spi, 0x33, 0x0000); + lb035q02_write_reg(spi, 0x34, 0x0707); + lb035q02_write_reg(spi, 0x35, 0x0004); + lb035q02_write_reg(spi, 0x36, 0x0302); + lb035q02_write_reg(spi, 0x37, 0x0202); + lb035q02_write_reg(spi, 0x3a, 0x0a0d); + lb035q02_write_reg(spi, 0x3b, 0x0806); +} + +static int __devinit lb035q02_panel_spi_probe(struct spi_device *spi) +{ + init_lb035q02_panel(spi); + return omap_dss_register_driver(&lb035q02_driver); +} + +static int __devexit lb035q02_panel_spi_remove(struct spi_device *spi) +{ + omap_dss_unregister_driver(&lb035q02_driver); + return 0; +} + +static struct spi_driver lb035q02_spi_driver = { + .driver = { + .name = "lgphilips_lb035q02_panel-spi", + .owner = THIS_MODULE, + }, + .probe = lb035q02_panel_spi_probe, + .remove = __devexit_p(lb035q02_panel_spi_remove), +}; + +static int __init lb035q02_panel_drv_init(void) +{ + return spi_register_driver(&lb035q02_spi_driver); +} + +static void __exit lb035q02_panel_drv_exit(void) +{ + spi_unregister_driver(&lb035q02_spi_driver); +} + +module_init(lb035q02_panel_drv_init); +module_exit(lb035q02_panel_drv_exit); +MODULE_LICENSE("GPL"); -- GitLab From 7b12d7b66bac4ff51aeea0029734b7a921cbe817 Mon Sep 17 00:00:00 2001 From: Steve Sakoman Date: Sat, 5 Mar 2011 07:58:39 -0600 Subject: [PATCH 0557/2822] OMAP: DSS2: Add DSS2 support for Overo This patch adds DSS2 support for DVI, S-video, the 480x272 Samsung LTE430WQ-F0C panel, and the 320x240 LG.Philips LB035Q02 panel. Signed-off-by: Steve Sakoman Signed-off-by: Tomi Valkeinen --- arch/arm/mach-omap2/board-overo.c | 237 +++++++++++++++++++++++++----- 1 file changed, 200 insertions(+), 37 deletions(-) diff --git a/arch/arm/mach-omap2/board-overo.c b/arch/arm/mach-omap2/board-overo.c index 60f8db31763c5..d621ee8fec0c4 100644 --- a/arch/arm/mach-omap2/board-overo.c +++ b/arch/arm/mach-omap2/board-overo.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #include @@ -41,10 +42,14 @@ #include #include +#include +#include #include #include #include #include +#include +#include #include #include "mux.h" @@ -68,8 +73,6 @@ #if defined(CONFIG_TOUCHSCREEN_ADS7846) || \ defined(CONFIG_TOUCHSCREEN_ADS7846_MODULE) -#include -#include #include static struct omap2_mcspi_device_config ads7846_mcspi_config = { @@ -94,18 +97,6 @@ static struct ads7846_platform_data ads7846_config = { .keep_vref_on = 1, }; -static struct spi_board_info overo_spi_board_info[] __initdata = { - { - .modalias = "ads7846", - .bus_num = 1, - .chip_select = 0, - .max_speed_hz = 1500000, - .controller_data = &ads7846_mcspi_config, - .irq = OMAP_GPIO_IRQ(OVERO_GPIO_PENDOWN), - .platform_data = &ads7846_config, - } -}; - static void __init overo_ads7846_init(void) { if ((gpio_request(OVERO_GPIO_PENDOWN, "ADS7846_PENDOWN") == 0) && @@ -115,9 +106,6 @@ static void __init overo_ads7846_init(void) printk(KERN_ERR "could not obtain gpio for ADS7846_PENDOWN\n"); return; } - - spi_register_board_info(overo_spi_board_info, - ARRAY_SIZE(overo_spi_board_info)); } #else @@ -233,6 +221,137 @@ static inline void __init overo_init_smsc911x(void) static inline void __init overo_init_smsc911x(void) { return; } #endif +/* DSS */ +static int lcd_enabled; +static int dvi_enabled; + +#define OVERO_GPIO_LCD_EN 144 +#define OVERO_GPIO_LCD_BL 145 + +static void __init overo_display_init(void) +{ + if ((gpio_request(OVERO_GPIO_LCD_EN, "OVERO_GPIO_LCD_EN") == 0) && + (gpio_direction_output(OVERO_GPIO_LCD_EN, 1) == 0)) + gpio_export(OVERO_GPIO_LCD_EN, 0); + else + printk(KERN_ERR "could not obtain gpio for " + "OVERO_GPIO_LCD_EN\n"); + + if ((gpio_request(OVERO_GPIO_LCD_BL, "OVERO_GPIO_LCD_BL") == 0) && + (gpio_direction_output(OVERO_GPIO_LCD_BL, 1) == 0)) + gpio_export(OVERO_GPIO_LCD_BL, 0); + else + printk(KERN_ERR "could not obtain gpio for " + "OVERO_GPIO_LCD_BL\n"); +} + +static int overo_panel_enable_dvi(struct omap_dss_device *dssdev) +{ + if (lcd_enabled) { + printk(KERN_ERR "cannot enable DVI, LCD is enabled\n"); + return -EINVAL; + } + dvi_enabled = 1; + + return 0; +} + +static void overo_panel_disable_dvi(struct omap_dss_device *dssdev) +{ + dvi_enabled = 0; +} + +static struct panel_generic_dpi_data dvi_panel = { + .name = "generic", + .platform_enable = overo_panel_enable_dvi, + .platform_disable = overo_panel_disable_dvi, +}; + +static struct omap_dss_device overo_dvi_device = { + .name = "dvi", + .type = OMAP_DISPLAY_TYPE_DPI, + .driver_name = "generic_dpi_panel", + .data = &dvi_panel, + .phy.dpi.data_lines = 24, +}; + +static struct omap_dss_device overo_tv_device = { + .name = "tv", + .driver_name = "venc", + .type = OMAP_DISPLAY_TYPE_VENC, + .phy.venc.type = OMAP_DSS_VENC_TYPE_SVIDEO, +}; + +static int overo_panel_enable_lcd(struct omap_dss_device *dssdev) +{ + if (dvi_enabled) { + printk(KERN_ERR "cannot enable LCD, DVI is enabled\n"); + return -EINVAL; + } + + gpio_set_value(OVERO_GPIO_LCD_EN, 1); + gpio_set_value(OVERO_GPIO_LCD_BL, 1); + lcd_enabled = 1; + return 0; +} + +static void overo_panel_disable_lcd(struct omap_dss_device *dssdev) +{ + gpio_set_value(OVERO_GPIO_LCD_EN, 0); + gpio_set_value(OVERO_GPIO_LCD_BL, 0); + lcd_enabled = 0; +} + +static struct panel_generic_dpi_data lcd43_panel = { + .name = "samsung_lte430wq_f0c", + .platform_enable = overo_panel_enable_lcd, + .platform_disable = overo_panel_disable_lcd, +}; + +static struct omap_dss_device overo_lcd43_device = { + .name = "lcd43", + .type = OMAP_DISPLAY_TYPE_DPI, + .driver_name = "generic_dpi_panel", + .data = &lcd43_panel, + .phy.dpi.data_lines = 24, +}; + +#if defined(CONFIG_PANEL_LGPHILIPS_LB035Q02) || \ + defined(CONFIG_PANEL_LGPHILIPS_LB035Q02_MODULE) +static struct omap_dss_device overo_lcd35_device = { + .type = OMAP_DISPLAY_TYPE_DPI, + .name = "lcd35", + .driver_name = "lgphilips_lb035q02_panel", + .phy.dpi.data_lines = 24, + .platform_enable = overo_panel_enable_lcd, + .platform_disable = overo_panel_disable_lcd, +}; +#endif + +static struct omap_dss_device *overo_dss_devices[] = { + &overo_dvi_device, + &overo_tv_device, +#if defined(CONFIG_PANEL_LGPHILIPS_LB035Q02) || \ + defined(CONFIG_PANEL_LGPHILIPS_LB035Q02_MODULE) + &overo_lcd35_device, +#endif + &overo_lcd43_device, +}; + +static struct omap_dss_board_info overo_dss_data = { + .num_devices = ARRAY_SIZE(overo_dss_devices), + .devices = overo_dss_devices, + .default_device = &overo_dvi_device, +}; + +static struct regulator_consumer_supply overo_vdda_dac_supply = + REGULATOR_SUPPLY("vdda_dac", "omapdss_venc"); + +static struct regulator_consumer_supply overo_vdds_dsi_supply[] = { + REGULATOR_SUPPLY("vdds_dsi", "omapdss"), + REGULATOR_SUPPLY("vdds_dsi", "omapdss_dsi1"), +}; + static struct mtd_partition overo_nand_partitions[] = { { .name = "xloader", @@ -358,6 +477,35 @@ static struct regulator_init_data overo_vmmc1 = { .consumer_supplies = &overo_vmmc1_supply, }; +/* VDAC for DSS driving S-Video (8 mA unloaded, max 65 mA) */ +static struct regulator_init_data overo_vdac = { + .constraints = { + .min_uV = 1800000, + .max_uV = 1800000, + .valid_modes_mask = REGULATOR_MODE_NORMAL + | REGULATOR_MODE_STANDBY, + .valid_ops_mask = REGULATOR_CHANGE_MODE + | REGULATOR_CHANGE_STATUS, + }, + .num_consumer_supplies = 1, + .consumer_supplies = &overo_vdda_dac_supply, +}; + +/* VPLL2 for digital video outputs */ +static struct regulator_init_data overo_vpll2 = { + .constraints = { + .name = "VDVI", + .min_uV = 1800000, + .max_uV = 1800000, + .valid_modes_mask = REGULATOR_MODE_NORMAL + | REGULATOR_MODE_STANDBY, + .valid_ops_mask = REGULATOR_CHANGE_MODE + | REGULATOR_CHANGE_STATUS, + }, + .num_consumer_supplies = ARRAY_SIZE(overo_vdds_dsi_supply), + .consumer_supplies = overo_vdds_dsi_supply, +}; + static struct twl4030_codec_audio_data overo_audio_data; static struct twl4030_codec_data overo_codec_data = { @@ -365,8 +513,6 @@ static struct twl4030_codec_data overo_codec_data = { .audio = &overo_audio_data, }; -/* mmc2 (WLAN) and Bluetooth don't use twl4030 regulators */ - static struct twl4030_platform_data overo_twldata = { .irq_base = TWL4030_IRQ_BASE, .irq_end = TWL4030_IRQ_END, @@ -374,6 +520,8 @@ static struct twl4030_platform_data overo_twldata = { .usb = &overo_usb_data, .codec = &overo_codec_data, .vmmc1 = &overo_vmmc1, + .vdac = &overo_vdac, + .vpll2 = &overo_vpll2, }; static struct i2c_board_info __initdata overo_i2c_boardinfo[] = { @@ -394,18 +542,38 @@ static int __init overo_i2c_init(void) return 0; } -static struct platform_device overo_lcd_device = { - .name = "overo_lcd", - .id = -1, -}; - -static struct omap_lcd_config overo_lcd_config __initdata = { - .ctrl_name = "internal", +static struct spi_board_info overo_spi_board_info[] __initdata = { +#if defined(CONFIG_TOUCHSCREEN_ADS7846) || \ + defined(CONFIG_TOUCHSCREEN_ADS7846_MODULE) + { + .modalias = "ads7846", + .bus_num = 1, + .chip_select = 0, + .max_speed_hz = 1500000, + .controller_data = &ads7846_mcspi_config, + .irq = OMAP_GPIO_IRQ(OVERO_GPIO_PENDOWN), + .platform_data = &ads7846_config, + }, +#endif +#if defined(CONFIG_PANEL_LGPHILIPS_LB035Q02) || \ + defined(CONFIG_PANEL_LGPHILIPS_LB035Q02_MODULE) + { + .modalias = "lgphilips_lb035q02_panel-spi", + .bus_num = 1, + .chip_select = 1, + .max_speed_hz = 500000, + .mode = SPI_MODE_3, + }, +#endif }; -static struct omap_board_config_kernel overo_config[] __initdata = { - { OMAP_TAG_LCD, &overo_lcd_config }, -}; +static int __init overo_spi_init(void) +{ + overo_ads7846_init(); + spi_register_board_info(overo_spi_board_info, + ARRAY_SIZE(overo_spi_board_info)); + return 0; +} static void __init overo_init_early(void) { @@ -414,10 +582,6 @@ static void __init overo_init_early(void) mt46h32m32lf6_sdrc_params); } -static struct platform_device *overo_devices[] __initdata = { - &overo_lcd_device, -}; - static const struct ehci_hcd_omap_platform_data ehci_pdata __initconst = { .port_mode[0] = EHCI_HCD_OMAP_MODE_UNKNOWN, .port_mode[1] = EHCI_HCD_OMAP_MODE_PHY, @@ -444,16 +608,15 @@ static struct omap_musb_board_data musb_board_data = { static void __init overo_init(void) { omap3_mux_init(board_mux, OMAP_PACKAGE_CBB); - omap_board_config = overo_config; - omap_board_config_size = ARRAY_SIZE(overo_config); overo_i2c_init(); - platform_add_devices(overo_devices, ARRAY_SIZE(overo_devices)); + omap_display_init(&overo_dss_data); omap_serial_init(); overo_flash_init(); usb_musb_init(&musb_board_data); usb_ehci_init(&ehci_pdata); - overo_ads7846_init(); + overo_spi_init(); overo_init_smsc911x(); + overo_display_init(); /* Ensure SDRC pins are mux'd for self-refresh */ omap_mux_init_signal("sdrc_cke0", OMAP_PIN_OUTPUT); -- GitLab From 66534e8e936a0b926863df90054dc59826d70528 Mon Sep 17 00:00:00 2001 From: "Taneja, Archit" Date: Tue, 8 Mar 2011 05:50:34 -0600 Subject: [PATCH 0558/2822] OMAP2PLUS: DSS2: Cleanup clock source related code Clean up some of the DSS functions which select/get clock sources, use switch to select the clock source members since more clock sources will be introduced later on. Remove the use of macro CONFIG_OMAP2_DSS_DSI in dispc_fclk_rate, use a dummy inline for function for dsi_get_pll_hsdiv_dispc_rate() instead for code clarity. Signed-off-by: Archit Taneja Signed-off-by: Tomi Valkeinen --- drivers/video/omap2/dss/dispc.c | 15 +++++++++------ drivers/video/omap2/dss/dss.c | 32 ++++++++++++++++++++------------ drivers/video/omap2/dss/dss.h | 5 +++++ 3 files changed, 34 insertions(+), 18 deletions(-) diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c index 4a368c47700e9..28b690f2447f5 100644 --- a/drivers/video/omap2/dss/dispc.c +++ b/drivers/video/omap2/dss/dispc.c @@ -2341,14 +2341,17 @@ unsigned long dispc_fclk_rate(void) { unsigned long r = 0; - if (dss_get_dispc_clk_source() == DSS_CLK_SRC_FCK) + switch (dss_get_dispc_clk_source()) { + case DSS_CLK_SRC_FCK: r = dss_clk_get_rate(DSS_CLK_FCK); - else -#ifdef CONFIG_OMAP2_DSS_DSI + break; + case DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC: r = dsi_get_pll_hsdiv_dispc_rate(); -#else - BUG(); -#endif + break; + default: + BUG(); + } + return r; } diff --git a/drivers/video/omap2/dss/dss.c b/drivers/video/omap2/dss/dss.c index 2be4d03ece437..93813fd626be2 100644 --- a/drivers/video/omap2/dss/dss.c +++ b/drivers/video/omap2/dss/dss.c @@ -293,13 +293,17 @@ void dss_select_dispc_clk_source(enum dss_clk_source clk_src) { int b; - BUG_ON(clk_src != DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC && - clk_src != DSS_CLK_SRC_FCK); - - b = clk_src == DSS_CLK_SRC_FCK ? 0 : 1; - - if (clk_src == DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC) + switch (clk_src) { + case DSS_CLK_SRC_FCK: + b = 0; + break; + case DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC: + b = 1; dsi_wait_pll_hsdiv_dispc_active(); + break; + default: + BUG(); + } REG_FLD_MOD(DSS_CONTROL, b, 0, 0); /* DISPC_CLK_SWITCH */ @@ -310,13 +314,17 @@ void dss_select_dsi_clk_source(enum dss_clk_source clk_src) { int b; - BUG_ON(clk_src != DSS_CLK_SRC_DSI_PLL_HSDIV_DSI && - clk_src != DSS_CLK_SRC_FCK); - - b = clk_src == DSS_CLK_SRC_FCK ? 0 : 1; - - if (clk_src == DSS_CLK_SRC_DSI_PLL_HSDIV_DSI) + switch (clk_src) { + case DSS_CLK_SRC_FCK: + b = 0; + break; + case DSS_CLK_SRC_DSI_PLL_HSDIV_DSI: + b = 1; dsi_wait_pll_hsdiv_dsi_active(); + break; + default: + BUG(); + } REG_FLD_MOD(DSS_CONTROL, b, 1, 1); /* DSI_CLK_SWITCH */ diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h index 85d4141689c14..fc41b3f0c27e4 100644 --- a/drivers/video/omap2/dss/dss.h +++ b/drivers/video/omap2/dss/dss.h @@ -299,6 +299,11 @@ static inline int dsi_init_platform_driver(void) static inline void dsi_uninit_platform_driver(void) { } +static inline unsigned long dsi_get_pll_hsdiv_dispc_rate(void) +{ + WARN("%s: DSI not compiled in, returning rate as 0\n", __func__); + return 0; +} static inline void dsi_wait_pll_hsdiv_dispc_active(void) { } -- GitLab From ea75159ee6f00bd809f57a58e5505dc362382cc8 Mon Sep 17 00:00:00 2001 From: "Taneja, Archit" Date: Tue, 8 Mar 2011 05:50:35 -0600 Subject: [PATCH 0559/2822] OMAP4: DSS2: Clock source changes for OMAP4 On OMAP3, the pixel clock for the LCD manager was derived through DISPC_FCLK as: Lcd Pixel clock = DISPC_FCLK / lcd / pcd Where lcd and pcd are divisors in the DISPC_DIVISOR register. On OMAP4, the pixel clocks for LCD1 and LCD2 managers are derived from 2 new clocks named LCD1_CLK and LCD2_CLK. The pixel clocks are calculated as: Lcd_o Pixel clock = LCDo_CLK / lcdo /pcdo, o = 1, 2 Where lcdo and pcdo registers are divisors in DISPC_DIVISORo registers. LCD1_CLK and LCD2_CLK can have DSS_FCLK, and the M4 divider clocks of DSI1 PLL and DSI2 PLL as clock sources respectively. Introduce functions to select and get the clock source for these new clocks. Modify DISPC functions get the correct lck and pck rates based on the clock source of these clocks. Since OMAP2/3 don't have these clocks, force OMAP2/3 to always have the LCD_CLK source as DSS_CLK_SRC_FCK by introducing a dss feature. Introduce clock source names for OMAP4 and some register field changes in DSS_CTRL on OMAP4. Currently, LCD2_CLK can only have DSS_FCLK as its clock source as DSI2 PLL functionality hasn't been introduced yet. BUG for now if DSI2 PLL is selected as clock. Signed-off-by: Archit Taneja Signed-off-by: Tomi Valkeinen --- drivers/video/omap2/dss/dispc.c | 31 ++++++++++++++++--- drivers/video/omap2/dss/dss.c | 42 +++++++++++++++++++++++++- drivers/video/omap2/dss/dss.h | 26 ++++++++++------ drivers/video/omap2/dss/dss_features.c | 13 ++++++-- drivers/video/omap2/dss/dss_features.h | 3 ++ 5 files changed, 98 insertions(+), 17 deletions(-) diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c index 28b690f2447f5..b8c576a0bc02c 100644 --- a/drivers/video/omap2/dss/dispc.c +++ b/drivers/video/omap2/dss/dispc.c @@ -2365,25 +2365,33 @@ unsigned long dispc_lclk_rate(enum omap_channel channel) lcd = FLD_GET(l, 23, 16); - r = dispc_fclk_rate(); + switch (dss_get_lcd_clk_source(channel)) { + case DSS_CLK_SRC_FCK: + r = dss_clk_get_rate(DSS_CLK_FCK); + break; + case DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC: + r = dsi_get_pll_hsdiv_dispc_rate(); + break; + default: + BUG(); + } return r / lcd; } unsigned long dispc_pclk_rate(enum omap_channel channel) { - int lcd, pcd; + int pcd; unsigned long r; u32 l; l = dispc_read_reg(DISPC_DIVISORo(channel)); - lcd = FLD_GET(l, 23, 16); pcd = FLD_GET(l, 7, 0); - r = dispc_fclk_rate(); + r = dispc_lclk_rate(channel); - return r / lcd / pcd; + return r / pcd; } void dispc_dump_clocks(struct seq_file *s) @@ -2391,6 +2399,7 @@ void dispc_dump_clocks(struct seq_file *s) int lcd, pcd; u32 l; enum dss_clk_source dispc_clk_src = dss_get_dispc_clk_source(); + enum dss_clk_source lcd_clk_src; enable_clocks(1); @@ -2412,6 +2421,12 @@ void dispc_dump_clocks(struct seq_file *s) } seq_printf(s, "- LCD1 -\n"); + lcd_clk_src = dss_get_lcd_clk_source(OMAP_DSS_CHANNEL_LCD); + + seq_printf(s, "lcd1_clk source = %s (%s)\n", + dss_get_generic_clk_source_name(lcd_clk_src), + dss_feat_get_clk_source_name(lcd_clk_src)); + dispc_get_lcd_divisor(OMAP_DSS_CHANNEL_LCD, &lcd, &pcd); seq_printf(s, "lck\t\t%-16lulck div\t%u\n", @@ -2421,6 +2436,12 @@ void dispc_dump_clocks(struct seq_file *s) if (dss_has_feature(FEAT_MGR_LCD2)) { seq_printf(s, "- LCD2 -\n"); + lcd_clk_src = dss_get_lcd_clk_source(OMAP_DSS_CHANNEL_LCD2); + + seq_printf(s, "lcd2_clk source = %s (%s)\n", + dss_get_generic_clk_source_name(lcd_clk_src), + dss_feat_get_clk_source_name(lcd_clk_src)); + dispc_get_lcd_divisor(OMAP_DSS_CHANNEL_LCD2, &lcd, &pcd); seq_printf(s, "lck\t\t%-16lulck div\t%u\n", diff --git a/drivers/video/omap2/dss/dss.c b/drivers/video/omap2/dss/dss.c index 93813fd626be2..aed9345e8adad 100644 --- a/drivers/video/omap2/dss/dss.c +++ b/drivers/video/omap2/dss/dss.c @@ -77,6 +77,7 @@ static struct { enum dss_clk_source dsi_clk_source; enum dss_clk_source dispc_clk_source; + enum dss_clk_source lcd_clk_source[MAX_DSS_LCD_MANAGERS]; u32 ctx[DSS_SZ_REGS / sizeof(u32)]; } dss; @@ -292,6 +293,7 @@ void dss_dump_regs(struct seq_file *s) void dss_select_dispc_clk_source(enum dss_clk_source clk_src) { int b; + u8 start, end; switch (clk_src) { case DSS_CLK_SRC_FCK: @@ -305,7 +307,9 @@ void dss_select_dispc_clk_source(enum dss_clk_source clk_src) BUG(); } - REG_FLD_MOD(DSS_CONTROL, b, 0, 0); /* DISPC_CLK_SWITCH */ + dss_feat_get_reg_field(FEAT_REG_DISPC_CLK_SWITCH, &start, &end); + + REG_FLD_MOD(DSS_CONTROL, b, start, end); /* DISPC_CLK_SWITCH */ dss.dispc_clk_source = clk_src; } @@ -331,6 +335,34 @@ void dss_select_dsi_clk_source(enum dss_clk_source clk_src) dss.dsi_clk_source = clk_src; } +void dss_select_lcd_clk_source(enum omap_channel channel, + enum dss_clk_source clk_src) +{ + int b, ix, pos; + + if (!dss_has_feature(FEAT_LCD_CLK_SRC)) + return; + + switch (clk_src) { + case DSS_CLK_SRC_FCK: + b = 0; + break; + case DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC: + BUG_ON(channel != OMAP_DSS_CHANNEL_LCD); + b = 1; + dsi_wait_pll_hsdiv_dispc_active(); + break; + default: + BUG(); + } + + pos = channel == OMAP_DSS_CHANNEL_LCD ? 0 : 12; + REG_FLD_MOD(DSS_CONTROL, b, pos, pos); /* LCDx_CLK_SWITCH */ + + ix = channel == OMAP_DSS_CHANNEL_LCD ? 0 : 1; + dss.lcd_clk_source[ix] = clk_src; +} + enum dss_clk_source dss_get_dispc_clk_source(void) { return dss.dispc_clk_source; @@ -341,6 +373,12 @@ enum dss_clk_source dss_get_dsi_clk_source(void) return dss.dsi_clk_source; } +enum dss_clk_source dss_get_lcd_clk_source(enum omap_channel channel) +{ + int ix = channel == OMAP_DSS_CHANNEL_LCD ? 0 : 1; + return dss.lcd_clk_source[ix]; +} + /* calculate clock rates using dividers in cinfo */ int dss_calc_clock_rates(struct dss_clock_info *cinfo) { @@ -624,6 +662,8 @@ static int dss_init(void) dss.dsi_clk_source = DSS_CLK_SRC_FCK; dss.dispc_clk_source = DSS_CLK_SRC_FCK; + dss.lcd_clk_source[0] = DSS_CLK_SRC_FCK; + dss.lcd_clk_source[1] = DSS_CLK_SRC_FCK; dss_save_context(); diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h index fc41b3f0c27e4..b845468d97062 100644 --- a/drivers/video/omap2/dss/dss.h +++ b/drivers/video/omap2/dss/dss.h @@ -118,9 +118,12 @@ enum dss_clock { }; enum dss_clk_source { - DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC, /* DSI1_PLL_FCLK */ - DSS_CLK_SRC_DSI_PLL_HSDIV_DSI, /* DSI2_PLL_FCLK */ - DSS_CLK_SRC_FCK, /* DSS1_ALWON_FCLK */ + DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC, /* OMAP3: DSI1_PLL_FCLK + * OMAP4: PLL1_CLK1 */ + DSS_CLK_SRC_DSI_PLL_HSDIV_DSI, /* OMAP3: DSI2_PLL_FCLK + * OMAP4: PLL1_CLK2 */ + DSS_CLK_SRC_FCK, /* OMAP2/3: DSS1_ALWON_FCLK + * OMAP4: DSS_FCLK */ }; /* Correlates clock source name and dss_clk_source member */ @@ -152,17 +155,19 @@ struct dsi_clock_info { unsigned long fint; unsigned long clkin4ddr; unsigned long clkin; - unsigned long dsi_pll_hsdiv_dispc_clk; /* DSI1_PLL_CLK */ - unsigned long dsi_pll_hsdiv_dsi_clk; /* DSI2_PLL_CLK */ - + unsigned long dsi_pll_hsdiv_dispc_clk; /* OMAP3: DSI1_PLL_CLK + * OMAP4: PLLx_CLK1 */ + unsigned long dsi_pll_hsdiv_dsi_clk; /* OMAP3: DSI2_PLL_CLK + * OMAP4: PLLx_CLK2 */ unsigned long lp_clk; /* dividers */ u16 regn; u16 regm; - u16 regm_dispc; /* REGM3 */ - u16 regm_dsi; /* REGM4 */ - + u16 regm_dispc; /* OMAP3: REGM3 + * OMAP4: REGM4 */ + u16 regm_dsi; /* OMAP3: REGM4 + * OMAP4: REGM5 */ u16 lp_clk_div; u8 highfreq; @@ -235,8 +240,11 @@ void dss_sdi_disable(void); void dss_select_dispc_clk_source(enum dss_clk_source clk_src); void dss_select_dsi_clk_source(enum dss_clk_source clk_src); +void dss_select_lcd_clk_source(enum omap_channel channel, + enum dss_clk_source clk_src); enum dss_clk_source dss_get_dispc_clk_source(void); enum dss_clk_source dss_get_dsi_clk_source(void); +enum dss_clk_source dss_get_lcd_clk_source(enum omap_channel channel); void dss_set_venc_output(enum omap_dss_venc_type type); void dss_set_dac_pwrdn_bgz(bool enable); diff --git a/drivers/video/omap2/dss/dss_features.c b/drivers/video/omap2/dss/dss_features.c index dc170ad079f2b..6eb6ec62a0002 100644 --- a/drivers/video/omap2/dss/dss_features.c +++ b/drivers/video/omap2/dss/dss_features.c @@ -59,6 +59,7 @@ static const struct dss_reg_field omap2_dss_reg_fields[] = { { FEAT_REG_FIFOSIZE, 8, 0 }, { FEAT_REG_HORIZONTALACCU, 9, 0 }, { FEAT_REG_VERTICALACCU, 25, 16 }, + { FEAT_REG_DISPC_CLK_SWITCH, 0, 0 }, }; static const struct dss_reg_field omap3_dss_reg_fields[] = { @@ -69,6 +70,7 @@ static const struct dss_reg_field omap3_dss_reg_fields[] = { { FEAT_REG_FIFOSIZE, 10, 0 }, { FEAT_REG_HORIZONTALACCU, 9, 0 }, { FEAT_REG_VERTICALACCU, 25, 16 }, + { FEAT_REG_DISPC_CLK_SWITCH, 0, 0 }, }; static const struct dss_reg_field omap4_dss_reg_fields[] = { @@ -79,6 +81,7 @@ static const struct dss_reg_field omap4_dss_reg_fields[] = { { FEAT_REG_FIFOSIZE, 15, 0 }, { FEAT_REG_HORIZONTALACCU, 10, 0 }, { FEAT_REG_VERTICALACCU, 26, 16 }, + { FEAT_REG_DISPC_CLK_SWITCH, 9, 8 }, }; static const enum omap_display_type omap2_dss_supported_displays[] = { @@ -171,6 +174,12 @@ static const struct dss_clk_source_name omap3_dss_clk_source_names[] = { { DSS_CLK_SRC_FCK, "DSS1_ALWON_FCLK" }, }; +static const struct dss_clk_source_name omap4_dss_clk_source_names[] = { + { DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC, "PLL1_CLK1" }, + { DSS_CLK_SRC_DSI_PLL_HSDIV_DSI, "PLL1_CLK2" }, + { DSS_CLK_SRC_FCK, "DSS_FCLK" }, +}; + /* OMAP2 DSS Features */ static struct omap_dss_features omap2_dss_features = { .reg_fields = omap2_dss_reg_fields, @@ -235,14 +244,14 @@ static struct omap_dss_features omap4_dss_features = { .has_feature = FEAT_GLOBAL_ALPHA | FEAT_PRE_MULT_ALPHA | FEAT_MGR_LCD2 | FEAT_GLOBAL_ALPHA_VID1 | - FEAT_CORE_CLK_DIV, + FEAT_CORE_CLK_DIV | FEAT_LCD_CLK_SRC, .num_mgrs = 3, .num_ovls = 3, .max_dss_fck = 186000000, .supported_displays = omap4_dss_supported_displays, .supported_color_modes = omap3_dss_supported_color_modes, - .clksrc_names = omap3_dss_clk_source_names, + .clksrc_names = omap4_dss_clk_source_names, }; /* Functions returning values related to a DSS feature */ diff --git a/drivers/video/omap2/dss/dss_features.h b/drivers/video/omap2/dss/dss_features.h index 569d1b295edda..729b5f19fa2e4 100644 --- a/drivers/video/omap2/dss/dss_features.h +++ b/drivers/video/omap2/dss/dss_features.h @@ -22,6 +22,7 @@ #define MAX_DSS_MANAGERS 3 #define MAX_DSS_OVERLAYS 3 +#define MAX_DSS_LCD_MANAGERS 2 /* DSS has feature id */ enum dss_feat_id { @@ -38,6 +39,7 @@ enum dss_feat_id { FEAT_RESIZECONF = 1 << 10, /* Independent core clk divider */ FEAT_CORE_CLK_DIV = 1 << 11, + FEAT_LCD_CLK_SRC = 1 << 12, }; /* DSS register field id */ @@ -49,6 +51,7 @@ enum dss_feat_reg_field { FEAT_REG_FIFOSIZE, FEAT_REG_HORIZONTALACCU, FEAT_REG_VERTICALACCU, + FEAT_REG_DISPC_CLK_SWITCH, }; /* DSS Feature Functions */ -- GitLab From ca0a6a6473f69f1773c97755840587262d841883 Mon Sep 17 00:00:00 2001 From: Steve Sakoman Date: Sat, 5 Mar 2011 10:12:26 -0600 Subject: [PATCH 0560/2822] omap: overo: Add regulator for ads7846 The ads7846 driver now requires a regulator. This patch adds the necessary regulator to the overo board file. Without it, the following error occurs (and the touchscreen will not function): ads7846 spi1.0: unable to get regulator: -19 Signed-off-by: Steve Sakoman Acked-by: Tony Lindgren Signed-off-by: Tomi Valkeinen --- arch/arm/mach-omap2/board-overo.c | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/arch/arm/mach-omap2/board-overo.c b/arch/arm/mach-omap2/board-overo.c index d621ee8fec0c4..4278ecb799a26 100644 --- a/arch/arm/mach-omap2/board-overo.c +++ b/arch/arm/mach-omap2/board-overo.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #include @@ -97,6 +98,34 @@ static struct ads7846_platform_data ads7846_config = { .keep_vref_on = 1, }; +/* fixed regulator for ads7846 */ +static struct regulator_consumer_supply ads7846_supply = + REGULATOR_SUPPLY("vcc", "spi1.0"); + +static struct regulator_init_data vads7846_regulator = { + .constraints = { + .valid_ops_mask = REGULATOR_CHANGE_STATUS, + }, + .num_consumer_supplies = 1, + .consumer_supplies = &ads7846_supply, +}; + +static struct fixed_voltage_config vads7846 = { + .supply_name = "vads7846", + .microvolts = 3300000, /* 3.3V */ + .gpio = -EINVAL, + .startup_delay = 0, + .init_data = &vads7846_regulator, +}; + +static struct platform_device vads7846_device = { + .name = "reg-fixed-voltage", + .id = 1, + .dev = { + .platform_data = &vads7846, + }, +}; + static void __init overo_ads7846_init(void) { if ((gpio_request(OVERO_GPIO_PENDOWN, "ADS7846_PENDOWN") == 0) && @@ -106,6 +135,8 @@ static void __init overo_ads7846_init(void) printk(KERN_ERR "could not obtain gpio for ADS7846_PENDOWN\n"); return; } + + platform_device_register(&vads7846_device); } #else -- GitLab From 7c94f68d7b490c7787c6b97c5b2d6d56d57b071c Mon Sep 17 00:00:00 2001 From: Steve Sakoman Date: Wed, 9 Mar 2011 18:08:05 -0600 Subject: [PATCH 0561/2822] OMAP: Add gpio-leds support for Overo This patch adds support for the standard LEDs on the Overo COM and expansion boards Signed-off-by: Steve Sakoman Acked-by: Tony Lindgren Signed-off-by: Tomi Valkeinen --- arch/arm/mach-omap2/board-overo.c | 53 +++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/arch/arm/mach-omap2/board-overo.c b/arch/arm/mach-omap2/board-overo.c index 4278ecb799a26..e694ebd2636cc 100644 --- a/arch/arm/mach-omap2/board-overo.c +++ b/arch/arm/mach-omap2/board-overo.c @@ -473,6 +473,52 @@ static struct regulator_consumer_supply overo_vmmc1_supply = { .supply = "vmmc", }; +#if defined(CONFIG_LEDS_GPIO) || defined(CONFIG_LEDS_GPIO_MODULE) +#include + +static struct gpio_led gpio_leds[] = { + { + .name = "overo:red:gpio21", + .default_trigger = "heartbeat", + .gpio = 21, + .active_low = true, + }, + { + .name = "overo:blue:gpio22", + .default_trigger = "none", + .gpio = 22, + .active_low = true, + }, + { + .name = "overo:blue:COM", + .default_trigger = "mmc0", + .gpio = -EINVAL, /* gets replaced */ + .active_low = true, + }, +}; + +static struct gpio_led_platform_data gpio_leds_pdata = { + .leds = gpio_leds, + .num_leds = ARRAY_SIZE(gpio_leds), +}; + +static struct platform_device gpio_leds_device = { + .name = "leds-gpio", + .id = -1, + .dev = { + .platform_data = &gpio_leds_pdata, + }, +}; + +static void __init overo_init_led(void) +{ + platform_device_register(&gpio_leds_device); +} + +#else +static inline void __init overo_init_led(void) { return; } +#endif + static int overo_twl_gpio_setup(struct device *dev, unsigned gpio, unsigned ngpio) { @@ -480,6 +526,11 @@ static int overo_twl_gpio_setup(struct device *dev, overo_vmmc1_supply.dev = mmc[0].dev; +#if defined(CONFIG_LEDS_GPIO) || defined(CONFIG_LEDS_GPIO_MODULE) + /* TWL4030_GPIO_MAX + 1 == ledB, PMU_STAT (out, active low LED) */ + gpio_leds[2].gpio = gpio + TWL4030_GPIO_MAX + 1; +#endif + return 0; } @@ -487,6 +538,7 @@ static struct twl4030_gpio_platform_data overo_gpio_data = { .gpio_base = OMAP_MAX_GPIO_LINES, .irq_base = TWL4030_GPIO_IRQ_BASE, .irq_end = TWL4030_GPIO_IRQ_END, + .use_leds = true, .setup = overo_twl_gpio_setup, }; @@ -648,6 +700,7 @@ static void __init overo_init(void) overo_spi_init(); overo_init_smsc911x(); overo_display_init(); + overo_init_led(); /* Ensure SDRC pins are mux'd for self-refresh */ omap_mux_init_signal("sdrc_cke0", OMAP_PIN_OUTPUT); -- GitLab From cce18a947967ed028e5301bce84cbaff395489a6 Mon Sep 17 00:00:00 2001 From: Steve Sakoman Date: Wed, 9 Mar 2011 18:08:06 -0600 Subject: [PATCH 0562/2822] OMAP: Add gpio-keys support for Overo This patch adds support for the standard push buttons available on Overo expansion boards. Signed-off-by: Steve Sakoman Acked-by: Tony Lindgren Signed-off-by: Tomi Valkeinen --- arch/arm/mach-omap2/board-overo.c | 42 +++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/arch/arm/mach-omap2/board-overo.c b/arch/arm/mach-omap2/board-overo.c index e694ebd2636cc..1e17061649e50 100644 --- a/arch/arm/mach-omap2/board-overo.c +++ b/arch/arm/mach-omap2/board-overo.c @@ -519,6 +519,47 @@ static void __init overo_init_led(void) static inline void __init overo_init_led(void) { return; } #endif +#if defined(CONFIG_KEYBOARD_GPIO) || defined(CONFIG_KEYBOARD_GPIO_MODULE) +#include +#include + +static struct gpio_keys_button gpio_buttons[] = { + { + .code = BTN_0, + .gpio = 23, + .desc = "button0", + .wakeup = 1, + }, + { + .code = BTN_1, + .gpio = 14, + .desc = "button1", + .wakeup = 1, + }, +}; + +static struct gpio_keys_platform_data gpio_keys_pdata = { + .buttons = gpio_buttons, + .nbuttons = ARRAY_SIZE(gpio_buttons), +}; + +static struct platform_device gpio_keys_device = { + .name = "gpio-keys", + .id = -1, + .dev = { + .platform_data = &gpio_keys_pdata, + }, +}; + +static void __init overo_init_keys(void) +{ + platform_device_register(&gpio_keys_device); +} + +#else +static inline void __init overo_init_keys(void) { return; } +#endif + static int overo_twl_gpio_setup(struct device *dev, unsigned gpio, unsigned ngpio) { @@ -701,6 +742,7 @@ static void __init overo_init(void) overo_init_smsc911x(); overo_display_init(); overo_init_led(); + overo_init_keys(); /* Ensure SDRC pins are mux'd for self-refresh */ omap_mux_init_signal("sdrc_cke0", OMAP_PIN_OUTPUT); -- GitLab From 4d42942cff0785d8a153bafcd62b6870726cd5f1 Mon Sep 17 00:00:00 2001 From: Dmitry Eremin-Solenikov Date: Tue, 11 Jan 2011 14:33:35 +0300 Subject: [PATCH 0563/2822] mtd: make MTD_CONCAT support mandatory Move mtdconcat to be an integral part of the mtd core. It's a tiny bit of code, which bears 'say Y if you don't know what to do' note in the Kconfig. OTOH there are several ugly ifdefs depending on the MTD_CONCAT. So, making MTD_CONCAT support mandatory will allow us to clean up code a lot. Kconfig entry is changed to be a bool defaulting to Y, so all code pieces depending on it, will have MTD_CONCAT Kconfig symbol and CONFIG_MTD_CONCAT define. This will be removed in one of next patches. Signed-off-by: Dmitry Eremin-Solenikov Acked-by: Stefan Roese Signed-off-by: Artem Bityutskiy Signed-off-by: David Woodhouse --- drivers/mtd/Kconfig | 3 ++- drivers/mtd/Makefile | 3 +-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/mtd/Kconfig b/drivers/mtd/Kconfig index 77414702cb00e..c800247c04fb1 100644 --- a/drivers/mtd/Kconfig +++ b/drivers/mtd/Kconfig @@ -34,7 +34,8 @@ config MTD_TESTS various checks and verifications when loaded. config MTD_CONCAT - tristate "MTD concatenating support" + bool + default y help Support for concatenating several MTD devices into a single (virtual) one. This allows you to have -for example- a JFFS(2) diff --git a/drivers/mtd/Makefile b/drivers/mtd/Makefile index d4e7f25b1ebb6..eff3dd53cc051 100644 --- a/drivers/mtd/Makefile +++ b/drivers/mtd/Makefile @@ -4,11 +4,10 @@ # Core functionality. obj-$(CONFIG_MTD) += mtd.o -mtd-y := mtdcore.o mtdsuper.o +mtd-y := mtdcore.o mtdsuper.o mtdconcat.o mtd-$(CONFIG_MTD_PARTITIONS) += mtdpart.o mtd-$(CONFIG_MTD_OF_PARTS) += ofpart.o -obj-$(CONFIG_MTD_CONCAT) += mtdconcat.o obj-$(CONFIG_MTD_REDBOOT_PARTS) += redboot.o obj-$(CONFIG_MTD_CMDLINE_PARTS) += cmdlinepart.o obj-$(CONFIG_MTD_AFS_PARTS) += afs.o -- GitLab From e1d6ee722285278b427007fc3fa4421a0c1b3b3c Mon Sep 17 00:00:00 2001 From: Dmitry Eremin-Solenikov Date: Tue, 11 Jan 2011 14:33:36 +0300 Subject: [PATCH 0564/2822] mtd: drop MTD_CONCAT dependencies from Kconfig As MTD_CONCAT is becoming a part of mtd core, it's no longer necessary to depend on it in Kconfig scripts. Drop such references. Signed-off-by: Dmitry Eremin-Solenikov Acked-by: Stefan Roese Signed-off-by: Artem Bityutskiy Signed-off-by: David Woodhouse --- drivers/mtd/maps/Kconfig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/mtd/maps/Kconfig b/drivers/mtd/maps/Kconfig index 5d37d315fa98e..803072a71ed74 100644 --- a/drivers/mtd/maps/Kconfig +++ b/drivers/mtd/maps/Kconfig @@ -114,7 +114,7 @@ config MTD_SUN_UFLASH config MTD_SC520CDP tristate "CFI Flash device mapped on AMD SC520 CDP" - depends on X86 && MTD_CFI && MTD_CONCAT + depends on X86 && MTD_CFI help The SC520 CDP board has two banks of CFI-compliant chips and one Dual-in-line JEDEC chip. This 'mapping' driver supports that @@ -262,7 +262,7 @@ config MTD_BCM963XX config MTD_DILNETPC tristate "CFI Flash device mapped on DIL/Net PC" - depends on X86 && MTD_CONCAT && MTD_PARTITIONS && MTD_CFI_INTELEXT && BROKEN + depends on X86 && MTD_PARTITIONS && MTD_CFI_INTELEXT && BROKEN help MTD map driver for SSV DIL/Net PC Boards "DNP" and "ADNP". For details, see -- GitLab From a8adc3f01b9a757a0d290b2987af6b998697399f Mon Sep 17 00:00:00 2001 From: Dmitry Eremin-Solenikov Date: Tue, 11 Jan 2011 14:33:37 +0300 Subject: [PATCH 0565/2822] mtd: drop CONFIG_MTD_CONCAT ifdefs As MTD_CONCAT is becoming a part of mtd core, it's now meaningless to to check for it in ifdefs. Drop such references from MTD code. Signed-off-by: Dmitry Eremin-Solenikov Acked-by: Stefan Roese Signed-off-by: Artem Bityutskiy Signed-off-by: David Woodhouse --- drivers/mtd/maps/ceiva.c | 6 ------ drivers/mtd/maps/integrator-flash.c | 10 ---------- drivers/mtd/maps/physmap.c | 8 -------- drivers/mtd/maps/physmap_of.c | 8 -------- drivers/mtd/maps/sa1100-flash.c | 8 -------- 5 files changed, 40 deletions(-) diff --git a/drivers/mtd/maps/ceiva.c b/drivers/mtd/maps/ceiva.c index c09f4f57093ee..e5f645b775ad1 100644 --- a/drivers/mtd/maps/ceiva.c +++ b/drivers/mtd/maps/ceiva.c @@ -194,16 +194,10 @@ static int __init clps_setup_mtd(struct clps_info *clps, int nr, struct mtd_info * We detected multiple devices. Concatenate * them together. */ -#ifdef CONFIG_MTD_CONCAT *rmtd = mtd_concat_create(subdev, found, "clps flash"); if (*rmtd == NULL) ret = -ENXIO; -#else - printk(KERN_ERR "clps flash: multiple devices " - "found but MTD concat support disabled.\n"); - ret = -ENXIO; -#endif } } diff --git a/drivers/mtd/maps/integrator-flash.c b/drivers/mtd/maps/integrator-flash.c index 2aac41bde8b31..e22ff5adbbf4b 100644 --- a/drivers/mtd/maps/integrator-flash.c +++ b/drivers/mtd/maps/integrator-flash.c @@ -202,7 +202,6 @@ static int armflash_probe(struct platform_device *dev) if (info->nr_subdev == 1) info->mtd = info->subdev[0].mtd; else if (info->nr_subdev > 1) { -#ifdef CONFIG_MTD_CONCAT struct mtd_info *cdev[info->nr_subdev]; /* @@ -215,11 +214,6 @@ static int armflash_probe(struct platform_device *dev) dev_name(&dev->dev)); if (info->mtd == NULL) err = -ENXIO; -#else - printk(KERN_ERR "armflash: multiple devices found but " - "MTD concat support disabled.\n"); - err = -ENXIO; -#endif } if (err < 0) @@ -244,10 +238,8 @@ static int armflash_probe(struct platform_device *dev) cleanup: if (info->mtd) { del_mtd_partitions(info->mtd); -#ifdef CONFIG_MTD_CONCAT if (info->mtd != info->subdev[0].mtd) mtd_concat_destroy(info->mtd); -#endif } kfree(info->parts); subdev_err: @@ -272,10 +264,8 @@ static int armflash_remove(struct platform_device *dev) if (info) { if (info->mtd) { del_mtd_partitions(info->mtd); -#ifdef CONFIG_MTD_CONCAT if (info->mtd != info->subdev[0].mtd) mtd_concat_destroy(info->mtd); -#endif } kfree(info->parts); diff --git a/drivers/mtd/maps/physmap.c b/drivers/mtd/maps/physmap.c index 4c18b98a31108..7522df4f71f1d 100644 --- a/drivers/mtd/maps/physmap.c +++ b/drivers/mtd/maps/physmap.c @@ -59,10 +59,8 @@ static int physmap_flash_remove(struct platform_device *dev) #else del_mtd_device(info->cmtd); #endif -#ifdef CONFIG_MTD_CONCAT if (info->cmtd != info->mtd[0]) mtd_concat_destroy(info->cmtd); -#endif } for (i = 0; i < MAX_RESOURCES; i++) { @@ -159,15 +157,9 @@ static int physmap_flash_probe(struct platform_device *dev) /* * We detected multiple devices. Concatenate them together. */ -#ifdef CONFIG_MTD_CONCAT info->cmtd = mtd_concat_create(info->mtd, devices_found, dev_name(&dev->dev)); if (info->cmtd == NULL) err = -ENXIO; -#else - printk(KERN_ERR "physmap-flash: multiple devices " - "found but MTD concat support disabled.\n"); - err = -ENXIO; -#endif } if (err) goto err_out; diff --git a/drivers/mtd/maps/physmap_of.c b/drivers/mtd/maps/physmap_of.c index 8506578e6a352..c85be8312488d 100644 --- a/drivers/mtd/maps/physmap_of.c +++ b/drivers/mtd/maps/physmap_of.c @@ -104,12 +104,10 @@ static int of_flash_remove(struct platform_device *dev) return 0; dev_set_drvdata(&dev->dev, NULL); -#ifdef CONFIG_MTD_CONCAT if (info->cmtd != info->list[0].mtd) { del_mtd_device(info->cmtd); mtd_concat_destroy(info->cmtd); } -#endif if (info->cmtd) { if (OF_FLASH_PARTS(info)) { @@ -334,16 +332,10 @@ static int __devinit of_flash_probe(struct platform_device *dev, /* * We detected multiple devices. Concatenate them together. */ -#ifdef CONFIG_MTD_CONCAT info->cmtd = mtd_concat_create(mtd_list, info->list_size, dev_name(&dev->dev)); if (info->cmtd == NULL) err = -ENXIO; -#else - printk(KERN_ERR "physmap_of: multiple devices " - "found but MTD concat support disabled.\n"); - err = -ENXIO; -#endif } if (err) goto err_out; diff --git a/drivers/mtd/maps/sa1100-flash.c b/drivers/mtd/maps/sa1100-flash.c index f3af87e08ecd8..da875908ea8e0 100644 --- a/drivers/mtd/maps/sa1100-flash.c +++ b/drivers/mtd/maps/sa1100-flash.c @@ -232,10 +232,8 @@ static void sa1100_destroy(struct sa_info *info, struct flash_platform_data *pla else del_mtd_partitions(info->mtd); #endif -#ifdef CONFIG_MTD_CONCAT if (info->mtd != info->subdev[0].mtd) mtd_concat_destroy(info->mtd); -#endif } kfree(info->parts); @@ -321,7 +319,6 @@ sa1100_setup_mtd(struct platform_device *pdev, struct flash_platform_data *plat) info->mtd = info->subdev[0].mtd; ret = 0; } else if (info->num_subdev > 1) { -#ifdef CONFIG_MTD_CONCAT struct mtd_info *cdev[nr]; /* * We detected multiple devices. Concatenate them together. @@ -333,11 +330,6 @@ sa1100_setup_mtd(struct platform_device *pdev, struct flash_platform_data *plat) plat->name); if (info->mtd == NULL) ret = -ENXIO; -#else - printk(KERN_ERR "SA1100 flash: multiple devices " - "found but MTD concat support disabled.\n"); - ret = -ENXIO; -#endif } if (ret == 0) -- GitLab From 06f2ae3c91ea04b0d640e0dd9cf69a265f5ecda6 Mon Sep 17 00:00:00 2001 From: Dmitry Eremin-Solenikov Date: Tue, 11 Jan 2011 14:33:38 +0300 Subject: [PATCH 0566/2822] CRIS: stop checking for MTD_CONCAT As MTD_CONCAT support is becoming an integral part of MTD core, there is no need for it's special treatment. So stop checking for MTD_CONCAT availability. Acked by Jesper Nilsson for merging this via the MTD tree. Signed-off-by: Dmitry Eremin-Solenikov Acked-by: Stefan Roese Signed-off-by: Jesper Nilsson Signed-off-by: Artem Bityutskiy Signed-off-by: David Woodhouse --- arch/cris/Kconfig | 1 - arch/cris/arch-v10/drivers/axisflashmap.c | 6 ------ arch/cris/arch-v32/drivers/Kconfig | 1 - arch/cris/arch-v32/drivers/axisflashmap.c | 6 ------ 4 files changed, 14 deletions(-) diff --git a/arch/cris/Kconfig b/arch/cris/Kconfig index 0a7a4c11d8b16..82985032233ab 100644 --- a/arch/cris/Kconfig +++ b/arch/cris/Kconfig @@ -275,7 +275,6 @@ config ETRAX_AXISFLASHMAP select MTD_CHAR select MTD_BLOCK select MTD_PARTITIONS - select MTD_CONCAT select MTD_COMPLEX_MAPPINGS help This option enables MTD mapping of flash devices. Needed to use diff --git a/arch/cris/arch-v10/drivers/axisflashmap.c b/arch/cris/arch-v10/drivers/axisflashmap.c index b2079703af7e3..ed708e19d09eb 100644 --- a/arch/cris/arch-v10/drivers/axisflashmap.c +++ b/arch/cris/arch-v10/drivers/axisflashmap.c @@ -234,7 +234,6 @@ static struct mtd_info *flash_probe(void) } if (mtd_cse0 && mtd_cse1) { -#ifdef CONFIG_MTD_CONCAT struct mtd_info *mtds[] = { mtd_cse0, mtd_cse1 }; /* Since the concatenation layer adds a small overhead we @@ -246,11 +245,6 @@ static struct mtd_info *flash_probe(void) */ mtd_cse = mtd_concat_create(mtds, ARRAY_SIZE(mtds), "cse0+cse1"); -#else - printk(KERN_ERR "%s and %s: Cannot concatenate due to kernel " - "(mis)configuration!\n", map_cse0.name, map_cse1.name); - mtd_cse = NULL; -#endif if (!mtd_cse) { printk(KERN_ERR "%s and %s: Concatenation failed!\n", map_cse0.name, map_cse1.name); diff --git a/arch/cris/arch-v32/drivers/Kconfig b/arch/cris/arch-v32/drivers/Kconfig index a2dd740c59078..1633b120aa81a 100644 --- a/arch/cris/arch-v32/drivers/Kconfig +++ b/arch/cris/arch-v32/drivers/Kconfig @@ -406,7 +406,6 @@ config ETRAX_AXISFLASHMAP select MTD_CHAR select MTD_BLOCK select MTD_PARTITIONS - select MTD_CONCAT select MTD_COMPLEX_MAPPINGS help This option enables MTD mapping of flash devices. Needed to use diff --git a/arch/cris/arch-v32/drivers/axisflashmap.c b/arch/cris/arch-v32/drivers/axisflashmap.c index 51e1e85df96d5..3d751250271be 100644 --- a/arch/cris/arch-v32/drivers/axisflashmap.c +++ b/arch/cris/arch-v32/drivers/axisflashmap.c @@ -275,7 +275,6 @@ static struct mtd_info *flash_probe(void) } if (count > 1) { -#ifdef CONFIG_MTD_CONCAT /* Since the concatenation layer adds a small overhead we * could try to figure out if the chips in cse0 and cse1 are * identical and reprobe the whole cse0+cse1 window. But since @@ -284,11 +283,6 @@ static struct mtd_info *flash_probe(void) * complicating the probing procedure. */ mtd_total = mtd_concat_create(mtds, count, "cse0+cse1"); -#else - printk(KERN_ERR "%s and %s: Cannot concatenate due to kernel " - "(mis)configuration!\n", map_cse0.name, map_cse1.name); - mtd_toal = NULL; -#endif if (!mtd_total) { printk(KERN_ERR "%s and %s: Concatenation failed!\n", map_cse0.name, map_cse1.name); -- GitLab From f53fdebcc3e1e5d15ffd0b1204d5944b4ceb8a07 Mon Sep 17 00:00:00 2001 From: Dmitry Eremin-Solenikov Date: Tue, 11 Jan 2011 14:33:39 +0300 Subject: [PATCH 0567/2822] mtd: drop MTD_CONCAT from Kconfig entirely As there are no more dependencies on MTD_CONCAT or CONFIG_MTD_CONCAT, drop this entry from Kconfig entirely. Signed-off-by: Dmitry Eremin-Solenikov Acked-by: Stefan Roese Signed-off-by: Artem Bityutskiy Signed-off-by: David Woodhouse --- drivers/mtd/Kconfig | 9 --------- 1 file changed, 9 deletions(-) diff --git a/drivers/mtd/Kconfig b/drivers/mtd/Kconfig index c800247c04fb1..23088b3372d08 100644 --- a/drivers/mtd/Kconfig +++ b/drivers/mtd/Kconfig @@ -33,15 +33,6 @@ config MTD_TESTS should normally be compiled as kernel modules. The modules perform various checks and verifications when loaded. -config MTD_CONCAT - bool - default y - help - Support for concatenating several MTD devices into a single - (virtual) one. This allows you to have -for example- a JFFS(2) - file system spanning multiple physical flash chips. If unsure, - say 'Y'. - config MTD_PARTITIONS bool "MTD partitioning support" help -- GitLab From 83025c824fce44b6d007b9bbc506c4189fb89da1 Mon Sep 17 00:00:00 2001 From: Jamie Iles Date: Tue, 11 Jan 2011 12:43:49 +0000 Subject: [PATCH 0568/2822] mtd: mpc5121_nfc: don't treat NULL clk as an error clk_get() returns a struct clk cookie to the driver and some platforms may return NULL if they only support a single clock. clk_get() has only failed if it returns a ERR_PTR() encoded pointer. Signed-off-by: Jamie Iles Reviewed-by: Wolfram Sang Signed-off-by: Artem Bityutskiy Signed-off-by: David Woodhouse --- drivers/mtd/nand/mpc5121_nfc.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/mtd/nand/mpc5121_nfc.c b/drivers/mtd/nand/mpc5121_nfc.c index 469e649c911c8..ddaf0011aa88c 100644 --- a/drivers/mtd/nand/mpc5121_nfc.c +++ b/drivers/mtd/nand/mpc5121_nfc.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #include #include @@ -758,9 +759,9 @@ static int __devinit mpc5121_nfc_probe(struct platform_device *op, /* Enable NFC clock */ prv->clk = clk_get(dev, "nfc_clk"); - if (!prv->clk) { + if (IS_ERR(prv->clk)) { dev_err(dev, "Unable to acquire NFC clock!\n"); - retval = -ENODEV; + retval = PTR_ERR(prv->clk); goto error; } -- GitLab From ca91facf6babe548b5386993bb2820b7dc9b743d Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 11 Jan 2011 18:37:25 -0600 Subject: [PATCH 0569/2822] mtd: local symbols should be static The three backing_dev_info symbols are only used in this file and should be static. Signed-off-by: H Hartley Sweeten Signed-off-by: Artem Bityutskiy Signed-off-by: David Woodhouse --- drivers/mtd/mtdcore.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c index 527cebf58da46..da69bc8a5a7d6 100644 --- a/drivers/mtd/mtdcore.c +++ b/drivers/mtd/mtdcore.c @@ -43,7 +43,7 @@ * backing device capabilities for non-mappable devices (such as NAND flash) * - permits private mappings, copies are taken of the data */ -struct backing_dev_info mtd_bdi_unmappable = { +static struct backing_dev_info mtd_bdi_unmappable = { .capabilities = BDI_CAP_MAP_COPY, }; @@ -52,7 +52,7 @@ struct backing_dev_info mtd_bdi_unmappable = { * - permits private mappings, copies are taken of the data * - permits non-writable shared mappings */ -struct backing_dev_info mtd_bdi_ro_mappable = { +static struct backing_dev_info mtd_bdi_ro_mappable = { .capabilities = (BDI_CAP_MAP_COPY | BDI_CAP_MAP_DIRECT | BDI_CAP_EXEC_MAP | BDI_CAP_READ_MAP), }; @@ -62,7 +62,7 @@ struct backing_dev_info mtd_bdi_ro_mappable = { * - permits private mappings, copies are taken of the data * - permits non-writable shared mappings */ -struct backing_dev_info mtd_bdi_rw_mappable = { +static struct backing_dev_info mtd_bdi_rw_mappable = { .capabilities = (BDI_CAP_MAP_COPY | BDI_CAP_MAP_DIRECT | BDI_CAP_EXEC_MAP | BDI_CAP_READ_MAP | BDI_CAP_WRITE_MAP), -- GitLab From 7f53f12f02b0b60af373a07fcac62b578381308e Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 11 Jan 2011 18:46:10 -0600 Subject: [PATCH 0570/2822] mtd: mtd_blkdevs: local symbols should be static The function blktrans_dev_release and blktrans_dev_put are only used locally in this file and should be static. Signed-off-by: H Hartley Sweeten Signed-off-by: Artem Bityutskiy Signed-off-by: David Woodhouse --- drivers/mtd/mtd_blkdevs.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/mtd/mtd_blkdevs.c b/drivers/mtd/mtd_blkdevs.c index e0a2373bf0e2f..344ac1037ee71 100644 --- a/drivers/mtd/mtd_blkdevs.c +++ b/drivers/mtd/mtd_blkdevs.c @@ -40,7 +40,7 @@ static LIST_HEAD(blktrans_majors); static DEFINE_MUTEX(blktrans_ref_mutex); -void blktrans_dev_release(struct kref *kref) +static void blktrans_dev_release(struct kref *kref) { struct mtd_blktrans_dev *dev = container_of(kref, struct mtd_blktrans_dev, ref); @@ -67,7 +67,7 @@ unlock: return dev; } -void blktrans_dev_put(struct mtd_blktrans_dev *dev) +static void blktrans_dev_put(struct mtd_blktrans_dev *dev) { mutex_lock(&blktrans_ref_mutex); kref_put(&dev->ref, blktrans_dev_release); -- GitLab From cbc6c5e73dfa598b1fa5e67cef28096186e2a7cd Mon Sep 17 00:00:00 2001 From: Hong Xu Date: Tue, 18 Jan 2011 14:36:05 +0800 Subject: [PATCH 0571/2822] mtd: atmel_nand: Add DMA support to access Nandflash Some SAM9 chips have the ability to perform DMA between CPU and SMC controller. This patch adds DMA support for SAM9RL, SAM9G45, SSAM9G46,AM9M10, SAM9M11. Signed-off-by: Hong Xu Tested-by: Ryan Mallon Acked-by: Ryan Mallon Signed-off-by: David Woodhouse --- drivers/mtd/nand/atmel_nand.c | 166 ++++++++++++++++++++++++++++++++-- 1 file changed, 157 insertions(+), 9 deletions(-) diff --git a/drivers/mtd/nand/atmel_nand.c b/drivers/mtd/nand/atmel_nand.c index ccce0f03b5dcf..6fae04b3fc6da 100644 --- a/drivers/mtd/nand/atmel_nand.c +++ b/drivers/mtd/nand/atmel_nand.c @@ -48,6 +48,9 @@ #define no_ecc 0 #endif +static int use_dma = 1; +module_param(use_dma, int, 0); + static int on_flash_bbt = 0; module_param(on_flash_bbt, int, 0); @@ -89,11 +92,20 @@ struct atmel_nand_host { struct nand_chip nand_chip; struct mtd_info mtd; void __iomem *io_base; + dma_addr_t io_phys; struct atmel_nand_data *board; struct device *dev; void __iomem *ecc; + + struct completion comp; + struct dma_chan *dma_chan; }; +static int cpu_has_dma(void) +{ + return cpu_is_at91sam9rl() || cpu_is_at91sam9g45(); +} + /* * Enable NAND. */ @@ -150,7 +162,7 @@ static int atmel_nand_device_ready(struct mtd_info *mtd) /* * Minimal-overhead PIO for data access. */ -static void atmel_read_buf(struct mtd_info *mtd, u8 *buf, int len) +static void atmel_read_buf8(struct mtd_info *mtd, u8 *buf, int len) { struct nand_chip *nand_chip = mtd->priv; @@ -164,7 +176,7 @@ static void atmel_read_buf16(struct mtd_info *mtd, u8 *buf, int len) __raw_readsw(nand_chip->IO_ADDR_R, buf, len / 2); } -static void atmel_write_buf(struct mtd_info *mtd, const u8 *buf, int len) +static void atmel_write_buf8(struct mtd_info *mtd, const u8 *buf, int len) { struct nand_chip *nand_chip = mtd->priv; @@ -178,6 +190,121 @@ static void atmel_write_buf16(struct mtd_info *mtd, const u8 *buf, int len) __raw_writesw(nand_chip->IO_ADDR_W, buf, len / 2); } +static void dma_complete_func(void *completion) +{ + complete(completion); +} + +static int atmel_nand_dma_op(struct mtd_info *mtd, void *buf, int len, + int is_read) +{ + struct dma_device *dma_dev; + enum dma_ctrl_flags flags; + dma_addr_t dma_src_addr, dma_dst_addr, phys_addr; + struct dma_async_tx_descriptor *tx = NULL; + dma_cookie_t cookie; + struct nand_chip *chip = mtd->priv; + struct atmel_nand_host *host = chip->priv; + void *p = buf; + int err = -EIO; + enum dma_data_direction dir = is_read ? DMA_FROM_DEVICE : DMA_TO_DEVICE; + + if (buf >= high_memory) { + struct page *pg; + + if (((size_t)buf & PAGE_MASK) != + ((size_t)(buf + len - 1) & PAGE_MASK)) { + dev_warn(host->dev, "Buffer not fit in one page\n"); + goto err_buf; + } + + pg = vmalloc_to_page(buf); + if (pg == 0) { + dev_err(host->dev, "Failed to vmalloc_to_page\n"); + goto err_buf; + } + p = page_address(pg) + ((size_t)buf & ~PAGE_MASK); + } + + dma_dev = host->dma_chan->device; + + flags = DMA_CTRL_ACK | DMA_PREP_INTERRUPT | DMA_COMPL_SKIP_SRC_UNMAP | + DMA_COMPL_SKIP_DEST_UNMAP; + + phys_addr = dma_map_single(dma_dev->dev, p, len, dir); + if (dma_mapping_error(dma_dev->dev, phys_addr)) { + dev_err(host->dev, "Failed to dma_map_single\n"); + goto err_buf; + } + + if (is_read) { + dma_src_addr = host->io_phys; + dma_dst_addr = phys_addr; + } else { + dma_src_addr = phys_addr; + dma_dst_addr = host->io_phys; + } + + tx = dma_dev->device_prep_dma_memcpy(host->dma_chan, dma_dst_addr, + dma_src_addr, len, flags); + if (!tx) { + dev_err(host->dev, "Failed to prepare DMA memcpy\n"); + goto err_dma; + } + + init_completion(&host->comp); + tx->callback = dma_complete_func; + tx->callback_param = &host->comp; + + cookie = tx->tx_submit(tx); + if (dma_submit_error(cookie)) { + dev_err(host->dev, "Failed to do DMA tx_submit\n"); + goto err_dma; + } + + dma_async_issue_pending(host->dma_chan); + wait_for_completion(&host->comp); + + err = 0; + +err_dma: + dma_unmap_single(dma_dev->dev, phys_addr, len, dir); +err_buf: + if (err != 0) + dev_warn(host->dev, "Fall back to CPU I/O\n"); + return err; +} + +static void atmel_read_buf(struct mtd_info *mtd, u8 *buf, int len) +{ + struct nand_chip *chip = mtd->priv; + struct atmel_nand_host *host = chip->priv; + + if (use_dma && len >= mtd->oobsize) + if (atmel_nand_dma_op(mtd, buf, len, 1) == 0) + return; + + if (host->board->bus_width_16) + atmel_read_buf16(mtd, buf, len); + else + atmel_read_buf8(mtd, buf, len); +} + +static void atmel_write_buf(struct mtd_info *mtd, const u8 *buf, int len) +{ + struct nand_chip *chip = mtd->priv; + struct atmel_nand_host *host = chip->priv; + + if (use_dma && len >= mtd->oobsize) + if (atmel_nand_dma_op(mtd, (void *)buf, len, 0) == 0) + return; + + if (host->board->bus_width_16) + atmel_write_buf16(mtd, buf, len); + else + atmel_write_buf8(mtd, buf, len); +} + /* * Calculate HW ECC * @@ -398,6 +525,8 @@ static int __init atmel_nand_probe(struct platform_device *pdev) return -ENOMEM; } + host->io_phys = (dma_addr_t)mem->start; + host->io_base = ioremap(mem->start, mem->end - mem->start + 1); if (host->io_base == NULL) { printk(KERN_ERR "atmel_nand: ioremap failed\n"); @@ -448,14 +577,11 @@ static int __init atmel_nand_probe(struct platform_device *pdev) nand_chip->chip_delay = 20; /* 20us command delay time */ - if (host->board->bus_width_16) { /* 16-bit bus width */ + if (host->board->bus_width_16) /* 16-bit bus width */ nand_chip->options |= NAND_BUSWIDTH_16; - nand_chip->read_buf = atmel_read_buf16; - nand_chip->write_buf = atmel_write_buf16; - } else { - nand_chip->read_buf = atmel_read_buf; - nand_chip->write_buf = atmel_write_buf; - } + + nand_chip->read_buf = atmel_read_buf; + nand_chip->write_buf = atmel_write_buf; platform_set_drvdata(pdev, host); atmel_nand_enable(host); @@ -473,6 +599,22 @@ static int __init atmel_nand_probe(struct platform_device *pdev) nand_chip->options |= NAND_USE_FLASH_BBT; } + if (cpu_has_dma() && use_dma) { + dma_cap_mask_t mask; + + dma_cap_zero(mask); + dma_cap_set(DMA_MEMCPY, mask); + host->dma_chan = dma_request_channel(mask, 0, NULL); + if (!host->dma_chan) { + dev_err(host->dev, "Failed to request DMA channel\n"); + use_dma = 0; + } + } + if (use_dma) + dev_info(host->dev, "Using DMA for NAND access.\n"); + else + dev_info(host->dev, "No DMA support for NAND access.\n"); + /* first scan to find the device and get the page size */ if (nand_scan_ident(mtd, 1, NULL)) { res = -ENXIO; @@ -555,6 +697,8 @@ err_scan_ident: err_no_card: atmel_nand_disable(host); platform_set_drvdata(pdev, NULL); + if (host->dma_chan) + dma_release_channel(host->dma_chan); if (host->ecc) iounmap(host->ecc); err_ecc_ioremap: @@ -578,6 +722,10 @@ static int __exit atmel_nand_remove(struct platform_device *pdev) if (host->ecc) iounmap(host->ecc); + + if (host->dma_chan) + dma_release_channel(host->dma_chan); + iounmap(host->io_base); kfree(host); -- GitLab From 771df61949cf2d6ae9ff07e209c80693cdbc9302 Mon Sep 17 00:00:00 2001 From: Holger Brunck Date: Mon, 24 Jan 2011 17:45:42 +0100 Subject: [PATCH 0572/2822] mtd: adapt writebufsize calculation for concat If different chips with different writebufsize are concatenated, the writebufsize from the concat device has to be taken from the device with the largest writebuffer. This writebufsize is used later on in the UBI layer for the min I/O size. Signed-off-by: Holger Brunck Signed-off-by: Artem Bityutskiy Signed-off-by: David Woodhouse --- drivers/mtd/mtdconcat.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/mtd/mtdconcat.c b/drivers/mtd/mtdconcat.c index 5f5777bd3f75f..5060e608ea5d4 100644 --- a/drivers/mtd/mtdconcat.c +++ b/drivers/mtd/mtdconcat.c @@ -750,6 +750,7 @@ struct mtd_info *mtd_concat_create(struct mtd_info *subdev[], /* subdevices to c struct mtd_concat *concat; uint32_t max_erasesize, curr_erasesize; int num_erase_region; + int max_writebufsize = 0; printk(KERN_NOTICE "Concatenating MTD devices:\n"); for (i = 0; i < num_devs; i++) @@ -776,7 +777,12 @@ struct mtd_info *mtd_concat_create(struct mtd_info *subdev[], /* subdevices to c concat->mtd.size = subdev[0]->size; concat->mtd.erasesize = subdev[0]->erasesize; concat->mtd.writesize = subdev[0]->writesize; - concat->mtd.writebufsize = subdev[0]->writebufsize; + + for (i = 0; i < num_devs; i++) + if (max_writebufsize < subdev[i]->writebufsize) + max_writebufsize = subdev[i]->writebufsize; + concat->mtd.writebufsize = max_writebufsize; + concat->mtd.subpage_sft = subdev[0]->subpage_sft; concat->mtd.oobsize = subdev[0]->oobsize; concat->mtd.oobavail = subdev[0]->oobavail; -- GitLab From 37a23c20181aaddb8019f0a57bcda334412b89f8 Mon Sep 17 00:00:00 2001 From: Gabor Juhos Date: Tue, 25 Jan 2011 11:20:26 +0100 Subject: [PATCH 0573/2822] mtd: m25p80: add support for the EON EN25F32 chip Signed-off-by: Gabor Juhos Signed-off-by: David Woodhouse --- drivers/mtd/devices/m25p80.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c index e4eba6cc1b2e7..8d83a8b316705 100644 --- a/drivers/mtd/devices/m25p80.c +++ b/drivers/mtd/devices/m25p80.c @@ -655,7 +655,8 @@ static const struct spi_device_id m25p_ids[] = { { "at26df161a", INFO(0x1f4601, 0, 64 * 1024, 32, SECT_4K) }, { "at26df321", INFO(0x1f4700, 0, 64 * 1024, 64, SECT_4K) }, - /* EON -- en25pxx */ + /* EON -- en25xxx */ + { "en25f32", INFO(0x1c3116, 0, 64 * 1024, 64, SECT_4K) }, { "en25p32", INFO(0x1c2016, 0, 64 * 1024, 64, 0) }, { "en25p64", INFO(0x1c2017, 0, 64 * 1024, 128, 0) }, -- GitLab From 07be303d22ac7e067b8a7172a4043ebe32b74b33 Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Wed, 2 Feb 2011 08:53:55 +0200 Subject: [PATCH 0574/2822] mtd: mtdram: initialize writebufsize field Set the 'mtd->writebufsize' field to 64 to mimic modern CFI flashes. Signed-off-by: Artem Bityutskiy Signed-off-by: David Woodhouse --- drivers/mtd/devices/mtdram.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/mtd/devices/mtdram.c b/drivers/mtd/devices/mtdram.c index 26a6e809013d2..1483e18971cef 100644 --- a/drivers/mtd/devices/mtdram.c +++ b/drivers/mtd/devices/mtdram.c @@ -121,6 +121,7 @@ int mtdram_init_device(struct mtd_info *mtd, void *mapped_address, mtd->flags = MTD_CAP_RAM; mtd->size = size; mtd->writesize = 1; + mtd->writebufsize = 64; /* Mimic CFI NOR flashes */ mtd->erasesize = MTDRAM_ERASE_SIZE; mtd->priv = mapped_address; -- GitLab From f17f12ce9dd6ec0a8e1f415ecdbaebfce0207464 Mon Sep 17 00:00:00 2001 From: Mathias Krause Date: Sun, 30 Jan 2011 10:31:48 +0100 Subject: [PATCH 0575/2822] mtd: phram: fix memory leak Commit 4f678a58 (mtd: fix memory leaks in phram_setup) missed two cases where the memory allocated for name would be leaked. This commit frees the memory when register_device() fails and on unregister_devices(). Signed-off-by: Mathias Krause Signed-off-by: Artem Bityutskiy Signed-off-by: David Woodhouse --- drivers/mtd/devices/phram.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/mtd/devices/phram.c b/drivers/mtd/devices/phram.c index 52393282eaf10..8d28fa02a5a2f 100644 --- a/drivers/mtd/devices/phram.c +++ b/drivers/mtd/devices/phram.c @@ -117,6 +117,7 @@ static void unregister_devices(void) list_for_each_entry_safe(this, safe, &phram_list, list) { del_mtd_device(&this->mtd); iounmap(this->mtd.priv); + kfree(this->mtd.name); kfree(this); } } @@ -275,6 +276,8 @@ static int phram_setup(const char *val, struct kernel_param *kp) ret = register_device(name, start, len); if (!ret) pr_info("%s device: %#x at %#x\n", name, len, start); + else + kfree(name); return ret; } -- GitLab From 3ee7451a023dd197fcfc1ba46dcce6d8ec5e1b78 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Wed, 2 Feb 2011 18:13:36 +0100 Subject: [PATCH 0576/2822] mtd: ts5500_flash: avoid calling map_destroy on NULL map_destroy dereferences its argument. The call is furthermore only reachable when this argument is NULL. Thus the call is dropped. The semantic match that finds this problem is as follows: (http://coccinelle.lip6.fr/) // @@ expression *x; @@ *if (x == NULL) { ... * map_destroy(x); ... return ...; } // Signed-off-by: Julia Lawall Signed-off-by: Artem Bityutskiy Signed-off-by: David Woodhouse --- drivers/mtd/maps/ts5500_flash.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/mtd/maps/ts5500_flash.c b/drivers/mtd/maps/ts5500_flash.c index e2147bf11c889..e02dfa9d4ddd8 100644 --- a/drivers/mtd/maps/ts5500_flash.c +++ b/drivers/mtd/maps/ts5500_flash.c @@ -94,7 +94,6 @@ static int __init init_ts5500_map(void) return 0; err1: - map_destroy(mymtd); iounmap(ts5500_map.virt); err2: return rc; -- GitLab From 7b7e905ec2ec511e06279181ca95a892db21e292 Mon Sep 17 00:00:00 2001 From: Roman Tereshonkov Date: Thu, 3 Feb 2011 13:45:56 +0200 Subject: [PATCH 0577/2822] mtd: tests: print correct values The ebcnt and pgcnt variable initialization is moved before printk which uses them. Signed-off-by: Roman Tereshonkov Signed-off-by: Artem Bityutskiy Signed-off-by: David Woodhouse --- drivers/mtd/tests/mtd_subpagetest.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/mtd/tests/mtd_subpagetest.c b/drivers/mtd/tests/mtd_subpagetest.c index 11204e8aab5f3..334eae53a3dba 100644 --- a/drivers/mtd/tests/mtd_subpagetest.c +++ b/drivers/mtd/tests/mtd_subpagetest.c @@ -394,6 +394,11 @@ static int __init mtd_subpagetest_init(void) } subpgsize = mtd->writesize >> mtd->subpage_sft; + tmp = mtd->size; + do_div(tmp, mtd->erasesize); + ebcnt = tmp; + pgcnt = mtd->erasesize / mtd->writesize; + printk(PRINT_PREF "MTD device size %llu, eraseblock size %u, " "page size %u, subpage size %u, count of eraseblocks %u, " "pages per eraseblock %u, OOB size %u\n", @@ -413,11 +418,6 @@ static int __init mtd_subpagetest_init(void) goto out; } - tmp = mtd->size; - do_div(tmp, mtd->erasesize); - ebcnt = tmp; - pgcnt = mtd->erasesize / mtd->writesize; - err = scan_for_bad_eraseblocks(); if (err) goto out; -- GitLab From 7912a5e7f37512d8d105785046137435b70347ce Mon Sep 17 00:00:00 2001 From: Stanislav Fomichev Date: Mon, 7 Feb 2011 23:48:25 +0300 Subject: [PATCH 0578/2822] mtd: nand: fix pointer NULL pointer dereferencing In 'verify_bbt_descr()', first check the "bd" pointer, then dereference it. Comments amended by Artem. Signed-off-by: Stanislav Fomichev Signed-off-by: Artem Bityutskiy Signed-off-by: David Woodhouse --- drivers/mtd/nand/nand_bbt.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/mtd/nand/nand_bbt.c b/drivers/mtd/nand/nand_bbt.c index 6ebd869993aa9..a1e8b30078d9a 100644 --- a/drivers/mtd/nand/nand_bbt.c +++ b/drivers/mtd/nand/nand_bbt.c @@ -1101,12 +1101,16 @@ static void mark_bbt_region(struct mtd_info *mtd, struct nand_bbt_descr *td) static void verify_bbt_descr(struct mtd_info *mtd, struct nand_bbt_descr *bd) { struct nand_chip *this = mtd->priv; - u32 pattern_len = bd->len; - u32 bits = bd->options & NAND_BBT_NRBITS_MSK; + u32 pattern_len; + u32 bits; u32 table_size; if (!bd) return; + + pattern_len = bd->len; + bits = bd->options & NAND_BBT_NRBITS_MSK; + BUG_ON((this->options & NAND_USE_FLASH_BBT_NO_OOB) && !(this->options & NAND_USE_FLASH_BBT)); BUG_ON(!bits); -- GitLab From b085058fe556328443f982d892c9657b3aff9d4a Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Tue, 8 Feb 2011 12:02:38 +0200 Subject: [PATCH 0579/2822] mtd: OneNAND: return read error for 4KiB page read When reading using the 4KiB page read function, I/O errors could be ignored if more than 1 page was read at a time. Signed-off-by: Adrian Hunter Acked-by: Kyungmin Park Signed-off-by: Artem Bityutskiy Signed-off-by: David Woodhouse --- drivers/mtd/onenand/onenand_base.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/mtd/onenand/onenand_base.c b/drivers/mtd/onenand/onenand_base.c index bac41caa8df72..38e6d76bcc0ee 100644 --- a/drivers/mtd/onenand/onenand_base.c +++ b/drivers/mtd/onenand/onenand_base.c @@ -1132,6 +1132,8 @@ static int onenand_mlc_read_ops_nolock(struct mtd_info *mtd, loff_t from, onenand_update_bufferram(mtd, from, !ret); if (ret == -EBADMSG) ret = 0; + if (ret) + break; } this->read_bufferram(mtd, ONENAND_DATARAM, buf, column, thislen); -- GitLab From e6da85685b2dec1e69e58366c22d1f883d6da575 Mon Sep 17 00:00:00 2001 From: Roman Tereshonkov Date: Tue, 8 Feb 2011 12:02:42 +0200 Subject: [PATCH 0580/2822] mtd: onenand_base: onenand_verify bugfix for writepage non-aligned address In onenand_verify function the address can be writepage non-aligned. When a page is read for comparing the right offset should be used for "this->verify_buf" to get the right matching with compared "buf" buffer. Signed-off-by: Roman Tereshonkov Signed-off-by: Adrian Hunter Acked-by: Kyungmin Park Signed-off-by: Artem Bityutskiy Signed-off-by: David Woodhouse --- drivers/mtd/onenand/onenand_base.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/mtd/onenand/onenand_base.c b/drivers/mtd/onenand/onenand_base.c index 38e6d76bcc0ee..4205b9423b89c 100644 --- a/drivers/mtd/onenand/onenand_base.c +++ b/drivers/mtd/onenand/onenand_base.c @@ -1648,11 +1648,10 @@ static int onenand_verify(struct mtd_info *mtd, const u_char *buf, loff_t addr, int ret = 0; int thislen, column; + column = addr & (this->writesize - 1); + while (len != 0) { - thislen = min_t(int, this->writesize, len); - column = addr & (this->writesize - 1); - if (column + thislen > this->writesize) - thislen = this->writesize - column; + thislen = min_t(int, this->writesize - column, len); this->command(mtd, ONENAND_CMD_READ, addr, this->writesize); @@ -1666,12 +1665,13 @@ static int onenand_verify(struct mtd_info *mtd, const u_char *buf, loff_t addr, this->read_bufferram(mtd, ONENAND_DATARAM, this->verify_buf, 0, mtd->writesize); - if (memcmp(buf, this->verify_buf, thislen)) + if (memcmp(buf, this->verify_buf + column, thislen)) return -EBADMSG; len -= thislen; buf += thislen; addr += thislen; + column = 0; } return 0; -- GitLab From fc7fe7691c6bbd5f8f51a87e759770975c648410 Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Tue, 8 Feb 2011 12:02:39 +0200 Subject: [PATCH 0581/2822] mtd: tests: add count parameter to mtd_speedtest By default mtd_speedtest uses all the eraseblocks of the MTD partition being tested. For large partitions a smaller number is sufficient and makes running the test quicker. For that reason, add a parameter 'count' to specify the maximum number of eraseblocks to use for testing. Signed-off-by: Adrian Hunter Signed-off-by: Artem Bityutskiy Signed-off-by: David Woodhouse --- drivers/mtd/tests/mtd_speedtest.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/drivers/mtd/tests/mtd_speedtest.c b/drivers/mtd/tests/mtd_speedtest.c index 161feeb7b8b9d..9bd986ef3b53e 100644 --- a/drivers/mtd/tests/mtd_speedtest.c +++ b/drivers/mtd/tests/mtd_speedtest.c @@ -16,7 +16,7 @@ * * Test read and write speed of a MTD device. * - * Author: Adrian Hunter + * Author: Adrian Hunter */ #include @@ -33,6 +33,11 @@ static int dev; module_param(dev, int, S_IRUGO); MODULE_PARM_DESC(dev, "MTD device number to use"); +static int count; +module_param(count, int, S_IRUGO); +MODULE_PARM_DESC(count, "Maximum number of eraseblocks to use " + "(0 means use all)"); + static struct mtd_info *mtd; static unsigned char *iobuf; static unsigned char *bbt; @@ -326,7 +331,10 @@ static int __init mtd_speedtest_init(void) printk(KERN_INFO "\n"); printk(KERN_INFO "=================================================\n"); - printk(PRINT_PREF "MTD device: %d\n", dev); + if (count) + printk(PRINT_PREF "MTD device: %d count: %d\n", dev, count); + else + printk(PRINT_PREF "MTD device: %d\n", dev); mtd = get_mtd_device(NULL, dev); if (IS_ERR(mtd)) { @@ -353,6 +361,9 @@ static int __init mtd_speedtest_init(void) (unsigned long long)mtd->size, mtd->erasesize, pgsize, ebcnt, pgcnt, mtd->oobsize); + if (count > 0 && count < ebcnt) + ebcnt = count; + err = -ENOMEM; iobuf = kmalloc(mtd->erasesize, GFP_KERNEL); if (!iobuf) { -- GitLab From 4085bcc682e1276ab4ac2da9866daadf944d7167 Mon Sep 17 00:00:00 2001 From: Roman Tereshonkov Date: Tue, 8 Feb 2011 12:02:40 +0200 Subject: [PATCH 0582/2822] mtd: tests: add multiblock erase test to the mtd_speedtest New multiblock erase speed test is added to mtd_speedtest. It consists of 2-, 4-, 8-, 16-, 32- and 64-blocks at once multiblock erase tests. Signed-off-by: Roman Tereshonkov Signed-off-by: Artem Bityutskiy Signed-off-by: David Woodhouse --- drivers/mtd/tests/mtd_speedtest.c | 59 +++++++++++++++++++++++++++++-- 1 file changed, 57 insertions(+), 2 deletions(-) diff --git a/drivers/mtd/tests/mtd_speedtest.c b/drivers/mtd/tests/mtd_speedtest.c index 9bd986ef3b53e..3ce6fce75e075 100644 --- a/drivers/mtd/tests/mtd_speedtest.c +++ b/drivers/mtd/tests/mtd_speedtest.c @@ -94,6 +94,33 @@ static int erase_eraseblock(int ebnum) return 0; } +static int multiblock_erase(int ebnum, int blocks) +{ + int err; + struct erase_info ei; + loff_t addr = ebnum * mtd->erasesize; + + memset(&ei, 0, sizeof(struct erase_info)); + ei.mtd = mtd; + ei.addr = addr; + ei.len = mtd->erasesize * blocks; + + err = mtd->erase(mtd, &ei); + if (err) { + printk(PRINT_PREF "error %d while erasing EB %d, blocks %d\n", + err, ebnum, blocks); + return err; + } + + if (ei.state == MTD_ERASE_FAILED) { + printk(PRINT_PREF "some erase error occurred at EB %d," + "blocks %d\n", ebnum, blocks); + return -EIO; + } + + return 0; +} + static int erase_whole_device(void) { int err; @@ -292,7 +319,10 @@ static long calc_speed(void) ms = (finish.tv_sec - start.tv_sec) * 1000 + (finish.tv_usec - start.tv_usec) / 1000; k = goodebcnt * mtd->erasesize / 1024; - speed = (k * 1000) / ms; + if (ms) + speed = (k * 1000) / ms; + else + speed = 0; return speed; } @@ -325,7 +355,7 @@ out: static int __init mtd_speedtest_init(void) { - int err, i; + int err, i, blocks, j, k; long speed; uint64_t tmp; @@ -495,6 +525,31 @@ static int __init mtd_speedtest_init(void) speed = calc_speed(); printk(PRINT_PREF "erase speed is %ld KiB/s\n", speed); + /* Multi-block erase all eraseblocks */ + for (k = 1; k < 7; k++) { + blocks = 1 << k; + printk(PRINT_PREF "Testing %dx multi-block erase speed\n", + blocks); + start_timing(); + for (i = 0; i < ebcnt; ) { + for (j = 0; j < blocks && (i + j) < ebcnt; j++) + if (bbt[i + j]) + break; + if (j < 1) { + i++; + continue; + } + err = multiblock_erase(i, j); + if (err) + goto out; + cond_resched(); + i += j; + } + stop_timing(); + speed = calc_speed(); + printk(PRINT_PREF "%dx multi-block erase speed is %ld KiB/s\n", + blocks, speed); + } printk(PRINT_PREF "finished\n"); out: kfree(iobuf); -- GitLab From d8f90b2c9d521500bcd4a1ecdcdb283bfdd2186f Mon Sep 17 00:00:00 2001 From: Yoshihiro Shimoda Date: Wed, 9 Feb 2011 17:00:33 +0900 Subject: [PATCH 0583/2822] mtd: m25p80: add support for M25PX64 Signed-off-by: Yoshihiro Shimoda Signed-off-by: David Woodhouse --- drivers/mtd/devices/m25p80.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c index 8d83a8b316705..3fb981d4bb510 100644 --- a/drivers/mtd/devices/m25p80.c +++ b/drivers/mtd/devices/m25p80.c @@ -729,6 +729,8 @@ static const struct spi_device_id m25p_ids[] = { { "m25pe80", INFO(0x208014, 0, 64 * 1024, 16, 0) }, { "m25pe16", INFO(0x208015, 0, 64 * 1024, 32, SECT_4K) }, + { "m25px64", INFO(0x207117, 0, 64 * 1024, 128, 0) }, + /* Winbond -- w25x "blocks" are 64K, "sectors" are 4KiB */ { "w25x10", INFO(0xef3011, 0, 64 * 1024, 2, SECT_4K) }, { "w25x20", INFO(0xef3012, 0, 64 * 1024, 4, SECT_4K) }, -- GitLab From 13ce77f46c79a3839e4c2ff9722c9416c165f498 Mon Sep 17 00:00:00 2001 From: Anatolij Gustschin Date: Thu, 10 Feb 2011 16:01:46 +0100 Subject: [PATCH 0584/2822] mtd: cfi: fix writebufsize initialization When initializing mtd->writebufsize, we must take into account possible flash chip interleaving. Wrong writebufsize initialization caused UBIFS recovery issues resulting in unmountable UBIFS file system on NOR flash partitions. Signed-off-by: Anatolij Gustschin Acked-by: Guillaume LECERF Signed-off-by: Artem Bityutskiy Signed-off-by: David Woodhouse --- drivers/mtd/chips/cfi_cmdset_0001.c | 2 +- drivers/mtd/chips/cfi_cmdset_0002.c | 2 +- drivers/mtd/chips/cfi_cmdset_0020.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/mtd/chips/cfi_cmdset_0001.c b/drivers/mtd/chips/cfi_cmdset_0001.c index 4aaa88f8ab5f0..092aef11120cb 100644 --- a/drivers/mtd/chips/cfi_cmdset_0001.c +++ b/drivers/mtd/chips/cfi_cmdset_0001.c @@ -455,7 +455,7 @@ struct mtd_info *cfi_cmdset_0001(struct map_info *map, int primary) mtd->flags = MTD_CAP_NORFLASH; mtd->name = map->name; mtd->writesize = 1; - mtd->writebufsize = 1 << cfi->cfiq->MaxBufWriteSize; + mtd->writebufsize = cfi_interleave(cfi) << cfi->cfiq->MaxBufWriteSize; mtd->reboot_notifier.notifier_call = cfi_intelext_reboot; diff --git a/drivers/mtd/chips/cfi_cmdset_0002.c b/drivers/mtd/chips/cfi_cmdset_0002.c index f072fcfde04ee..7e9c4e9c274a4 100644 --- a/drivers/mtd/chips/cfi_cmdset_0002.c +++ b/drivers/mtd/chips/cfi_cmdset_0002.c @@ -440,7 +440,7 @@ struct mtd_info *cfi_cmdset_0002(struct map_info *map, int primary) mtd->flags = MTD_CAP_NORFLASH; mtd->name = map->name; mtd->writesize = 1; - mtd->writebufsize = 1 << cfi->cfiq->MaxBufWriteSize; + mtd->writebufsize = cfi_interleave(cfi) << cfi->cfiq->MaxBufWriteSize; DEBUG(MTD_DEBUG_LEVEL3, "MTD %s(): write buffer size %d\n", __func__, mtd->writebufsize); diff --git a/drivers/mtd/chips/cfi_cmdset_0020.c b/drivers/mtd/chips/cfi_cmdset_0020.c index c04b7658abe90..ed56ad3884fbc 100644 --- a/drivers/mtd/chips/cfi_cmdset_0020.c +++ b/drivers/mtd/chips/cfi_cmdset_0020.c @@ -238,7 +238,7 @@ static struct mtd_info *cfi_staa_setup(struct map_info *map) mtd->resume = cfi_staa_resume; mtd->flags = MTD_CAP_NORFLASH & ~MTD_BIT_WRITEABLE; mtd->writesize = 8; /* FIXME: Should be 0 for STMicro flashes w/out ECC */ - mtd->writebufsize = 1 << cfi->cfiq->MaxBufWriteSize; + mtd->writebufsize = cfi_interleave(cfi) << cfi->cfiq->MaxBufWriteSize; map->fldrv = &cfi_staa_chipdrv; __module_get(THIS_MODULE); mtd->name = map->name; -- GitLab From c7519dbf6f4b4408229d279d799c938ffdd06f21 Mon Sep 17 00:00:00 2001 From: Jarkko Lavinen Date: Mon, 14 Feb 2011 16:16:09 +0200 Subject: [PATCH 0585/2822] mtd_blkdevs: Add background processing support Add a new background method into mtd_blktrans_ops, add background support into mtd_blktrans_thread(), and add mtd_blktrans_cease_background(). If the mtd blktrans dev has the background support, the thread will call background function when the request queue becomes empty. The background operation may run as long as needs to until mtd_blktrans_cease_background() tells to stop. Signed-off-by: Jarkko Lavinen Tested-by: Artem Bityutskiy Signed-off-by: David Woodhouse --- drivers/mtd/mtd_blkdevs.c | 26 ++++++++++++++++++++++++++ include/linux/mtd/blktrans.h | 2 ++ 2 files changed, 28 insertions(+) diff --git a/drivers/mtd/mtd_blkdevs.c b/drivers/mtd/mtd_blkdevs.c index 344ac1037ee71..e0b5f64421714 100644 --- a/drivers/mtd/mtd_blkdevs.c +++ b/drivers/mtd/mtd_blkdevs.c @@ -119,11 +119,22 @@ static int do_blktrans_request(struct mtd_blktrans_ops *tr, } } +int mtd_blktrans_cease_background(struct mtd_blktrans_dev *dev) +{ + if (kthread_should_stop()) + return 1; + + return !elv_queue_empty(dev->rq); +} +EXPORT_SYMBOL_GPL(mtd_blktrans_cease_background); + static int mtd_blktrans_thread(void *arg) { struct mtd_blktrans_dev *dev = arg; + struct mtd_blktrans_ops *tr = dev->tr; struct request_queue *rq = dev->rq; struct request *req = NULL; + int background_done = 0; spin_lock_irq(rq->queue_lock); @@ -131,6 +142,19 @@ static int mtd_blktrans_thread(void *arg) int res; if (!req && !(req = blk_fetch_request(rq))) { + if (tr->background && !background_done) { + spin_unlock_irq(rq->queue_lock); + mutex_lock(&dev->lock); + tr->background(dev); + mutex_unlock(&dev->lock); + spin_lock_irq(rq->queue_lock); + /* + * Do background processing just once per idle + * period. + */ + background_done = 1; + continue; + } set_current_state(TASK_INTERRUPTIBLE); if (kthread_should_stop()) @@ -152,6 +176,8 @@ static int mtd_blktrans_thread(void *arg) if (!__blk_end_request_cur(req, res)) req = NULL; + + background_done = 0; } if (req) diff --git a/include/linux/mtd/blktrans.h b/include/linux/mtd/blktrans.h index 26529ebd59ccf..66bec4bf2b0a5 100644 --- a/include/linux/mtd/blktrans.h +++ b/include/linux/mtd/blktrans.h @@ -62,6 +62,7 @@ struct mtd_blktrans_ops { unsigned long block, char *buffer); int (*discard)(struct mtd_blktrans_dev *dev, unsigned long block, unsigned nr_blocks); + void (*background)(struct mtd_blktrans_dev *dev); /* Block layer ioctls */ int (*getgeo)(struct mtd_blktrans_dev *dev, struct hd_geometry *geo); @@ -85,6 +86,7 @@ extern int register_mtd_blktrans(struct mtd_blktrans_ops *tr); extern int deregister_mtd_blktrans(struct mtd_blktrans_ops *tr); extern int add_mtd_blktrans_dev(struct mtd_blktrans_dev *dev); extern int del_mtd_blktrans_dev(struct mtd_blktrans_dev *dev); +extern int mtd_blktrans_cease_background(struct mtd_blktrans_dev *dev); #endif /* __MTD_TRANS_H__ */ -- GitLab From 115ee88c15b55859a8b59c5dccb3882bbd47e542 Mon Sep 17 00:00:00 2001 From: Jarkko Lavinen Date: Mon, 14 Feb 2011 16:16:10 +0200 Subject: [PATCH 0586/2822] mtd_blkdevs: Set the maximum discards size Set max_discard_sectors to UINT_MAX. Signed-off-by: Jarkko Lavinen Tested-by: Artem Bityutskiy Signed-off-by: David Woodhouse --- drivers/mtd/mtd_blkdevs.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/mtd/mtd_blkdevs.c b/drivers/mtd/mtd_blkdevs.c index e0b5f64421714..6505113040307 100644 --- a/drivers/mtd/mtd_blkdevs.c +++ b/drivers/mtd/mtd_blkdevs.c @@ -405,9 +405,10 @@ int add_mtd_blktrans_dev(struct mtd_blktrans_dev *new) new->rq->queuedata = new; blk_queue_logical_block_size(new->rq, tr->blksize); - if (tr->discard) - queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, - new->rq); + if (tr->discard) { + queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, new->rq); + new->rq->limits.max_discard_sectors = UINT_MAX; + } gd->queue = new->rq; -- GitLab From a321590246202f2598aca2f4ef63b992e8fc97ef Mon Sep 17 00:00:00 2001 From: Jarkko Lavinen Date: Mon, 14 Feb 2011 16:16:11 +0200 Subject: [PATCH 0587/2822] mtd: Add mtdswap block driver Add a driver for allowing an mtd device to be used as a block device for swapping. The block device is volatile, and the mapping of swapped pages is not stored on flash. Signed-off-by: Jarkko Lavinen Tested-by: Artem Bityutskiy Signed-off-by: David Woodhouse --- drivers/mtd/Kconfig | 18 + drivers/mtd/Makefile | 1 + drivers/mtd/mtdswap.c | 1593 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 1612 insertions(+) create mode 100644 drivers/mtd/mtdswap.c diff --git a/drivers/mtd/Kconfig b/drivers/mtd/Kconfig index 23088b3372d08..5fe01d5566572 100644 --- a/drivers/mtd/Kconfig +++ b/drivers/mtd/Kconfig @@ -325,6 +325,24 @@ config MTD_OOPS To use, add console=ttyMTDx to the kernel command line, where x is the MTD device number to use. +config MTD_SWAP + tristate "Swap on MTD device support" + depends on MTD && SWAP + select MTD_BLKDEVS + help + Provides volatile block device driver on top of mtd partition + suitable for swapping. The mapping of written blocks is not saved. + The driver provides wear leveling by storing erase counter into the + OOB. + +config MTD_SWAP_STRICT + bool "Strict erase error handling" + depends on MTD_SWAP + help + Enables strict tolerance on failed erasures, marking erase blocks bad + right after the first failed operation. With non-strict mode the + erase operation is retried. + source "drivers/mtd/chips/Kconfig" source "drivers/mtd/maps/Kconfig" diff --git a/drivers/mtd/Makefile b/drivers/mtd/Makefile index eff3dd53cc051..d578095fb2559 100644 --- a/drivers/mtd/Makefile +++ b/drivers/mtd/Makefile @@ -25,6 +25,7 @@ obj-$(CONFIG_RFD_FTL) += rfd_ftl.o obj-$(CONFIG_SSFDC) += ssfdc.o obj-$(CONFIG_SM_FTL) += sm_ftl.o obj-$(CONFIG_MTD_OOPS) += mtdoops.o +obj-$(CONFIG_MTD_SWAP) += mtdswap.o nftl-objs := nftlcore.o nftlmount.o inftl-objs := inftlcore.o inftlmount.o diff --git a/drivers/mtd/mtdswap.c b/drivers/mtd/mtdswap.c new file mode 100644 index 0000000000000..57e6cc30bc429 --- /dev/null +++ b/drivers/mtd/mtdswap.c @@ -0,0 +1,1593 @@ +/* + * Swap block device support for MTDs + * Turns an MTD device into a swap device with block wear leveling + * + * Copyright © 2007,2011 Nokia Corporation. All rights reserved. + * + * Authors: Jarkko Lavinen + * + * Based on Richard Purdie's earlier implementation in 2007. Background + * support and lock-less operation written by Adrian Hunter. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MTDSWAP_PREFIX "mtdswap" + +/* + * The number of free eraseblocks when GC should stop + */ +#define CLEAN_BLOCK_THRESHOLD 20 + +/* + * Number of free eraseblocks below which GC can also collect low frag + * blocks. + */ +#define LOW_FRAG_GC_TRESHOLD 5 + +/* + * Wear level cost amortization. We want to do wear leveling on the background + * without disturbing gc too much. This is made by defining max GC frequency. + * Frequency value 6 means 1/6 of the GC passes will pick an erase block based + * on the biggest wear difference rather than the biggest dirtiness. + * + * The lower freq2 should be chosen so that it makes sure the maximum erase + * difference will decrease even if a malicious application is deliberately + * trying to make erase differences large. + */ +#define MAX_ERASE_DIFF 4000 +#define COLLECT_NONDIRTY_BASE MAX_ERASE_DIFF +#define COLLECT_NONDIRTY_FREQ1 6 +#define COLLECT_NONDIRTY_FREQ2 4 + +#define PAGE_UNDEF UINT_MAX +#define BLOCK_UNDEF UINT_MAX +#define BLOCK_ERROR (UINT_MAX - 1) +#define BLOCK_MAX (UINT_MAX - 2) + +#define EBLOCK_BAD (1 << 0) +#define EBLOCK_NOMAGIC (1 << 1) +#define EBLOCK_BITFLIP (1 << 2) +#define EBLOCK_FAILED (1 << 3) +#define EBLOCK_READERR (1 << 4) +#define EBLOCK_IDX_SHIFT 5 + +struct swap_eb { + struct rb_node rb; + struct rb_root *root; + + unsigned int flags; + unsigned int active_count; + unsigned int erase_count; + unsigned int pad; /* speeds up pointer decremtnt */ +}; + +#define MTDSWAP_ECNT_MIN(rbroot) (rb_entry(rb_first(rbroot), struct swap_eb, \ + rb)->erase_count) +#define MTDSWAP_ECNT_MAX(rbroot) (rb_entry(rb_last(rbroot), struct swap_eb, \ + rb)->erase_count) + +struct mtdswap_tree { + struct rb_root root; + unsigned int count; +}; + +enum { + MTDSWAP_CLEAN, + MTDSWAP_USED, + MTDSWAP_LOWFRAG, + MTDSWAP_HIFRAG, + MTDSWAP_DIRTY, + MTDSWAP_BITFLIP, + MTDSWAP_FAILING, + MTDSWAP_TREE_CNT, +}; + +struct mtdswap_dev { + struct mtd_blktrans_dev *mbd_dev; + struct mtd_info *mtd; + struct device *dev; + + unsigned int *page_data; + unsigned int *revmap; + + unsigned int eblks; + unsigned int spare_eblks; + unsigned int pages_per_eblk; + unsigned int max_erase_count; + struct swap_eb *eb_data; + + struct mtdswap_tree trees[MTDSWAP_TREE_CNT]; + + unsigned long long sect_read_count; + unsigned long long sect_write_count; + unsigned long long mtd_write_count; + unsigned long long mtd_read_count; + unsigned long long discard_count; + unsigned long long discard_page_count; + + unsigned int curr_write_pos; + struct swap_eb *curr_write; + + char *page_buf; + char *oob_buf; + + struct dentry *debugfs_root; +}; + +struct mtdswap_oobdata { + __le16 magic; + __le32 count; +} __attribute__((packed)); + +#define MTDSWAP_MAGIC_CLEAN 0x2095 +#define MTDSWAP_MAGIC_DIRTY (MTDSWAP_MAGIC_CLEAN + 1) +#define MTDSWAP_TYPE_CLEAN 0 +#define MTDSWAP_TYPE_DIRTY 1 +#define MTDSWAP_OOBSIZE sizeof(struct mtdswap_oobdata) + +#define MTDSWAP_ERASE_RETRIES 3 /* Before marking erase block bad */ +#define MTDSWAP_IO_RETRIES 3 + +#ifdef CONFIG_MTD_SWAP_STRICT +#define MTDSWAP_STRICT 1 +#else +#define MTDSWAP_STRICT 0 +#endif + +enum { + MTDSWAP_SCANNED_CLEAN, + MTDSWAP_SCANNED_DIRTY, + MTDSWAP_SCANNED_BITFLIP, + MTDSWAP_SCANNED_BAD, +}; + +/* + * In the worst case mtdswap_writesect() has allocated the last clean + * page from the current block and is then pre-empted by the GC + * thread. The thread can consume a full erase block when moving a + * block. + */ +#define MIN_SPARE_EBLOCKS 2 +#define MIN_ERASE_BLOCKS (MIN_SPARE_EBLOCKS + 1) + +#define TREE_ROOT(d, name) (&d->trees[MTDSWAP_ ## name].root) +#define TREE_EMPTY(d, name) (TREE_ROOT(d, name)->rb_node == NULL) +#define TREE_NONEMPTY(d, name) (!TREE_EMPTY(d, name)) +#define TREE_COUNT(d, name) (d->trees[MTDSWAP_ ## name].count) + +#define MTDSWAP_MBD_TO_MTDSWAP(dev) ((struct mtdswap_dev *)dev->priv) + +static char partitions[128] = ""; +module_param_string(partitions, partitions, sizeof(partitions), 0444); +MODULE_PARM_DESC(partitions, "MTD partition numbers to use as swap " + "partitions=\"1,3,5\""); + +static unsigned int spare_eblocks = 10; +module_param(spare_eblocks, uint, 0444); +MODULE_PARM_DESC(spare_eblocks, "Percentage of spare erase blocks for " + "garbage collection (default 10%)"); + +static bool header; /* false */ +module_param(header, bool, 0444); +MODULE_PARM_DESC(header, + "Include builtin swap header (default 0, without header)"); + +static int mtdswap_gc(struct mtdswap_dev *d, unsigned int background); + +static loff_t mtdswap_eb_offset(struct mtdswap_dev *d, struct swap_eb *eb) +{ + return (loff_t)(eb - d->eb_data) * d->mtd->erasesize; +} + +static void mtdswap_eb_detach(struct mtdswap_dev *d, struct swap_eb *eb) +{ + unsigned int oldidx; + struct mtdswap_tree *tp; + + if (eb->root) { + tp = container_of(eb->root, struct mtdswap_tree, root); + oldidx = tp - &d->trees[0]; + + d->trees[oldidx].count--; + rb_erase(&eb->rb, eb->root); + } +} + +static void __mtdswap_rb_add(struct rb_root *root, struct swap_eb *eb) +{ + struct rb_node **p, *parent = NULL; + struct swap_eb *cur; + + p = &root->rb_node; + while (*p) { + parent = *p; + cur = rb_entry(parent, struct swap_eb, rb); + if (eb->erase_count > cur->erase_count) + p = &(*p)->rb_right; + else + p = &(*p)->rb_left; + } + + rb_link_node(&eb->rb, parent, p); + rb_insert_color(&eb->rb, root); +} + +static void mtdswap_rb_add(struct mtdswap_dev *d, struct swap_eb *eb, int idx) +{ + struct rb_root *root; + + if (eb->root == &d->trees[idx].root) + return; + + mtdswap_eb_detach(d, eb); + root = &d->trees[idx].root; + __mtdswap_rb_add(root, eb); + eb->root = root; + d->trees[idx].count++; +} + +static struct rb_node *mtdswap_rb_index(struct rb_root *root, unsigned int idx) +{ + struct rb_node *p; + unsigned int i; + + p = rb_first(root); + i = 0; + while (i < idx && p) { + p = rb_next(p); + i++; + } + + return p; +} + +static int mtdswap_handle_badblock(struct mtdswap_dev *d, struct swap_eb *eb) +{ + int ret; + loff_t offset; + + d->spare_eblks--; + eb->flags |= EBLOCK_BAD; + mtdswap_eb_detach(d, eb); + eb->root = NULL; + + /* badblocks not supported */ + if (!d->mtd->block_markbad) + return 1; + + offset = mtdswap_eb_offset(d, eb); + dev_warn(d->dev, "Marking bad block at %08llx\n", offset); + ret = d->mtd->block_markbad(d->mtd, offset); + + if (ret) { + dev_warn(d->dev, "Mark block bad failed for block at %08llx " + "error %d\n", offset, ret); + return ret; + } + + return 1; + +} + +static int mtdswap_handle_write_error(struct mtdswap_dev *d, struct swap_eb *eb) +{ + unsigned int marked = eb->flags & EBLOCK_FAILED; + struct swap_eb *curr_write = d->curr_write; + + eb->flags |= EBLOCK_FAILED; + if (curr_write == eb) { + d->curr_write = NULL; + + if (!marked && d->curr_write_pos != 0) { + mtdswap_rb_add(d, eb, MTDSWAP_FAILING); + return 0; + } + } + + return mtdswap_handle_badblock(d, eb); +} + +static int mtdswap_read_oob(struct mtdswap_dev *d, loff_t from, + struct mtd_oob_ops *ops) +{ + int ret = d->mtd->read_oob(d->mtd, from, ops); + + if (ret == -EUCLEAN) + return ret; + + if (ret) { + dev_warn(d->dev, "Read OOB failed %d for block at %08llx\n", + ret, from); + return ret; + } + + if (ops->oobretlen < ops->ooblen) { + dev_warn(d->dev, "Read OOB return short read (%zd bytes not " + "%d) for block at %08llx\n", + ops->oobretlen, ops->ooblen, from); + return -EIO; + } + + return 0; +} + +static int mtdswap_read_markers(struct mtdswap_dev *d, struct swap_eb *eb) +{ + struct mtdswap_oobdata *data, *data2; + int ret; + loff_t offset; + struct mtd_oob_ops ops; + + offset = mtdswap_eb_offset(d, eb); + + /* Check first if the block is bad. */ + if (d->mtd->block_isbad && d->mtd->block_isbad(d->mtd, offset)) + return MTDSWAP_SCANNED_BAD; + + ops.ooblen = 2 * d->mtd->ecclayout->oobavail; + ops.oobbuf = d->oob_buf; + ops.ooboffs = 0; + ops.datbuf = NULL; + ops.mode = MTD_OOB_AUTO; + + ret = mtdswap_read_oob(d, offset, &ops); + + if (ret && ret != -EUCLEAN) + return ret; + + data = (struct mtdswap_oobdata *)d->oob_buf; + data2 = (struct mtdswap_oobdata *) + (d->oob_buf + d->mtd->ecclayout->oobavail); + + if (le16_to_cpu(data->magic) == MTDSWAP_MAGIC_CLEAN) { + eb->erase_count = le32_to_cpu(data->count); + if (ret == -EUCLEAN) + ret = MTDSWAP_SCANNED_BITFLIP; + else { + if (le16_to_cpu(data2->magic) == MTDSWAP_MAGIC_DIRTY) + ret = MTDSWAP_SCANNED_DIRTY; + else + ret = MTDSWAP_SCANNED_CLEAN; + } + } else { + eb->flags |= EBLOCK_NOMAGIC; + ret = MTDSWAP_SCANNED_DIRTY; + } + + return ret; +} + +static int mtdswap_write_marker(struct mtdswap_dev *d, struct swap_eb *eb, + u16 marker) +{ + struct mtdswap_oobdata n; + int ret; + loff_t offset; + struct mtd_oob_ops ops; + + ops.ooboffs = 0; + ops.oobbuf = (uint8_t *)&n; + ops.mode = MTD_OOB_AUTO; + ops.datbuf = NULL; + + if (marker == MTDSWAP_TYPE_CLEAN) { + n.magic = cpu_to_le16(MTDSWAP_MAGIC_CLEAN); + n.count = cpu_to_le32(eb->erase_count); + ops.ooblen = MTDSWAP_OOBSIZE; + offset = mtdswap_eb_offset(d, eb); + } else { + n.magic = cpu_to_le16(MTDSWAP_MAGIC_DIRTY); + ops.ooblen = sizeof(n.magic); + offset = mtdswap_eb_offset(d, eb) + d->mtd->writesize; + } + + ret = d->mtd->write_oob(d->mtd, offset , &ops); + + if (ret) { + dev_warn(d->dev, "Write OOB failed for block at %08llx " + "error %d\n", offset, ret); + if (ret == -EIO || ret == -EBADMSG) + mtdswap_handle_write_error(d, eb); + return ret; + } + + if (ops.oobretlen != ops.ooblen) { + dev_warn(d->dev, "Short OOB write for block at %08llx: " + "%zd not %d\n", + offset, ops.oobretlen, ops.ooblen); + return ret; + } + + return 0; +} + +/* + * Are there any erase blocks without MAGIC_CLEAN header, presumably + * because power was cut off after erase but before header write? We + * need to guestimate the erase count. + */ +static void mtdswap_check_counts(struct mtdswap_dev *d) +{ + struct rb_root hist_root = RB_ROOT; + struct rb_node *medrb; + struct swap_eb *eb; + unsigned int i, cnt, median; + + cnt = 0; + for (i = 0; i < d->eblks; i++) { + eb = d->eb_data + i; + + if (eb->flags & (EBLOCK_NOMAGIC | EBLOCK_BAD | EBLOCK_READERR)) + continue; + + __mtdswap_rb_add(&hist_root, eb); + cnt++; + } + + if (cnt == 0) + return; + + medrb = mtdswap_rb_index(&hist_root, cnt / 2); + median = rb_entry(medrb, struct swap_eb, rb)->erase_count; + + d->max_erase_count = MTDSWAP_ECNT_MAX(&hist_root); + + for (i = 0; i < d->eblks; i++) { + eb = d->eb_data + i; + + if (eb->flags & (EBLOCK_NOMAGIC | EBLOCK_READERR)) + eb->erase_count = median; + + if (eb->flags & (EBLOCK_NOMAGIC | EBLOCK_BAD | EBLOCK_READERR)) + continue; + + rb_erase(&eb->rb, &hist_root); + } +} + +static void mtdswap_scan_eblks(struct mtdswap_dev *d) +{ + int status; + unsigned int i, idx; + struct swap_eb *eb; + + for (i = 0; i < d->eblks; i++) { + eb = d->eb_data + i; + + status = mtdswap_read_markers(d, eb); + if (status < 0) + eb->flags |= EBLOCK_READERR; + else if (status == MTDSWAP_SCANNED_BAD) { + eb->flags |= EBLOCK_BAD; + continue; + } + + switch (status) { + case MTDSWAP_SCANNED_CLEAN: + idx = MTDSWAP_CLEAN; + break; + case MTDSWAP_SCANNED_DIRTY: + case MTDSWAP_SCANNED_BITFLIP: + idx = MTDSWAP_DIRTY; + break; + default: + idx = MTDSWAP_FAILING; + } + + eb->flags |= (idx << EBLOCK_IDX_SHIFT); + } + + mtdswap_check_counts(d); + + for (i = 0; i < d->eblks; i++) { + eb = d->eb_data + i; + + if (eb->flags & EBLOCK_BAD) + continue; + + idx = eb->flags >> EBLOCK_IDX_SHIFT; + mtdswap_rb_add(d, eb, idx); + } +} + +/* + * Place eblk into a tree corresponding to its number of active blocks + * it contains. + */ +static void mtdswap_store_eb(struct mtdswap_dev *d, struct swap_eb *eb) +{ + unsigned int weight = eb->active_count; + unsigned int maxweight = d->pages_per_eblk; + + if (eb == d->curr_write) + return; + + if (eb->flags & EBLOCK_BITFLIP) + mtdswap_rb_add(d, eb, MTDSWAP_BITFLIP); + else if (eb->flags & (EBLOCK_READERR | EBLOCK_FAILED)) + mtdswap_rb_add(d, eb, MTDSWAP_FAILING); + if (weight == maxweight) + mtdswap_rb_add(d, eb, MTDSWAP_USED); + else if (weight == 0) + mtdswap_rb_add(d, eb, MTDSWAP_DIRTY); + else if (weight > (maxweight/2)) + mtdswap_rb_add(d, eb, MTDSWAP_LOWFRAG); + else + mtdswap_rb_add(d, eb, MTDSWAP_HIFRAG); +} + + +static void mtdswap_erase_callback(struct erase_info *done) +{ + wait_queue_head_t *wait_q = (wait_queue_head_t *)done->priv; + wake_up(wait_q); +} + +static int mtdswap_erase_block(struct mtdswap_dev *d, struct swap_eb *eb) +{ + struct mtd_info *mtd = d->mtd; + struct erase_info erase; + wait_queue_head_t wq; + unsigned int retries = 0; + int ret; + + eb->erase_count++; + if (eb->erase_count > d->max_erase_count) + d->max_erase_count = eb->erase_count; + +retry: + init_waitqueue_head(&wq); + memset(&erase, 0, sizeof(struct erase_info)); + + erase.mtd = mtd; + erase.callback = mtdswap_erase_callback; + erase.addr = mtdswap_eb_offset(d, eb); + erase.len = mtd->erasesize; + erase.priv = (u_long)&wq; + + ret = mtd->erase(mtd, &erase); + if (ret) { + if (retries++ < MTDSWAP_ERASE_RETRIES && !MTDSWAP_STRICT) { + dev_warn(d->dev, + "erase of erase block %#llx on %s failed", + erase.addr, mtd->name); + yield(); + goto retry; + } + + dev_err(d->dev, "Cannot erase erase block %#llx on %s\n", + erase.addr, mtd->name); + + mtdswap_handle_badblock(d, eb); + return -EIO; + } + + ret = wait_event_interruptible(wq, erase.state == MTD_ERASE_DONE || + erase.state == MTD_ERASE_FAILED); + if (ret) { + dev_err(d->dev, "Interrupted erase block %#llx erassure on %s", + erase.addr, mtd->name); + return -EINTR; + } + + if (erase.state == MTD_ERASE_FAILED) { + if (retries++ < MTDSWAP_ERASE_RETRIES) { + dev_warn(d->dev, + "erase of erase block %#llx on %s failed", + erase.addr, mtd->name); + yield(); + goto retry; + } + + mtdswap_handle_badblock(d, eb); + return -EIO; + } + + return 0; +} + +static int mtdswap_map_free_block(struct mtdswap_dev *d, unsigned int page, + unsigned int *block) +{ + int ret; + struct swap_eb *old_eb = d->curr_write; + struct rb_root *clean_root; + struct swap_eb *eb; + + if (old_eb == NULL || d->curr_write_pos >= d->pages_per_eblk) { + do { + if (TREE_EMPTY(d, CLEAN)) + return -ENOSPC; + + clean_root = TREE_ROOT(d, CLEAN); + eb = rb_entry(rb_first(clean_root), struct swap_eb, rb); + rb_erase(&eb->rb, clean_root); + eb->root = NULL; + TREE_COUNT(d, CLEAN)--; + + ret = mtdswap_write_marker(d, eb, MTDSWAP_TYPE_DIRTY); + } while (ret == -EIO || ret == -EBADMSG); + + if (ret) + return ret; + + d->curr_write_pos = 0; + d->curr_write = eb; + if (old_eb) + mtdswap_store_eb(d, old_eb); + } + + *block = (d->curr_write - d->eb_data) * d->pages_per_eblk + + d->curr_write_pos; + + d->curr_write->active_count++; + d->revmap[*block] = page; + d->curr_write_pos++; + + return 0; +} + +static unsigned int mtdswap_free_page_cnt(struct mtdswap_dev *d) +{ + return TREE_COUNT(d, CLEAN) * d->pages_per_eblk + + d->pages_per_eblk - d->curr_write_pos; +} + +static unsigned int mtdswap_enough_free_pages(struct mtdswap_dev *d) +{ + return mtdswap_free_page_cnt(d) > d->pages_per_eblk; +} + +static int mtdswap_write_block(struct mtdswap_dev *d, char *buf, + unsigned int page, unsigned int *bp, int gc_context) +{ + struct mtd_info *mtd = d->mtd; + struct swap_eb *eb; + size_t retlen; + loff_t writepos; + int ret; + +retry: + if (!gc_context) + while (!mtdswap_enough_free_pages(d)) + if (mtdswap_gc(d, 0) > 0) + return -ENOSPC; + + ret = mtdswap_map_free_block(d, page, bp); + eb = d->eb_data + (*bp / d->pages_per_eblk); + + if (ret == -EIO || ret == -EBADMSG) { + d->curr_write = NULL; + eb->active_count--; + d->revmap[*bp] = PAGE_UNDEF; + goto retry; + } + + if (ret < 0) + return ret; + + writepos = (loff_t)*bp << PAGE_SHIFT; + ret = mtd->write(mtd, writepos, PAGE_SIZE, &retlen, buf); + if (ret == -EIO || ret == -EBADMSG) { + d->curr_write_pos--; + eb->active_count--; + d->revmap[*bp] = PAGE_UNDEF; + mtdswap_handle_write_error(d, eb); + goto retry; + } + + if (ret < 0) { + dev_err(d->dev, "Write to MTD device failed: %d (%d written)", + ret, retlen); + goto err; + } + + if (retlen != PAGE_SIZE) { + dev_err(d->dev, "Short write to MTD device: %d written", + retlen); + ret = -EIO; + goto err; + } + + return ret; + +err: + d->curr_write_pos--; + eb->active_count--; + d->revmap[*bp] = PAGE_UNDEF; + + return ret; +} + +static int mtdswap_move_block(struct mtdswap_dev *d, unsigned int oldblock, + unsigned int *newblock) +{ + struct mtd_info *mtd = d->mtd; + struct swap_eb *eb, *oldeb; + int ret; + size_t retlen; + unsigned int page, retries; + loff_t readpos; + + page = d->revmap[oldblock]; + readpos = (loff_t) oldblock << PAGE_SHIFT; + retries = 0; + +retry: + ret = mtd->read(mtd, readpos, PAGE_SIZE, &retlen, d->page_buf); + + if (ret < 0 && ret != -EUCLEAN) { + oldeb = d->eb_data + oldblock / d->pages_per_eblk; + oldeb->flags |= EBLOCK_READERR; + + dev_err(d->dev, "Read Error: %d (block %u)\n", ret, + oldblock); + retries++; + if (retries < MTDSWAP_IO_RETRIES) + goto retry; + + goto read_error; + } + + if (retlen != PAGE_SIZE) { + dev_err(d->dev, "Short read: %d (block %u)\n", retlen, + oldblock); + ret = -EIO; + goto read_error; + } + + ret = mtdswap_write_block(d, d->page_buf, page, newblock, 1); + if (ret < 0) { + d->page_data[page] = BLOCK_ERROR; + dev_err(d->dev, "Write error: %d\n", ret); + return ret; + } + + eb = d->eb_data + *newblock / d->pages_per_eblk; + d->page_data[page] = *newblock; + d->revmap[oldblock] = PAGE_UNDEF; + eb = d->eb_data + oldblock / d->pages_per_eblk; + eb->active_count--; + + return 0; + +read_error: + d->page_data[page] = BLOCK_ERROR; + d->revmap[oldblock] = PAGE_UNDEF; + return ret; +} + +static int mtdswap_gc_eblock(struct mtdswap_dev *d, struct swap_eb *eb) +{ + unsigned int i, block, eblk_base, newblock; + int ret, errcode; + + errcode = 0; + eblk_base = (eb - d->eb_data) * d->pages_per_eblk; + + for (i = 0; i < d->pages_per_eblk; i++) { + if (d->spare_eblks < MIN_SPARE_EBLOCKS) + return -ENOSPC; + + block = eblk_base + i; + if (d->revmap[block] == PAGE_UNDEF) + continue; + + ret = mtdswap_move_block(d, block, &newblock); + if (ret < 0 && !errcode) + errcode = ret; + } + + return errcode; +} + +static int __mtdswap_choose_gc_tree(struct mtdswap_dev *d) +{ + int idx, stopat; + + if (TREE_COUNT(d, CLEAN) < LOW_FRAG_GC_TRESHOLD) + stopat = MTDSWAP_LOWFRAG; + else + stopat = MTDSWAP_HIFRAG; + + for (idx = MTDSWAP_BITFLIP; idx >= stopat; idx--) + if (d->trees[idx].root.rb_node != NULL) + return idx; + + return -1; +} + +static int mtdswap_wlfreq(unsigned int maxdiff) +{ + unsigned int h, x, y, dist, base; + + /* + * Calculate linear ramp down from f1 to f2 when maxdiff goes from + * MAX_ERASE_DIFF to MAX_ERASE_DIFF + COLLECT_NONDIRTY_BASE. Similar + * to triangle with height f1 - f1 and width COLLECT_NONDIRTY_BASE. + */ + + dist = maxdiff - MAX_ERASE_DIFF; + if (dist > COLLECT_NONDIRTY_BASE) + dist = COLLECT_NONDIRTY_BASE; + + /* + * Modelling the slop as right angular triangle with base + * COLLECT_NONDIRTY_BASE and height freq1 - freq2. The ratio y/x is + * equal to the ratio h/base. + */ + h = COLLECT_NONDIRTY_FREQ1 - COLLECT_NONDIRTY_FREQ2; + base = COLLECT_NONDIRTY_BASE; + + x = dist - base; + y = (x * h + base / 2) / base; + + return COLLECT_NONDIRTY_FREQ2 + y; +} + +static int mtdswap_choose_wl_tree(struct mtdswap_dev *d) +{ + static unsigned int pick_cnt; + unsigned int i, idx, wear, max; + struct rb_root *root; + + max = 0; + for (i = 0; i <= MTDSWAP_DIRTY; i++) { + root = &d->trees[i].root; + if (root->rb_node == NULL) + continue; + + wear = d->max_erase_count - MTDSWAP_ECNT_MIN(root); + if (wear > max) { + max = wear; + idx = i; + } + } + + if (max > MAX_ERASE_DIFF && pick_cnt >= mtdswap_wlfreq(max) - 1) { + pick_cnt = 0; + return idx; + } + + pick_cnt++; + return -1; +} + +static int mtdswap_choose_gc_tree(struct mtdswap_dev *d, + unsigned int background) +{ + int idx; + + if (TREE_NONEMPTY(d, FAILING) && + (background || (TREE_EMPTY(d, CLEAN) && TREE_EMPTY(d, DIRTY)))) + return MTDSWAP_FAILING; + + idx = mtdswap_choose_wl_tree(d); + if (idx >= MTDSWAP_CLEAN) + return idx; + + return __mtdswap_choose_gc_tree(d); +} + +static struct swap_eb *mtdswap_pick_gc_eblk(struct mtdswap_dev *d, + unsigned int background) +{ + struct rb_root *rp = NULL; + struct swap_eb *eb = NULL; + int idx; + + if (background && TREE_COUNT(d, CLEAN) > CLEAN_BLOCK_THRESHOLD && + TREE_EMPTY(d, DIRTY) && TREE_EMPTY(d, FAILING)) + return NULL; + + idx = mtdswap_choose_gc_tree(d, background); + if (idx < 0) + return NULL; + + rp = &d->trees[idx].root; + eb = rb_entry(rb_first(rp), struct swap_eb, rb); + + rb_erase(&eb->rb, rp); + eb->root = NULL; + d->trees[idx].count--; + return eb; +} + +static unsigned int mtdswap_test_patt(unsigned int i) +{ + return i % 2 ? 0x55555555 : 0xAAAAAAAA; +} + +static unsigned int mtdswap_eblk_passes(struct mtdswap_dev *d, + struct swap_eb *eb) +{ + struct mtd_info *mtd = d->mtd; + unsigned int test, i, j, patt, mtd_pages; + loff_t base, pos; + unsigned int *p1 = (unsigned int *)d->page_buf; + unsigned char *p2 = (unsigned char *)d->oob_buf; + struct mtd_oob_ops ops; + int ret; + + ops.mode = MTD_OOB_AUTO; + ops.len = mtd->writesize; + ops.ooblen = mtd->ecclayout->oobavail; + ops.ooboffs = 0; + ops.datbuf = d->page_buf; + ops.oobbuf = d->oob_buf; + base = mtdswap_eb_offset(d, eb); + mtd_pages = d->pages_per_eblk * PAGE_SIZE / mtd->writesize; + + for (test = 0; test < 2; test++) { + pos = base; + for (i = 0; i < mtd_pages; i++) { + patt = mtdswap_test_patt(test + i); + memset(d->page_buf, patt, mtd->writesize); + memset(d->oob_buf, patt, mtd->ecclayout->oobavail); + ret = mtd->write_oob(mtd, pos, &ops); + if (ret) + goto error; + + pos += mtd->writesize; + } + + pos = base; + for (i = 0; i < mtd_pages; i++) { + ret = mtd->read_oob(mtd, pos, &ops); + if (ret) + goto error; + + patt = mtdswap_test_patt(test + i); + for (j = 0; j < mtd->writesize/sizeof(int); j++) + if (p1[j] != patt) + goto error; + + for (j = 0; j < mtd->ecclayout->oobavail; j++) + if (p2[j] != (unsigned char)patt) + goto error; + + pos += mtd->writesize; + } + + ret = mtdswap_erase_block(d, eb); + if (ret) + goto error; + } + + eb->flags &= ~EBLOCK_READERR; + return 1; + +error: + mtdswap_handle_badblock(d, eb); + return 0; +} + +static int mtdswap_gc(struct mtdswap_dev *d, unsigned int background) +{ + struct swap_eb *eb; + int ret; + + if (d->spare_eblks < MIN_SPARE_EBLOCKS) + return 1; + + eb = mtdswap_pick_gc_eblk(d, background); + if (!eb) + return 1; + + ret = mtdswap_gc_eblock(d, eb); + if (ret == -ENOSPC) + return 1; + + if (eb->flags & EBLOCK_FAILED) { + mtdswap_handle_badblock(d, eb); + return 0; + } + + eb->flags &= ~EBLOCK_BITFLIP; + ret = mtdswap_erase_block(d, eb); + if ((eb->flags & EBLOCK_READERR) && + (ret || !mtdswap_eblk_passes(d, eb))) + return 0; + + if (ret == 0) + ret = mtdswap_write_marker(d, eb, MTDSWAP_TYPE_CLEAN); + + if (ret == 0) + mtdswap_rb_add(d, eb, MTDSWAP_CLEAN); + else if (ret != -EIO && ret != -EBADMSG) + mtdswap_rb_add(d, eb, MTDSWAP_DIRTY); + + return 0; +} + +static void mtdswap_background(struct mtd_blktrans_dev *dev) +{ + struct mtdswap_dev *d = MTDSWAP_MBD_TO_MTDSWAP(dev); + int ret; + + while (1) { + ret = mtdswap_gc(d, 1); + if (ret || mtd_blktrans_cease_background(dev)) + return; + } +} + +static void mtdswap_cleanup(struct mtdswap_dev *d) +{ + vfree(d->eb_data); + vfree(d->revmap); + vfree(d->page_data); + kfree(d->oob_buf); + kfree(d->page_buf); +} + +static int mtdswap_flush(struct mtd_blktrans_dev *dev) +{ + struct mtdswap_dev *d = MTDSWAP_MBD_TO_MTDSWAP(dev); + + if (d->mtd->sync) + d->mtd->sync(d->mtd); + return 0; +} + +static unsigned int mtdswap_badblocks(struct mtd_info *mtd, uint64_t size) +{ + loff_t offset; + unsigned int badcnt; + + badcnt = 0; + + if (mtd->block_isbad) + for (offset = 0; offset < size; offset += mtd->erasesize) + if (mtd->block_isbad(mtd, offset)) + badcnt++; + + return badcnt; +} + +static int mtdswap_writesect(struct mtd_blktrans_dev *dev, + unsigned long page, char *buf) +{ + struct mtdswap_dev *d = MTDSWAP_MBD_TO_MTDSWAP(dev); + unsigned int newblock, mapped; + struct swap_eb *eb; + int ret; + + d->sect_write_count++; + + if (d->spare_eblks < MIN_SPARE_EBLOCKS) + return -ENOSPC; + + if (header) { + /* Ignore writes to the header page */ + if (unlikely(page == 0)) + return 0; + + page--; + } + + mapped = d->page_data[page]; + if (mapped <= BLOCK_MAX) { + eb = d->eb_data + (mapped / d->pages_per_eblk); + eb->active_count--; + mtdswap_store_eb(d, eb); + d->page_data[page] = BLOCK_UNDEF; + d->revmap[mapped] = PAGE_UNDEF; + } + + ret = mtdswap_write_block(d, buf, page, &newblock, 0); + d->mtd_write_count++; + + if (ret < 0) + return ret; + + eb = d->eb_data + (newblock / d->pages_per_eblk); + d->page_data[page] = newblock; + + return 0; +} + +/* Provide a dummy swap header for the kernel */ +static int mtdswap_auto_header(struct mtdswap_dev *d, char *buf) +{ + union swap_header *hd = (union swap_header *)(buf); + + memset(buf, 0, PAGE_SIZE - 10); + + hd->info.version = 1; + hd->info.last_page = d->mbd_dev->size - 1; + hd->info.nr_badpages = 0; + + memcpy(buf + PAGE_SIZE - 10, "SWAPSPACE2", 10); + + return 0; +} + +static int mtdswap_readsect(struct mtd_blktrans_dev *dev, + unsigned long page, char *buf) +{ + struct mtdswap_dev *d = MTDSWAP_MBD_TO_MTDSWAP(dev); + struct mtd_info *mtd = d->mtd; + unsigned int realblock, retries; + loff_t readpos; + struct swap_eb *eb; + size_t retlen; + int ret; + + d->sect_read_count++; + + if (header) { + if (unlikely(page == 0)) + return mtdswap_auto_header(d, buf); + + page--; + } + + realblock = d->page_data[page]; + if (realblock > BLOCK_MAX) { + memset(buf, 0x0, PAGE_SIZE); + if (realblock == BLOCK_UNDEF) + return 0; + else + return -EIO; + } + + eb = d->eb_data + (realblock / d->pages_per_eblk); + BUG_ON(d->revmap[realblock] == PAGE_UNDEF); + + readpos = (loff_t)realblock << PAGE_SHIFT; + retries = 0; + +retry: + ret = mtd->read(mtd, readpos, PAGE_SIZE, &retlen, buf); + + d->mtd_read_count++; + if (ret == -EUCLEAN) { + eb->flags |= EBLOCK_BITFLIP; + mtdswap_rb_add(d, eb, MTDSWAP_BITFLIP); + ret = 0; + } + + if (ret < 0) { + dev_err(d->dev, "Read error %d\n", ret); + eb->flags |= EBLOCK_READERR; + mtdswap_rb_add(d, eb, MTDSWAP_FAILING); + retries++; + if (retries < MTDSWAP_IO_RETRIES) + goto retry; + + return ret; + } + + if (retlen != PAGE_SIZE) { + dev_err(d->dev, "Short read %d\n", retlen); + return -EIO; + } + + return 0; +} + +static int mtdswap_discard(struct mtd_blktrans_dev *dev, unsigned long first, + unsigned nr_pages) +{ + struct mtdswap_dev *d = MTDSWAP_MBD_TO_MTDSWAP(dev); + unsigned long page; + struct swap_eb *eb; + unsigned int mapped; + + d->discard_count++; + + for (page = first; page < first + nr_pages; page++) { + mapped = d->page_data[page]; + if (mapped <= BLOCK_MAX) { + eb = d->eb_data + (mapped / d->pages_per_eblk); + eb->active_count--; + mtdswap_store_eb(d, eb); + d->page_data[page] = BLOCK_UNDEF; + d->revmap[mapped] = PAGE_UNDEF; + d->discard_page_count++; + } else if (mapped == BLOCK_ERROR) { + d->page_data[page] = BLOCK_UNDEF; + d->discard_page_count++; + } + } + + return 0; +} + +static int mtdswap_show(struct seq_file *s, void *data) +{ + struct mtdswap_dev *d = (struct mtdswap_dev *) s->private; + unsigned long sum; + unsigned int count[MTDSWAP_TREE_CNT]; + unsigned int min[MTDSWAP_TREE_CNT]; + unsigned int max[MTDSWAP_TREE_CNT]; + unsigned int i, cw = 0, cwp = 0, cwecount = 0, bb_cnt, mapped, pages; + uint64_t use_size; + char *name[] = {"clean", "used", "low", "high", "dirty", "bitflip", + "failing"}; + + mutex_lock(&d->mbd_dev->lock); + + for (i = 0; i < MTDSWAP_TREE_CNT; i++) { + struct rb_root *root = &d->trees[i].root; + + if (root->rb_node) { + count[i] = d->trees[i].count; + min[i] = rb_entry(rb_first(root), struct swap_eb, + rb)->erase_count; + max[i] = rb_entry(rb_last(root), struct swap_eb, + rb)->erase_count; + } else + count[i] = 0; + } + + if (d->curr_write) { + cw = 1; + cwp = d->curr_write_pos; + cwecount = d->curr_write->erase_count; + } + + sum = 0; + for (i = 0; i < d->eblks; i++) + sum += d->eb_data[i].erase_count; + + use_size = (uint64_t)d->eblks * d->mtd->erasesize; + bb_cnt = mtdswap_badblocks(d->mtd, use_size); + + mapped = 0; + pages = d->mbd_dev->size; + for (i = 0; i < pages; i++) + if (d->page_data[i] != BLOCK_UNDEF) + mapped++; + + mutex_unlock(&d->mbd_dev->lock); + + for (i = 0; i < MTDSWAP_TREE_CNT; i++) { + if (!count[i]) + continue; + + if (min[i] != max[i]) + seq_printf(s, "%s:\t%5d erase blocks, erased min %d, " + "max %d times\n", + name[i], count[i], min[i], max[i]); + else + seq_printf(s, "%s:\t%5d erase blocks, all erased %d " + "times\n", name[i], count[i], min[i]); + } + + if (bb_cnt) + seq_printf(s, "bad:\t%5u erase blocks\n", bb_cnt); + + if (cw) + seq_printf(s, "current erase block: %u pages used, %u free, " + "erased %u times\n", + cwp, d->pages_per_eblk - cwp, cwecount); + + seq_printf(s, "total erasures: %lu\n", sum); + + seq_printf(s, "\n"); + + seq_printf(s, "mtdswap_readsect count: %llu\n", d->sect_read_count); + seq_printf(s, "mtdswap_writesect count: %llu\n", d->sect_write_count); + seq_printf(s, "mtdswap_discard count: %llu\n", d->discard_count); + seq_printf(s, "mtd read count: %llu\n", d->mtd_read_count); + seq_printf(s, "mtd write count: %llu\n", d->mtd_write_count); + seq_printf(s, "discarded pages count: %llu\n", d->discard_page_count); + + seq_printf(s, "\n"); + seq_printf(s, "total pages: %lu\n", pages); + seq_printf(s, "pages mapped: %u\n", mapped); + + return 0; +} + +static int mtdswap_open(struct inode *inode, struct file *file) +{ + return single_open(file, mtdswap_show, inode->i_private); +} + +static const struct file_operations mtdswap_fops = { + .open = mtdswap_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static int mtdswap_add_debugfs(struct mtdswap_dev *d) +{ + struct gendisk *gd = d->mbd_dev->disk; + struct device *dev = disk_to_dev(gd); + + struct dentry *root; + struct dentry *dent; + + root = debugfs_create_dir(gd->disk_name, NULL); + if (IS_ERR(root)) + return 0; + + if (!root) { + dev_err(dev, "failed to initialize debugfs\n"); + return -1; + } + + d->debugfs_root = root; + + dent = debugfs_create_file("stats", S_IRUSR, root, d, + &mtdswap_fops); + if (!dent) { + dev_err(d->dev, "debugfs_create_file failed\n"); + debugfs_remove_recursive(root); + d->debugfs_root = NULL; + return -1; + } + + return 0; +} + +static int mtdswap_init(struct mtdswap_dev *d, unsigned int eblocks, + unsigned int spare_cnt) +{ + struct mtd_info *mtd = d->mbd_dev->mtd; + unsigned int i, eblk_bytes, pages, blocks; + int ret = -ENOMEM; + + d->mtd = mtd; + d->eblks = eblocks; + d->spare_eblks = spare_cnt; + d->pages_per_eblk = mtd->erasesize >> PAGE_SHIFT; + + pages = d->mbd_dev->size; + blocks = eblocks * d->pages_per_eblk; + + for (i = 0; i < MTDSWAP_TREE_CNT; i++) + d->trees[i].root = RB_ROOT; + + d->page_data = vmalloc(sizeof(int)*pages); + if (!d->page_data) + goto page_data_fail; + + d->revmap = vmalloc(sizeof(int)*blocks); + if (!d->revmap) + goto revmap_fail; + + eblk_bytes = sizeof(struct swap_eb)*d->eblks; + d->eb_data = vmalloc(eblk_bytes); + if (!d->eb_data) + goto eb_data_fail; + + memset(d->eb_data, 0, eblk_bytes); + for (i = 0; i < pages; i++) + d->page_data[i] = BLOCK_UNDEF; + + for (i = 0; i < blocks; i++) + d->revmap[i] = PAGE_UNDEF; + + d->page_buf = kmalloc(PAGE_SIZE, GFP_KERNEL); + if (!d->page_buf) + goto page_buf_fail; + + d->oob_buf = kmalloc(2 * mtd->ecclayout->oobavail, GFP_KERNEL); + if (!d->oob_buf) + goto oob_buf_fail; + + mtdswap_scan_eblks(d); + + return 0; + +oob_buf_fail: + kfree(d->page_buf); +page_buf_fail: + vfree(d->eb_data); +eb_data_fail: + vfree(d->revmap); +revmap_fail: + vfree(d->page_data); +page_data_fail: + printk(KERN_ERR "%s: init failed (%d)\n", MTDSWAP_PREFIX, ret); + return ret; +} + +static void mtdswap_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd) +{ + struct mtdswap_dev *d; + struct mtd_blktrans_dev *mbd_dev; + char *parts; + char *this_opt; + unsigned long part; + unsigned int eblocks, eavailable, bad_blocks, spare_cnt; + uint64_t swap_size, use_size, size_limit; + struct nand_ecclayout *oinfo; + int ret; + + parts = &partitions[0]; + if (!*parts) + return; + + while ((this_opt = strsep(&parts, ",")) != NULL) { + if (strict_strtoul(this_opt, 0, &part) < 0) + return; + + if (mtd->index == part) + break; + } + + if (mtd->index != part) + return; + + if (mtd->erasesize < PAGE_SIZE || mtd->erasesize % PAGE_SIZE) { + printk(KERN_ERR "%s: Erase size %u not multiple of PAGE_SIZE " + "%lu\n", MTDSWAP_PREFIX, mtd->erasesize, PAGE_SIZE); + return; + } + + if (PAGE_SIZE % mtd->writesize || mtd->writesize > PAGE_SIZE) { + printk(KERN_ERR "%s: PAGE_SIZE %lu not multiple of write size" + " %u\n", MTDSWAP_PREFIX, PAGE_SIZE, mtd->writesize); + return; + } + + oinfo = mtd->ecclayout; + if (!mtd->oobsize || !oinfo || oinfo->oobavail < MTDSWAP_OOBSIZE) { + printk(KERN_ERR "%s: Not enough free bytes in OOB, " + "%d available, %u needed.\n", + MTDSWAP_PREFIX, oinfo->oobavail, MTDSWAP_OOBSIZE); + return; + } + + if (spare_eblocks > 100) + spare_eblocks = 100; + + use_size = mtd->size; + size_limit = (uint64_t) BLOCK_MAX * PAGE_SIZE; + + if (mtd->size > size_limit) { + printk(KERN_WARNING "%s: Device too large. Limiting size to " + "%llu bytes\n", MTDSWAP_PREFIX, size_limit); + use_size = size_limit; + } + + eblocks = mtd_div_by_eb(use_size, mtd); + use_size = eblocks * mtd->erasesize; + bad_blocks = mtdswap_badblocks(mtd, use_size); + eavailable = eblocks - bad_blocks; + + if (eavailable < MIN_ERASE_BLOCKS) { + printk(KERN_ERR "%s: Not enough erase blocks. %u available, " + "%d needed\n", MTDSWAP_PREFIX, eavailable, + MIN_ERASE_BLOCKS); + return; + } + + spare_cnt = div_u64((uint64_t)eavailable * spare_eblocks, 100); + + if (spare_cnt < MIN_SPARE_EBLOCKS) + spare_cnt = MIN_SPARE_EBLOCKS; + + if (spare_cnt > eavailable - 1) + spare_cnt = eavailable - 1; + + swap_size = (uint64_t)(eavailable - spare_cnt) * mtd->erasesize + + (header ? PAGE_SIZE : 0); + + printk(KERN_INFO "%s: Enabling MTD swap on device %lu, size %llu KB, " + "%u spare, %u bad blocks\n", + MTDSWAP_PREFIX, part, swap_size / 1024, spare_cnt, bad_blocks); + + d = kzalloc(sizeof(struct mtdswap_dev), GFP_KERNEL); + if (!d) + return; + + mbd_dev = kzalloc(sizeof(struct mtd_blktrans_dev), GFP_KERNEL); + if (!mbd_dev) { + kfree(d); + return; + } + + d->mbd_dev = mbd_dev; + mbd_dev->priv = d; + + mbd_dev->mtd = mtd; + mbd_dev->devnum = mtd->index; + mbd_dev->size = swap_size >> PAGE_SHIFT; + mbd_dev->tr = tr; + + if (!(mtd->flags & MTD_WRITEABLE)) + mbd_dev->readonly = 1; + + if (mtdswap_init(d, eblocks, spare_cnt) < 0) + goto init_failed; + + if (add_mtd_blktrans_dev(mbd_dev) < 0) + goto cleanup; + + d->dev = disk_to_dev(mbd_dev->disk); + + ret = mtdswap_add_debugfs(d); + if (ret < 0) + goto debugfs_failed; + + return; + +debugfs_failed: + del_mtd_blktrans_dev(mbd_dev); + +cleanup: + mtdswap_cleanup(d); + +init_failed: + kfree(mbd_dev); + kfree(d); +} + +static void mtdswap_remove_dev(struct mtd_blktrans_dev *dev) +{ + struct mtdswap_dev *d = MTDSWAP_MBD_TO_MTDSWAP(dev); + + debugfs_remove_recursive(d->debugfs_root); + del_mtd_blktrans_dev(dev); + mtdswap_cleanup(d); + kfree(d); +} + +static struct mtd_blktrans_ops mtdswap_ops = { + .name = "mtdswap", + .major = 0, + .part_bits = 0, + .blksize = PAGE_SIZE, + .flush = mtdswap_flush, + .readsect = mtdswap_readsect, + .writesect = mtdswap_writesect, + .discard = mtdswap_discard, + .background = mtdswap_background, + .add_mtd = mtdswap_add_mtd, + .remove_dev = mtdswap_remove_dev, + .owner = THIS_MODULE, +}; + +static int __init mtdswap_modinit(void) +{ + return register_mtd_blktrans(&mtdswap_ops); +} + +static void __exit mtdswap_modexit(void) +{ + deregister_mtd_blktrans(&mtdswap_ops); +} + +module_init(mtdswap_modinit); +module_exit(mtdswap_modexit); + + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Jarkko Lavinen "); +MODULE_DESCRIPTION("Block device access to an MTD suitable for using as " + "swap space"); -- GitLab From dcfb81d61da1367e52f7f7e3ceff0d0044c3c7ee Mon Sep 17 00:00:00 2001 From: David Griego Date: Tue, 30 Nov 2010 15:32:05 +0530 Subject: [PATCH 0588/2822] mtd: NOR flash driver for OMAP-L137/AM17x OMAP-L137/AM17x has limited number of dedicated EMIFA address pins, enough to interface directly to an SDRAM. If a device such as an asynchronous flash needs to be attached to the EMIFA, then either GPIO pins or a chip select may be used to control the flash device's upper address lines. This patch adds support for the NOR flash on the OMAP-L137/ AM17x user interface daughter board using the latch-addr-flash MTD mapping driver which allows flashes to be partially physically addressed. The upper address lines are set by a board specific code which is a separate patch. Signed-off-by: David Griego Signed-off-by: Aleksey Makarov Signed-off-by: Sergei Shtylyov Signed-off-by: Savinay Dharmappa Signed-off-by: Artem Bityutskiy Signed-off-by: David Woodhouse --- drivers/mtd/maps/Kconfig | 9 + drivers/mtd/maps/Makefile | 1 + drivers/mtd/maps/latch-addr-flash.c | 272 +++++++++++++++++++++++++++ include/linux/mtd/latch-addr-flash.h | 29 +++ 4 files changed, 311 insertions(+) create mode 100644 drivers/mtd/maps/latch-addr-flash.c create mode 100644 include/linux/mtd/latch-addr-flash.h diff --git a/drivers/mtd/maps/Kconfig b/drivers/mtd/maps/Kconfig index 803072a71ed74..44b1f46458cab 100644 --- a/drivers/mtd/maps/Kconfig +++ b/drivers/mtd/maps/Kconfig @@ -552,4 +552,13 @@ config MTD_PISMO When built as a module, it will be called pismo.ko +config MTD_LATCH_ADDR + tristate "Latch-assisted Flash Chip Support" + depends on MTD_COMPLEX_MAPPINGS + help + Map driver which allows flashes to be partially physically addressed + and have the upper address lines set by a board specific code. + + If compiled as a module, it will be called latch-addr-flash. + endmenu diff --git a/drivers/mtd/maps/Makefile b/drivers/mtd/maps/Makefile index c7869c7a6b18f..08533bd5cba7c 100644 --- a/drivers/mtd/maps/Makefile +++ b/drivers/mtd/maps/Makefile @@ -59,3 +59,4 @@ obj-$(CONFIG_MTD_RBTX4939) += rbtx4939-flash.o obj-$(CONFIG_MTD_VMU) += vmu-flash.o obj-$(CONFIG_MTD_GPIO_ADDR) += gpio-addr-flash.o obj-$(CONFIG_MTD_BCM963XX) += bcm963xx-flash.o +obj-$(CONFIG_MTD_LATCH_ADDR) += latch-addr-flash.o diff --git a/drivers/mtd/maps/latch-addr-flash.c b/drivers/mtd/maps/latch-addr-flash.c new file mode 100644 index 0000000000000..ee25480853346 --- /dev/null +++ b/drivers/mtd/maps/latch-addr-flash.c @@ -0,0 +1,272 @@ +/* + * Interface for NOR flash driver whose high address lines are latched + * + * Copyright © 2000 Nicolas Pitre + * Copyright © 2005-2008 Analog Devices Inc. + * Copyright © 2008 MontaVista Software, Inc. + * + * This file is licensed under the terms of the GNU General Public License + * version 2. This program is licensed "as is" without any warranty of any + * kind, whether express or implied. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DRIVER_NAME "latch-addr-flash" + +struct latch_addr_flash_info { + struct mtd_info *mtd; + struct map_info map; + struct resource *res; + + void (*set_window)(unsigned long offset, void *data); + void *data; + + /* cache; could be found out of res */ + unsigned long win_mask; + + int nr_parts; + struct mtd_partition *parts; + + spinlock_t lock; +}; + +static map_word lf_read(struct map_info *map, unsigned long ofs) +{ + struct latch_addr_flash_info *info; + map_word datum; + + info = (struct latch_addr_flash_info *)map->map_priv_1; + + spin_lock(&info->lock); + + info->set_window(ofs, info->data); + datum = inline_map_read(map, info->win_mask & ofs); + + spin_unlock(&info->lock); + + return datum; +} + +static void lf_write(struct map_info *map, map_word datum, unsigned long ofs) +{ + struct latch_addr_flash_info *info; + + info = (struct latch_addr_flash_info *)map->map_priv_1; + + spin_lock(&info->lock); + + info->set_window(ofs, info->data); + inline_map_write(map, datum, info->win_mask & ofs); + + spin_unlock(&info->lock); +} + +static void lf_copy_from(struct map_info *map, void *to, + unsigned long from, ssize_t len) +{ + struct latch_addr_flash_info *info = + (struct latch_addr_flash_info *) map->map_priv_1; + unsigned n; + + while (len > 0) { + n = info->win_mask + 1 - (from & info->win_mask); + if (n > len) + n = len; + + spin_lock(&info->lock); + + info->set_window(from, info->data); + memcpy_fromio(to, map->virt + (from & info->win_mask), n); + + spin_unlock(&info->lock); + + to += n; + from += n; + len -= n; + } +} + +static char *rom_probe_types[] = { "cfi_probe", NULL }; + +static char *part_probe_types[] = { "cmdlinepart", NULL }; + +static int latch_addr_flash_remove(struct platform_device *dev) +{ + struct latch_addr_flash_info *info; + struct latch_addr_flash_data *latch_addr_data; + + info = platform_get_drvdata(dev); + if (info == NULL) + return 0; + platform_set_drvdata(dev, NULL); + + latch_addr_data = dev->dev.platform_data; + + if (info->mtd != NULL) { + if (mtd_has_partitions()) { + if (info->nr_parts) { + del_mtd_partitions(info->mtd); + kfree(info->parts); + } else if (latch_addr_data->nr_parts) { + del_mtd_partitions(info->mtd); + } else { + del_mtd_device(info->mtd); + } + } else { + del_mtd_device(info->mtd); + } + map_destroy(info->mtd); + } + + if (info->map.virt != NULL) + iounmap(info->map.virt); + + if (info->res != NULL) + release_mem_region(info->res->start, resource_size(info->res)); + + kfree(info); + + if (latch_addr_data->done) + latch_addr_data->done(latch_addr_data->data); + + return 0; +} + +static int __devinit latch_addr_flash_probe(struct platform_device *dev) +{ + struct latch_addr_flash_data *latch_addr_data; + struct latch_addr_flash_info *info; + resource_size_t win_base = dev->resource->start; + resource_size_t win_size = resource_size(dev->resource); + char **probe_type; + int chipsel; + int err; + + latch_addr_data = dev->dev.platform_data; + if (latch_addr_data == NULL) + return -ENODEV; + + pr_notice("latch-addr platform flash device: %#llx byte " + "window at %#.8llx\n", + (unsigned long long)win_size, (unsigned long long)win_base); + + chipsel = dev->id; + + if (latch_addr_data->init) { + err = latch_addr_data->init(latch_addr_data->data, chipsel); + if (err != 0) + return err; + } + + info = kzalloc(sizeof(struct latch_addr_flash_info), GFP_KERNEL); + if (info == NULL) { + err = -ENOMEM; + goto done; + } + + platform_set_drvdata(dev, info); + + info->res = request_mem_region(win_base, win_size, DRIVER_NAME); + if (info->res == NULL) { + dev_err(&dev->dev, "Could not reserve memory region\n"); + err = -EBUSY; + goto free_info; + } + + info->map.name = DRIVER_NAME; + info->map.size = latch_addr_data->size; + info->map.bankwidth = latch_addr_data->width; + + info->map.phys = NO_XIP; + info->map.virt = ioremap(win_base, win_size); + if (!info->map.virt) { + err = -ENOMEM; + goto free_res; + } + + info->map.map_priv_1 = (unsigned long)info; + + info->map.read = lf_read; + info->map.copy_from = lf_copy_from; + info->map.write = lf_write; + info->set_window = latch_addr_data->set_window; + info->data = latch_addr_data->data; + info->win_mask = win_size - 1; + + spin_lock_init(&info->lock); + + for (probe_type = rom_probe_types; !info->mtd && *probe_type; + probe_type++) + info->mtd = do_map_probe(*probe_type, &info->map); + + if (info->mtd == NULL) { + dev_err(&dev->dev, "map_probe failed\n"); + err = -ENODEV; + goto iounmap; + } + info->mtd->owner = THIS_MODULE; + + if (mtd_has_partitions()) { + + err = parse_mtd_partitions(info->mtd, + (const char **)part_probe_types, + &info->parts, 0); + if (err > 0) { + add_mtd_partitions(info->mtd, info->parts, err); + return 0; + } + if (latch_addr_data->nr_parts) { + pr_notice("Using latch-addr-flash partition information\n"); + add_mtd_partitions(info->mtd, latch_addr_data->parts, + latch_addr_data->nr_parts); + return 0; + } + } + add_mtd_device(info->mtd); + return 0; + +iounmap: + iounmap(info->map.virt); +free_res: + release_mem_region(info->res->start, resource_size(info->res)); +free_info: + kfree(info); +done: + if (latch_addr_data->done) + latch_addr_data->done(latch_addr_data->data); + return err; +} + +static struct platform_driver latch_addr_flash_driver = { + .probe = latch_addr_flash_probe, + .remove = __devexit_p(latch_addr_flash_remove), + .driver = { + .name = DRIVER_NAME, + }, +}; + +static int __init latch_addr_flash_init(void) +{ + return platform_driver_register(&latch_addr_flash_driver); +} +module_init(latch_addr_flash_init); + +static void __exit latch_addr_flash_exit(void) +{ + platform_driver_unregister(&latch_addr_flash_driver); +} +module_exit(latch_addr_flash_exit); + +MODULE_AUTHOR("David Griego "); +MODULE_DESCRIPTION("MTD map driver for flashes addressed physically with upper " + "address lines being set board specifically"); +MODULE_LICENSE("GPL v2"); diff --git a/include/linux/mtd/latch-addr-flash.h b/include/linux/mtd/latch-addr-flash.h new file mode 100644 index 0000000000000..e94b8e128074e --- /dev/null +++ b/include/linux/mtd/latch-addr-flash.h @@ -0,0 +1,29 @@ +/* + * Interface for NOR flash driver whose high address lines are latched + * + * Copyright © 2008 MontaVista Software, Inc. + * + * This file is licensed under the terms of the GNU General Public License + * version 2. This program is licensed "as is" without any warranty of any + * kind, whether express or implied. + */ +#ifndef __LATCH_ADDR_FLASH__ +#define __LATCH_ADDR_FLASH__ + +struct map_info; +struct mtd_partition; + +struct latch_addr_flash_data { + unsigned int width; + unsigned int size; + + int (*init)(void *data, int cs); + void (*done)(void *data); + void (*set_window)(unsigned long offset, void *data); + void *data; + + unsigned int nr_parts; + struct mtd_partition *parts; +}; + +#endif -- GitLab From b3dcfd35244e1cb8dc8dfa5c05013b133dbb437a Mon Sep 17 00:00:00 2001 From: Roman Tereshonkov Date: Thu, 17 Feb 2011 13:44:41 +0200 Subject: [PATCH 0589/2822] mtd: onenand: add new option to control initial onenand unlocking A new option ONENAND_SKIP_INITIAL_UNLOCKING is added. This allows to disable initial onenand unlocking when the driver is initialized. Signed-off-by: Roman Tereshonkov Signed-off-by: Artem Bityutskiy Signed-off-by: David Woodhouse --- drivers/mtd/onenand/onenand_base.c | 3 ++- include/linux/mtd/onenand.h | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/mtd/onenand/onenand_base.c b/drivers/mtd/onenand/onenand_base.c index 4205b9423b89c..56a8b2005bdac 100644 --- a/drivers/mtd/onenand/onenand_base.c +++ b/drivers/mtd/onenand/onenand_base.c @@ -4085,7 +4085,8 @@ int onenand_scan(struct mtd_info *mtd, int maxchips) mtd->writebufsize = mtd->writesize; /* Unlock whole block */ - this->unlock_all(mtd); + if (!(this->options & ONENAND_SKIP_INITIAL_UNLOCKING)) + this->unlock_all(mtd); ret = this->scan_bbt(mtd); if ((!FLEXONENAND(this)) || ret) diff --git a/include/linux/mtd/onenand.h b/include/linux/mtd/onenand.h index ae418e41d8f52..52b6f187bf49b 100644 --- a/include/linux/mtd/onenand.h +++ b/include/linux/mtd/onenand.h @@ -198,6 +198,7 @@ struct onenand_chip { #define ONENAND_SKIP_UNLOCK_CHECK (0x0100) #define ONENAND_PAGEBUF_ALLOC (0x1000) #define ONENAND_OOBBUF_ALLOC (0x2000) +#define ONENAND_SKIP_INITIAL_UNLOCKING (0x4000) #define ONENAND_IS_4KB_PAGE(this) \ (this->options & ONENAND_HAS_4KB_PAGE) -- GitLab From c93ff6bf16523d33e991a1fadde1b8d63eb7cd2c Mon Sep 17 00:00:00 2001 From: Roman Tereshonkov Date: Thu, 17 Feb 2011 13:44:42 +0200 Subject: [PATCH 0590/2822] mtd: omap: add new variable to platform data to control onenand unlocking New variable skip_initial_unlocking is added to the omap_onenand_platform_data. This is used to inform the onenand driver to skip onenand unlocking when it is initialized. Signed-off-by: Roman Tereshonkov Signed-off-by: Artem Bityutskiy Signed-off-by: David Woodhouse --- arch/arm/plat-omap/include/plat/onenand.h | 1 + drivers/mtd/onenand/omap2.c | 7 +++++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/arch/arm/plat-omap/include/plat/onenand.h b/arch/arm/plat-omap/include/plat/onenand.h index affe87e9ece70..1b430d5fdd543 100644 --- a/arch/arm/plat-omap/include/plat/onenand.h +++ b/arch/arm/plat-omap/include/plat/onenand.h @@ -24,6 +24,7 @@ struct omap_onenand_platform_data { int dma_channel; u8 flags; u8 regulator_can_sleep; + u8 skip_initial_unlocking; }; #define ONENAND_MAX_PARTITIONS 8 diff --git a/drivers/mtd/onenand/omap2.c b/drivers/mtd/onenand/omap2.c index c849cacf4b2fa..ea32c2fc46223 100644 --- a/drivers/mtd/onenand/omap2.c +++ b/drivers/mtd/onenand/omap2.c @@ -631,6 +631,7 @@ static int __devinit omap2_onenand_probe(struct platform_device *pdev) { struct omap_onenand_platform_data *pdata; struct omap2_onenand *c; + struct onenand_chip *this; int r; pdata = pdev->dev.platform_data; @@ -728,9 +729,8 @@ static int __devinit omap2_onenand_probe(struct platform_device *pdev) c->mtd.dev.parent = &pdev->dev; + this = &c->onenand; if (c->dma_channel >= 0) { - struct onenand_chip *this = &c->onenand; - this->wait = omap2_onenand_wait; if (cpu_is_omap34xx()) { this->read_bufferram = omap3_onenand_read_bufferram; @@ -751,6 +751,9 @@ static int __devinit omap2_onenand_probe(struct platform_device *pdev) c->onenand.disable = omap2_onenand_disable; } + if (pdata->skip_initial_unlocking) + this->options |= ONENAND_SKIP_INITIAL_UNLOCKING; + if ((r = onenand_scan(&c->mtd, 1)) < 0) goto err_release_regulator; -- GitLab From 775adc3d44c8076d3e475fabebb61c08421c4421 Mon Sep 17 00:00:00 2001 From: Jason Liu Date: Fri, 25 Feb 2011 13:06:18 +0800 Subject: [PATCH 0591/2822] mtd: nand: fix a typo in a commentary Signed-off-by: Jason Liu Signed-off-by: Artem Bityutskiy Signed-off-by: David Woodhouse --- drivers/mtd/nand/nand_base.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index a9c6ce745767a..da7604050347c 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c @@ -2377,7 +2377,7 @@ static int nand_do_write_oob(struct mtd_info *mtd, loff_t to, return -EINVAL; } - /* Do not allow reads past end of device */ + /* Do not allow write past end of device */ if (unlikely(to >= mtd->size || ops->ooboffs + ops->ooblen > ((mtd->size >> chip->page_shift) - -- GitLab From bea9312839c51853a2837336405c829b0bf18f88 Mon Sep 17 00:00:00 2001 From: Tracey Dent Date: Sat, 26 Feb 2011 11:15:13 -0500 Subject: [PATCH 0592/2822] jffs2: remove a trailing white space in commentaries Signed-off-by: Tracey Dent Signed-off-by: Artem Bityutskiy Signed-off-by: David Woodhouse --- fs/jffs2/xattr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/jffs2/xattr.c b/fs/jffs2/xattr.c index 4f9cc04829492..3e93cdd190055 100644 --- a/fs/jffs2/xattr.c +++ b/fs/jffs2/xattr.c @@ -31,7 +31,7 @@ * is used to release xattr name/value pair and detach from c->xattrindex. * reclaim_xattr_datum(c) * is used to reclaim xattr name/value pairs on the xattr name/value pair cache when - * memory usage by cache is over c->xdatum_mem_threshold. Currently, this threshold + * memory usage by cache is over c->xdatum_mem_threshold. Currently, this threshold * is hard coded as 32KiB. * do_verify_xattr_datum(c, xd) * is used to load the xdatum informations without name/value pair from the medium. -- GitLab From 74f1b7244e502c5a98906a5dcc5ec389aacd25e6 Mon Sep 17 00:00:00 2001 From: John Ogness Date: Mon, 28 Feb 2011 13:12:46 +0100 Subject: [PATCH 0593/2822] mtd: omap3: nand: report corrected ecc errors The number of corrected ECC errors should be reported since other MTD systems make use of this information (such as UBI data scrubbing). Signed-off-by: John Ogness Signed-off-by: Artem Bityutskiy Signed-off-by: David Woodhouse --- drivers/mtd/nand/omap2.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c index 28af71c61834e..d7a4e2550b132 100644 --- a/drivers/mtd/nand/omap2.c +++ b/drivers/mtd/nand/omap2.c @@ -517,6 +517,8 @@ static void gen_true_ecc(u8 *ecc_buf) * * This function compares two ECC's and indicates if there is an error. * If the error can be corrected it will be corrected to the buffer. + * If there is no error, %0 is returned. If there is an error but it + * was corrected, %1 is returned. Otherwise, %-1 is returned. */ static int omap_compare_ecc(u8 *ecc_data1, /* read from NAND memory */ u8 *ecc_data2, /* read from register */ @@ -622,7 +624,7 @@ static int omap_compare_ecc(u8 *ecc_data1, /* read from NAND memory */ page_data[find_byte] ^= (1 << find_bit); - return 0; + return 1; default: if (isEccFF) { if (ecc_data2[0] == 0 && @@ -643,8 +645,11 @@ static int omap_compare_ecc(u8 *ecc_data1, /* read from NAND memory */ * @calc_ecc: ecc read from HW ECC registers * * Compares the ecc read from nand spare area with ECC registers values - * and if ECC's mismached, it will call 'omap_compare_ecc' for error detection - * and correction. + * and if ECC's mismatched, it will call 'omap_compare_ecc' for error + * detection and correction. If there are no errors, %0 is returned. If + * there were errors and all of the errors were corrected, the number of + * corrected errors is returned. If uncorrectable errors exist, %-1 is + * returned. */ static int omap_correct_data(struct mtd_info *mtd, u_char *dat, u_char *read_ecc, u_char *calc_ecc) @@ -652,6 +657,7 @@ static int omap_correct_data(struct mtd_info *mtd, u_char *dat, struct omap_nand_info *info = container_of(mtd, struct omap_nand_info, mtd); int blockCnt = 0, i = 0, ret = 0; + int stat = 0; /* Ex NAND_ECC_HW12_2048 */ if ((info->nand.ecc.mode == NAND_ECC_HW) && @@ -665,12 +671,14 @@ static int omap_correct_data(struct mtd_info *mtd, u_char *dat, ret = omap_compare_ecc(read_ecc, calc_ecc, dat); if (ret < 0) return ret; + /* keep track of the number of corrected errors */ + stat += ret; } read_ecc += 3; calc_ecc += 3; dat += 512; } - return 0; + return stat; } /** -- GitLab From 5d9d9936209e589569a97985285b3282310cf2db Mon Sep 17 00:00:00 2001 From: Baruch Siach Date: Wed, 2 Mar 2011 16:47:55 +0200 Subject: [PATCH 0594/2822] mtd: mxc_nand: fix read past buffer end Signed-off-by: Baruch Siach Acked-by: Sascha hauer Signed-off-by: David Woodhouse --- drivers/mtd/nand/mxc_nand.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/mtd/nand/mxc_nand.c b/drivers/mtd/nand/mxc_nand.c index ef932ba55a0b3..6cd78ed439a74 100644 --- a/drivers/mtd/nand/mxc_nand.c +++ b/drivers/mtd/nand/mxc_nand.c @@ -641,9 +641,9 @@ static void mxc_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len) n = min(n, len); - memcpy(buf, host->data_buf + col, len); + memcpy(buf, host->data_buf + col, n); - host->buf_start += len; + host->buf_start += n; } /* Used by the upper layer to verify the data in NAND Flash -- GitLab From e70727e442eb61581f836a9a0ca0c3b70d8a3ff2 Mon Sep 17 00:00:00 2001 From: David Lambert Date: Mon, 7 Mar 2011 12:00:46 +0200 Subject: [PATCH 0595/2822] mtd: speedtest: fix integer overflow 32-bit integers used in 'calc_speed()' may overflow and lead to incorrect results. Use 64-bit integers instead. Signed-off-by: David Lambert Signed-off-by: Artem Bityutskiy Signed-off-by: David Woodhouse --- drivers/mtd/tests/mtd_speedtest.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/mtd/tests/mtd_speedtest.c b/drivers/mtd/tests/mtd_speedtest.c index 3ce6fce75e075..627d4e2466a3b 100644 --- a/drivers/mtd/tests/mtd_speedtest.c +++ b/drivers/mtd/tests/mtd_speedtest.c @@ -314,16 +314,16 @@ static inline void stop_timing(void) static long calc_speed(void) { - long ms, k, speed; + uint64_t k; + long ms; ms = (finish.tv_sec - start.tv_sec) * 1000 + (finish.tv_usec - start.tv_usec) / 1000; - k = goodebcnt * mtd->erasesize / 1024; - if (ms) - speed = (k * 1000) / ms; - else - speed = 0; - return speed; + if (ms == 0) + return 0; + k = goodebcnt * (mtd->erasesize / 1024) * 1000; + do_div(k, ms); + return k; } static int scan_for_bad_eraseblocks(void) -- GitLab From e353a20afaee1e3e67fc4fa663a76c68a4c1fb74 Mon Sep 17 00:00:00 2001 From: Lei Wen Date: Thu, 3 Mar 2011 11:08:30 +0800 Subject: [PATCH 0596/2822] mtd: pxa3xx_nand: make scan procedure more clear The previous probe function is some kind of big part. This patch seperate the resource allocation to keep the probe process more clear than before. Signed-off-by: Lei Wen Signed-off-by: Haojian Zhuang Signed-off-by: David Woodhouse --- drivers/mtd/nand/pxa3xx_nand.c | 99 +++++++++++++++++++--------------- 1 file changed, 55 insertions(+), 44 deletions(-) diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c index ea2c288df3f6b..f44044381360d 100644 --- a/drivers/mtd/nand/pxa3xx_nand.c +++ b/drivers/mtd/nand/pxa3xx_nand.c @@ -126,6 +126,7 @@ struct pxa3xx_nand_info { unsigned int buf_start; unsigned int buf_count; + struct mtd_info *mtd; /* DMA information */ int drcmr_dat; int drcmr_cmd; @@ -1044,34 +1045,27 @@ static void pxa3xx_nand_init_mtd(struct mtd_info *mtd, this->chip_delay = 25; } -static int pxa3xx_nand_probe(struct platform_device *pdev) +static +struct pxa3xx_nand_info *alloc_nand_resource(struct platform_device *pdev) { - struct pxa3xx_nand_platform_data *pdata; + struct pxa3xx_nand_platform_data *pdata = pdev->dev.platform_data; struct pxa3xx_nand_info *info; - struct nand_chip *this; struct mtd_info *mtd; struct resource *r; - int ret = 0, irq; - - pdata = pdev->dev.platform_data; - - if (!pdata) { - dev_err(&pdev->dev, "no platform data defined\n"); - return -ENODEV; - } + int ret, irq; mtd = kzalloc(sizeof(struct mtd_info) + sizeof(struct pxa3xx_nand_info), GFP_KERNEL); if (!mtd) { dev_err(&pdev->dev, "failed to allocate memory\n"); - return -ENOMEM; + return NULL; } info = (struct pxa3xx_nand_info *)(&mtd[1]); info->pdev = pdev; - this = &info->nand_chip; mtd->priv = info; + info->mtd = mtd; mtd->owner = THIS_MODULE; info->clk = clk_get(&pdev->dev, NULL); @@ -1149,31 +1143,9 @@ static int pxa3xx_nand_probe(struct platform_device *pdev) } pxa3xx_nand_init_mtd(mtd, info); + platform_set_drvdata(pdev, info); - platform_set_drvdata(pdev, mtd); - - if (nand_scan(mtd, 1)) { - dev_err(&pdev->dev, "failed to scan nand\n"); - ret = -ENXIO; - goto fail_free_irq; - } - -#ifdef CONFIG_MTD_PARTITIONS - if (mtd_has_cmdlinepart()) { - static const char *probes[] = { "cmdlinepart", NULL }; - struct mtd_partition *parts; - int nr_parts; - - nr_parts = parse_mtd_partitions(mtd, probes, &parts, 0); - - if (nr_parts) - return add_mtd_partitions(mtd, parts, nr_parts); - } - - return add_mtd_partitions(mtd, pdata->parts, pdata->nr_parts); -#else - return 0; -#endif + return info; fail_free_irq: free_irq(irq, info); @@ -1193,13 +1165,13 @@ fail_put_clk: clk_put(info->clk); fail_free_mtd: kfree(mtd); - return ret; + return NULL; } static int pxa3xx_nand_remove(struct platform_device *pdev) { - struct mtd_info *mtd = platform_get_drvdata(pdev); - struct pxa3xx_nand_info *info = mtd->priv; + struct pxa3xx_nand_info *info = platform_get_drvdata(pdev); + struct mtd_info *mtd = info->mtd; struct resource *r; int irq; @@ -1230,11 +1202,50 @@ static int pxa3xx_nand_remove(struct platform_device *pdev) return 0; } +static int pxa3xx_nand_probe(struct platform_device *pdev) +{ + struct pxa3xx_nand_platform_data *pdata; + struct pxa3xx_nand_info *info; + + pdata = pdev->dev.platform_data; + if (!pdata) { + dev_err(&pdev->dev, "no platform data defined\n"); + return -ENODEV; + } + + info = alloc_nand_resource(pdev); + if (info == NULL) + return -ENOMEM; + + if (nand_scan(info->mtd, 1)) { + dev_err(&pdev->dev, "failed to scan nand\n"); + pxa3xx_nand_remove(pdev); + return -ENODEV; + } + +#ifdef CONFIG_MTD_PARTITIONS + if (mtd_has_cmdlinepart()) { + const char *probes[] = { "cmdlinepart", NULL }; + struct mtd_partition *parts; + int nr_parts; + + nr_parts = parse_mtd_partitions(info->mtd, probes, &parts, 0); + + if (nr_parts) + return add_mtd_partitions(mtd, parts, nr_parts); + } + + return add_mtd_partitions(mtd, pdata->parts, pdata->nr_parts); +#else + return 0; +#endif +} + #ifdef CONFIG_PM static int pxa3xx_nand_suspend(struct platform_device *pdev, pm_message_t state) { - struct mtd_info *mtd = (struct mtd_info *)platform_get_drvdata(pdev); - struct pxa3xx_nand_info *info = mtd->priv; + struct pxa3xx_nand_info *info = platform_get_drvdata(pdev); + struct mtd_info *mtd = info->mtd; if (info->state != STATE_READY) { dev_err(&pdev->dev, "driver busy, state = %d\n", info->state); @@ -1246,8 +1257,8 @@ static int pxa3xx_nand_suspend(struct platform_device *pdev, pm_message_t state) static int pxa3xx_nand_resume(struct platform_device *pdev) { - struct mtd_info *mtd = (struct mtd_info *)platform_get_drvdata(pdev); - struct pxa3xx_nand_info *info = mtd->priv; + struct pxa3xx_nand_info *info = platform_get_drvdata(pdev); + struct mtd_info *mtd = info->mtd; nand_writel(info, NDTR0CS0, info->ndtr0cs0); nand_writel(info, NDTR1CS0, info->ndtr1cs0); -- GitLab From f8155a404db95656f1519b28fdb96cb68f8b2364 Mon Sep 17 00:00:00 2001 From: Lei Wen Date: Mon, 28 Feb 2011 10:32:11 +0800 Subject: [PATCH 0597/2822] mtd: pxa3xx_nand: rework irq logic Enable all irq when we start the nand controller, and put all the transaction logic in the pxa3xx_nand_irq. By doing this way, we could dramatically increase the performance by avoid unnecessary delay. Signed-off-by: Lei Wen Signed-off-by: Haojian Zhuang Signed-off-by: David Woodhouse --- drivers/mtd/nand/pxa3xx_nand.c | 399 +++++++++++++++------------------ 1 file changed, 187 insertions(+), 212 deletions(-) diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c index f44044381360d..3264b1d5a638f 100644 --- a/drivers/mtd/nand/pxa3xx_nand.c +++ b/drivers/mtd/nand/pxa3xx_nand.c @@ -27,6 +27,7 @@ #include #define CHIP_DELAY_TIMEOUT (2 * HZ/10) +#define NAND_STOP_DELAY (2 * HZ/50) /* registers and bit definitions */ #define NDCR (0x00) /* Control register */ @@ -52,16 +53,18 @@ #define NDCR_ND_MODE (0x3 << 21) #define NDCR_NAND_MODE (0x0) #define NDCR_CLR_PG_CNT (0x1 << 20) -#define NDCR_CLR_ECC (0x1 << 19) +#define NDCR_STOP_ON_UNCOR (0x1 << 19) #define NDCR_RD_ID_CNT_MASK (0x7 << 16) #define NDCR_RD_ID_CNT(x) (((x) << 16) & NDCR_RD_ID_CNT_MASK) #define NDCR_RA_START (0x1 << 15) #define NDCR_PG_PER_BLK (0x1 << 14) #define NDCR_ND_ARB_EN (0x1 << 12) +#define NDCR_INT_MASK (0xFFF) #define NDSR_MASK (0xfff) -#define NDSR_RDY (0x1 << 11) +#define NDSR_RDY (0x1 << 12) +#define NDSR_FLASH_RDY (0x1 << 11) #define NDSR_CS0_PAGED (0x1 << 10) #define NDSR_CS1_PAGED (0x1 << 9) #define NDSR_CS0_CMDD (0x1 << 8) @@ -104,13 +107,15 @@ enum { }; enum { - STATE_READY = 0, + STATE_IDLE = 0, STATE_CMD_HANDLE, STATE_DMA_READING, STATE_DMA_WRITING, STATE_DMA_DONE, STATE_PIO_READING, STATE_PIO_WRITING, + STATE_CMD_DONE, + STATE_READY, }; struct pxa3xx_nand_info { @@ -292,7 +297,48 @@ static void pxa3xx_set_datasize(struct pxa3xx_nand_info *info) } } -static int prepare_read_prog_cmd(struct pxa3xx_nand_info *info, +/** + * NOTE: it is a must to set ND_RUN firstly, then write + * command buffer, otherwise, it does not work. + * We enable all the interrupt at the same time, and + * let pxa3xx_nand_irq to handle all logic. + */ +static void pxa3xx_nand_start(struct pxa3xx_nand_info *info) +{ + uint32_t ndcr; + + ndcr = info->reg_ndcr; + ndcr |= info->use_ecc ? NDCR_ECC_EN : 0; + ndcr |= info->use_dma ? NDCR_DMA_EN : 0; + ndcr |= NDCR_ND_RUN; + + /* clear status bits and run */ + nand_writel(info, NDCR, 0); + nand_writel(info, NDSR, NDSR_MASK); + nand_writel(info, NDCR, ndcr); +} + +static void pxa3xx_nand_stop(struct pxa3xx_nand_info *info) +{ + uint32_t ndcr; + int timeout = NAND_STOP_DELAY; + + /* wait RUN bit in NDCR become 0 */ + ndcr = nand_readl(info, NDCR); + while ((ndcr & NDCR_ND_RUN) && (timeout-- > 0)) { + ndcr = nand_readl(info, NDCR); + udelay(1); + } + + if (timeout <= 0) { + ndcr &= ~NDCR_ND_RUN; + nand_writel(info, NDCR, ndcr); + } + /* clear status bits */ + nand_writel(info, NDSR, NDSR_MASK); +} + +static void prepare_read_prog_cmd(struct pxa3xx_nand_info *info, uint16_t cmd, int column, int page_addr) { const struct pxa3xx_nand_cmdset *cmdset = info->cmdset; @@ -319,21 +365,18 @@ static int prepare_read_prog_cmd(struct pxa3xx_nand_info *info, if (cmd == cmdset->program) info->ndcb0 |= NDCB0_CMD_TYPE(1) | NDCB0_AUTO_RS; - - return 0; } -static int prepare_erase_cmd(struct pxa3xx_nand_info *info, +static void prepare_erase_cmd(struct pxa3xx_nand_info *info, uint16_t cmd, int page_addr) { info->ndcb0 = cmd | ((cmd & 0xff00) ? NDCB0_DBC : 0); info->ndcb0 |= NDCB0_CMD_TYPE(2) | NDCB0_AUTO_RS | NDCB0_ADDR_CYC(3); info->ndcb1 = page_addr; info->ndcb2 = 0; - return 0; } -static int prepare_other_cmd(struct pxa3xx_nand_info *info, uint16_t cmd) +static void prepare_other_cmd(struct pxa3xx_nand_info *info, uint16_t cmd) { const struct pxa3xx_nand_cmdset *cmdset = info->cmdset; @@ -343,7 +386,7 @@ static int prepare_other_cmd(struct pxa3xx_nand_info *info, uint16_t cmd) info->oob_size = 0; if (cmd == cmdset->read_id) { - info->ndcb0 |= NDCB0_CMD_TYPE(3); + info->ndcb0 |= NDCB0_CMD_TYPE(3) | NDCB0_ADDR_CYC(1); info->data_size = 8; } else if (cmd == cmdset->read_status) { info->ndcb0 |= NDCB0_CMD_TYPE(4); @@ -352,9 +395,7 @@ static int prepare_other_cmd(struct pxa3xx_nand_info *info, uint16_t cmd) cmd == cmdset->unlock) { info->ndcb0 |= NDCB0_CMD_TYPE(5); } else - return -EINVAL; - - return 0; + BUG(); } static void enable_int(struct pxa3xx_nand_info *info, uint32_t int_mask) @@ -402,10 +443,8 @@ static int write_cmd(struct pxa3xx_nand_info *info) return 0; } -static int handle_data_pio(struct pxa3xx_nand_info *info) +static void handle_data_pio(struct pxa3xx_nand_info *info) { - int ret, timeout = CHIP_DELAY_TIMEOUT; - switch (info->state) { case STATE_PIO_WRITING: __raw_writesl(info->mmio_base + NDDB, info->data_buff, @@ -413,14 +452,6 @@ static int handle_data_pio(struct pxa3xx_nand_info *info) if (info->oob_size > 0) __raw_writesl(info->mmio_base + NDDB, info->oob_buff, DIV_ROUND_UP(info->oob_size, 4)); - - enable_int(info, NDSR_CS0_BBD | NDSR_CS0_CMDD); - - ret = wait_for_completion_timeout(&info->cmd_complete, timeout); - if (!ret) { - printk(KERN_ERR "program command time out\n"); - return -1; - } break; case STATE_PIO_READING: __raw_readsl(info->mmio_base + NDDB, info->data_buff, @@ -432,14 +463,11 @@ static int handle_data_pio(struct pxa3xx_nand_info *info) default: printk(KERN_ERR "%s: invalid state %d\n", __func__, info->state); - return -EINVAL; + BUG(); } - - info->state = STATE_READY; - return 0; } -static void start_data_dma(struct pxa3xx_nand_info *info, int dir_out) +static void start_data_dma(struct pxa3xx_nand_info *info) { struct pxa_dma_desc *desc = info->data_desc; int dma_len = ALIGN(info->data_size + info->oob_size, 32); @@ -447,14 +475,21 @@ static void start_data_dma(struct pxa3xx_nand_info *info, int dir_out) desc->ddadr = DDADR_STOP; desc->dcmd = DCMD_ENDIRQEN | DCMD_WIDTH4 | DCMD_BURST32 | dma_len; - if (dir_out) { + switch (info->state) { + case STATE_DMA_WRITING: desc->dsadr = info->data_buff_phys; desc->dtadr = info->mmio_phys + NDDB; desc->dcmd |= DCMD_INCSRCADDR | DCMD_FLOWTRG; - } else { + break; + case STATE_DMA_READING: desc->dtadr = info->data_buff_phys; desc->dsadr = info->mmio_phys + NDDB; desc->dcmd |= DCMD_INCTRGADDR | DCMD_FLOWSRC; + break; + default: + printk(KERN_ERR "%s: invalid state %d\n", __func__, + info->state); + BUG(); } DRCMR(info->drcmr_dat) = DRCMR_MAPVLD | info->data_dma_ch; @@ -472,93 +507,60 @@ static void pxa3xx_nand_data_dma_irq(int channel, void *data) if (dcsr & DCSR_BUSERR) { info->retcode = ERR_DMABUSERR; - complete(&info->cmd_complete); } - if (info->state == STATE_DMA_WRITING) { - info->state = STATE_DMA_DONE; - enable_int(info, NDSR_CS0_BBD | NDSR_CS0_CMDD); - } else { - info->state = STATE_READY; - complete(&info->cmd_complete); - } + info->state = STATE_DMA_DONE; + enable_int(info, NDCR_INT_MASK); + nand_writel(info, NDSR, NDSR_WRDREQ | NDSR_RDDREQ); } static irqreturn_t pxa3xx_nand_irq(int irq, void *devid) { struct pxa3xx_nand_info *info = devid; - unsigned int status; + unsigned int status, is_completed = 0; status = nand_readl(info, NDSR); - if (status & (NDSR_RDDREQ | NDSR_DBERR | NDSR_SBERR)) { - if (status & NDSR_DBERR) - info->retcode = ERR_DBERR; - else if (status & NDSR_SBERR) - info->retcode = ERR_SBERR; - - disable_int(info, NDSR_RDDREQ | NDSR_DBERR | NDSR_SBERR); - - if (info->use_dma) { - info->state = STATE_DMA_READING; - start_data_dma(info, 0); - } else { - info->state = STATE_PIO_READING; - complete(&info->cmd_complete); - } - } else if (status & NDSR_WRDREQ) { - disable_int(info, NDSR_WRDREQ); + if (status & NDSR_DBERR) + info->retcode = ERR_DBERR; + if (status & NDSR_SBERR) + info->retcode = ERR_SBERR; + if (status & (NDSR_RDDREQ | NDSR_WRDREQ)) { + /* whether use dma to transfer data */ if (info->use_dma) { - info->state = STATE_DMA_WRITING; - start_data_dma(info, 1); + disable_int(info, NDCR_INT_MASK); + info->state = (status & NDSR_RDDREQ) ? + STATE_DMA_READING : STATE_DMA_WRITING; + start_data_dma(info); + goto NORMAL_IRQ_EXIT; } else { - info->state = STATE_PIO_WRITING; - complete(&info->cmd_complete); + info->state = (status & NDSR_RDDREQ) ? + STATE_PIO_READING : STATE_PIO_WRITING; + handle_data_pio(info); } - } else if (status & (NDSR_CS0_BBD | NDSR_CS0_CMDD)) { - if (status & NDSR_CS0_BBD) - info->retcode = ERR_BBERR; - - disable_int(info, NDSR_CS0_BBD | NDSR_CS0_CMDD); - info->state = STATE_READY; - complete(&info->cmd_complete); } - nand_writel(info, NDSR, status); - return IRQ_HANDLED; -} - -static int pxa3xx_nand_do_cmd(struct pxa3xx_nand_info *info, uint32_t event) -{ - uint32_t ndcr; - int ret, timeout = CHIP_DELAY_TIMEOUT; - - if (write_cmd(info)) { - info->retcode = ERR_SENDCMD; - goto fail_stop; + if (status & NDSR_CS0_CMDD) { + info->state = STATE_CMD_DONE; + is_completed = 1; } + if (status & NDSR_FLASH_RDY) + info->state = STATE_READY; - info->state = STATE_CMD_HANDLE; - - enable_int(info, event); - - ret = wait_for_completion_timeout(&info->cmd_complete, timeout); - if (!ret) { - printk(KERN_ERR "command execution timed out\n"); - info->retcode = ERR_SENDCMD; - goto fail_stop; + if (status & NDSR_WRCMDREQ) { + nand_writel(info, NDSR, NDSR_WRCMDREQ); + status &= ~NDSR_WRCMDREQ; + info->state = STATE_CMD_HANDLE; + nand_writel(info, NDCB0, info->ndcb0); + nand_writel(info, NDCB0, info->ndcb1); + nand_writel(info, NDCB0, info->ndcb2); } - if (info->use_dma == 0 && info->data_size > 0) - if (handle_data_pio(info)) - goto fail_stop; - - return 0; - -fail_stop: - ndcr = nand_readl(info, NDCR); - nand_writel(info, NDCR, ndcr & ~NDCR_ND_RUN); - udelay(10); - return -ETIMEDOUT; + /* clear NDSR to let the controller exit the IRQ */ + nand_writel(info, NDSR, status); + if (is_completed) + complete(&info->cmd_complete); +NORMAL_IRQ_EXIT: + return IRQ_HANDLED; } static int pxa3xx_nand_dev_ready(struct mtd_info *mtd) @@ -580,14 +582,13 @@ static void pxa3xx_nand_cmdfunc(struct mtd_info *mtd, unsigned command, { struct pxa3xx_nand_info *info = mtd->priv; const struct pxa3xx_nand_cmdset *cmdset = info->cmdset; - int ret; + int ret, exec_cmd = 0; info->use_dma = (use_dma) ? 1 : 0; info->use_ecc = 0; info->data_size = 0; - info->state = STATE_READY; - - init_completion(&info->cmd_complete); + info->state = 0; + info->retcode = ERR_NONE; switch (command) { case NAND_CMD_READOOB: @@ -596,36 +597,18 @@ static void pxa3xx_nand_cmdfunc(struct mtd_info *mtd, unsigned command, info->buf_start = mtd->writesize + column; memset(info->data_buff, 0xFF, info->buf_count); - if (prepare_read_prog_cmd(info, cmdset->read1, column, page_addr)) - break; - - pxa3xx_nand_do_cmd(info, NDSR_RDDREQ | NDSR_DBERR | NDSR_SBERR); - - /* We only are OOB, so if the data has error, does not matter */ - if (info->retcode == ERR_DBERR) - info->retcode = ERR_NONE; + prepare_read_prog_cmd(info, cmdset->read1, column, page_addr); + exec_cmd = 1; break; case NAND_CMD_READ0: info->use_ecc = 1; - info->retcode = ERR_NONE; info->buf_start = column; info->buf_count = mtd->writesize + mtd->oobsize; memset(info->data_buff, 0xFF, info->buf_count); - if (prepare_read_prog_cmd(info, cmdset->read1, column, page_addr)) - break; - - pxa3xx_nand_do_cmd(info, NDSR_RDDREQ | NDSR_DBERR | NDSR_SBERR); - - if (info->retcode == ERR_DBERR) { - /* for blank page (all 0xff), HW will calculate its ECC as - * 0, which is different from the ECC information within - * OOB, ignore such double bit errors - */ - if (is_buf_blank(info->data_buff, mtd->writesize)) - info->retcode = ERR_NONE; - } + prepare_read_prog_cmd(info, cmdset->read1, column, page_addr); + exec_cmd = 1; break; case NAND_CMD_SEQIN: info->buf_start = column; @@ -639,17 +622,13 @@ static void pxa3xx_nand_cmdfunc(struct mtd_info *mtd, unsigned command, case NAND_CMD_PAGEPROG: info->use_ecc = (info->seqin_column >= mtd->writesize) ? 0 : 1; - if (prepare_read_prog_cmd(info, cmdset->program, - info->seqin_column, info->seqin_page_addr)) - break; - - pxa3xx_nand_do_cmd(info, NDSR_WRDREQ); + prepare_read_prog_cmd(info, cmdset->program, + info->seqin_column, info->seqin_page_addr); + exec_cmd = 1; break; case NAND_CMD_ERASE1: - if (prepare_erase_cmd(info, cmdset->erase, page_addr)) - break; - - pxa3xx_nand_do_cmd(info, NDSR_CS0_BBD | NDSR_CS0_CMDD); + prepare_erase_cmd(info, cmdset->erase, page_addr); + exec_cmd = 1; break; case NAND_CMD_ERASE2: break; @@ -660,40 +639,69 @@ static void pxa3xx_nand_cmdfunc(struct mtd_info *mtd, unsigned command, info->buf_count = (command == NAND_CMD_READID) ? info->read_id_bytes : 1; - if (prepare_other_cmd(info, (command == NAND_CMD_READID) ? - cmdset->read_id : cmdset->read_status)) - break; - - pxa3xx_nand_do_cmd(info, NDSR_RDDREQ); + prepare_other_cmd(info, (command == NAND_CMD_READID) ? + cmdset->read_id : cmdset->read_status); + exec_cmd = 1; break; case NAND_CMD_RESET: - if (prepare_other_cmd(info, cmdset->reset)) - break; - - ret = pxa3xx_nand_do_cmd(info, NDSR_CS0_CMDD); - if (ret == 0) { - int timeout = 2; - uint32_t ndcr; - - while (timeout--) { - if (nand_readl(info, NDSR) & NDSR_RDY) - break; - msleep(10); - } - - ndcr = nand_readl(info, NDCR); - nand_writel(info, NDCR, ndcr & ~NDCR_ND_RUN); - } + prepare_other_cmd(info, cmdset->reset); + exec_cmd = 1; break; default: printk(KERN_ERR "non-supported command.\n"); break; } - if (info->retcode == ERR_DBERR) { - printk(KERN_ERR "double bit error @ page %08x\n", page_addr); - info->retcode = ERR_NONE; + if (exec_cmd) { + init_completion(&info->cmd_complete); + pxa3xx_nand_start(info); + + ret = wait_for_completion_timeout(&info->cmd_complete, + CHIP_DELAY_TIMEOUT); + if (!ret) { + printk(KERN_ERR "Wait time out!!!\n"); + /* Stop State Machine for next command cycle */ + pxa3xx_nand_stop(info); + } + info->state = STATE_IDLE; + } +} + +static void pxa3xx_nand_write_page_hwecc(struct mtd_info *mtd, + struct nand_chip *chip, const uint8_t *buf) +{ + chip->write_buf(mtd, buf, mtd->writesize); + chip->write_buf(mtd, chip->oob_poi, mtd->oobsize); +} + +static int pxa3xx_nand_read_page_hwecc(struct mtd_info *mtd, + struct nand_chip *chip, uint8_t *buf, int page) +{ + struct pxa3xx_nand_info *info = mtd->priv; + + chip->read_buf(mtd, buf, mtd->writesize); + chip->read_buf(mtd, chip->oob_poi, mtd->oobsize); + + if (info->retcode == ERR_SBERR) { + switch (info->use_ecc) { + case 1: + mtd->ecc_stats.corrected++; + break; + case 0: + default: + break; + } + } else if (info->retcode == ERR_DBERR) { + /* + * for blank page (all 0xff), HW will calculate its ECC as + * 0, which is different from the ECC information within + * OOB, ignore such double bit errors + */ + if (is_buf_blank(buf, mtd->writesize)) + mtd->ecc_stats.failed++; } + + return 0; } static uint8_t pxa3xx_nand_read_byte(struct mtd_info *mtd) @@ -770,47 +778,13 @@ static int pxa3xx_nand_waitfunc(struct mtd_info *mtd, struct nand_chip *this) return 0; } -static void pxa3xx_nand_ecc_hwctl(struct mtd_info *mtd, int mode) -{ - return; -} - -static int pxa3xx_nand_ecc_calculate(struct mtd_info *mtd, - const uint8_t *dat, uint8_t *ecc_code) -{ - return 0; -} - -static int pxa3xx_nand_ecc_correct(struct mtd_info *mtd, - uint8_t *dat, uint8_t *read_ecc, uint8_t *calc_ecc) -{ - struct pxa3xx_nand_info *info = mtd->priv; - /* - * Any error include ERR_SEND_CMD, ERR_DBERR, ERR_BUSERR, we - * consider it as a ecc error which will tell the caller the - * read fail We have distinguish all the errors, but the - * nand_read_ecc only check this function return value - * - * Corrected (single-bit) errors must also be noted. - */ - if (info->retcode == ERR_SBERR) - return 1; - else if (info->retcode != ERR_NONE) - return -1; - - return 0; -} - static int __readid(struct pxa3xx_nand_info *info, uint32_t *id) { const struct pxa3xx_nand_cmdset *cmdset = info->cmdset; uint32_t ndcr; uint8_t id_buff[8]; - if (prepare_other_cmd(info, cmdset->read_id)) { - printk(KERN_ERR "failed to prepare command\n"); - return -EINVAL; - } + prepare_other_cmd(info, cmdset->read_id); /* Send command */ if (write_cmd(info)) @@ -836,7 +810,7 @@ static int pxa3xx_nand_config_flash(struct pxa3xx_nand_info *info, { struct platform_device *pdev = info->pdev; struct pxa3xx_nand_platform_data *pdata = pdev->dev.platform_data; - uint32_t ndcr = 0x00000FFF; /* disable all interrupts */ + uint32_t ndcr = 0x0; /* enable all interrupts */ if (f->page_size != 2048 && f->page_size != 512) return -EINVAL; @@ -888,11 +862,12 @@ static int pxa3xx_nand_detect_config(struct pxa3xx_nand_info *info) info->reg_ndcr = ndcr; info->cmdset = &default_cmdset; - if (__readid(info, &id)) + pxa3xx_nand_cmdfunc(info->mtd, NAND_CMD_READID, 0, 0); + id = *((uint16_t *)(info->data_buff)); + if (id == 0) return -ENODEV; /* Lookup the flash id */ - id = (id >> 8) & 0xff; /* device id is byte 2 */ for (i = 0; nand_flash_ids[i].name != NULL; i++) { if (id == nand_flash_ids[i].id) { type = &nand_flash_ids[i]; @@ -935,8 +910,8 @@ static int pxa3xx_nand_detect_flash(struct pxa3xx_nand_info *info, /* we use default timing to detect id */ f = DEFAULT_FLASH_TYPE; pxa3xx_nand_config_flash(info, f); - if (__readid(info, &id)) - goto fail_detect; + pxa3xx_nand_cmdfunc(info->mtd, NAND_CMD_READID, 0, 0); + id = *((uint16_t *)(info->data_buff)); for (i=0; inum_flash - 1; i++) { /* we first choose the flash definition from platfrom */ @@ -954,7 +929,6 @@ static int pxa3xx_nand_detect_flash(struct pxa3xx_nand_info *info, dev_warn(&info->pdev->dev, "failed to detect configured nand flash; found %04x instead of\n", id); -fail_detect: return -ENODEV; } @@ -1025,6 +999,8 @@ static void pxa3xx_nand_init_mtd(struct mtd_info *mtd, this->select_chip = pxa3xx_nand_select_chip; this->dev_ready = pxa3xx_nand_dev_ready; this->cmdfunc = pxa3xx_nand_cmdfunc; + this->ecc.read_page = pxa3xx_nand_read_page_hwecc; + this->ecc.write_page = pxa3xx_nand_write_page_hwecc; this->read_word = pxa3xx_nand_read_word; this->read_byte = pxa3xx_nand_read_byte; this->read_buf = pxa3xx_nand_read_buf; @@ -1032,9 +1008,6 @@ static void pxa3xx_nand_init_mtd(struct mtd_info *mtd, this->verify_buf = pxa3xx_nand_verify_buf; this->ecc.mode = NAND_ECC_HW; - this->ecc.hwctl = pxa3xx_nand_ecc_hwctl; - this->ecc.calculate = pxa3xx_nand_ecc_calculate; - this->ecc.correct = pxa3xx_nand_ecc_correct; this->ecc.size = info->page_size; if (info->page_size == 2048) @@ -1177,10 +1150,6 @@ static int pxa3xx_nand_remove(struct platform_device *pdev) platform_set_drvdata(pdev, NULL); - del_mtd_device(mtd); -#ifdef CONFIG_MTD_PARTITIONS - del_mtd_partitions(mtd); -#endif irq = platform_get_irq(pdev, 0); if (irq >= 0) free_irq(irq, info); @@ -1198,7 +1167,13 @@ static int pxa3xx_nand_remove(struct platform_device *pdev) clk_disable(info->clk); clk_put(info->clk); - kfree(mtd); + if (mtd) { + del_mtd_device(mtd); +#ifdef CONFIG_MTD_PARTITIONS + del_mtd_partitions(mtd); +#endif + kfree(mtd); + } return 0; } @@ -1232,10 +1207,10 @@ static int pxa3xx_nand_probe(struct platform_device *pdev) nr_parts = parse_mtd_partitions(info->mtd, probes, &parts, 0); if (nr_parts) - return add_mtd_partitions(mtd, parts, nr_parts); + return add_mtd_partitions(info->mtd, parts, nr_parts); } - return add_mtd_partitions(mtd, pdata->parts, pdata->nr_parts); + return add_mtd_partitions(info->mtd, pdata->parts, pdata->nr_parts); #else return 0; #endif @@ -1247,7 +1222,7 @@ static int pxa3xx_nand_suspend(struct platform_device *pdev, pm_message_t state) struct pxa3xx_nand_info *info = platform_get_drvdata(pdev); struct mtd_info *mtd = info->mtd; - if (info->state != STATE_READY) { + if (info->state) { dev_err(&pdev->dev, "driver busy, state = %d\n", info->state); return -EAGAIN; } -- GitLab From 38caf7f68e6b4ad84094095887a490e3fa2ec501 Mon Sep 17 00:00:00 2001 From: Lei Wen Date: Mon, 28 Feb 2011 10:32:12 +0800 Subject: [PATCH 0598/2822] mtd: pxa3xx_nand: discard wait_for_event,write_cmd,__readid function Since we have rework the irq process, we don't need additional delay in wait_for_event. Also write_cmd and __readid is also discarded for the same reason. Signed-off-by: Lei Wen Signed-off-by: Haojian Zhuang Acked-by: Eric Miao Signed-off-by: David Woodhouse --- drivers/mtd/nand/pxa3xx_nand.c | 77 +--------------------------------- 1 file changed, 1 insertion(+), 76 deletions(-) diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c index 3264b1d5a638f..be0aa44ada427 100644 --- a/drivers/mtd/nand/pxa3xx_nand.c +++ b/drivers/mtd/nand/pxa3xx_nand.c @@ -258,25 +258,6 @@ static void pxa3xx_nand_set_timing(struct pxa3xx_nand_info *info, nand_writel(info, NDTR1CS0, ndtr1); } -#define WAIT_EVENT_TIMEOUT 10 - -static int wait_for_event(struct pxa3xx_nand_info *info, uint32_t event) -{ - int timeout = WAIT_EVENT_TIMEOUT; - uint32_t ndsr; - - while (timeout--) { - ndsr = nand_readl(info, NDSR) & NDSR_MASK; - if (ndsr & event) { - nand_writel(info, NDSR, ndsr); - return 0; - } - udelay(10); - } - - return -ETIMEDOUT; -} - static void pxa3xx_set_datasize(struct pxa3xx_nand_info *info) { int oob_enable = info->reg_ndcr & NDCR_SPARE_EN; @@ -414,35 +395,6 @@ static void disable_int(struct pxa3xx_nand_info *info, uint32_t int_mask) nand_writel(info, NDCR, ndcr | int_mask); } -/* NOTE: it is a must to set ND_RUN firstly, then write command buffer - * otherwise, it does not work - */ -static int write_cmd(struct pxa3xx_nand_info *info) -{ - uint32_t ndcr; - - /* clear status bits and run */ - nand_writel(info, NDSR, NDSR_MASK); - - ndcr = info->reg_ndcr; - - ndcr |= info->use_ecc ? NDCR_ECC_EN : 0; - ndcr |= info->use_dma ? NDCR_DMA_EN : 0; - ndcr |= NDCR_ND_RUN; - - nand_writel(info, NDCR, ndcr); - - if (wait_for_event(info, NDSR_WRCMDREQ)) { - printk(KERN_ERR "timed out writing command\n"); - return -ETIMEDOUT; - } - - nand_writel(info, NDCB0, info->ndcb0); - nand_writel(info, NDCB0, info->ndcb1); - nand_writel(info, NDCB0, info->ndcb2); - return 0; -} - static void handle_data_pio(struct pxa3xx_nand_info *info) { switch (info->state) { @@ -778,33 +730,6 @@ static int pxa3xx_nand_waitfunc(struct mtd_info *mtd, struct nand_chip *this) return 0; } -static int __readid(struct pxa3xx_nand_info *info, uint32_t *id) -{ - const struct pxa3xx_nand_cmdset *cmdset = info->cmdset; - uint32_t ndcr; - uint8_t id_buff[8]; - - prepare_other_cmd(info, cmdset->read_id); - - /* Send command */ - if (write_cmd(info)) - goto fail_timeout; - - /* Wait for CMDDM(command done successfully) */ - if (wait_for_event(info, NDSR_RDDREQ)) - goto fail_timeout; - - __raw_readsl(info->mmio_base + NDDB, id_buff, 2); - *id = id_buff[0] | (id_buff[1] << 8); - return 0; - -fail_timeout: - ndcr = nand_readl(info, NDCR); - nand_writel(info, NDCR, ndcr & ~NDCR_ND_RUN); - udelay(10); - return -ETIMEDOUT; -} - static int pxa3xx_nand_config_flash(struct pxa3xx_nand_info *info, const struct pxa3xx_nand_flash *f) { @@ -857,7 +782,7 @@ static int pxa3xx_nand_detect_config(struct pxa3xx_nand_info *info) page_per_block = ndcr & NDCR_PG_PER_BLK ? 64 : 32; info->page_size = ndcr & NDCR_PAGE_SZ ? 2048 : 512; - /* set info fields needed to __readid */ + /* set info fields needed to read id */ info->read_id_bytes = (info->page_size == 2048) ? 4 : 2; info->reg_ndcr = ndcr; info->cmdset = &default_cmdset; -- GitLab From 4eb2da8994042d68e84e31138788429a102da2ea Mon Sep 17 00:00:00 2001 From: Lei Wen Date: Mon, 28 Feb 2011 10:32:13 +0800 Subject: [PATCH 0599/2822] mtd: pxa3xx_nand: unify prepare command Make the interface simpler which could make both debug and enhancement easier. Signed-off-by: Lei Wen Signed-off-by: Haojian Zhuang Signed-off-by: David Woodhouse --- drivers/mtd/nand/pxa3xx_nand.c | 249 ++++++++++++++++++--------------- 1 file changed, 139 insertions(+), 110 deletions(-) diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c index be0aa44ada427..de0a2a25eb016 100644 --- a/drivers/mtd/nand/pxa3xx_nand.c +++ b/drivers/mtd/nand/pxa3xx_nand.c @@ -28,6 +28,7 @@ #define CHIP_DELAY_TIMEOUT (2 * HZ/10) #define NAND_STOP_DELAY (2 * HZ/50) +#define PAGE_CHUNK_SIZE (2048) /* registers and bit definitions */ #define NDCR (0x00) /* Control register */ @@ -77,6 +78,7 @@ #define NDSR_RDDREQ (0x1 << 1) #define NDSR_WRCMDREQ (0x1) +#define NDCB0_ST_ROW_EN (0x1 << 26) #define NDCB0_AUTO_RS (0x1 << 25) #define NDCB0_CSEL (0x1 << 24) #define NDCB0_CMD_TYPE_MASK (0x7 << 21) @@ -319,66 +321,6 @@ static void pxa3xx_nand_stop(struct pxa3xx_nand_info *info) nand_writel(info, NDSR, NDSR_MASK); } -static void prepare_read_prog_cmd(struct pxa3xx_nand_info *info, - uint16_t cmd, int column, int page_addr) -{ - const struct pxa3xx_nand_cmdset *cmdset = info->cmdset; - pxa3xx_set_datasize(info); - - /* generate values for NDCBx registers */ - info->ndcb0 = cmd | ((cmd & 0xff00) ? NDCB0_DBC : 0); - info->ndcb1 = 0; - info->ndcb2 = 0; - info->ndcb0 |= NDCB0_ADDR_CYC(info->row_addr_cycles + info->col_addr_cycles); - - if (info->col_addr_cycles == 2) { - /* large block, 2 cycles for column address - * row address starts from 3rd cycle - */ - info->ndcb1 |= page_addr << 16; - if (info->row_addr_cycles == 3) - info->ndcb2 = (page_addr >> 16) & 0xff; - } else - /* small block, 1 cycles for column address - * row address starts from 2nd cycle - */ - info->ndcb1 = page_addr << 8; - - if (cmd == cmdset->program) - info->ndcb0 |= NDCB0_CMD_TYPE(1) | NDCB0_AUTO_RS; -} - -static void prepare_erase_cmd(struct pxa3xx_nand_info *info, - uint16_t cmd, int page_addr) -{ - info->ndcb0 = cmd | ((cmd & 0xff00) ? NDCB0_DBC : 0); - info->ndcb0 |= NDCB0_CMD_TYPE(2) | NDCB0_AUTO_RS | NDCB0_ADDR_CYC(3); - info->ndcb1 = page_addr; - info->ndcb2 = 0; -} - -static void prepare_other_cmd(struct pxa3xx_nand_info *info, uint16_t cmd) -{ - const struct pxa3xx_nand_cmdset *cmdset = info->cmdset; - - info->ndcb0 = cmd | ((cmd & 0xff00) ? NDCB0_DBC : 0); - info->ndcb1 = 0; - info->ndcb2 = 0; - - info->oob_size = 0; - if (cmd == cmdset->read_id) { - info->ndcb0 |= NDCB0_CMD_TYPE(3) | NDCB0_ADDR_CYC(1); - info->data_size = 8; - } else if (cmd == cmdset->read_status) { - info->ndcb0 |= NDCB0_CMD_TYPE(4); - info->data_size = 8; - } else if (cmd == cmdset->reset || cmd == cmdset->lock || - cmd == cmdset->unlock) { - info->ndcb0 |= NDCB0_CMD_TYPE(5); - } else - BUG(); -} - static void enable_int(struct pxa3xx_nand_info *info, uint32_t int_mask) { uint32_t ndcr; @@ -529,81 +471,167 @@ static inline int is_buf_blank(uint8_t *buf, size_t len) return 1; } -static void pxa3xx_nand_cmdfunc(struct mtd_info *mtd, unsigned command, - int column, int page_addr) +static int prepare_command_pool(struct pxa3xx_nand_info *info, int command, + uint16_t column, int page_addr) { - struct pxa3xx_nand_info *info = mtd->priv; - const struct pxa3xx_nand_cmdset *cmdset = info->cmdset; - int ret, exec_cmd = 0; + uint16_t cmd; + int addr_cycle, exec_cmd, ndcb0; + struct mtd_info *mtd = info->mtd; + + ndcb0 = 0; + addr_cycle = 0; + exec_cmd = 1; - info->use_dma = (use_dma) ? 1 : 0; - info->use_ecc = 0; - info->data_size = 0; - info->state = 0; - info->retcode = ERR_NONE; + /* reset data and oob column point to handle data */ + info->buf_start = 0; + info->buf_count = 0; + info->oob_size = 0; + info->use_ecc = 0; + info->retcode = ERR_NONE; switch (command) { + case NAND_CMD_READ0: + case NAND_CMD_PAGEPROG: + info->use_ecc = 1; case NAND_CMD_READOOB: - /* disable HW ECC to get all the OOB data */ - info->buf_count = mtd->writesize + mtd->oobsize; - info->buf_start = mtd->writesize + column; - memset(info->data_buff, 0xFF, info->buf_count); - - prepare_read_prog_cmd(info, cmdset->read1, column, page_addr); - exec_cmd = 1; + pxa3xx_set_datasize(info); + break; + case NAND_CMD_SEQIN: + exec_cmd = 0; + break; + default: + info->ndcb1 = 0; + info->ndcb2 = 0; break; + } + + info->ndcb0 = ndcb0; + addr_cycle = NDCB0_ADDR_CYC(info->row_addr_cycles + + info->col_addr_cycles); + switch (command) { + case NAND_CMD_READOOB: case NAND_CMD_READ0: - info->use_ecc = 1; - info->buf_start = column; - info->buf_count = mtd->writesize + mtd->oobsize; - memset(info->data_buff, 0xFF, info->buf_count); + cmd = info->cmdset->read1; + if (command == NAND_CMD_READOOB) + info->buf_start = mtd->writesize + column; + else + info->buf_start = column; + + if (unlikely(info->page_size < PAGE_CHUNK_SIZE)) + info->ndcb0 |= NDCB0_CMD_TYPE(0) + | addr_cycle + | (cmd & NDCB0_CMD1_MASK); + else + info->ndcb0 |= NDCB0_CMD_TYPE(0) + | NDCB0_DBC + | addr_cycle + | cmd; - prepare_read_prog_cmd(info, cmdset->read1, column, page_addr); - exec_cmd = 1; - break; case NAND_CMD_SEQIN: - info->buf_start = column; + /* small page addr setting */ + if (unlikely(info->page_size < PAGE_CHUNK_SIZE)) { + info->ndcb1 = ((page_addr & 0xFFFFFF) << 8) + | (column & 0xFF); + + info->ndcb2 = 0; + } else { + info->ndcb1 = ((page_addr & 0xFFFF) << 16) + | (column & 0xFFFF); + + if (page_addr & 0xFF0000) + info->ndcb2 = (page_addr & 0xFF0000) >> 16; + else + info->ndcb2 = 0; + } + info->buf_count = mtd->writesize + mtd->oobsize; - memset(info->data_buff, 0xff, info->buf_count); + memset(info->data_buff, 0xFF, info->buf_count); - /* save column/page_addr for next CMD_PAGEPROG */ - info->seqin_column = column; - info->seqin_page_addr = page_addr; break; + case NAND_CMD_PAGEPROG: - info->use_ecc = (info->seqin_column >= mtd->writesize) ? 0 : 1; + if (is_buf_blank(info->data_buff, + (mtd->writesize + mtd->oobsize))) { + exec_cmd = 0; + break; + } - prepare_read_prog_cmd(info, cmdset->program, - info->seqin_column, info->seqin_page_addr); - exec_cmd = 1; - break; - case NAND_CMD_ERASE1: - prepare_erase_cmd(info, cmdset->erase, page_addr); - exec_cmd = 1; - break; - case NAND_CMD_ERASE2: + cmd = info->cmdset->program; + info->ndcb0 |= NDCB0_CMD_TYPE(0x1) + | NDCB0_AUTO_RS + | NDCB0_ST_ROW_EN + | NDCB0_DBC + | cmd + | addr_cycle; break; + case NAND_CMD_READID: + cmd = info->cmdset->read_id; + info->buf_count = info->read_id_bytes; + info->ndcb0 |= NDCB0_CMD_TYPE(3) + | NDCB0_ADDR_CYC(1) + | cmd; + + info->data_size = 8; + break; case NAND_CMD_STATUS: - info->use_dma = 0; /* force PIO read */ - info->buf_start = 0; - info->buf_count = (command == NAND_CMD_READID) ? - info->read_id_bytes : 1; - - prepare_other_cmd(info, (command == NAND_CMD_READID) ? - cmdset->read_id : cmdset->read_status); - exec_cmd = 1; + cmd = info->cmdset->read_status; + info->buf_count = 1; + info->ndcb0 |= NDCB0_CMD_TYPE(4) + | NDCB0_ADDR_CYC(1) + | cmd; + + info->data_size = 8; + break; + + case NAND_CMD_ERASE1: + cmd = info->cmdset->erase; + info->ndcb0 |= NDCB0_CMD_TYPE(2) + | NDCB0_AUTO_RS + | NDCB0_ADDR_CYC(3) + | NDCB0_DBC + | cmd; + info->ndcb1 = page_addr; + info->ndcb2 = 0; + break; case NAND_CMD_RESET: - prepare_other_cmd(info, cmdset->reset); - exec_cmd = 1; + cmd = info->cmdset->reset; + info->ndcb0 |= NDCB0_CMD_TYPE(5) + | cmd; + + break; + + case NAND_CMD_ERASE2: + exec_cmd = 0; break; + default: - printk(KERN_ERR "non-supported command.\n"); + exec_cmd = 0; + printk(KERN_ERR "pxa3xx-nand: non-supported" + " command %x\n", command); break; } + return exec_cmd; +} + +static void pxa3xx_nand_cmdfunc(struct mtd_info *mtd, unsigned command, + int column, int page_addr) +{ + struct pxa3xx_nand_info *info = mtd->priv; + int ret, exec_cmd; + + /* + * if this is a x16 device ,then convert the input + * "byte" address into a "word" address appropriate + * for indexing a word-oriented device + */ + if (info->reg_ndcr & NDCR_DWIDTH_M) + column /= 2; + + exec_cmd = prepare_command_pool(info, command, column, page_addr); if (exec_cmd) { init_completion(&info->cmd_complete); pxa3xx_nand_start(info); @@ -919,6 +947,7 @@ static void pxa3xx_nand_init_mtd(struct mtd_info *mtd, struct nand_chip *this = &info->nand_chip; this->options = (info->reg_ndcr & NDCR_DWIDTH_C) ? NAND_BUSWIDTH_16: 0; + this->options |= NAND_NO_AUTOINCR; this->waitfunc = pxa3xx_nand_waitfunc; this->select_chip = pxa3xx_nand_select_chip; -- GitLab From 401e67e225f350757e11e39392dcc6a0fddcea63 Mon Sep 17 00:00:00 2001 From: Lei Wen Date: Mon, 28 Feb 2011 10:32:14 +0800 Subject: [PATCH 0600/2822] mtd: pxa3xx_nand: mtd scan id process could be defined by driver itself Different NAND driver may require its unique detection. For pxa3xx_nand, it use its self id database to get the necessary info. Signed-off-by: Lei Wen Signed-off-by: Haojian Zhuang Signed-off-by: David Woodhouse --- drivers/mtd/nand/pxa3xx_nand.c | 216 +++++++++++++++++++-------------- 1 file changed, 123 insertions(+), 93 deletions(-) diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c index de0a2a25eb016..bb50cf2b11c4d 100644 --- a/drivers/mtd/nand/pxa3xx_nand.c +++ b/drivers/mtd/nand/pxa3xx_nand.c @@ -123,6 +123,7 @@ enum { struct pxa3xx_nand_info { struct nand_chip nand_chip; + struct nand_hw_control controller; struct platform_device *pdev; struct pxa3xx_nand_cmdset *cmdset; @@ -157,6 +158,7 @@ struct pxa3xx_nand_info { int use_ecc; /* use HW ECC ? */ int use_dma; /* use DMA ? */ + int is_ready; unsigned int page_size; /* page size of attached chip */ unsigned int data_size; /* data size in FIFO */ @@ -223,6 +225,8 @@ static struct pxa3xx_nand_flash builtin_flash_types[] = { /* Define a default flash type setting serve as flash detecting only */ #define DEFAULT_FLASH_TYPE (&builtin_flash_types[0]) +const char *mtd_names[] = {"pxa3xx_nand-0", NULL}; + #define NDTR0_tCH(c) (min((c), 7) << 19) #define NDTR0_tCS(c) (min((c), 7) << 16) #define NDTR0_tWH(c) (min((c), 7) << 11) @@ -437,8 +441,10 @@ static irqreturn_t pxa3xx_nand_irq(int irq, void *devid) info->state = STATE_CMD_DONE; is_completed = 1; } - if (status & NDSR_FLASH_RDY) + if (status & NDSR_FLASH_RDY) { + info->is_ready = 1; info->state = STATE_READY; + } if (status & NDSR_WRCMDREQ) { nand_writel(info, NDSR, NDSR_WRCMDREQ); @@ -483,10 +489,11 @@ static int prepare_command_pool(struct pxa3xx_nand_info *info, int command, exec_cmd = 1; /* reset data and oob column point to handle data */ - info->buf_start = 0; - info->buf_count = 0; + info->buf_start = 0; + info->buf_count = 0; info->oob_size = 0; info->use_ecc = 0; + info->is_ready = 0; info->retcode = ERR_NONE; switch (command) { @@ -849,42 +856,6 @@ static int pxa3xx_nand_detect_config(struct pxa3xx_nand_info *info) return 0; } -static int pxa3xx_nand_detect_flash(struct pxa3xx_nand_info *info, - const struct pxa3xx_nand_platform_data *pdata) -{ - const struct pxa3xx_nand_flash *f; - uint32_t id = -1; - int i; - - if (pdata->keep_config) - if (pxa3xx_nand_detect_config(info) == 0) - return 0; - - /* we use default timing to detect id */ - f = DEFAULT_FLASH_TYPE; - pxa3xx_nand_config_flash(info, f); - pxa3xx_nand_cmdfunc(info->mtd, NAND_CMD_READID, 0, 0); - id = *((uint16_t *)(info->data_buff)); - - for (i=0; inum_flash - 1; i++) { - /* we first choose the flash definition from platfrom */ - if (i < pdata->num_flash) - f = pdata->flash + i; - else - f = &builtin_flash_types[i - pdata->num_flash + 1]; - if (f->chip_id == id) { - dev_info(&info->pdev->dev, "detect chip id: 0x%x\n", id); - pxa3xx_nand_config_flash(info, f); - return 0; - } - } - - dev_warn(&info->pdev->dev, - "failed to detect configured nand flash; found %04x instead of\n", - id); - return -ENODEV; -} - /* the maximum possible buffer size for large page with OOB data * is: 2048 + 64 = 2112 bytes, allocate a page here for both the * data buffer and the DMA descriptor @@ -926,57 +897,110 @@ static int pxa3xx_nand_init_buff(struct pxa3xx_nand_info *info) return 0; } -static struct nand_ecclayout hw_smallpage_ecclayout = { - .eccbytes = 6, - .eccpos = {8, 9, 10, 11, 12, 13 }, - .oobfree = { {2, 6} } -}; +static int pxa3xx_nand_sensing(struct pxa3xx_nand_info *info) +{ + struct mtd_info *mtd = info->mtd; + struct nand_chip *chip = mtd->priv; -static struct nand_ecclayout hw_largepage_ecclayout = { - .eccbytes = 24, - .eccpos = { - 40, 41, 42, 43, 44, 45, 46, 47, - 48, 49, 50, 51, 52, 53, 54, 55, - 56, 57, 58, 59, 60, 61, 62, 63}, - .oobfree = { {2, 38} } -}; + /* use the common timing to make a try */ + pxa3xx_nand_config_flash(info, &builtin_flash_types[0]); + chip->cmdfunc(mtd, NAND_CMD_RESET, 0, 0); + if (info->is_ready) + return 1; + else + return 0; +} -static void pxa3xx_nand_init_mtd(struct mtd_info *mtd, - struct pxa3xx_nand_info *info) +static int pxa3xx_nand_scan(struct mtd_info *mtd) { - struct nand_chip *this = &info->nand_chip; - - this->options = (info->reg_ndcr & NDCR_DWIDTH_C) ? NAND_BUSWIDTH_16: 0; - this->options |= NAND_NO_AUTOINCR; - - this->waitfunc = pxa3xx_nand_waitfunc; - this->select_chip = pxa3xx_nand_select_chip; - this->dev_ready = pxa3xx_nand_dev_ready; - this->cmdfunc = pxa3xx_nand_cmdfunc; - this->ecc.read_page = pxa3xx_nand_read_page_hwecc; - this->ecc.write_page = pxa3xx_nand_write_page_hwecc; - this->read_word = pxa3xx_nand_read_word; - this->read_byte = pxa3xx_nand_read_byte; - this->read_buf = pxa3xx_nand_read_buf; - this->write_buf = pxa3xx_nand_write_buf; - this->verify_buf = pxa3xx_nand_verify_buf; - - this->ecc.mode = NAND_ECC_HW; - this->ecc.size = info->page_size; - - if (info->page_size == 2048) - this->ecc.layout = &hw_largepage_ecclayout; - else - this->ecc.layout = &hw_smallpage_ecclayout; + struct pxa3xx_nand_info *info = mtd->priv; + struct platform_device *pdev = info->pdev; + struct pxa3xx_nand_platform_data *pdata = pdev->dev.platform_data; + const struct pxa3xx_nand_flash *f = NULL; + struct nand_chip *chip = mtd->priv; + uint32_t id = -1; + int i, ret, num; + + if (pdata->keep_config && !pxa3xx_nand_detect_config(info)) + return 0; + + ret = pxa3xx_nand_sensing(info); + if (!ret) { + kfree(mtd); + info->mtd = NULL; + printk(KERN_INFO "There is no nand chip on cs 0!\n"); + + return -EINVAL; + } + + chip->cmdfunc(mtd, NAND_CMD_READID, 0, 0); + id = *((uint16_t *)(info->data_buff)); + if (id != 0) + printk(KERN_INFO "Detect a flash id %x\n", id); + else { + kfree(mtd); + info->mtd = NULL; + printk(KERN_WARNING "Read out ID 0, potential timing set wrong!!\n"); + + return -EINVAL; + } + + num = ARRAY_SIZE(builtin_flash_types) + pdata->num_flash - 1; + for (i = 0; i < num; i++) { + if (i < pdata->num_flash) + f = pdata->flash + i; + else + f = &builtin_flash_types[i - pdata->num_flash + 1]; + + /* find the chip in default list */ + if (f->chip_id == id) { + pxa3xx_nand_config_flash(info, f); + mtd->writesize = f->page_size; + mtd->writesize_shift = ffs(mtd->writesize) - 1; + mtd->writesize_mask = (1 << mtd->writesize_shift) - 1; + mtd->oobsize = mtd->writesize / 32; + mtd->erasesize = f->page_size * f->page_per_block; + mtd->erasesize_shift = ffs(mtd->erasesize) - 1; + mtd->erasesize_mask = (1 << mtd->erasesize_shift) - 1; + + mtd->name = mtd_names[0]; + break; + } + } + + if (i >= (ARRAY_SIZE(builtin_flash_types) + pdata->num_flash)) { + kfree(mtd); + info->mtd = NULL; + printk(KERN_ERR "ERROR!! flash not defined!!!\n"); + + return -EINVAL; + } + + chip->ecc.mode = NAND_ECC_HW; + chip->ecc.size = f->page_size; + chip->chipsize = (uint64_t)f->num_blocks * f->page_per_block + * f->page_size; + mtd->size = chip->chipsize; + + /* Calculate the address shift from the page size */ + chip->page_shift = ffs(mtd->writesize) - 1; + chip->pagemask = mtd_div_by_ws(chip->chipsize, mtd) - 1; + chip->numchips = 1; + chip->phys_erase_shift = ffs(mtd->erasesize) - 1; + chip->bbt_erase_shift = chip->phys_erase_shift; + + chip->options = (f->flash_width == 16) ? NAND_BUSWIDTH_16 : 0; + chip->options |= NAND_NO_AUTOINCR; + chip->options |= NAND_NO_READRDY; - this->chip_delay = 25; + return nand_scan_tail(mtd); } static struct pxa3xx_nand_info *alloc_nand_resource(struct platform_device *pdev) { - struct pxa3xx_nand_platform_data *pdata = pdev->dev.platform_data; struct pxa3xx_nand_info *info; + struct nand_chip *chip; struct mtd_info *mtd; struct resource *r; int ret, irq; @@ -989,12 +1013,27 @@ struct pxa3xx_nand_info *alloc_nand_resource(struct platform_device *pdev) } info = (struct pxa3xx_nand_info *)(&mtd[1]); + chip = (struct nand_chip *)(&mtd[1]); info->pdev = pdev; - - mtd->priv = info; info->mtd = mtd; + mtd->priv = info; mtd->owner = THIS_MODULE; + chip->ecc.read_page = pxa3xx_nand_read_page_hwecc; + chip->ecc.write_page = pxa3xx_nand_write_page_hwecc; + chip->controller = &info->controller; + chip->waitfunc = pxa3xx_nand_waitfunc; + chip->select_chip = pxa3xx_nand_select_chip; + chip->dev_ready = pxa3xx_nand_dev_ready; + chip->cmdfunc = pxa3xx_nand_cmdfunc; + chip->read_word = pxa3xx_nand_read_word; + chip->read_byte = pxa3xx_nand_read_byte; + chip->read_buf = pxa3xx_nand_read_buf; + chip->write_buf = pxa3xx_nand_write_buf; + chip->verify_buf = pxa3xx_nand_verify_buf; + + spin_lock_init(&chip->controller->lock); + init_waitqueue_head(&chip->controller->wq); info->clk = clk_get(&pdev->dev, NULL); if (IS_ERR(info->clk)) { dev_err(&pdev->dev, "failed to get nand clock\n"); @@ -1062,21 +1101,12 @@ struct pxa3xx_nand_info *alloc_nand_resource(struct platform_device *pdev) goto fail_free_buf; } - ret = pxa3xx_nand_detect_flash(info, pdata); - if (ret) { - dev_err(&pdev->dev, "failed to detect flash\n"); - ret = -ENODEV; - goto fail_free_irq; - } - - pxa3xx_nand_init_mtd(mtd, info); platform_set_drvdata(pdev, info); return info; -fail_free_irq: - free_irq(irq, info); fail_free_buf: + free_irq(irq, info); if (use_dma) { pxa_free_dma(info->data_dma_ch); dma_free_coherent(&pdev->dev, info->data_buff_size, @@ -1146,7 +1176,7 @@ static int pxa3xx_nand_probe(struct platform_device *pdev) if (info == NULL) return -ENOMEM; - if (nand_scan(info->mtd, 1)) { + if (pxa3xx_nand_scan(info->mtd)) { dev_err(&pdev->dev, "failed to scan nand\n"); pxa3xx_nand_remove(pdev); return -ENODEV; -- GitLab From 4332c116869ceca58638beabd9e9a5d7db4cef83 Mon Sep 17 00:00:00 2001 From: Lei Wen Date: Thu, 3 Mar 2011 11:27:01 +0800 Subject: [PATCH 0601/2822] mtd: pxa3xx_nand: clean the keep configure code Use nand_scan_ident to unify the need of mtd member initilization for both normal detection and keep configuration method. Signed-off-by: Lei Wen Signed-off-by: Haojian Zhuang Signed-off-by: David Woodhouse --- arch/arm/plat-pxa/include/plat/pxa3xx_nand.h | 2 +- drivers/mtd/nand/pxa3xx_nand.c | 103 +++++++------------ 2 files changed, 36 insertions(+), 69 deletions(-) diff --git a/arch/arm/plat-pxa/include/plat/pxa3xx_nand.h b/arch/arm/plat-pxa/include/plat/pxa3xx_nand.h index 01a8448e471c8..442301fe48b41 100644 --- a/arch/arm/plat-pxa/include/plat/pxa3xx_nand.h +++ b/arch/arm/plat-pxa/include/plat/pxa3xx_nand.h @@ -30,6 +30,7 @@ struct pxa3xx_nand_cmdset { }; struct pxa3xx_nand_flash { + char *name; uint32_t chip_id; unsigned int page_per_block; /* Pages per block (PG_PER_BLK) */ unsigned int page_size; /* Page size in bytes (PAGE_SZ) */ @@ -37,7 +38,6 @@ struct pxa3xx_nand_flash { unsigned int dfc_width; /* Width of flash controller(DWIDTH_C) */ unsigned int num_blocks; /* Number of physical blocks in Flash */ - struct pxa3xx_nand_cmdset *cmdset; /* NAND command set */ struct pxa3xx_nand_timing *timing; /* NAND Flash timing */ }; diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c index bb50cf2b11c4d..ab7f4c33ced60 100644 --- a/drivers/mtd/nand/pxa3xx_nand.c +++ b/drivers/mtd/nand/pxa3xx_nand.c @@ -211,15 +211,15 @@ static struct pxa3xx_nand_timing timing[] = { }; static struct pxa3xx_nand_flash builtin_flash_types[] = { - { 0, 0, 2048, 8, 8, 0, &default_cmdset, &timing[0] }, - { 0x46ec, 32, 512, 16, 16, 4096, &default_cmdset, &timing[1] }, - { 0xdaec, 64, 2048, 8, 8, 2048, &default_cmdset, &timing[1] }, - { 0xd7ec, 128, 4096, 8, 8, 8192, &default_cmdset, &timing[1] }, - { 0xa12c, 64, 2048, 8, 8, 1024, &default_cmdset, &timing[2] }, - { 0xb12c, 64, 2048, 16, 16, 1024, &default_cmdset, &timing[2] }, - { 0xdc2c, 64, 2048, 8, 8, 4096, &default_cmdset, &timing[2] }, - { 0xcc2c, 64, 2048, 16, 16, 4096, &default_cmdset, &timing[2] }, - { 0xba20, 64, 2048, 16, 16, 2048, &default_cmdset, &timing[3] }, +{ "DEFAULT FLASH", 0, 0, 2048, 8, 8, 0, &timing[0] }, +{ "64MiB 16-bit", 0x46ec, 32, 512, 16, 16, 4096, &timing[1] }, +{ "256MiB 8-bit", 0xdaec, 64, 2048, 8, 8, 2048, &timing[1] }, +{ "4GiB 8-bit", 0xd7ec, 128, 4096, 8, 8, 8192, &timing[1] }, +{ "128MiB 8-bit", 0xa12c, 64, 2048, 8, 8, 1024, &timing[2] }, +{ "128MiB 16-bit", 0xb12c, 64, 2048, 16, 16, 1024, &timing[2] }, +{ "512MiB 8-bit", 0xdc2c, 64, 2048, 8, 8, 4096, &timing[2] }, +{ "512MiB 16-bit", 0xcc2c, 64, 2048, 16, 16, 4096, &timing[2] }, +{ "256MiB 16-bit", 0xba20, 64, 2048, 16, 16, 2048, &timing[3] }, }; /* Define a default flash type setting serve as flash detecting only */ @@ -779,9 +779,8 @@ static int pxa3xx_nand_config_flash(struct pxa3xx_nand_info *info, return -EINVAL; /* calculate flash information */ - info->cmdset = f->cmdset; + info->cmdset = &default_cmdset; info->page_size = f->page_size; - info->oob_buff = info->data_buff + f->page_size; info->read_id_bytes = (f->page_size == 2048) ? 4 : 2; /* calculate addressing information */ @@ -811,45 +810,12 @@ static int pxa3xx_nand_config_flash(struct pxa3xx_nand_info *info, static int pxa3xx_nand_detect_config(struct pxa3xx_nand_info *info) { uint32_t ndcr = nand_readl(info, NDCR); - struct nand_flash_dev *type = NULL; - uint32_t id = -1, page_per_block, num_blocks; - int i; - - page_per_block = ndcr & NDCR_PG_PER_BLK ? 64 : 32; info->page_size = ndcr & NDCR_PAGE_SZ ? 2048 : 512; /* set info fields needed to read id */ info->read_id_bytes = (info->page_size == 2048) ? 4 : 2; info->reg_ndcr = ndcr; info->cmdset = &default_cmdset; - pxa3xx_nand_cmdfunc(info->mtd, NAND_CMD_READID, 0, 0); - id = *((uint16_t *)(info->data_buff)); - if (id == 0) - return -ENODEV; - - /* Lookup the flash id */ - for (i = 0; nand_flash_ids[i].name != NULL; i++) { - if (id == nand_flash_ids[i].id) { - type = &nand_flash_ids[i]; - break; - } - } - - if (!type) - return -ENODEV; - - /* fill the missing flash information */ - i = __ffs(page_per_block * info->page_size); - num_blocks = type->chipsize << (20 - i); - - /* calculate addressing information */ - info->col_addr_cycles = (info->page_size == 2048) ? 2 : 1; - - if (num_blocks * page_per_block > 65536) - info->row_addr_cycles = 3; - else - info->row_addr_cycles = 2; - info->ndtr0cs0 = nand_readl(info, NDTR0CS0); info->ndtr1cs0 = nand_readl(info, NDTR1CS0); @@ -916,13 +882,15 @@ static int pxa3xx_nand_scan(struct mtd_info *mtd) struct pxa3xx_nand_info *info = mtd->priv; struct platform_device *pdev = info->pdev; struct pxa3xx_nand_platform_data *pdata = pdev->dev.platform_data; + struct nand_flash_dev pxa3xx_flash_ids[2] = { {NULL,}, {NULL,} }; const struct pxa3xx_nand_flash *f = NULL; struct nand_chip *chip = mtd->priv; uint32_t id = -1; + uint64_t chipsize; int i, ret, num; if (pdata->keep_config && !pxa3xx_nand_detect_config(info)) - return 0; + goto KEEP_CONFIG; ret = pxa3xx_nand_sensing(info); if (!ret) { @@ -953,22 +921,11 @@ static int pxa3xx_nand_scan(struct mtd_info *mtd) f = &builtin_flash_types[i - pdata->num_flash + 1]; /* find the chip in default list */ - if (f->chip_id == id) { - pxa3xx_nand_config_flash(info, f); - mtd->writesize = f->page_size; - mtd->writesize_shift = ffs(mtd->writesize) - 1; - mtd->writesize_mask = (1 << mtd->writesize_shift) - 1; - mtd->oobsize = mtd->writesize / 32; - mtd->erasesize = f->page_size * f->page_per_block; - mtd->erasesize_shift = ffs(mtd->erasesize) - 1; - mtd->erasesize_mask = (1 << mtd->erasesize_shift) - 1; - - mtd->name = mtd_names[0]; + if (f->chip_id == id) break; - } } - if (i >= (ARRAY_SIZE(builtin_flash_types) + pdata->num_flash)) { + if (i >= (ARRAY_SIZE(builtin_flash_types) + pdata->num_flash - 1)) { kfree(mtd); info->mtd = NULL; printk(KERN_ERR "ERROR!! flash not defined!!!\n"); @@ -976,18 +933,28 @@ static int pxa3xx_nand_scan(struct mtd_info *mtd) return -EINVAL; } + pxa3xx_nand_config_flash(info, f); + pxa3xx_flash_ids[0].name = f->name; + pxa3xx_flash_ids[0].id = (f->chip_id >> 8) & 0xffff; + pxa3xx_flash_ids[0].pagesize = f->page_size; + chipsize = (uint64_t)f->num_blocks * f->page_per_block * f->page_size; + pxa3xx_flash_ids[0].chipsize = chipsize >> 20; + pxa3xx_flash_ids[0].erasesize = f->page_size * f->page_per_block; + if (f->flash_width == 16) + pxa3xx_flash_ids[0].options = NAND_BUSWIDTH_16; +KEEP_CONFIG: + if (nand_scan_ident(mtd, 1, pxa3xx_flash_ids)) + return -ENODEV; + /* calculate addressing information */ + info->col_addr_cycles = (mtd->writesize >= 2048) ? 2 : 1; + info->oob_buff = info->data_buff + mtd->writesize; + if ((mtd->size >> chip->page_shift) > 65536) + info->row_addr_cycles = 3; + else + info->row_addr_cycles = 2; + mtd->name = mtd_names[0]; chip->ecc.mode = NAND_ECC_HW; chip->ecc.size = f->page_size; - chip->chipsize = (uint64_t)f->num_blocks * f->page_per_block - * f->page_size; - mtd->size = chip->chipsize; - - /* Calculate the address shift from the page size */ - chip->page_shift = ffs(mtd->writesize) - 1; - chip->pagemask = mtd_div_by_ws(chip->chipsize, mtd) - 1; - chip->numchips = 1; - chip->phys_erase_shift = ffs(mtd->erasesize) - 1; - chip->bbt_erase_shift = chip->phys_erase_shift; chip->options = (f->flash_width == 16) ? NAND_BUSWIDTH_16 : 0; chip->options |= NAND_NO_AUTOINCR; -- GitLab From f43272c482661bc88347bba237976eecfc1dbf5b Mon Sep 17 00:00:00 2001 From: Sandeep Paulraj Date: Mon, 7 Mar 2011 13:50:44 -0500 Subject: [PATCH 0602/2822] mtd: DaVinci: Removed header file that is not required The DaVinci NAND driver was including the mach-types.h header file. This prevented the DaVinci NAND driver from getting used in a DSP only device. The linux port on c6x devices can make use of the same driver and does not define a corresponding header file. This header file was required in the driver because earlier there was code dependent on a machine_* check. This piece of code has now been factored out and is in arch/arm/mach-davinci/aemif.c Thus removing the header file is harmless Signed-off-by: Sandeep Paulraj Signed-off-by: Artem Bityutskiy Signed-off-by: David Woodhouse --- drivers/mtd/nand/davinci_nand.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/mtd/nand/davinci_nand.c b/drivers/mtd/nand/davinci_nand.c index a90fde3ede28c..aff3468867ac0 100644 --- a/drivers/mtd/nand/davinci_nand.c +++ b/drivers/mtd/nand/davinci_nand.c @@ -37,9 +37,6 @@ #include #include -#include - - /* * This is a device driver for the NAND flash controller found on the * various DaVinci family chips. It handles up to four SoC chipselects, -- GitLab From 2c1c5f199482356c00f70b6f2f368c3455d1230c Mon Sep 17 00:00:00 2001 From: Baruch Siach Date: Wed, 9 Mar 2011 16:12:20 +0200 Subject: [PATCH 0603/2822] mtd: mxc_nand: fix OOB corruption when page size > 2KiB When page size is 4KiB, ecc.total is set to 8*9, and this causes nand_write_page_hwecc() to read past the initialized part of the eccpos array, which corrupts chip->oob_poi with bogus values from ecc_calc. Fix this by creating a proper nand_ecclayout for 4KiB flashes. Signed-off-by: Baruch Siach Acked-by: Sascha Hauer Signed-off-by: David Woodhouse --- drivers/mtd/nand/mxc_nand.c | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/drivers/mtd/nand/mxc_nand.c b/drivers/mtd/nand/mxc_nand.c index 6cd78ed439a74..b7d5a5b9a5434 100644 --- a/drivers/mtd/nand/mxc_nand.c +++ b/drivers/mtd/nand/mxc_nand.c @@ -211,6 +211,31 @@ static struct nand_ecclayout nandv2_hw_eccoob_largepage = { } }; +/* OOB description for 4096 byte pages with 128 byte OOB */ +static struct nand_ecclayout nandv2_hw_eccoob_4k = { + .eccbytes = 8 * 9, + .eccpos = { + 7, 8, 9, 10, 11, 12, 13, 14, 15, + 23, 24, 25, 26, 27, 28, 29, 30, 31, + 39, 40, 41, 42, 43, 44, 45, 46, 47, + 55, 56, 57, 58, 59, 60, 61, 62, 63, + 71, 72, 73, 74, 75, 76, 77, 78, 79, + 87, 88, 89, 90, 91, 92, 93, 94, 95, + 103, 104, 105, 106, 107, 108, 109, 110, 111, + 119, 120, 121, 122, 123, 124, 125, 126, 127, + }, + .oobfree = { + {.offset = 2, .length = 4}, + {.offset = 16, .length = 7}, + {.offset = 32, .length = 7}, + {.offset = 48, .length = 7}, + {.offset = 64, .length = 7}, + {.offset = 80, .length = 7}, + {.offset = 96, .length = 7}, + {.offset = 112, .length = 7}, + } +}; + #ifdef CONFIG_MTD_PARTITIONS static const char *part_probes[] = { "RedBoot", "cmdlinepart", NULL }; #endif @@ -1186,6 +1211,8 @@ static int __init mxcnd_probe(struct platform_device *pdev) if (mtd->writesize == 2048) this->ecc.layout = oob_largepage; + if (nfc_is_v21() && mtd->writesize == 4096) + this->ecc.layout = &nandv2_hw_eccoob_4k; /* second phase scan */ if (nand_scan_tail(mtd)) { -- GitLab From 437aa565e2656776a7104aaacd792fe789ea8b2d Mon Sep 17 00:00:00 2001 From: Ivan Djelic Date: Fri, 11 Mar 2011 11:05:32 +0100 Subject: [PATCH 0604/2822] lib: add shared BCH ECC library MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is a new software BCH encoding/decoding library, similar to the shared Reed-Solomon library. Binary BCH (Bose-Chaudhuri-Hocquenghem) codes are widely used to correct errors in NAND flash devices requiring more than 1-bit ecc correction; they are generally better suited for NAND flash than RS codes because NAND bit errors do not occur in bursts. Latest SLC NAND devices typically require at least 4-bit ecc protection per 512 bytes block. This library provides software encoding/decoding, but may also be used with ASIC/SoC hardware BCH engines to perform error correction. It is being currently used for this purpose on an OMAP3630 board (4bit/8bit HW BCH). It has also been used to decode raw dumps of NAND devices with on-die BCH ecc engines (e.g. Micron 4bit ecc SLC devices). Latest NAND devices (including SLC) can exhibit high error rates (typically a dozen or more bitflips per hour during stress tests); in order to minimize the performance impact of error correction, this library implements recently developed algorithms for fast polynomial root finding (see bch.c header for details) instead of the traditional exhaustive Chien root search; a few performance figures are provided below: Platform: arm926ejs @ 468 MHz, 32 KiB icache, 16 KiB dcache BCH ecc : 4-bit per 512 bytes Encoding average throughput: 250 Mbits/s Error correction time (compared with Chien search): average worst average (Chien) worst (Chien) ---------------------------------------------------------- 1 bit 8.5 µs 11 µs 200 µs 383 µs 2 bit 9.7 µs 12.5 µs 477 µs 728 µs 3 bit 18.1 µs 20.6 µs 758 µs 1010 µs 4 bit 19.5 µs 23 µs 1028 µs 1280 µs In the above figures, "worst" is meant in terms of error pattern, not in terms of cache miss / page faults effects (not taken into account here). The library has been extensively tested on the following platforms: x86, x86_64, arm926ejs, omap3630, qemu-ppc64, qemu-mips. Signed-off-by: Ivan Djelic Signed-off-by: David Woodhouse --- include/linux/bch.h | 79 +++ lib/Kconfig | 39 ++ lib/Makefile | 1 + lib/bch.c | 1368 +++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 1487 insertions(+) create mode 100644 include/linux/bch.h create mode 100644 lib/bch.c diff --git a/include/linux/bch.h b/include/linux/bch.h new file mode 100644 index 0000000000000..295b4ef153bb7 --- /dev/null +++ b/include/linux/bch.h @@ -0,0 +1,79 @@ +/* + * Generic binary BCH encoding/decoding library + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published by + * the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., 51 + * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Copyright © 2011 Parrot S.A. + * + * Author: Ivan Djelic + * + * Description: + * + * This library provides runtime configurable encoding/decoding of binary + * Bose-Chaudhuri-Hocquenghem (BCH) codes. +*/ +#ifndef _BCH_H +#define _BCH_H + +#include + +/** + * struct bch_control - BCH control structure + * @m: Galois field order + * @n: maximum codeword size in bits (= 2^m-1) + * @t: error correction capability in bits + * @ecc_bits: ecc exact size in bits, i.e. generator polynomial degree (<=m*t) + * @ecc_bytes: ecc max size (m*t bits) in bytes + * @a_pow_tab: Galois field GF(2^m) exponentiation lookup table + * @a_log_tab: Galois field GF(2^m) log lookup table + * @mod8_tab: remainder generator polynomial lookup tables + * @ecc_buf: ecc parity words buffer + * @ecc_buf2: ecc parity words buffer + * @xi_tab: GF(2^m) base for solving degree 2 polynomial roots + * @syn: syndrome buffer + * @cache: log-based polynomial representation buffer + * @elp: error locator polynomial + * @poly_2t: temporary polynomials of degree 2t + */ +struct bch_control { + unsigned int m; + unsigned int n; + unsigned int t; + unsigned int ecc_bits; + unsigned int ecc_bytes; +/* private: */ + uint16_t *a_pow_tab; + uint16_t *a_log_tab; + uint32_t *mod8_tab; + uint32_t *ecc_buf; + uint32_t *ecc_buf2; + unsigned int *xi_tab; + unsigned int *syn; + int *cache; + struct gf_poly *elp; + struct gf_poly *poly_2t[4]; +}; + +struct bch_control *init_bch(int m, int t, unsigned int prim_poly); + +void free_bch(struct bch_control *bch); + +void encode_bch(struct bch_control *bch, const uint8_t *data, + unsigned int len, uint8_t *ecc); + +int decode_bch(struct bch_control *bch, const uint8_t *data, unsigned int len, + const uint8_t *recv_ecc, const uint8_t *calc_ecc, + const unsigned int *syn, unsigned int *errloc); + +#endif /* _BCH_H */ diff --git a/lib/Kconfig b/lib/Kconfig index 0ee67e08ad3ec..b9fef78ed04f8 100644 --- a/lib/Kconfig +++ b/lib/Kconfig @@ -154,6 +154,45 @@ config REED_SOLOMON_ENC16 config REED_SOLOMON_DEC16 boolean +# +# BCH support is selected if needed +# +config BCH + tristate + +config BCH_CONST_PARAMS + boolean + help + Drivers may select this option to force specific constant + values for parameters 'm' (Galois field order) and 't' + (error correction capability). Those specific values must + be set by declaring default values for symbols BCH_CONST_M + and BCH_CONST_T. + Doing so will enable extra compiler optimizations, + improving encoding and decoding performance up to 2x for + usual (m,t) values (typically such that m*t < 200). + When this option is selected, the BCH library supports + only a single (m,t) configuration. This is mainly useful + for NAND flash board drivers requiring known, fixed BCH + parameters. + +config BCH_CONST_M + int + range 5 15 + help + Constant value for Galois field order 'm'. If 'k' is the + number of data bits to protect, 'm' should be chosen such + that (k + m*t) <= 2**m - 1. + Drivers should declare a default value for this symbol if + they select option BCH_CONST_PARAMS. + +config BCH_CONST_T + int + help + Constant value for error correction capability in bits 't'. + Drivers should declare a default value for this symbol if + they select option BCH_CONST_PARAMS. + # # Textsearch support is select'ed if needed # diff --git a/lib/Makefile b/lib/Makefile index cbb774f7d41d0..0544c814d827e 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -67,6 +67,7 @@ obj-$(CONFIG_GENERIC_ALLOCATOR) += genalloc.o obj-$(CONFIG_ZLIB_INFLATE) += zlib_inflate/ obj-$(CONFIG_ZLIB_DEFLATE) += zlib_deflate/ obj-$(CONFIG_REED_SOLOMON) += reed_solomon/ +obj-$(CONFIG_BCH) += bch.o obj-$(CONFIG_LZO_COMPRESS) += lzo/ obj-$(CONFIG_LZO_DECOMPRESS) += lzo/ obj-$(CONFIG_XZ_DEC) += xz/ diff --git a/lib/bch.c b/lib/bch.c new file mode 100644 index 0000000000000..bc89dfe4d1b38 --- /dev/null +++ b/lib/bch.c @@ -0,0 +1,1368 @@ +/* + * Generic binary BCH encoding/decoding library + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published by + * the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., 51 + * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Copyright © 2011 Parrot S.A. + * + * Author: Ivan Djelic + * + * Description: + * + * This library provides runtime configurable encoding/decoding of binary + * Bose-Chaudhuri-Hocquenghem (BCH) codes. + * + * Call init_bch to get a pointer to a newly allocated bch_control structure for + * the given m (Galois field order), t (error correction capability) and + * (optional) primitive polynomial parameters. + * + * Call encode_bch to compute and store ecc parity bytes to a given buffer. + * Call decode_bch to detect and locate errors in received data. + * + * On systems supporting hw BCH features, intermediate results may be provided + * to decode_bch in order to skip certain steps. See decode_bch() documentation + * for details. + * + * Option CONFIG_BCH_CONST_PARAMS can be used to force fixed values of + * parameters m and t; thus allowing extra compiler optimizations and providing + * better (up to 2x) encoding performance. Using this option makes sense when + * (m,t) are fixed and known in advance, e.g. when using BCH error correction + * on a particular NAND flash device. + * + * Algorithmic details: + * + * Encoding is performed by processing 32 input bits in parallel, using 4 + * remainder lookup tables. + * + * The final stage of decoding involves the following internal steps: + * a. Syndrome computation + * b. Error locator polynomial computation using Berlekamp-Massey algorithm + * c. Error locator root finding (by far the most expensive step) + * + * In this implementation, step c is not performed using the usual Chien search. + * Instead, an alternative approach described in [1] is used. It consists in + * factoring the error locator polynomial using the Berlekamp Trace algorithm + * (BTA) down to a certain degree (4), after which ad hoc low-degree polynomial + * solving techniques [2] are used. The resulting algorithm, called BTZ, yields + * much better performance than Chien search for usual (m,t) values (typically + * m >= 13, t < 32, see [1]). + * + * [1] B. Biswas, V. Herbert. Efficient root finding of polynomials over fields + * of characteristic 2, in: Western European Workshop on Research in Cryptology + * - WEWoRC 2009, Graz, Austria, LNCS, Springer, July 2009, to appear. + * [2] [Zin96] V.A. Zinoviev. On the solution of equations of degree 10 over + * finite fields GF(2^q). In Rapport de recherche INRIA no 2829, 1996. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#if defined(CONFIG_BCH_CONST_PARAMS) +#define GF_M(_p) (CONFIG_BCH_CONST_M) +#define GF_T(_p) (CONFIG_BCH_CONST_T) +#define GF_N(_p) ((1 << (CONFIG_BCH_CONST_M))-1) +#else +#define GF_M(_p) ((_p)->m) +#define GF_T(_p) ((_p)->t) +#define GF_N(_p) ((_p)->n) +#endif + +#define BCH_ECC_WORDS(_p) DIV_ROUND_UP(GF_M(_p)*GF_T(_p), 32) +#define BCH_ECC_BYTES(_p) DIV_ROUND_UP(GF_M(_p)*GF_T(_p), 8) + +#ifndef dbg +#define dbg(_fmt, args...) do {} while (0) +#endif + +/* + * represent a polynomial over GF(2^m) + */ +struct gf_poly { + unsigned int deg; /* polynomial degree */ + unsigned int c[0]; /* polynomial terms */ +}; + +/* given its degree, compute a polynomial size in bytes */ +#define GF_POLY_SZ(_d) (sizeof(struct gf_poly)+((_d)+1)*sizeof(unsigned int)) + +/* polynomial of degree 1 */ +struct gf_poly_deg1 { + struct gf_poly poly; + unsigned int c[2]; +}; + +/* + * same as encode_bch(), but process input data one byte at a time + */ +static void encode_bch_unaligned(struct bch_control *bch, + const unsigned char *data, unsigned int len, + uint32_t *ecc) +{ + int i; + const uint32_t *p; + const int l = BCH_ECC_WORDS(bch)-1; + + while (len--) { + p = bch->mod8_tab + (l+1)*(((ecc[0] >> 24)^(*data++)) & 0xff); + + for (i = 0; i < l; i++) + ecc[i] = ((ecc[i] << 8)|(ecc[i+1] >> 24))^(*p++); + + ecc[l] = (ecc[l] << 8)^(*p); + } +} + +/* + * convert ecc bytes to aligned, zero-padded 32-bit ecc words + */ +static void load_ecc8(struct bch_control *bch, uint32_t *dst, + const uint8_t *src) +{ + uint8_t pad[4] = {0, 0, 0, 0}; + unsigned int i, nwords = BCH_ECC_WORDS(bch)-1; + + for (i = 0; i < nwords; i++, src += 4) + dst[i] = (src[0] << 24)|(src[1] << 16)|(src[2] << 8)|src[3]; + + memcpy(pad, src, BCH_ECC_BYTES(bch)-4*nwords); + dst[nwords] = (pad[0] << 24)|(pad[1] << 16)|(pad[2] << 8)|pad[3]; +} + +/* + * convert 32-bit ecc words to ecc bytes + */ +static void store_ecc8(struct bch_control *bch, uint8_t *dst, + const uint32_t *src) +{ + uint8_t pad[4]; + unsigned int i, nwords = BCH_ECC_WORDS(bch)-1; + + for (i = 0; i < nwords; i++) { + *dst++ = (src[i] >> 24); + *dst++ = (src[i] >> 16) & 0xff; + *dst++ = (src[i] >> 8) & 0xff; + *dst++ = (src[i] >> 0) & 0xff; + } + pad[0] = (src[nwords] >> 24); + pad[1] = (src[nwords] >> 16) & 0xff; + pad[2] = (src[nwords] >> 8) & 0xff; + pad[3] = (src[nwords] >> 0) & 0xff; + memcpy(dst, pad, BCH_ECC_BYTES(bch)-4*nwords); +} + +/** + * encode_bch - calculate BCH ecc parity of data + * @bch: BCH control structure + * @data: data to encode + * @len: data length in bytes + * @ecc: ecc parity data, must be initialized by caller + * + * The @ecc parity array is used both as input and output parameter, in order to + * allow incremental computations. It should be of the size indicated by member + * @ecc_bytes of @bch, and should be initialized to 0 before the first call. + * + * The exact number of computed ecc parity bits is given by member @ecc_bits of + * @bch; it may be less than m*t for large values of t. + */ +void encode_bch(struct bch_control *bch, const uint8_t *data, + unsigned int len, uint8_t *ecc) +{ + const unsigned int l = BCH_ECC_WORDS(bch)-1; + unsigned int i, mlen; + unsigned long m; + uint32_t w, r[l+1]; + const uint32_t * const tab0 = bch->mod8_tab; + const uint32_t * const tab1 = tab0 + 256*(l+1); + const uint32_t * const tab2 = tab1 + 256*(l+1); + const uint32_t * const tab3 = tab2 + 256*(l+1); + const uint32_t *pdata, *p0, *p1, *p2, *p3; + + if (ecc) { + /* load ecc parity bytes into internal 32-bit buffer */ + load_ecc8(bch, bch->ecc_buf, ecc); + } else { + memset(bch->ecc_buf, 0, sizeof(r)); + } + + /* process first unaligned data bytes */ + m = ((unsigned long)data) & 3; + if (m) { + mlen = (len < (4-m)) ? len : 4-m; + encode_bch_unaligned(bch, data, mlen, bch->ecc_buf); + data += mlen; + len -= mlen; + } + + /* process 32-bit aligned data words */ + pdata = (uint32_t *)data; + mlen = len/4; + data += 4*mlen; + len -= 4*mlen; + memcpy(r, bch->ecc_buf, sizeof(r)); + + /* + * split each 32-bit word into 4 polynomials of weight 8 as follows: + * + * 31 ...24 23 ...16 15 ... 8 7 ... 0 + * xxxxxxxx yyyyyyyy zzzzzzzz tttttttt + * tttttttt mod g = r0 (precomputed) + * zzzzzzzz 00000000 mod g = r1 (precomputed) + * yyyyyyyy 00000000 00000000 mod g = r2 (precomputed) + * xxxxxxxx 00000000 00000000 00000000 mod g = r3 (precomputed) + * xxxxxxxx yyyyyyyy zzzzzzzz tttttttt mod g = r0^r1^r2^r3 + */ + while (mlen--) { + /* input data is read in big-endian format */ + w = r[0]^cpu_to_be32(*pdata++); + p0 = tab0 + (l+1)*((w >> 0) & 0xff); + p1 = tab1 + (l+1)*((w >> 8) & 0xff); + p2 = tab2 + (l+1)*((w >> 16) & 0xff); + p3 = tab3 + (l+1)*((w >> 24) & 0xff); + + for (i = 0; i < l; i++) + r[i] = r[i+1]^p0[i]^p1[i]^p2[i]^p3[i]; + + r[l] = p0[l]^p1[l]^p2[l]^p3[l]; + } + memcpy(bch->ecc_buf, r, sizeof(r)); + + /* process last unaligned bytes */ + if (len) + encode_bch_unaligned(bch, data, len, bch->ecc_buf); + + /* store ecc parity bytes into original parity buffer */ + if (ecc) + store_ecc8(bch, ecc, bch->ecc_buf); +} +EXPORT_SYMBOL_GPL(encode_bch); + +static inline int modulo(struct bch_control *bch, unsigned int v) +{ + const unsigned int n = GF_N(bch); + while (v >= n) { + v -= n; + v = (v & n) + (v >> GF_M(bch)); + } + return v; +} + +/* + * shorter and faster modulo function, only works when v < 2N. + */ +static inline int mod_s(struct bch_control *bch, unsigned int v) +{ + const unsigned int n = GF_N(bch); + return (v < n) ? v : v-n; +} + +static inline int deg(unsigned int poly) +{ + /* polynomial degree is the most-significant bit index */ + return fls(poly)-1; +} + +static inline int parity(unsigned int x) +{ + /* + * public domain code snippet, lifted from + * http://www-graphics.stanford.edu/~seander/bithacks.html + */ + x ^= x >> 1; + x ^= x >> 2; + x = (x & 0x11111111U) * 0x11111111U; + return (x >> 28) & 1; +} + +/* Galois field basic operations: multiply, divide, inverse, etc. */ + +static inline unsigned int gf_mul(struct bch_control *bch, unsigned int a, + unsigned int b) +{ + return (a && b) ? bch->a_pow_tab[mod_s(bch, bch->a_log_tab[a]+ + bch->a_log_tab[b])] : 0; +} + +static inline unsigned int gf_sqr(struct bch_control *bch, unsigned int a) +{ + return a ? bch->a_pow_tab[mod_s(bch, 2*bch->a_log_tab[a])] : 0; +} + +static inline unsigned int gf_div(struct bch_control *bch, unsigned int a, + unsigned int b) +{ + return a ? bch->a_pow_tab[mod_s(bch, bch->a_log_tab[a]+ + GF_N(bch)-bch->a_log_tab[b])] : 0; +} + +static inline unsigned int gf_inv(struct bch_control *bch, unsigned int a) +{ + return bch->a_pow_tab[GF_N(bch)-bch->a_log_tab[a]]; +} + +static inline unsigned int a_pow(struct bch_control *bch, int i) +{ + return bch->a_pow_tab[modulo(bch, i)]; +} + +static inline int a_log(struct bch_control *bch, unsigned int x) +{ + return bch->a_log_tab[x]; +} + +static inline int a_ilog(struct bch_control *bch, unsigned int x) +{ + return mod_s(bch, GF_N(bch)-bch->a_log_tab[x]); +} + +/* + * compute 2t syndromes of ecc polynomial, i.e. ecc(a^j) for j=1..2t + */ +static void compute_syndromes(struct bch_control *bch, uint32_t *ecc, + unsigned int *syn) +{ + int i, j, s; + unsigned int m; + uint32_t poly; + const int t = GF_T(bch); + + s = bch->ecc_bits; + + /* make sure extra bits in last ecc word are cleared */ + m = ((unsigned int)s) & 31; + if (m) + ecc[s/32] &= ~((1u << (32-m))-1); + memset(syn, 0, 2*t*sizeof(*syn)); + + /* compute v(a^j) for j=1 .. 2t-1 */ + do { + poly = *ecc++; + s -= 32; + while (poly) { + i = deg(poly); + for (j = 0; j < 2*t; j += 2) + syn[j] ^= a_pow(bch, (j+1)*(i+s)); + + poly ^= (1 << i); + } + } while (s > 0); + + /* v(a^(2j)) = v(a^j)^2 */ + for (j = 0; j < t; j++) + syn[2*j+1] = gf_sqr(bch, syn[j]); +} + +static void gf_poly_copy(struct gf_poly *dst, struct gf_poly *src) +{ + memcpy(dst, src, GF_POLY_SZ(src->deg)); +} + +static int compute_error_locator_polynomial(struct bch_control *bch, + const unsigned int *syn) +{ + const unsigned int t = GF_T(bch); + const unsigned int n = GF_N(bch); + unsigned int i, j, tmp, l, pd = 1, d = syn[0]; + struct gf_poly *elp = bch->elp; + struct gf_poly *pelp = bch->poly_2t[0]; + struct gf_poly *elp_copy = bch->poly_2t[1]; + int k, pp = -1; + + memset(pelp, 0, GF_POLY_SZ(2*t)); + memset(elp, 0, GF_POLY_SZ(2*t)); + + pelp->deg = 0; + pelp->c[0] = 1; + elp->deg = 0; + elp->c[0] = 1; + + /* use simplified binary Berlekamp-Massey algorithm */ + for (i = 0; (i < t) && (elp->deg <= t); i++) { + if (d) { + k = 2*i-pp; + gf_poly_copy(elp_copy, elp); + /* e[i+1](X) = e[i](X)+di*dp^-1*X^2(i-p)*e[p](X) */ + tmp = a_log(bch, d)+n-a_log(bch, pd); + for (j = 0; j <= pelp->deg; j++) { + if (pelp->c[j]) { + l = a_log(bch, pelp->c[j]); + elp->c[j+k] ^= a_pow(bch, tmp+l); + } + } + /* compute l[i+1] = max(l[i]->c[l[p]+2*(i-p]) */ + tmp = pelp->deg+k; + if (tmp > elp->deg) { + elp->deg = tmp; + gf_poly_copy(pelp, elp_copy); + pd = d; + pp = 2*i; + } + } + /* di+1 = S(2i+3)+elp[i+1].1*S(2i+2)+...+elp[i+1].lS(2i+3-l) */ + if (i < t-1) { + d = syn[2*i+2]; + for (j = 1; j <= elp->deg; j++) + d ^= gf_mul(bch, elp->c[j], syn[2*i+2-j]); + } + } + dbg("elp=%s\n", gf_poly_str(elp)); + return (elp->deg > t) ? -1 : (int)elp->deg; +} + +/* + * solve a m x m linear system in GF(2) with an expected number of solutions, + * and return the number of found solutions + */ +static int solve_linear_system(struct bch_control *bch, unsigned int *rows, + unsigned int *sol, int nsol) +{ + const int m = GF_M(bch); + unsigned int tmp, mask; + int rem, c, r, p, k, param[m]; + + k = 0; + mask = 1 << m; + + /* Gaussian elimination */ + for (c = 0; c < m; c++) { + rem = 0; + p = c-k; + /* find suitable row for elimination */ + for (r = p; r < m; r++) { + if (rows[r] & mask) { + if (r != p) { + tmp = rows[r]; + rows[r] = rows[p]; + rows[p] = tmp; + } + rem = r+1; + break; + } + } + if (rem) { + /* perform elimination on remaining rows */ + tmp = rows[p]; + for (r = rem; r < m; r++) { + if (rows[r] & mask) + rows[r] ^= tmp; + } + } else { + /* elimination not needed, store defective row index */ + param[k++] = c; + } + mask >>= 1; + } + /* rewrite system, inserting fake parameter rows */ + if (k > 0) { + p = k; + for (r = m-1; r >= 0; r--) { + if ((r > m-1-k) && rows[r]) + /* system has no solution */ + return 0; + + rows[r] = (p && (r == param[p-1])) ? + p--, 1u << (m-r) : rows[r-p]; + } + } + + if (nsol != (1 << k)) + /* unexpected number of solutions */ + return 0; + + for (p = 0; p < nsol; p++) { + /* set parameters for p-th solution */ + for (c = 0; c < k; c++) + rows[param[c]] = (rows[param[c]] & ~1)|((p >> c) & 1); + + /* compute unique solution */ + tmp = 0; + for (r = m-1; r >= 0; r--) { + mask = rows[r] & (tmp|1); + tmp |= parity(mask) << (m-r); + } + sol[p] = tmp >> 1; + } + return nsol; +} + +/* + * this function builds and solves a linear system for finding roots of a degree + * 4 affine monic polynomial X^4+aX^2+bX+c over GF(2^m). + */ +static int find_affine4_roots(struct bch_control *bch, unsigned int a, + unsigned int b, unsigned int c, + unsigned int *roots) +{ + int i, j, k; + const int m = GF_M(bch); + unsigned int mask = 0xff, t, rows[16] = {0,}; + + j = a_log(bch, b); + k = a_log(bch, a); + rows[0] = c; + + /* buid linear system to solve X^4+aX^2+bX+c = 0 */ + for (i = 0; i < m; i++) { + rows[i+1] = bch->a_pow_tab[4*i]^ + (a ? bch->a_pow_tab[mod_s(bch, k)] : 0)^ + (b ? bch->a_pow_tab[mod_s(bch, j)] : 0); + j++; + k += 2; + } + /* + * transpose 16x16 matrix before passing it to linear solver + * warning: this code assumes m < 16 + */ + for (j = 8; j != 0; j >>= 1, mask ^= (mask << j)) { + for (k = 0; k < 16; k = (k+j+1) & ~j) { + t = ((rows[k] >> j)^rows[k+j]) & mask; + rows[k] ^= (t << j); + rows[k+j] ^= t; + } + } + return solve_linear_system(bch, rows, roots, 4); +} + +/* + * compute root r of a degree 1 polynomial over GF(2^m) (returned as log(1/r)) + */ +static int find_poly_deg1_roots(struct bch_control *bch, struct gf_poly *poly, + unsigned int *roots) +{ + int n = 0; + + if (poly->c[0]) + /* poly[X] = bX+c with c!=0, root=c/b */ + roots[n++] = mod_s(bch, GF_N(bch)-bch->a_log_tab[poly->c[0]]+ + bch->a_log_tab[poly->c[1]]); + return n; +} + +/* + * compute roots of a degree 2 polynomial over GF(2^m) + */ +static int find_poly_deg2_roots(struct bch_control *bch, struct gf_poly *poly, + unsigned int *roots) +{ + int n = 0, i, l0, l1, l2; + unsigned int u, v, r; + + if (poly->c[0] && poly->c[1]) { + + l0 = bch->a_log_tab[poly->c[0]]; + l1 = bch->a_log_tab[poly->c[1]]; + l2 = bch->a_log_tab[poly->c[2]]; + + /* using z=a/bX, transform aX^2+bX+c into z^2+z+u (u=ac/b^2) */ + u = a_pow(bch, l0+l2+2*(GF_N(bch)-l1)); + /* + * let u = sum(li.a^i) i=0..m-1; then compute r = sum(li.xi): + * r^2+r = sum(li.(xi^2+xi)) = sum(li.(a^i+Tr(a^i).a^k)) = + * u + sum(li.Tr(a^i).a^k) = u+a^k.Tr(sum(li.a^i)) = u+a^k.Tr(u) + * i.e. r and r+1 are roots iff Tr(u)=0 + */ + r = 0; + v = u; + while (v) { + i = deg(v); + r ^= bch->xi_tab[i]; + v ^= (1 << i); + } + /* verify root */ + if ((gf_sqr(bch, r)^r) == u) { + /* reverse z=a/bX transformation and compute log(1/r) */ + roots[n++] = modulo(bch, 2*GF_N(bch)-l1- + bch->a_log_tab[r]+l2); + roots[n++] = modulo(bch, 2*GF_N(bch)-l1- + bch->a_log_tab[r^1]+l2); + } + } + return n; +} + +/* + * compute roots of a degree 3 polynomial over GF(2^m) + */ +static int find_poly_deg3_roots(struct bch_control *bch, struct gf_poly *poly, + unsigned int *roots) +{ + int i, n = 0; + unsigned int a, b, c, a2, b2, c2, e3, tmp[4]; + + if (poly->c[0]) { + /* transform polynomial into monic X^3 + a2X^2 + b2X + c2 */ + e3 = poly->c[3]; + c2 = gf_div(bch, poly->c[0], e3); + b2 = gf_div(bch, poly->c[1], e3); + a2 = gf_div(bch, poly->c[2], e3); + + /* (X+a2)(X^3+a2X^2+b2X+c2) = X^4+aX^2+bX+c (affine) */ + c = gf_mul(bch, a2, c2); /* c = a2c2 */ + b = gf_mul(bch, a2, b2)^c2; /* b = a2b2 + c2 */ + a = gf_sqr(bch, a2)^b2; /* a = a2^2 + b2 */ + + /* find the 4 roots of this affine polynomial */ + if (find_affine4_roots(bch, a, b, c, tmp) == 4) { + /* remove a2 from final list of roots */ + for (i = 0; i < 4; i++) { + if (tmp[i] != a2) + roots[n++] = a_ilog(bch, tmp[i]); + } + } + } + return n; +} + +/* + * compute roots of a degree 4 polynomial over GF(2^m) + */ +static int find_poly_deg4_roots(struct bch_control *bch, struct gf_poly *poly, + unsigned int *roots) +{ + int i, l, n = 0; + unsigned int a, b, c, d, e = 0, f, a2, b2, c2, e4; + + if (poly->c[0] == 0) + return 0; + + /* transform polynomial into monic X^4 + aX^3 + bX^2 + cX + d */ + e4 = poly->c[4]; + d = gf_div(bch, poly->c[0], e4); + c = gf_div(bch, poly->c[1], e4); + b = gf_div(bch, poly->c[2], e4); + a = gf_div(bch, poly->c[3], e4); + + /* use Y=1/X transformation to get an affine polynomial */ + if (a) { + /* first, eliminate cX by using z=X+e with ae^2+c=0 */ + if (c) { + /* compute e such that e^2 = c/a */ + f = gf_div(bch, c, a); + l = a_log(bch, f); + l += (l & 1) ? GF_N(bch) : 0; + e = a_pow(bch, l/2); + /* + * use transformation z=X+e: + * z^4+e^4 + a(z^3+ez^2+e^2z+e^3) + b(z^2+e^2) +cz+ce+d + * z^4 + az^3 + (ae+b)z^2 + (ae^2+c)z+e^4+be^2+ae^3+ce+d + * z^4 + az^3 + (ae+b)z^2 + e^4+be^2+d + * z^4 + az^3 + b'z^2 + d' + */ + d = a_pow(bch, 2*l)^gf_mul(bch, b, f)^d; + b = gf_mul(bch, a, e)^b; + } + /* now, use Y=1/X to get Y^4 + b/dY^2 + a/dY + 1/d */ + if (d == 0) + /* assume all roots have multiplicity 1 */ + return 0; + + c2 = gf_inv(bch, d); + b2 = gf_div(bch, a, d); + a2 = gf_div(bch, b, d); + } else { + /* polynomial is already affine */ + c2 = d; + b2 = c; + a2 = b; + } + /* find the 4 roots of this affine polynomial */ + if (find_affine4_roots(bch, a2, b2, c2, roots) == 4) { + for (i = 0; i < 4; i++) { + /* post-process roots (reverse transformations) */ + f = a ? gf_inv(bch, roots[i]) : roots[i]; + roots[i] = a_ilog(bch, f^e); + } + n = 4; + } + return n; +} + +/* + * build monic, log-based representation of a polynomial + */ +static void gf_poly_logrep(struct bch_control *bch, + const struct gf_poly *a, int *rep) +{ + int i, d = a->deg, l = GF_N(bch)-a_log(bch, a->c[a->deg]); + + /* represent 0 values with -1; warning, rep[d] is not set to 1 */ + for (i = 0; i < d; i++) + rep[i] = a->c[i] ? mod_s(bch, a_log(bch, a->c[i])+l) : -1; +} + +/* + * compute polynomial Euclidean division remainder in GF(2^m)[X] + */ +static void gf_poly_mod(struct bch_control *bch, struct gf_poly *a, + const struct gf_poly *b, int *rep) +{ + int la, p, m; + unsigned int i, j, *c = a->c; + const unsigned int d = b->deg; + + if (a->deg < d) + return; + + /* reuse or compute log representation of denominator */ + if (!rep) { + rep = bch->cache; + gf_poly_logrep(bch, b, rep); + } + + for (j = a->deg; j >= d; j--) { + if (c[j]) { + la = a_log(bch, c[j]); + p = j-d; + for (i = 0; i < d; i++, p++) { + m = rep[i]; + if (m >= 0) + c[p] ^= bch->a_pow_tab[mod_s(bch, + m+la)]; + } + } + } + a->deg = d-1; + while (!c[a->deg] && a->deg) + a->deg--; +} + +/* + * compute polynomial Euclidean division quotient in GF(2^m)[X] + */ +static void gf_poly_div(struct bch_control *bch, struct gf_poly *a, + const struct gf_poly *b, struct gf_poly *q) +{ + if (a->deg >= b->deg) { + q->deg = a->deg-b->deg; + /* compute a mod b (modifies a) */ + gf_poly_mod(bch, a, b, NULL); + /* quotient is stored in upper part of polynomial a */ + memcpy(q->c, &a->c[b->deg], (1+q->deg)*sizeof(unsigned int)); + } else { + q->deg = 0; + q->c[0] = 0; + } +} + +/* + * compute polynomial GCD (Greatest Common Divisor) in GF(2^m)[X] + */ +static struct gf_poly *gf_poly_gcd(struct bch_control *bch, struct gf_poly *a, + struct gf_poly *b) +{ + struct gf_poly *tmp; + + dbg("gcd(%s,%s)=", gf_poly_str(a), gf_poly_str(b)); + + if (a->deg < b->deg) { + tmp = b; + b = a; + a = tmp; + } + + while (b->deg > 0) { + gf_poly_mod(bch, a, b, NULL); + tmp = b; + b = a; + a = tmp; + } + + dbg("%s\n", gf_poly_str(a)); + + return a; +} + +/* + * Given a polynomial f and an integer k, compute Tr(a^kX) mod f + * This is used in Berlekamp Trace algorithm for splitting polynomials + */ +static void compute_trace_bk_mod(struct bch_control *bch, int k, + const struct gf_poly *f, struct gf_poly *z, + struct gf_poly *out) +{ + const int m = GF_M(bch); + int i, j; + + /* z contains z^2j mod f */ + z->deg = 1; + z->c[0] = 0; + z->c[1] = bch->a_pow_tab[k]; + + out->deg = 0; + memset(out, 0, GF_POLY_SZ(f->deg)); + + /* compute f log representation only once */ + gf_poly_logrep(bch, f, bch->cache); + + for (i = 0; i < m; i++) { + /* add a^(k*2^i)(z^(2^i) mod f) and compute (z^(2^i) mod f)^2 */ + for (j = z->deg; j >= 0; j--) { + out->c[j] ^= z->c[j]; + z->c[2*j] = gf_sqr(bch, z->c[j]); + z->c[2*j+1] = 0; + } + if (z->deg > out->deg) + out->deg = z->deg; + + if (i < m-1) { + z->deg *= 2; + /* z^(2(i+1)) mod f = (z^(2^i) mod f)^2 mod f */ + gf_poly_mod(bch, z, f, bch->cache); + } + } + while (!out->c[out->deg] && out->deg) + out->deg--; + + dbg("Tr(a^%d.X) mod f = %s\n", k, gf_poly_str(out)); +} + +/* + * factor a polynomial using Berlekamp Trace algorithm (BTA) + */ +static void factor_polynomial(struct bch_control *bch, int k, struct gf_poly *f, + struct gf_poly **g, struct gf_poly **h) +{ + struct gf_poly *f2 = bch->poly_2t[0]; + struct gf_poly *q = bch->poly_2t[1]; + struct gf_poly *tk = bch->poly_2t[2]; + struct gf_poly *z = bch->poly_2t[3]; + struct gf_poly *gcd; + + dbg("factoring %s...\n", gf_poly_str(f)); + + *g = f; + *h = NULL; + + /* tk = Tr(a^k.X) mod f */ + compute_trace_bk_mod(bch, k, f, z, tk); + + if (tk->deg > 0) { + /* compute g = gcd(f, tk) (destructive operation) */ + gf_poly_copy(f2, f); + gcd = gf_poly_gcd(bch, f2, tk); + if (gcd->deg < f->deg) { + /* compute h=f/gcd(f,tk); this will modify f and q */ + gf_poly_div(bch, f, gcd, q); + /* store g and h in-place (clobbering f) */ + *h = &((struct gf_poly_deg1 *)f)[gcd->deg].poly; + gf_poly_copy(*g, gcd); + gf_poly_copy(*h, q); + } + } +} + +/* + * find roots of a polynomial, using BTZ algorithm; see the beginning of this + * file for details + */ +static int find_poly_roots(struct bch_control *bch, unsigned int k, + struct gf_poly *poly, unsigned int *roots) +{ + int cnt; + struct gf_poly *f1, *f2; + + switch (poly->deg) { + /* handle low degree polynomials with ad hoc techniques */ + case 1: + cnt = find_poly_deg1_roots(bch, poly, roots); + break; + case 2: + cnt = find_poly_deg2_roots(bch, poly, roots); + break; + case 3: + cnt = find_poly_deg3_roots(bch, poly, roots); + break; + case 4: + cnt = find_poly_deg4_roots(bch, poly, roots); + break; + default: + /* factor polynomial using Berlekamp Trace Algorithm (BTA) */ + cnt = 0; + if (poly->deg && (k <= GF_M(bch))) { + factor_polynomial(bch, k, poly, &f1, &f2); + if (f1) + cnt += find_poly_roots(bch, k+1, f1, roots); + if (f2) + cnt += find_poly_roots(bch, k+1, f2, roots+cnt); + } + break; + } + return cnt; +} + +#if defined(USE_CHIEN_SEARCH) +/* + * exhaustive root search (Chien) implementation - not used, included only for + * reference/comparison tests + */ +static int chien_search(struct bch_control *bch, unsigned int len, + struct gf_poly *p, unsigned int *roots) +{ + int m; + unsigned int i, j, syn, syn0, count = 0; + const unsigned int k = 8*len+bch->ecc_bits; + + /* use a log-based representation of polynomial */ + gf_poly_logrep(bch, p, bch->cache); + bch->cache[p->deg] = 0; + syn0 = gf_div(bch, p->c[0], p->c[p->deg]); + + for (i = GF_N(bch)-k+1; i <= GF_N(bch); i++) { + /* compute elp(a^i) */ + for (j = 1, syn = syn0; j <= p->deg; j++) { + m = bch->cache[j]; + if (m >= 0) + syn ^= a_pow(bch, m+j*i); + } + if (syn == 0) { + roots[count++] = GF_N(bch)-i; + if (count == p->deg) + break; + } + } + return (count == p->deg) ? count : 0; +} +#define find_poly_roots(_p, _k, _elp, _loc) chien_search(_p, len, _elp, _loc) +#endif /* USE_CHIEN_SEARCH */ + +/** + * decode_bch - decode received codeword and find bit error locations + * @bch: BCH control structure + * @data: received data, ignored if @calc_ecc is provided + * @len: data length in bytes, must always be provided + * @recv_ecc: received ecc, if NULL then assume it was XORed in @calc_ecc + * @calc_ecc: calculated ecc, if NULL then calc_ecc is computed from @data + * @syn: hw computed syndrome data (if NULL, syndrome is calculated) + * @errloc: output array of error locations + * + * Returns: + * The number of errors found, or -EBADMSG if decoding failed, or -EINVAL if + * invalid parameters were provided + * + * Depending on the available hw BCH support and the need to compute @calc_ecc + * separately (using encode_bch()), this function should be called with one of + * the following parameter configurations - + * + * by providing @data and @recv_ecc only: + * decode_bch(@bch, @data, @len, @recv_ecc, NULL, NULL, @errloc) + * + * by providing @recv_ecc and @calc_ecc: + * decode_bch(@bch, NULL, @len, @recv_ecc, @calc_ecc, NULL, @errloc) + * + * by providing ecc = recv_ecc XOR calc_ecc: + * decode_bch(@bch, NULL, @len, NULL, ecc, NULL, @errloc) + * + * by providing syndrome results @syn: + * decode_bch(@bch, NULL, @len, NULL, NULL, @syn, @errloc) + * + * Once decode_bch() has successfully returned with a positive value, error + * locations returned in array @errloc should be interpreted as follows - + * + * if (errloc[n] >= 8*len), then n-th error is located in ecc (no need for + * data correction) + * + * if (errloc[n] < 8*len), then n-th error is located in data and can be + * corrected with statement data[errloc[n]/8] ^= 1 << (errloc[n] % 8); + * + * Note that this function does not perform any data correction by itself, it + * merely indicates error locations. + */ +int decode_bch(struct bch_control *bch, const uint8_t *data, unsigned int len, + const uint8_t *recv_ecc, const uint8_t *calc_ecc, + const unsigned int *syn, unsigned int *errloc) +{ + const unsigned int ecc_words = BCH_ECC_WORDS(bch); + unsigned int nbits; + int i, err, nroots; + uint32_t sum; + + /* sanity check: make sure data length can be handled */ + if (8*len > (bch->n-bch->ecc_bits)) + return -EINVAL; + + /* if caller does not provide syndromes, compute them */ + if (!syn) { + if (!calc_ecc) { + /* compute received data ecc into an internal buffer */ + if (!data || !recv_ecc) + return -EINVAL; + encode_bch(bch, data, len, NULL); + } else { + /* load provided calculated ecc */ + load_ecc8(bch, bch->ecc_buf, calc_ecc); + } + /* load received ecc or assume it was XORed in calc_ecc */ + if (recv_ecc) { + load_ecc8(bch, bch->ecc_buf2, recv_ecc); + /* XOR received and calculated ecc */ + for (i = 0, sum = 0; i < (int)ecc_words; i++) { + bch->ecc_buf[i] ^= bch->ecc_buf2[i]; + sum |= bch->ecc_buf[i]; + } + if (!sum) + /* no error found */ + return 0; + } + compute_syndromes(bch, bch->ecc_buf, bch->syn); + syn = bch->syn; + } + + err = compute_error_locator_polynomial(bch, syn); + if (err > 0) { + nroots = find_poly_roots(bch, 1, bch->elp, errloc); + if (err != nroots) + err = -1; + } + if (err > 0) { + /* post-process raw error locations for easier correction */ + nbits = (len*8)+bch->ecc_bits; + for (i = 0; i < err; i++) { + if (errloc[i] >= nbits) { + err = -1; + break; + } + errloc[i] = nbits-1-errloc[i]; + errloc[i] = (errloc[i] & ~7)|(7-(errloc[i] & 7)); + } + } + return (err >= 0) ? err : -EBADMSG; +} +EXPORT_SYMBOL_GPL(decode_bch); + +/* + * generate Galois field lookup tables + */ +static int build_gf_tables(struct bch_control *bch, unsigned int poly) +{ + unsigned int i, x = 1; + const unsigned int k = 1 << deg(poly); + + /* primitive polynomial must be of degree m */ + if (k != (1u << GF_M(bch))) + return -1; + + for (i = 0; i < GF_N(bch); i++) { + bch->a_pow_tab[i] = x; + bch->a_log_tab[x] = i; + if (i && (x == 1)) + /* polynomial is not primitive (a^i=1 with 0a_pow_tab[GF_N(bch)] = 1; + bch->a_log_tab[0] = 0; + + return 0; +} + +/* + * compute generator polynomial remainder tables for fast encoding + */ +static void build_mod8_tables(struct bch_control *bch, const uint32_t *g) +{ + int i, j, b, d; + uint32_t data, hi, lo, *tab; + const int l = BCH_ECC_WORDS(bch); + const int plen = DIV_ROUND_UP(bch->ecc_bits+1, 32); + const int ecclen = DIV_ROUND_UP(bch->ecc_bits, 32); + + memset(bch->mod8_tab, 0, 4*256*l*sizeof(*bch->mod8_tab)); + + for (i = 0; i < 256; i++) { + /* p(X)=i is a small polynomial of weight <= 8 */ + for (b = 0; b < 4; b++) { + /* we want to compute (p(X).X^(8*b+deg(g))) mod g(X) */ + tab = bch->mod8_tab + (b*256+i)*l; + data = i << (8*b); + while (data) { + d = deg(data); + /* subtract X^d.g(X) from p(X).X^(8*b+deg(g)) */ + data ^= g[0] >> (31-d); + for (j = 0; j < ecclen; j++) { + hi = (d < 31) ? g[j] << (d+1) : 0; + lo = (j+1 < plen) ? + g[j+1] >> (31-d) : 0; + tab[j] ^= hi|lo; + } + } + } + } +} + +/* + * build a base for factoring degree 2 polynomials + */ +static int build_deg2_base(struct bch_control *bch) +{ + const int m = GF_M(bch); + int i, j, r; + unsigned int sum, x, y, remaining, ak = 0, xi[m]; + + /* find k s.t. Tr(a^k) = 1 and 0 <= k < m */ + for (i = 0; i < m; i++) { + for (j = 0, sum = 0; j < m; j++) + sum ^= a_pow(bch, i*(1 << j)); + + if (sum) { + ak = bch->a_pow_tab[i]; + break; + } + } + /* find xi, i=0..m-1 such that xi^2+xi = a^i+Tr(a^i).a^k */ + remaining = m; + memset(xi, 0, sizeof(xi)); + + for (x = 0; (x <= GF_N(bch)) && remaining; x++) { + y = gf_sqr(bch, x)^x; + for (i = 0; i < 2; i++) { + r = a_log(bch, y); + if (y && (r < m) && !xi[r]) { + bch->xi_tab[r] = x; + xi[r] = 1; + remaining--; + dbg("x%d = %x\n", r, x); + break; + } + y ^= ak; + } + } + /* should not happen but check anyway */ + return remaining ? -1 : 0; +} + +static void *bch_alloc(size_t size, int *err) +{ + void *ptr; + + ptr = kmalloc(size, GFP_KERNEL); + if (ptr == NULL) + *err = 1; + return ptr; +} + +/* + * compute generator polynomial for given (m,t) parameters. + */ +static uint32_t *compute_generator_polynomial(struct bch_control *bch) +{ + const unsigned int m = GF_M(bch); + const unsigned int t = GF_T(bch); + int n, err = 0; + unsigned int i, j, nbits, r, word, *roots; + struct gf_poly *g; + uint32_t *genpoly; + + g = bch_alloc(GF_POLY_SZ(m*t), &err); + roots = bch_alloc((bch->n+1)*sizeof(*roots), &err); + genpoly = bch_alloc(DIV_ROUND_UP(m*t+1, 32)*sizeof(*genpoly), &err); + + if (err) { + kfree(genpoly); + genpoly = NULL; + goto finish; + } + + /* enumerate all roots of g(X) */ + memset(roots , 0, (bch->n+1)*sizeof(*roots)); + for (i = 0; i < t; i++) { + for (j = 0, r = 2*i+1; j < m; j++) { + roots[r] = 1; + r = mod_s(bch, 2*r); + } + } + /* build generator polynomial g(X) */ + g->deg = 0; + g->c[0] = 1; + for (i = 0; i < GF_N(bch); i++) { + if (roots[i]) { + /* multiply g(X) by (X+root) */ + r = bch->a_pow_tab[i]; + g->c[g->deg+1] = 1; + for (j = g->deg; j > 0; j--) + g->c[j] = gf_mul(bch, g->c[j], r)^g->c[j-1]; + + g->c[0] = gf_mul(bch, g->c[0], r); + g->deg++; + } + } + /* store left-justified binary representation of g(X) */ + n = g->deg+1; + i = 0; + + while (n > 0) { + nbits = (n > 32) ? 32 : n; + for (j = 0, word = 0; j < nbits; j++) { + if (g->c[n-1-j]) + word |= 1u << (31-j); + } + genpoly[i++] = word; + n -= nbits; + } + bch->ecc_bits = g->deg; + +finish: + kfree(g); + kfree(roots); + + return genpoly; +} + +/** + * init_bch - initialize a BCH encoder/decoder + * @m: Galois field order, should be in the range 5-15 + * @t: maximum error correction capability, in bits + * @prim_poly: user-provided primitive polynomial (or 0 to use default) + * + * Returns: + * a newly allocated BCH control structure if successful, NULL otherwise + * + * This initialization can take some time, as lookup tables are built for fast + * encoding/decoding; make sure not to call this function from a time critical + * path. Usually, init_bch() should be called on module/driver init and + * free_bch() should be called to release memory on exit. + * + * You may provide your own primitive polynomial of degree @m in argument + * @prim_poly, or let init_bch() use its default polynomial. + * + * Once init_bch() has successfully returned a pointer to a newly allocated + * BCH control structure, ecc length in bytes is given by member @ecc_bytes of + * the structure. + */ +struct bch_control *init_bch(int m, int t, unsigned int prim_poly) +{ + int err = 0; + unsigned int i, words; + uint32_t *genpoly; + struct bch_control *bch = NULL; + + const int min_m = 5; + const int max_m = 15; + + /* default primitive polynomials */ + static const unsigned int prim_poly_tab[] = { + 0x25, 0x43, 0x83, 0x11d, 0x211, 0x409, 0x805, 0x1053, 0x201b, + 0x402b, 0x8003, + }; + +#if defined(CONFIG_BCH_CONST_PARAMS) + if ((m != (CONFIG_BCH_CONST_M)) || (t != (CONFIG_BCH_CONST_T))) { + printk(KERN_ERR "bch encoder/decoder was configured to support " + "parameters m=%d, t=%d only!\n", + CONFIG_BCH_CONST_M, CONFIG_BCH_CONST_T); + goto fail; + } +#endif + if ((m < min_m) || (m > max_m)) + /* + * values of m greater than 15 are not currently supported; + * supporting m > 15 would require changing table base type + * (uint16_t) and a small patch in matrix transposition + */ + goto fail; + + /* sanity checks */ + if ((t < 1) || (m*t >= ((1 << m)-1))) + /* invalid t value */ + goto fail; + + /* select a primitive polynomial for generating GF(2^m) */ + if (prim_poly == 0) + prim_poly = prim_poly_tab[m-min_m]; + + bch = kzalloc(sizeof(*bch), GFP_KERNEL); + if (bch == NULL) + goto fail; + + bch->m = m; + bch->t = t; + bch->n = (1 << m)-1; + words = DIV_ROUND_UP(m*t, 32); + bch->ecc_bytes = DIV_ROUND_UP(m*t, 8); + bch->a_pow_tab = bch_alloc((1+bch->n)*sizeof(*bch->a_pow_tab), &err); + bch->a_log_tab = bch_alloc((1+bch->n)*sizeof(*bch->a_log_tab), &err); + bch->mod8_tab = bch_alloc(words*1024*sizeof(*bch->mod8_tab), &err); + bch->ecc_buf = bch_alloc(words*sizeof(*bch->ecc_buf), &err); + bch->ecc_buf2 = bch_alloc(words*sizeof(*bch->ecc_buf2), &err); + bch->xi_tab = bch_alloc(m*sizeof(*bch->xi_tab), &err); + bch->syn = bch_alloc(2*t*sizeof(*bch->syn), &err); + bch->cache = bch_alloc(2*t*sizeof(*bch->cache), &err); + bch->elp = bch_alloc((t+1)*sizeof(struct gf_poly_deg1), &err); + + for (i = 0; i < ARRAY_SIZE(bch->poly_2t); i++) + bch->poly_2t[i] = bch_alloc(GF_POLY_SZ(2*t), &err); + + if (err) + goto fail; + + err = build_gf_tables(bch, prim_poly); + if (err) + goto fail; + + /* use generator polynomial for computing encoding tables */ + genpoly = compute_generator_polynomial(bch); + if (genpoly == NULL) + goto fail; + + build_mod8_tables(bch, genpoly); + kfree(genpoly); + + err = build_deg2_base(bch); + if (err) + goto fail; + + return bch; + +fail: + free_bch(bch); + return NULL; +} +EXPORT_SYMBOL_GPL(init_bch); + +/** + * free_bch - free the BCH control structure + * @bch: BCH control structure to release + */ +void free_bch(struct bch_control *bch) +{ + unsigned int i; + + if (bch) { + kfree(bch->a_pow_tab); + kfree(bch->a_log_tab); + kfree(bch->mod8_tab); + kfree(bch->ecc_buf); + kfree(bch->ecc_buf2); + kfree(bch->xi_tab); + kfree(bch->syn); + kfree(bch->cache); + kfree(bch->elp); + + for (i = 0; i < ARRAY_SIZE(bch->poly_2t); i++) + kfree(bch->poly_2t[i]); + + kfree(bch); + } +} +EXPORT_SYMBOL_GPL(free_bch); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Ivan Djelic "); +MODULE_DESCRIPTION("Binary BCH encoder/decoder"); -- GitLab From 1065cda8a1a57d0d3bfccdce1a655a84439d24e0 Mon Sep 17 00:00:00 2001 From: Steffen Sledz Date: Thu, 10 Mar 2011 09:05:12 +0100 Subject: [PATCH 0605/2822] mtd: cfi: add support for AMIC flashes (e.g. A29L160AT) Signed-off-by: Steffen Sledz Signed-off-by: David Woodhouse --- drivers/mtd/chips/cfi_cmdset_0002.c | 1 + include/linux/mtd/cfi.h | 1 + 2 files changed, 2 insertions(+) diff --git a/drivers/mtd/chips/cfi_cmdset_0002.c b/drivers/mtd/chips/cfi_cmdset_0002.c index 7e9c4e9c274a4..f9a5331e9445a 100644 --- a/drivers/mtd/chips/cfi_cmdset_0002.c +++ b/drivers/mtd/chips/cfi_cmdset_0002.c @@ -349,6 +349,7 @@ static struct cfi_fixup cfi_fixup_table[] = { { CFI_MFR_ATMEL, CFI_ID_ANY, fixup_convert_atmel_pri }, #ifdef AMD_BOOTLOC_BUG { CFI_MFR_AMD, CFI_ID_ANY, fixup_amd_bootblock }, + { CFI_MFR_AMIC, CFI_ID_ANY, fixup_amd_bootblock }, { CFI_MFR_MACRONIX, CFI_ID_ANY, fixup_amd_bootblock }, #endif { CFI_MFR_AMD, 0x0050, fixup_use_secsi }, diff --git a/include/linux/mtd/cfi.h b/include/linux/mtd/cfi.h index a9baee6864afe..0d823f2dd6679 100644 --- a/include/linux/mtd/cfi.h +++ b/include/linux/mtd/cfi.h @@ -535,6 +535,7 @@ struct cfi_fixup { #define CFI_MFR_CONTINUATION 0x007F #define CFI_MFR_AMD 0x0001 +#define CFI_MFR_AMIC 0x0037 #define CFI_MFR_ATMEL 0x001F #define CFI_MFR_EON 0x001C #define CFI_MFR_FUJITSU 0x0004 -- GitLab From 629286b9561982e90a6d49893a1c641e71b6a2a3 Mon Sep 17 00:00:00 2001 From: Xiaochen Wang Date: Thu, 10 Mar 2011 22:31:39 +0800 Subject: [PATCH 0606/2822] mtd: sm_rtl: check kmalloc return value Because malloc/kzalloc may fail, we should check kmalloc/kzalloc return value in sm_create_sysfs_attributes(), mtd/sm_rtl.c and do error handling. Meanwhile, we should check sm_create_sysfs_attributes return value. Signed-off-by: Xiaochen Wang Signed-off-by: Artem Bityutskiy Signed-off-by: David Woodhouse --- drivers/mtd/sm_ftl.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/drivers/mtd/sm_ftl.c b/drivers/mtd/sm_ftl.c index 67822cf6c0253..6405a95dc5bd4 100644 --- a/drivers/mtd/sm_ftl.c +++ b/drivers/mtd/sm_ftl.c @@ -64,12 +64,16 @@ struct attribute_group *sm_create_sysfs_attributes(struct sm_ftl *ftl) SM_SMALL_PAGE - SM_CIS_VENDOR_OFFSET); char *vendor = kmalloc(vendor_len, GFP_KERNEL); + if (!vendor) + goto error1; memcpy(vendor, ftl->cis_buffer + SM_CIS_VENDOR_OFFSET, vendor_len); vendor[vendor_len] = 0; /* Initialize sysfs attributes */ vendor_attribute = kzalloc(sizeof(struct sm_sysfs_attribute), GFP_KERNEL); + if (!vendor_attribute) + goto error2; sysfs_attr_init(&vendor_attribute->dev_attr.attr); @@ -83,12 +87,24 @@ struct attribute_group *sm_create_sysfs_attributes(struct sm_ftl *ftl) /* Create array of pointers to the attributes */ attributes = kzalloc(sizeof(struct attribute *) * (NUM_ATTRIBUTES + 1), GFP_KERNEL); + if (!attributes) + goto error3; attributes[0] = &vendor_attribute->dev_attr.attr; /* Finally create the attribute group */ attr_group = kzalloc(sizeof(struct attribute_group), GFP_KERNEL); + if (!attr_group) + goto error4; attr_group->attrs = attributes; return attr_group; +error4: + kfree(attributes); +error3: + kfree(vendor_attribute); +error2: + kfree(vendor); +error1: + return NULL; } void sm_delete_sysfs_attributes(struct sm_ftl *ftl) @@ -1178,6 +1194,8 @@ static void sm_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd) } ftl->disk_attributes = sm_create_sysfs_attributes(ftl); + if (!ftl->disk_attributes) + goto error6; trans->disk_attributes = ftl->disk_attributes; sm_printk("Found %d MiB xD/SmartMedia FTL on mtd%d", -- GitLab From 89d8d32060de17c23f761df74799c7c07b79dd01 Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Fri, 11 Mar 2011 15:17:41 +0000 Subject: [PATCH 0607/2822] mtd: fix printf format warnings, mostly lack of %zd for size_t, in mtdswap Signed-off-by: David Woodhouse --- drivers/mtd/mtdswap.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/mtd/mtdswap.c b/drivers/mtd/mtdswap.c index 57e6cc30bc429..a65594fee4a37 100644 --- a/drivers/mtd/mtdswap.c +++ b/drivers/mtd/mtdswap.c @@ -331,7 +331,7 @@ static int mtdswap_read_oob(struct mtdswap_dev *d, loff_t from, if (ops->oobretlen < ops->ooblen) { dev_warn(d->dev, "Read OOB return short read (%zd bytes not " - "%d) for block at %08llx\n", + "%zd) for block at %08llx\n", ops->oobretlen, ops->ooblen, from); return -EIO; } @@ -421,7 +421,7 @@ static int mtdswap_write_marker(struct mtdswap_dev *d, struct swap_eb *eb, if (ops.oobretlen != ops.ooblen) { dev_warn(d->dev, "Short OOB write for block at %08llx: " - "%zd not %d\n", + "%zd not %zd\n", offset, ops.oobretlen, ops.ooblen); return ret; } @@ -705,13 +705,13 @@ retry: } if (ret < 0) { - dev_err(d->dev, "Write to MTD device failed: %d (%d written)", + dev_err(d->dev, "Write to MTD device failed: %d (%zd written)", ret, retlen); goto err; } if (retlen != PAGE_SIZE) { - dev_err(d->dev, "Short write to MTD device: %d written", + dev_err(d->dev, "Short write to MTD device: %zd written", retlen); ret = -EIO; goto err; @@ -758,7 +758,7 @@ retry: } if (retlen != PAGE_SIZE) { - dev_err(d->dev, "Short read: %d (block %u)\n", retlen, + dev_err(d->dev, "Short read: %zd (block %u)\n", retlen, oldblock); ret = -EIO; goto read_error; @@ -1188,7 +1188,7 @@ retry: } if (retlen != PAGE_SIZE) { - dev_err(d->dev, "Short read %d\n", retlen); + dev_err(d->dev, "Short read %zd\n", retlen); return -EIO; } @@ -1304,7 +1304,7 @@ static int mtdswap_show(struct seq_file *s, void *data) seq_printf(s, "discarded pages count: %llu\n", d->discard_page_count); seq_printf(s, "\n"); - seq_printf(s, "total pages: %lu\n", pages); + seq_printf(s, "total pages: %u\n", pages); seq_printf(s, "pages mapped: %u\n", mapped); return 0; @@ -1458,7 +1458,7 @@ static void mtdswap_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd) oinfo = mtd->ecclayout; if (!mtd->oobsize || !oinfo || oinfo->oobavail < MTDSWAP_OOBSIZE) { printk(KERN_ERR "%s: Not enough free bytes in OOB, " - "%d available, %u needed.\n", + "%d available, %lu needed.\n", MTDSWAP_PREFIX, oinfo->oobavail, MTDSWAP_OOBSIZE); return; } -- GitLab From 1a757fe5d4234293d6a3acccd7196f1386443956 Mon Sep 17 00:00:00 2001 From: Christoph Lameter Date: Fri, 25 Feb 2011 11:38:51 -0600 Subject: [PATCH 0608/2822] slub: min_partial needs to be in first cacheline It is used in unfreeze_slab() which is a performance critical function. Signed-off-by: Christoph Lameter Signed-off-by: Pekka Enberg --- include/linux/slub_def.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/linux/slub_def.h b/include/linux/slub_def.h index 8b6e8ae5d5cab..875df55ab36d3 100644 --- a/include/linux/slub_def.h +++ b/include/linux/slub_def.h @@ -70,6 +70,7 @@ struct kmem_cache { struct kmem_cache_cpu __percpu *cpu_slab; /* Used for retriving partial slabs etc */ unsigned long flags; + unsigned long min_partial; int size; /* The size of an object including meta data */ int objsize; /* The size of an object without meta data */ int offset; /* Free pointer offset. */ @@ -83,7 +84,6 @@ struct kmem_cache { void (*ctor)(void *); int inuse; /* Offset to metadata */ int align; /* Alignment */ - unsigned long min_partial; const char *name; /* Name (only for display!) */ struct list_head list; /* List of slab caches */ #ifdef CONFIG_SYSFS -- GitLab From d3f661d69a486db0e0e6343b452f45d91b4b3656 Mon Sep 17 00:00:00 2001 From: Christoph Lameter Date: Fri, 25 Feb 2011 11:38:52 -0600 Subject: [PATCH 0609/2822] slub: Get rid of slab_free_hook_irq() The following patch will make the fastpaths lockless and will no longer require interrupts to be disabled. Calling the free hook with irq disabled will no longer be possible. Move the slab_free_hook_irq() logic into slab_free_hook. Only disable interrupts if the features are selected that require callbacks with interrupts off and reenable after calls have been made. Signed-off-by: Christoph Lameter Signed-off-by: Pekka Enberg --- mm/slub.c | 29 +++++++++++++++++------------ 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/mm/slub.c b/mm/slub.c index e15aa7f193c97..bae7a5c636f48 100644 --- a/mm/slub.c +++ b/mm/slub.c @@ -807,14 +807,24 @@ static inline void slab_post_alloc_hook(struct kmem_cache *s, gfp_t flags, void static inline void slab_free_hook(struct kmem_cache *s, void *x) { kmemleak_free_recursive(x, s->flags); -} -static inline void slab_free_hook_irq(struct kmem_cache *s, void *object) -{ - kmemcheck_slab_free(s, object, s->objsize); - debug_check_no_locks_freed(object, s->objsize); - if (!(s->flags & SLAB_DEBUG_OBJECTS)) - debug_check_no_obj_freed(object, s->objsize); + /* + * Trouble is that we may no longer disable interupts in the fast path + * So in order to make the debug calls that expect irqs to be + * disabled we need to disable interrupts temporarily. + */ +#if defined(CONFIG_KMEMCHECK) || defined(CONFIG_LOCKDEP) + { + unsigned long flags; + + local_irq_save(flags); + kmemcheck_slab_free(s, x, s->objsize); + debug_check_no_locks_freed(x, s->objsize); + if (!(s->flags & SLAB_DEBUG_OBJECTS)) + debug_check_no_obj_freed(x, s->objsize); + local_irq_restore(flags); + } +#endif } /* @@ -1101,9 +1111,6 @@ static inline void slab_post_alloc_hook(struct kmem_cache *s, gfp_t flags, static inline void slab_free_hook(struct kmem_cache *s, void *x) {} -static inline void slab_free_hook_irq(struct kmem_cache *s, - void *object) {} - #endif /* CONFIG_SLUB_DEBUG */ /* @@ -1909,8 +1916,6 @@ static __always_inline void slab_free(struct kmem_cache *s, local_irq_save(flags); c = __this_cpu_ptr(s->cpu_slab); - slab_free_hook_irq(s, x); - if (likely(page == c->page && c->node != NUMA_NO_NODE)) { set_freepointer(s, object, c->freelist); c->freelist = object; -- GitLab From 8a5ec0ba42c4919e2d8f4c3138cc8b987fdb0b79 Mon Sep 17 00:00:00 2001 From: Christoph Lameter Date: Fri, 25 Feb 2011 11:38:54 -0600 Subject: [PATCH 0610/2822] Lockless (and preemptless) fastpaths for slub Use the this_cpu_cmpxchg_double functionality to implement a lockless allocation algorithm on arches that support fast this_cpu_ops. Each of the per cpu pointers is paired with a transaction id that ensures that updates of the per cpu information can only occur in sequence on a certain cpu. A transaction id is a "long" integer that is comprised of an event number and the cpu number. The event number is incremented for every change to the per cpu state. This means that the cmpxchg instruction can verify for an update that nothing interfered and that we are updating the percpu structure for the processor where we picked up the information and that we are also currently on that processor when we update the information. This results in a significant decrease of the overhead in the fastpaths. It also makes it easy to adopt the fast path for realtime kernels since this is lockless and does not require the use of the current per cpu area over the critical section. It is only important that the per cpu area is current at the beginning of the critical section and at the end. So there is no need even to disable preemption. Test results show that the fastpath cycle count is reduced by up to ~ 40% (alloc/free test goes from ~140 cycles down to ~80). The slowpath for kfree adds a few cycles. Sadly this does nothing for the slowpath which is where the main issues with performance in slub are but the best case performance rises significantly. (For that see the more complex slub patches that require cmpxchg_double) Kmalloc: alloc/free test Before: 10000 times kmalloc(8)/kfree -> 134 cycles 10000 times kmalloc(16)/kfree -> 152 cycles 10000 times kmalloc(32)/kfree -> 144 cycles 10000 times kmalloc(64)/kfree -> 142 cycles 10000 times kmalloc(128)/kfree -> 142 cycles 10000 times kmalloc(256)/kfree -> 132 cycles 10000 times kmalloc(512)/kfree -> 132 cycles 10000 times kmalloc(1024)/kfree -> 135 cycles 10000 times kmalloc(2048)/kfree -> 135 cycles 10000 times kmalloc(4096)/kfree -> 135 cycles 10000 times kmalloc(8192)/kfree -> 144 cycles 10000 times kmalloc(16384)/kfree -> 754 cycles After: 10000 times kmalloc(8)/kfree -> 78 cycles 10000 times kmalloc(16)/kfree -> 78 cycles 10000 times kmalloc(32)/kfree -> 82 cycles 10000 times kmalloc(64)/kfree -> 88 cycles 10000 times kmalloc(128)/kfree -> 79 cycles 10000 times kmalloc(256)/kfree -> 79 cycles 10000 times kmalloc(512)/kfree -> 85 cycles 10000 times kmalloc(1024)/kfree -> 82 cycles 10000 times kmalloc(2048)/kfree -> 82 cycles 10000 times kmalloc(4096)/kfree -> 85 cycles 10000 times kmalloc(8192)/kfree -> 82 cycles 10000 times kmalloc(16384)/kfree -> 706 cycles Kmalloc: Repeatedly allocate then free test Before: 10000 times kmalloc(8) -> 211 cycles kfree -> 113 cycles 10000 times kmalloc(16) -> 174 cycles kfree -> 115 cycles 10000 times kmalloc(32) -> 235 cycles kfree -> 129 cycles 10000 times kmalloc(64) -> 222 cycles kfree -> 120 cycles 10000 times kmalloc(128) -> 343 cycles kfree -> 139 cycles 10000 times kmalloc(256) -> 827 cycles kfree -> 147 cycles 10000 times kmalloc(512) -> 1048 cycles kfree -> 272 cycles 10000 times kmalloc(1024) -> 2043 cycles kfree -> 528 cycles 10000 times kmalloc(2048) -> 4002 cycles kfree -> 571 cycles 10000 times kmalloc(4096) -> 7740 cycles kfree -> 628 cycles 10000 times kmalloc(8192) -> 8062 cycles kfree -> 850 cycles 10000 times kmalloc(16384) -> 8895 cycles kfree -> 1249 cycles After: 10000 times kmalloc(8) -> 190 cycles kfree -> 129 cycles 10000 times kmalloc(16) -> 76 cycles kfree -> 123 cycles 10000 times kmalloc(32) -> 126 cycles kfree -> 124 cycles 10000 times kmalloc(64) -> 181 cycles kfree -> 128 cycles 10000 times kmalloc(128) -> 310 cycles kfree -> 140 cycles 10000 times kmalloc(256) -> 809 cycles kfree -> 165 cycles 10000 times kmalloc(512) -> 1005 cycles kfree -> 269 cycles 10000 times kmalloc(1024) -> 1999 cycles kfree -> 527 cycles 10000 times kmalloc(2048) -> 3967 cycles kfree -> 570 cycles 10000 times kmalloc(4096) -> 7658 cycles kfree -> 637 cycles 10000 times kmalloc(8192) -> 8111 cycles kfree -> 859 cycles 10000 times kmalloc(16384) -> 8791 cycles kfree -> 1173 cycles Signed-off-by: Christoph Lameter Signed-off-by: Pekka Enberg --- include/linux/slub_def.h | 5 +- mm/slub.c | 205 ++++++++++++++++++++++++++++++++++++++- 2 files changed, 207 insertions(+), 3 deletions(-) diff --git a/include/linux/slub_def.h b/include/linux/slub_def.h index 875df55ab36d3..009b0020079d9 100644 --- a/include/linux/slub_def.h +++ b/include/linux/slub_def.h @@ -35,7 +35,10 @@ enum stat_item { NR_SLUB_STAT_ITEMS }; struct kmem_cache_cpu { - void **freelist; /* Pointer to first free per cpu object */ + void **freelist; /* Pointer to next available object */ +#ifdef CONFIG_CMPXCHG_LOCAL + unsigned long tid; /* Globally unique transaction id */ +#endif struct page *page; /* The slab from which we are allocating */ int node; /* The node of the page (or -1 for debug) */ #ifdef CONFIG_SLUB_STATS diff --git a/mm/slub.c b/mm/slub.c index bae7a5c636f48..65030c7fd7e22 100644 --- a/mm/slub.c +++ b/mm/slub.c @@ -1494,6 +1494,77 @@ static void unfreeze_slab(struct kmem_cache *s, struct page *page, int tail) } } +#ifdef CONFIG_CMPXCHG_LOCAL +#ifdef CONFIG_PREEMPT +/* + * Calculate the next globally unique transaction for disambiguiation + * during cmpxchg. The transactions start with the cpu number and are then + * incremented by CONFIG_NR_CPUS. + */ +#define TID_STEP roundup_pow_of_two(CONFIG_NR_CPUS) +#else +/* + * No preemption supported therefore also no need to check for + * different cpus. + */ +#define TID_STEP 1 +#endif + +static inline unsigned long next_tid(unsigned long tid) +{ + return tid + TID_STEP; +} + +static inline unsigned int tid_to_cpu(unsigned long tid) +{ + return tid % TID_STEP; +} + +static inline unsigned long tid_to_event(unsigned long tid) +{ + return tid / TID_STEP; +} + +static inline unsigned int init_tid(int cpu) +{ + return cpu; +} + +static inline void note_cmpxchg_failure(const char *n, + const struct kmem_cache *s, unsigned long tid) +{ +#ifdef SLUB_DEBUG_CMPXCHG + unsigned long actual_tid = __this_cpu_read(s->cpu_slab->tid); + + printk(KERN_INFO "%s %s: cmpxchg redo ", n, s->name); + +#ifdef CONFIG_PREEMPT + if (tid_to_cpu(tid) != tid_to_cpu(actual_tid)) + printk("due to cpu change %d -> %d\n", + tid_to_cpu(tid), tid_to_cpu(actual_tid)); + else +#endif + if (tid_to_event(tid) != tid_to_event(actual_tid)) + printk("due to cpu running other code. Event %ld->%ld\n", + tid_to_event(tid), tid_to_event(actual_tid)); + else + printk("for unknown reason: actual=%lx was=%lx target=%lx\n", + actual_tid, tid, next_tid(tid)); +#endif +} + +#endif + +void init_kmem_cache_cpus(struct kmem_cache *s) +{ +#if defined(CONFIG_CMPXCHG_LOCAL) && defined(CONFIG_PREEMPT) + int cpu; + + for_each_possible_cpu(cpu) + per_cpu_ptr(s->cpu_slab, cpu)->tid = init_tid(cpu); +#endif + +} /* * Remove the cpu slab */ @@ -1525,6 +1596,9 @@ static void deactivate_slab(struct kmem_cache *s, struct kmem_cache_cpu *c) page->inuse--; } c->page = NULL; +#ifdef CONFIG_CMPXCHG_LOCAL + c->tid = next_tid(c->tid); +#endif unfreeze_slab(s, page, tail); } @@ -1659,6 +1733,19 @@ static void *__slab_alloc(struct kmem_cache *s, gfp_t gfpflags, int node, { void **object; struct page *new; +#ifdef CONFIG_CMPXCHG_LOCAL + unsigned long flags; + + local_irq_save(flags); +#ifdef CONFIG_PREEMPT + /* + * We may have been preempted and rescheduled on a different + * cpu before disabling interrupts. Need to reload cpu area + * pointer. + */ + c = this_cpu_ptr(s->cpu_slab); +#endif +#endif /* We handle __GFP_ZERO in the caller */ gfpflags &= ~__GFP_ZERO; @@ -1685,6 +1772,10 @@ load_freelist: c->node = page_to_nid(c->page); unlock_out: slab_unlock(c->page); +#ifdef CONFIG_CMPXCHG_LOCAL + c->tid = next_tid(c->tid); + local_irq_restore(flags); +#endif stat(s, ALLOC_SLOWPATH); return object; @@ -1746,23 +1837,76 @@ static __always_inline void *slab_alloc(struct kmem_cache *s, { void **object; struct kmem_cache_cpu *c; +#ifdef CONFIG_CMPXCHG_LOCAL + unsigned long tid; +#else unsigned long flags; +#endif if (slab_pre_alloc_hook(s, gfpflags)) return NULL; +#ifndef CONFIG_CMPXCHG_LOCAL local_irq_save(flags); +#else +redo: +#endif + + /* + * Must read kmem_cache cpu data via this cpu ptr. Preemption is + * enabled. We may switch back and forth between cpus while + * reading from one cpu area. That does not matter as long + * as we end up on the original cpu again when doing the cmpxchg. + */ c = __this_cpu_ptr(s->cpu_slab); + +#ifdef CONFIG_CMPXCHG_LOCAL + /* + * The transaction ids are globally unique per cpu and per operation on + * a per cpu queue. Thus they can be guarantee that the cmpxchg_double + * occurs on the right processor and that there was no operation on the + * linked list in between. + */ + tid = c->tid; + barrier(); +#endif + object = c->freelist; if (unlikely(!object || !node_match(c, node))) object = __slab_alloc(s, gfpflags, node, addr, c); else { +#ifdef CONFIG_CMPXCHG_LOCAL + /* + * The cmpxchg will only match if there was no additonal + * operation and if we are on the right processor. + * + * The cmpxchg does the following atomically (without lock semantics!) + * 1. Relocate first pointer to the current per cpu area. + * 2. Verify that tid and freelist have not been changed + * 3. If they were not changed replace tid and freelist + * + * Since this is without lock semantics the protection is only against + * code executing on this cpu *not* from access by other cpus. + */ + if (unlikely(!this_cpu_cmpxchg_double( + s->cpu_slab->freelist, s->cpu_slab->tid, + object, tid, + get_freepointer(s, object), next_tid(tid)))) { + + note_cmpxchg_failure("slab_alloc", s, tid); + goto redo; + } +#else c->freelist = get_freepointer(s, object); +#endif stat(s, ALLOC_FASTPATH); } + +#ifndef CONFIG_CMPXCHG_LOCAL local_irq_restore(flags); +#endif if (unlikely(gfpflags & __GFP_ZERO) && object) memset(object, 0, s->objsize); @@ -1840,9 +1984,13 @@ static void __slab_free(struct kmem_cache *s, struct page *page, { void *prior; void **object = (void *)x; +#ifdef CONFIG_CMPXCHG_LOCAL + unsigned long flags; - stat(s, FREE_SLOWPATH); + local_irq_save(flags); +#endif slab_lock(page); + stat(s, FREE_SLOWPATH); if (kmem_cache_debug(s)) goto debug; @@ -1872,6 +2020,9 @@ checks_ok: out_unlock: slab_unlock(page); +#ifdef CONFIG_CMPXCHG_LOCAL + local_irq_restore(flags); +#endif return; slab_empty: @@ -1883,6 +2034,9 @@ slab_empty: stat(s, FREE_REMOVE_PARTIAL); } slab_unlock(page); +#ifdef CONFIG_CMPXCHG_LOCAL + local_irq_restore(flags); +#endif stat(s, FREE_SLAB); discard_slab(s, page); return; @@ -1909,21 +2063,54 @@ static __always_inline void slab_free(struct kmem_cache *s, { void **object = (void *)x; struct kmem_cache_cpu *c; +#ifdef CONFIG_CMPXCHG_LOCAL + unsigned long tid; +#else unsigned long flags; +#endif slab_free_hook(s, x); +#ifndef CONFIG_CMPXCHG_LOCAL local_irq_save(flags); +#endif + +redo: + /* + * Determine the currently cpus per cpu slab. + * The cpu may change afterward. However that does not matter since + * data is retrieved via this pointer. If we are on the same cpu + * during the cmpxchg then the free will succedd. + */ c = __this_cpu_ptr(s->cpu_slab); +#ifdef CONFIG_CMPXCHG_LOCAL + tid = c->tid; + barrier(); +#endif + if (likely(page == c->page && c->node != NUMA_NO_NODE)) { set_freepointer(s, object, c->freelist); + +#ifdef CONFIG_CMPXCHG_LOCAL + if (unlikely(!this_cpu_cmpxchg_double( + s->cpu_slab->freelist, s->cpu_slab->tid, + c->freelist, tid, + object, next_tid(tid)))) { + + note_cmpxchg_failure("slab_free", s, tid); + goto redo; + } +#else c->freelist = object; +#endif stat(s, FREE_FASTPATH); } else __slab_free(s, page, x, addr); +#ifndef CONFIG_CMPXCHG_LOCAL local_irq_restore(flags); +#endif } void kmem_cache_free(struct kmem_cache *s, void *x) @@ -2115,9 +2302,23 @@ static inline int alloc_kmem_cache_cpus(struct kmem_cache *s) BUILD_BUG_ON(PERCPU_DYNAMIC_EARLY_SIZE < SLUB_PAGE_SHIFT * sizeof(struct kmem_cache_cpu)); +#ifdef CONFIG_CMPXCHG_LOCAL + /* + * Must align to double word boundary for the double cmpxchg instructions + * to work. + */ + s->cpu_slab = __alloc_percpu(sizeof(struct kmem_cache_cpu), 2 * sizeof(void *)); +#else + /* Regular alignment is sufficient */ s->cpu_slab = alloc_percpu(struct kmem_cache_cpu); +#endif + + if (!s->cpu_slab) + return 0; + + init_kmem_cache_cpus(s); - return s->cpu_slab != NULL; + return 1; } static struct kmem_cache *kmem_cache_node; -- GitLab From ab9a0f196f2f4f080df54402493ea3dc31b5243e Mon Sep 17 00:00:00 2001 From: Lai Jiangshan Date: Thu, 10 Mar 2011 15:21:48 +0800 Subject: [PATCH 0611/2822] slub: automatically reserve bytes at the end of slab There is no "struct" for slub's slab, it shares with struct page. But struct page is very small, it is insufficient when we need to add some metadata for slab. So we add a field "reserved" to struct kmem_cache, when a slab is allocated, kmem_cache->reserved bytes are automatically reserved at the end of the slab for slab's metadata. Changed from v1: Export the reserved field via sysfs Acked-by: Christoph Lameter Signed-off-by: Lai Jiangshan Signed-off-by: Pekka Enberg --- include/linux/slub_def.h | 1 + mm/slub.c | 47 +++++++++++++++++++++++++--------------- 2 files changed, 31 insertions(+), 17 deletions(-) diff --git a/include/linux/slub_def.h b/include/linux/slub_def.h index 8b6e8ae5d5cab..ae0093cc51894 100644 --- a/include/linux/slub_def.h +++ b/include/linux/slub_def.h @@ -83,6 +83,7 @@ struct kmem_cache { void (*ctor)(void *); int inuse; /* Offset to metadata */ int align; /* Alignment */ + int reserved; /* Reserved bytes at the end of slabs */ unsigned long min_partial; const char *name; /* Name (only for display!) */ struct list_head list; /* List of slab caches */ diff --git a/mm/slub.c b/mm/slub.c index e15aa7f193c97..d3d17677bab54 100644 --- a/mm/slub.c +++ b/mm/slub.c @@ -281,11 +281,16 @@ static inline int slab_index(void *p, struct kmem_cache *s, void *addr) return (p - addr) / s->size; } +static inline int order_objects(int order, unsigned long size, int reserved) +{ + return ((PAGE_SIZE << order) - reserved) / size; +} + static inline struct kmem_cache_order_objects oo_make(int order, - unsigned long size) + unsigned long size, int reserved) { struct kmem_cache_order_objects x = { - (order << OO_SHIFT) + (PAGE_SIZE << order) / size + (order << OO_SHIFT) + order_objects(order, size, reserved) }; return x; @@ -617,7 +622,7 @@ static int slab_pad_check(struct kmem_cache *s, struct page *page) return 1; start = page_address(page); - length = (PAGE_SIZE << compound_order(page)); + length = (PAGE_SIZE << compound_order(page)) - s->reserved; end = start + length; remainder = length % s->size; if (!remainder) @@ -698,7 +703,7 @@ static int check_slab(struct kmem_cache *s, struct page *page) return 0; } - maxobj = (PAGE_SIZE << compound_order(page)) / s->size; + maxobj = order_objects(compound_order(page), s->size, s->reserved); if (page->objects > maxobj) { slab_err(s, page, "objects %u > max %u", s->name, page->objects, maxobj); @@ -748,7 +753,7 @@ static int on_freelist(struct kmem_cache *s, struct page *page, void *search) nr++; } - max_objects = (PAGE_SIZE << compound_order(page)) / s->size; + max_objects = order_objects(compound_order(page), s->size, s->reserved); if (max_objects > MAX_OBJS_PER_PAGE) max_objects = MAX_OBJS_PER_PAGE; @@ -1988,13 +1993,13 @@ static int slub_nomerge; * the smallest order which will fit the object. */ static inline int slab_order(int size, int min_objects, - int max_order, int fract_leftover) + int max_order, int fract_leftover, int reserved) { int order; int rem; int min_order = slub_min_order; - if ((PAGE_SIZE << min_order) / size > MAX_OBJS_PER_PAGE) + if (order_objects(min_order, size, reserved) > MAX_OBJS_PER_PAGE) return get_order(size * MAX_OBJS_PER_PAGE) - 1; for (order = max(min_order, @@ -2003,10 +2008,10 @@ static inline int slab_order(int size, int min_objects, unsigned long slab_size = PAGE_SIZE << order; - if (slab_size < min_objects * size) + if (slab_size < min_objects * size + reserved) continue; - rem = slab_size % size; + rem = (slab_size - reserved) % size; if (rem <= slab_size / fract_leftover) break; @@ -2016,7 +2021,7 @@ static inline int slab_order(int size, int min_objects, return order; } -static inline int calculate_order(int size) +static inline int calculate_order(int size, int reserved) { int order; int min_objects; @@ -2034,14 +2039,14 @@ static inline int calculate_order(int size) min_objects = slub_min_objects; if (!min_objects) min_objects = 4 * (fls(nr_cpu_ids) + 1); - max_objects = (PAGE_SIZE << slub_max_order)/size; + max_objects = order_objects(slub_max_order, size, reserved); min_objects = min(min_objects, max_objects); while (min_objects > 1) { fraction = 16; while (fraction >= 4) { order = slab_order(size, min_objects, - slub_max_order, fraction); + slub_max_order, fraction, reserved); if (order <= slub_max_order) return order; fraction /= 2; @@ -2053,14 +2058,14 @@ static inline int calculate_order(int size) * We were unable to place multiple objects in a slab. Now * lets see if we can place a single object there. */ - order = slab_order(size, 1, slub_max_order, 1); + order = slab_order(size, 1, slub_max_order, 1, reserved); if (order <= slub_max_order) return order; /* * Doh this slab cannot be placed using slub_max_order. */ - order = slab_order(size, 1, MAX_ORDER, 1); + order = slab_order(size, 1, MAX_ORDER, 1, reserved); if (order < MAX_ORDER) return order; return -ENOSYS; @@ -2311,7 +2316,7 @@ static int calculate_sizes(struct kmem_cache *s, int forced_order) if (forced_order >= 0) order = forced_order; else - order = calculate_order(size); + order = calculate_order(size, s->reserved); if (order < 0) return 0; @@ -2329,8 +2334,8 @@ static int calculate_sizes(struct kmem_cache *s, int forced_order) /* * Determine the number of objects per slab */ - s->oo = oo_make(order, size); - s->min = oo_make(get_order(size), size); + s->oo = oo_make(order, size, s->reserved); + s->min = oo_make(get_order(size), size, s->reserved); if (oo_objects(s->oo) > oo_objects(s->max)) s->max = s->oo; @@ -2349,6 +2354,7 @@ static int kmem_cache_open(struct kmem_cache *s, s->objsize = size; s->align = align; s->flags = kmem_cache_flags(size, flags, name, ctor); + s->reserved = 0; if (!calculate_sizes(s, -1)) goto error; @@ -4017,6 +4023,12 @@ static ssize_t destroy_by_rcu_show(struct kmem_cache *s, char *buf) } SLAB_ATTR_RO(destroy_by_rcu); +static ssize_t reserved_show(struct kmem_cache *s, char *buf) +{ + return sprintf(buf, "%d\n", s->reserved); +} +SLAB_ATTR_RO(reserved); + #ifdef CONFIG_SLUB_DEBUG static ssize_t slabs_show(struct kmem_cache *s, char *buf) { @@ -4303,6 +4315,7 @@ static struct attribute *slab_attrs[] = { &reclaim_account_attr.attr, &destroy_by_rcu_attr.attr, &shrink_attr.attr, + &reserved_attr.attr, #ifdef CONFIG_SLUB_DEBUG &total_objects_attr.attr, &slabs_attr.attr, -- GitLab From da9a638c6f8fc0633fa94a334f1c053f5e307177 Mon Sep 17 00:00:00 2001 From: Lai Jiangshan Date: Thu, 10 Mar 2011 15:22:00 +0800 Subject: [PATCH 0612/2822] slub,rcu: don't assume the size of struct rcu_head The size of struct rcu_head may be changed. When it becomes larger, it will pollute the page array. We reserve some some bytes for struct rcu_head when a slab is allocated in this situation. Changed from V1: use VM_BUG_ON instead BUG_ON Acked-by: Christoph Lameter Signed-off-by: Lai Jiangshan Signed-off-by: Pekka Enberg --- mm/slub.c | 30 +++++++++++++++++++++++++----- 1 file changed, 25 insertions(+), 5 deletions(-) diff --git a/mm/slub.c b/mm/slub.c index d3d17677bab54..ebba3eb193692 100644 --- a/mm/slub.c +++ b/mm/slub.c @@ -1254,21 +1254,38 @@ static void __free_slab(struct kmem_cache *s, struct page *page) __free_pages(page, order); } +#define need_reserve_slab_rcu \ + (sizeof(((struct page *)NULL)->lru) < sizeof(struct rcu_head)) + static void rcu_free_slab(struct rcu_head *h) { struct page *page; - page = container_of((struct list_head *)h, struct page, lru); + if (need_reserve_slab_rcu) + page = virt_to_head_page(h); + else + page = container_of((struct list_head *)h, struct page, lru); + __free_slab(page->slab, page); } static void free_slab(struct kmem_cache *s, struct page *page) { if (unlikely(s->flags & SLAB_DESTROY_BY_RCU)) { - /* - * RCU free overloads the RCU head over the LRU - */ - struct rcu_head *head = (void *)&page->lru; + struct rcu_head *head; + + if (need_reserve_slab_rcu) { + int order = compound_order(page); + int offset = (PAGE_SIZE << order) - s->reserved; + + VM_BUG_ON(s->reserved != sizeof(*head)); + head = page_address(page) + offset; + } else { + /* + * RCU free overloads the RCU head over the LRU + */ + head = (void *)&page->lru; + } call_rcu(head, rcu_free_slab); } else @@ -2356,6 +2373,9 @@ static int kmem_cache_open(struct kmem_cache *s, s->flags = kmem_cache_flags(size, flags, name, ctor); s->reserved = 0; + if (need_reserve_slab_rcu && (s->flags & SLAB_DESTROY_BY_RCU)) + s->reserved = sizeof(struct rcu_head); + if (!calculate_sizes(s, -1)) goto error; if (disable_higher_order_debug) { -- GitLab From 5bfe53a77e8a3ffce4a10003c75f464a138e272d Mon Sep 17 00:00:00 2001 From: Lai Jiangshan Date: Thu, 10 Mar 2011 15:22:24 +0800 Subject: [PATCH 0613/2822] slab,rcu: don't assume the size of struct rcu_head The size of struct rcu_head may be changed. When it becomes larger, it may pollute the data after struct slab. Acked-by: Christoph Lameter Signed-off-by: Lai Jiangshan Signed-off-by: Pekka Enberg --- mm/slab.c | 39 +++++++++++++++++++++------------------ 1 file changed, 21 insertions(+), 18 deletions(-) diff --git a/mm/slab.c b/mm/slab.c index 37961d1f584fe..52cf0b4634d41 100644 --- a/mm/slab.c +++ b/mm/slab.c @@ -190,22 +190,6 @@ typedef unsigned int kmem_bufctl_t; #define BUFCTL_ACTIVE (((kmem_bufctl_t)(~0U))-2) #define SLAB_LIMIT (((kmem_bufctl_t)(~0U))-3) -/* - * struct slab - * - * Manages the objs in a slab. Placed either at the beginning of mem allocated - * for a slab, or allocated from an general cache. - * Slabs are chained into three list: fully used, partial, fully free slabs. - */ -struct slab { - struct list_head list; - unsigned long colouroff; - void *s_mem; /* including colour offset */ - unsigned int inuse; /* num of objs active in slab */ - kmem_bufctl_t free; - unsigned short nodeid; -}; - /* * struct slab_rcu * @@ -219,8 +203,6 @@ struct slab { * * rcu_read_lock before reading the address, then rcu_read_unlock after * taking the spinlock within the structure expected at that address. - * - * We assume struct slab_rcu can overlay struct slab when destroying. */ struct slab_rcu { struct rcu_head head; @@ -228,6 +210,27 @@ struct slab_rcu { void *addr; }; +/* + * struct slab + * + * Manages the objs in a slab. Placed either at the beginning of mem allocated + * for a slab, or allocated from an general cache. + * Slabs are chained into three list: fully used, partial, fully free slabs. + */ +struct slab { + union { + struct { + struct list_head list; + unsigned long colouroff; + void *s_mem; /* including colour offset */ + unsigned int inuse; /* num of objs active in slab */ + kmem_bufctl_t free; + unsigned short nodeid; + }; + struct slab_rcu __slab_cover_slab_rcu; + }; +}; + /* * struct array_cache * -- GitLab From 193bd40026443835e1b96c79d5efe559d01509ae Mon Sep 17 00:00:00 2001 From: Ivan Djelic Date: Fri, 11 Mar 2011 11:05:33 +0100 Subject: [PATCH 0614/2822] mtd: nand: add software BCH ECC support This patch adds software BCH ECC support to mtd, in order to handle recent NAND device ecc requirements (4 bits or more). It does so by adding a new ecc mode (NAND_ECC_SOFT_BCH) for use by board drivers, and a new Kconfig option to enable BCH support. It relies on the generic BCH library introduced in a previous patch. When a board driver uses mode NAND_ECC_SOFT_BCH, it should also set fields chip->ecc.size and chip->ecc.bytes to select BCH ecc data size and required error correction capability. See nand_bch_init() documentation for details. It has been tested on the following platforms using mtd-utils, UBI and UBIFS: x86 (with nandsim), arm926ejs. Signed-off-by: Ivan Djelic Signed-off-by: David Woodhouse --- drivers/mtd/nand/Kconfig | 15 +++ drivers/mtd/nand/Makefile | 1 + drivers/mtd/nand/nand_base.c | 40 +++++- drivers/mtd/nand/nand_bch.c | 243 +++++++++++++++++++++++++++++++++++ include/linux/mtd/nand.h | 3 + include/linux/mtd/nand_bch.h | 72 +++++++++++ 6 files changed, 373 insertions(+), 1 deletion(-) create mode 100644 drivers/mtd/nand/nand_bch.c create mode 100644 include/linux/mtd/nand_bch.h diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig index c89592239bc70..78205ac2b10f2 100644 --- a/drivers/mtd/nand/Kconfig +++ b/drivers/mtd/nand/Kconfig @@ -31,6 +31,21 @@ config MTD_NAND_VERIFY_WRITE device thinks the write was successful, a bit could have been flipped accidentally due to device wear or something else. +config MTD_NAND_BCH + tristate + select BCH + depends on MTD_NAND_ECC_BCH + default MTD_NAND + +config MTD_NAND_ECC_BCH + bool "Support software BCH ECC" + default n + help + This enables support for software BCH error correction. Binary BCH + codes are more powerful and cpu intensive than traditional Hamming + ECC codes. They are used with NAND devices requiring more than 1 bit + of error correction. + config MTD_SM_COMMON tristate default n diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile index 8ad6faec72cb3..5745d831168e4 100644 --- a/drivers/mtd/nand/Makefile +++ b/drivers/mtd/nand/Makefile @@ -4,6 +4,7 @@ obj-$(CONFIG_MTD_NAND) += nand.o obj-$(CONFIG_MTD_NAND_ECC) += nand_ecc.o +obj-$(CONFIG_MTD_NAND_BCH) += nand_bch.o obj-$(CONFIG_MTD_NAND_IDS) += nand_ids.o obj-$(CONFIG_MTD_SM_COMMON) += sm_common.o diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index da7604050347c..85cfc061d41cd 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c @@ -42,6 +42,7 @@ #include #include #include +#include #include #include #include @@ -3248,7 +3249,7 @@ int nand_scan_tail(struct mtd_info *mtd) /* * If no default placement scheme is given, select an appropriate one */ - if (!chip->ecc.layout) { + if (!chip->ecc.layout && (chip->ecc.mode != NAND_ECC_SOFT_BCH)) { switch (mtd->oobsize) { case 8: chip->ecc.layout = &nand_oob_8; @@ -3351,6 +3352,40 @@ int nand_scan_tail(struct mtd_info *mtd) chip->ecc.bytes = 3; break; + case NAND_ECC_SOFT_BCH: + if (!mtd_nand_has_bch()) { + printk(KERN_WARNING "CONFIG_MTD_ECC_BCH not enabled\n"); + BUG(); + } + chip->ecc.calculate = nand_bch_calculate_ecc; + chip->ecc.correct = nand_bch_correct_data; + chip->ecc.read_page = nand_read_page_swecc; + chip->ecc.read_subpage = nand_read_subpage; + chip->ecc.write_page = nand_write_page_swecc; + chip->ecc.read_page_raw = nand_read_page_raw; + chip->ecc.write_page_raw = nand_write_page_raw; + chip->ecc.read_oob = nand_read_oob_std; + chip->ecc.write_oob = nand_write_oob_std; + /* + * Board driver should supply ecc.size and ecc.bytes values to + * select how many bits are correctable; see nand_bch_init() + * for details. + * Otherwise, default to 4 bits for large page devices + */ + if (!chip->ecc.size && (mtd->oobsize >= 64)) { + chip->ecc.size = 512; + chip->ecc.bytes = 7; + } + chip->ecc.priv = nand_bch_init(mtd, + chip->ecc.size, + chip->ecc.bytes, + &chip->ecc.layout); + if (!chip->ecc.priv) { + printk(KERN_WARNING "BCH ECC initialization failed!\n"); + BUG(); + } + break; + case NAND_ECC_NONE: printk(KERN_WARNING "NAND_ECC_NONE selected by board driver. " "This is not recommended !!\n"); @@ -3501,6 +3536,9 @@ void nand_release(struct mtd_info *mtd) { struct nand_chip *chip = mtd->priv; + if (chip->ecc.mode == NAND_ECC_SOFT_BCH) + nand_bch_free((struct nand_bch_control *)chip->ecc.priv); + #ifdef CONFIG_MTD_PARTITIONS /* Deregister partitions */ del_mtd_partitions(mtd); diff --git a/drivers/mtd/nand/nand_bch.c b/drivers/mtd/nand/nand_bch.c new file mode 100644 index 0000000000000..0f931e757116f --- /dev/null +++ b/drivers/mtd/nand/nand_bch.c @@ -0,0 +1,243 @@ +/* + * This file provides ECC correction for more than 1 bit per block of data, + * using binary BCH codes. It relies on the generic BCH library lib/bch.c. + * + * Copyright © 2011 Ivan Djelic + * + * This file is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 or (at your option) any + * later version. + * + * This file is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this file; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/** + * struct nand_bch_control - private NAND BCH control structure + * @bch: BCH control structure + * @ecclayout: private ecc layout for this BCH configuration + * @errloc: error location array + * @eccmask: XOR ecc mask, allows erased pages to be decoded as valid + */ +struct nand_bch_control { + struct bch_control *bch; + struct nand_ecclayout ecclayout; + unsigned int *errloc; + unsigned char *eccmask; +}; + +/** + * nand_bch_calculate_ecc - [NAND Interface] Calculate ECC for data block + * @mtd: MTD block structure + * @buf: input buffer with raw data + * @code: output buffer with ECC + */ +int nand_bch_calculate_ecc(struct mtd_info *mtd, const unsigned char *buf, + unsigned char *code) +{ + const struct nand_chip *chip = mtd->priv; + struct nand_bch_control *nbc = chip->ecc.priv; + unsigned int i; + + memset(code, 0, chip->ecc.bytes); + encode_bch(nbc->bch, buf, chip->ecc.size, code); + + /* apply mask so that an erased page is a valid codeword */ + for (i = 0; i < chip->ecc.bytes; i++) + code[i] ^= nbc->eccmask[i]; + + return 0; +} +EXPORT_SYMBOL(nand_bch_calculate_ecc); + +/** + * nand_bch_correct_data - [NAND Interface] Detect and correct bit error(s) + * @mtd: MTD block structure + * @buf: raw data read from the chip + * @read_ecc: ECC from the chip + * @calc_ecc: the ECC calculated from raw data + * + * Detect and correct bit errors for a data byte block + */ +int nand_bch_correct_data(struct mtd_info *mtd, unsigned char *buf, + unsigned char *read_ecc, unsigned char *calc_ecc) +{ + const struct nand_chip *chip = mtd->priv; + struct nand_bch_control *nbc = chip->ecc.priv; + unsigned int *errloc = nbc->errloc; + int i, count; + + count = decode_bch(nbc->bch, NULL, chip->ecc.size, read_ecc, calc_ecc, + NULL, errloc); + if (count > 0) { + for (i = 0; i < count; i++) { + if (errloc[i] < (chip->ecc.size*8)) + /* error is located in data, correct it */ + buf[errloc[i] >> 3] ^= (1 << (errloc[i] & 7)); + /* else error in ecc, no action needed */ + + DEBUG(MTD_DEBUG_LEVEL0, "%s: corrected bitflip %u\n", + __func__, errloc[i]); + } + } else if (count < 0) { + printk(KERN_ERR "ecc unrecoverable error\n"); + count = -1; + } + return count; +} +EXPORT_SYMBOL(nand_bch_correct_data); + +/** + * nand_bch_init - [NAND Interface] Initialize NAND BCH error correction + * @mtd: MTD block structure + * @eccsize: ecc block size in bytes + * @eccbytes: ecc length in bytes + * @ecclayout: output default layout + * + * Returns: + * a pointer to a new NAND BCH control structure, or NULL upon failure + * + * Initialize NAND BCH error correction. Parameters @eccsize and @eccbytes + * are used to compute BCH parameters m (Galois field order) and t (error + * correction capability). @eccbytes should be equal to the number of bytes + * required to store m*t bits, where m is such that 2^m-1 > @eccsize*8. + * + * Example: to configure 4 bit correction per 512 bytes, you should pass + * @eccsize = 512 (thus, m=13 is the smallest integer such that 2^m-1 > 512*8) + * @eccbytes = 7 (7 bytes are required to store m*t = 13*4 = 52 bits) + */ +struct nand_bch_control * +nand_bch_init(struct mtd_info *mtd, unsigned int eccsize, unsigned int eccbytes, + struct nand_ecclayout **ecclayout) +{ + unsigned int m, t, eccsteps, i; + struct nand_ecclayout *layout; + struct nand_bch_control *nbc = NULL; + unsigned char *erased_page; + + if (!eccsize || !eccbytes) { + printk(KERN_WARNING "ecc parameters not supplied\n"); + goto fail; + } + + m = fls(1+8*eccsize); + t = (eccbytes*8)/m; + + nbc = kzalloc(sizeof(*nbc), GFP_KERNEL); + if (!nbc) + goto fail; + + nbc->bch = init_bch(m, t, 0); + if (!nbc->bch) + goto fail; + + /* verify that eccbytes has the expected value */ + if (nbc->bch->ecc_bytes != eccbytes) { + printk(KERN_WARNING "invalid eccbytes %u, should be %u\n", + eccbytes, nbc->bch->ecc_bytes); + goto fail; + } + + eccsteps = mtd->writesize/eccsize; + + /* if no ecc placement scheme was provided, build one */ + if (!*ecclayout) { + + /* handle large page devices only */ + if (mtd->oobsize < 64) { + printk(KERN_WARNING "must provide an oob scheme for " + "oobsize %d\n", mtd->oobsize); + goto fail; + } + + layout = &nbc->ecclayout; + layout->eccbytes = eccsteps*eccbytes; + + /* reserve 2 bytes for bad block marker */ + if (layout->eccbytes+2 > mtd->oobsize) { + printk(KERN_WARNING "no suitable oob scheme available " + "for oobsize %d eccbytes %u\n", mtd->oobsize, + eccbytes); + goto fail; + } + /* put ecc bytes at oob tail */ + for (i = 0; i < layout->eccbytes; i++) + layout->eccpos[i] = mtd->oobsize-layout->eccbytes+i; + + layout->oobfree[0].offset = 2; + layout->oobfree[0].length = mtd->oobsize-2-layout->eccbytes; + + *ecclayout = layout; + } + + /* sanity checks */ + if (8*(eccsize+eccbytes) >= (1 << m)) { + printk(KERN_WARNING "eccsize %u is too large\n", eccsize); + goto fail; + } + if ((*ecclayout)->eccbytes != (eccsteps*eccbytes)) { + printk(KERN_WARNING "invalid ecc layout\n"); + goto fail; + } + + nbc->eccmask = kmalloc(eccbytes, GFP_KERNEL); + nbc->errloc = kmalloc(t*sizeof(*nbc->errloc), GFP_KERNEL); + if (!nbc->eccmask || !nbc->errloc) + goto fail; + /* + * compute and store the inverted ecc of an erased ecc block + */ + erased_page = kmalloc(eccsize, GFP_KERNEL); + if (!erased_page) + goto fail; + + memset(erased_page, 0xff, eccsize); + memset(nbc->eccmask, 0, eccbytes); + encode_bch(nbc->bch, erased_page, eccsize, nbc->eccmask); + kfree(erased_page); + + for (i = 0; i < eccbytes; i++) + nbc->eccmask[i] ^= 0xff; + + return nbc; +fail: + nand_bch_free(nbc); + return NULL; +} +EXPORT_SYMBOL(nand_bch_init); + +/** + * nand_bch_free - [NAND Interface] Release NAND BCH ECC resources + * @nbc: NAND BCH control structure + */ +void nand_bch_free(struct nand_bch_control *nbc) +{ + if (nbc) { + free_bch(nbc->bch); + kfree(nbc->errloc); + kfree(nbc->eccmask); + kfree(nbc); + } +} +EXPORT_SYMBOL(nand_bch_free); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Ivan Djelic "); +MODULE_DESCRIPTION("NAND software BCH ECC support"); diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h index 1f489b247a297..ae67ef56a8f5a 100644 --- a/include/linux/mtd/nand.h +++ b/include/linux/mtd/nand.h @@ -140,6 +140,7 @@ typedef enum { NAND_ECC_HW, NAND_ECC_HW_SYNDROME, NAND_ECC_HW_OOB_FIRST, + NAND_ECC_SOFT_BCH, } nand_ecc_modes_t; /* @@ -339,6 +340,7 @@ struct nand_hw_control { * @prepad: padding information for syndrome based ecc generators * @postpad: padding information for syndrome based ecc generators * @layout: ECC layout control struct pointer + * @priv: pointer to private ecc control data * @hwctl: function to control hardware ecc generator. Must only * be provided if an hardware ECC is available * @calculate: function for ecc calculation or readback from ecc hardware @@ -362,6 +364,7 @@ struct nand_ecc_ctrl { int prepad; int postpad; struct nand_ecclayout *layout; + void *priv; void (*hwctl)(struct mtd_info *mtd, int mode); int (*calculate)(struct mtd_info *mtd, const uint8_t *dat, uint8_t *ecc_code); diff --git a/include/linux/mtd/nand_bch.h b/include/linux/mtd/nand_bch.h new file mode 100644 index 0000000000000..74acf5367556e --- /dev/null +++ b/include/linux/mtd/nand_bch.h @@ -0,0 +1,72 @@ +/* + * Copyright © 2011 Ivan Djelic + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This file is the header for the NAND BCH ECC implementation. + */ + +#ifndef __MTD_NAND_BCH_H__ +#define __MTD_NAND_BCH_H__ + +struct mtd_info; +struct nand_bch_control; + +#if defined(CONFIG_MTD_NAND_ECC_BCH) + +static inline int mtd_nand_has_bch(void) { return 1; } + +/* + * Calculate BCH ecc code + */ +int nand_bch_calculate_ecc(struct mtd_info *mtd, const u_char *dat, + u_char *ecc_code); + +/* + * Detect and correct bit errors + */ +int nand_bch_correct_data(struct mtd_info *mtd, u_char *dat, u_char *read_ecc, + u_char *calc_ecc); +/* + * Initialize BCH encoder/decoder + */ +struct nand_bch_control * +nand_bch_init(struct mtd_info *mtd, unsigned int eccsize, + unsigned int eccbytes, struct nand_ecclayout **ecclayout); +/* + * Release BCH encoder/decoder resources + */ +void nand_bch_free(struct nand_bch_control *nbc); + +#else /* !CONFIG_MTD_NAND_ECC_BCH */ + +static inline int mtd_nand_has_bch(void) { return 0; } + +static inline int +nand_bch_calculate_ecc(struct mtd_info *mtd, const u_char *dat, + u_char *ecc_code) +{ + return -1; +} + +static inline int +nand_bch_correct_data(struct mtd_info *mtd, unsigned char *buf, + unsigned char *read_ecc, unsigned char *calc_ecc) +{ + return -1; +} + +static inline struct nand_bch_control * +nand_bch_init(struct mtd_info *mtd, unsigned int eccsize, + unsigned int eccbytes, struct nand_ecclayout **ecclayout) +{ + return NULL; +} + +static inline void nand_bch_free(struct nand_bch_control *nbc) {} + +#endif /* CONFIG_MTD_NAND_ECC_BCH */ + +#endif /* __MTD_NAND_BCH_H__ */ -- GitLab From fc2ff592b5b41f3f32e790dd124eeb3bc80706c8 Mon Sep 17 00:00:00 2001 From: Ivan Djelic Date: Fri, 11 Mar 2011 11:05:34 +0100 Subject: [PATCH 0615/2822] mtd: nand: enable software BCH ECC in nand simulator This patch adds option 'bch' to nandsim, which can be used to enable software BCH ECC (introduced in previous patches) and select BCH error correction capability. Signed-off-by: Ivan Djelic Signed-off-by: David Woodhouse --- drivers/mtd/nand/nandsim.c | 43 +++++++++++++++++++++++++++++++++++++- 1 file changed, 42 insertions(+), 1 deletion(-) diff --git a/drivers/mtd/nand/nandsim.c b/drivers/mtd/nand/nandsim.c index a5aa99f014bac..213181be0d9a7 100644 --- a/drivers/mtd/nand/nandsim.c +++ b/drivers/mtd/nand/nandsim.c @@ -34,6 +34,7 @@ #include #include #include +#include #include #include #include @@ -108,6 +109,7 @@ static unsigned int rptwear = 0; static unsigned int overridesize = 0; static char *cache_file = NULL; static unsigned int bbt; +static unsigned int bch; module_param(first_id_byte, uint, 0400); module_param(second_id_byte, uint, 0400); @@ -132,6 +134,7 @@ module_param(rptwear, uint, 0400); module_param(overridesize, uint, 0400); module_param(cache_file, charp, 0400); module_param(bbt, uint, 0400); +module_param(bch, uint, 0400); MODULE_PARM_DESC(first_id_byte, "The first byte returned by NAND Flash 'read ID' command (manufacturer ID)"); MODULE_PARM_DESC(second_id_byte, "The second byte returned by NAND Flash 'read ID' command (chip ID)"); @@ -165,6 +168,8 @@ MODULE_PARM_DESC(overridesize, "Specifies the NAND Flash size overriding the I " e.g. 5 means a size of 32 erase blocks"); MODULE_PARM_DESC(cache_file, "File to use to cache nand pages instead of memory"); MODULE_PARM_DESC(bbt, "0 OOB, 1 BBT with marker in OOB, 2 BBT with marker in data area"); +MODULE_PARM_DESC(bch, "Enable BCH ecc and set how many bits should " + "be correctable in 512-byte blocks"); /* The largest possible page size */ #define NS_LARGEST_PAGE_SIZE 4096 @@ -2309,7 +2314,43 @@ static int __init ns_init_module(void) if ((retval = parse_gravepages()) != 0) goto error; - if ((retval = nand_scan(nsmtd, 1)) != 0) { + retval = nand_scan_ident(nsmtd, 1, NULL); + if (retval) { + NS_ERR("cannot scan NAND Simulator device\n"); + if (retval > 0) + retval = -ENXIO; + goto error; + } + + if (bch) { + unsigned int eccsteps, eccbytes; + if (!mtd_nand_has_bch()) { + NS_ERR("BCH ECC support is disabled\n"); + retval = -EINVAL; + goto error; + } + /* use 512-byte ecc blocks */ + eccsteps = nsmtd->writesize/512; + eccbytes = (bch*13+7)/8; + /* do not bother supporting small page devices */ + if ((nsmtd->oobsize < 64) || !eccsteps) { + NS_ERR("bch not available on small page devices\n"); + retval = -EINVAL; + goto error; + } + if ((eccbytes*eccsteps+2) > nsmtd->oobsize) { + NS_ERR("invalid bch value %u\n", bch); + retval = -EINVAL; + goto error; + } + chip->ecc.mode = NAND_ECC_SOFT_BCH; + chip->ecc.size = 512; + chip->ecc.bytes = eccbytes; + NS_INFO("using %u-bit/%u bytes BCH ECC\n", bch, chip->ecc.size); + } + + retval = nand_scan_tail(nsmtd); + if (retval) { NS_ERR("can't register NAND Simulator\n"); if (retval > 0) retval = -ENXIO; -- GitLab From 883ae7992c09435927dda642b61f1455fceb5b85 Mon Sep 17 00:00:00 2001 From: Ike Panhc Date: Wed, 23 Feb 2011 21:39:59 +0800 Subject: [PATCH 0616/2822] ideapad: read brightness setting on brightness key notify BugLink: https://bugzilla.kernel.org/show_bug.cgi?id=25922 On ideapad Y530, the brightness key notify will be blocked if the last notify is not responsed by getting the brightness value. Read value when we get the notify shall fix the problem and will not have any difference on other ideapads. Signed-off-by: Ike Panhc Signed-off-by: Matthew Garrett --- drivers/platform/x86/ideapad-laptop.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/platform/x86/ideapad-laptop.c b/drivers/platform/x86/ideapad-laptop.c index 114d95247cdf8..21b101899baee 100644 --- a/drivers/platform/x86/ideapad-laptop.c +++ b/drivers/platform/x86/ideapad-laptop.c @@ -459,6 +459,8 @@ static void ideapad_acpi_notify(struct acpi_device *adevice, u32 event) if (test_bit(vpc_bit, &vpc1)) { if (vpc_bit == 9) ideapad_sync_rfk_state(adevice); + else if (vpc_bit == 4) + read_ec_data(handle, 0x12, &vpc2); else ideapad_input_report(priv, vpc_bit); } -- GitLab From 957c2ec558caff09a3bdf333871fc617830f063d Mon Sep 17 00:00:00 2001 From: "Stephen M. Cameron" Date: Fri, 11 Mar 2011 20:06:09 +0100 Subject: [PATCH 0617/2822] cciss: export resettable host attribute This attribute, requested by Redhat, allows kexec-tools to know whether the controller can honor the reset_devices kernel parameter and actually reset the controller. For kdump to work properly it is necessary that the reset_devices parameter be honored. This attribute enables kexec-tools to warn the user if they attempt to designate a non-resettable controller as the dump device. Signed-off-by: Stephen M. Cameron Signed-off-by: Jens Axboe --- .../ABI/testing/sysfs-bus-pci-devices-cciss | 12 ++++++ drivers/block/cciss.c | 39 +++++++++++++++++++ 2 files changed, 51 insertions(+) diff --git a/Documentation/ABI/testing/sysfs-bus-pci-devices-cciss b/Documentation/ABI/testing/sysfs-bus-pci-devices-cciss index 4f29e5f1ebfa5..f5bb0a3bb8c0d 100644 --- a/Documentation/ABI/testing/sysfs-bus-pci-devices-cciss +++ b/Documentation/ABI/testing/sysfs-bus-pci-devices-cciss @@ -59,3 +59,15 @@ Kernel Version: 2.6.31 Contact: iss_storagedev@hp.com Description: Displays the usage count (number of opens) of logical drive Y of controller X. + +Where: /sys/bus/pci/devices//ccissX/resettable +Date: February 2011 +Kernel Version: 2.6.38 +Contact: iss_storagedev@hp.com +Description: Value of 1 indicates the controller can honor the reset_devices + kernel parameter. Value of 0 indicates reset_devices cannot be + honored. This is to allow, for example, kexec tools to be able + to warn the user if they designate an unresettable device as + a dump device, as kdump requires resetting the device in order + to work reliably. + diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c index 35658f445fca4..eeed7aeb0b83a 100644 --- a/drivers/block/cciss.c +++ b/drivers/block/cciss.c @@ -556,6 +556,44 @@ static void __devinit cciss_procinit(ctlr_info_t *h) #define to_hba(n) container_of(n, struct ctlr_info, dev) #define to_drv(n) container_of(n, drive_info_struct, dev) +/* List of controllers which cannot be reset on kexec with reset_devices */ +static u32 unresettable_controller[] = { + 0x324a103C, /* Smart Array P712m */ + 0x324b103C, /* SmartArray P711m */ + 0x3223103C, /* Smart Array P800 */ + 0x3234103C, /* Smart Array P400 */ + 0x3235103C, /* Smart Array P400i */ + 0x3211103C, /* Smart Array E200i */ + 0x3212103C, /* Smart Array E200 */ + 0x3213103C, /* Smart Array E200i */ + 0x3214103C, /* Smart Array E200i */ + 0x3215103C, /* Smart Array E200i */ + 0x3237103C, /* Smart Array E500 */ + 0x323D103C, /* Smart Array P700m */ + 0x409C0E11, /* Smart Array 6400 */ + 0x409D0E11, /* Smart Array 6400 EM */ +}; + +static int ctlr_is_resettable(struct ctlr_info *h) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(unresettable_controller); i++) + if (unresettable_controller[i] == h->board_id) + return 0; + return 1; +} + +static ssize_t host_show_resettable(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct ctlr_info *h = to_hba(dev); + + return snprintf(buf, 20, "%d\n", ctlr_is_resettable(h)); +} +static DEVICE_ATTR(resettable, S_IRUGO, host_show_resettable, NULL); + static ssize_t host_store_rescan(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) @@ -741,6 +779,7 @@ static DEVICE_ATTR(usage_count, S_IRUGO, cciss_show_usage_count, NULL); static struct attribute *cciss_host_attrs[] = { &dev_attr_rescan.attr, + &dev_attr_resettable.attr, NULL }; -- GitLab From 978eb516a4e1a1b47163518d6f5d5e81ab27a583 Mon Sep 17 00:00:00 2001 From: "Stephen M. Cameron" Date: Fri, 11 Mar 2011 20:07:38 +0100 Subject: [PATCH 0618/2822] cciss: Add missing allocation in scsi_cmd_stack_setup and corresponding deallocation This bit got lost somewhere along the way. Without this, panic. Signed-off-by: Stephen M. Cameron Cc: stable@kernel.org Signed-off-by: Jens Axboe --- drivers/block/cciss_scsi.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/block/cciss_scsi.c b/drivers/block/cciss_scsi.c index 727d0225b7d04..3bfbde8b4013a 100644 --- a/drivers/block/cciss_scsi.c +++ b/drivers/block/cciss_scsi.c @@ -226,6 +226,13 @@ scsi_cmd_stack_setup(ctlr_info_t *h, struct cciss_scsi_adapter_data_t *sa) return -ENOMEM; } + stk->elem = kmalloc(sizeof(stk->elem[0]) * stk->nelems, GFP_KERNEL); + if (!stk->elem) { + pci_free_consistent(h->pdev, size, stk->pool, + stk->cmd_pool_handle); + return -1; + } + for (i=0; ielem[i] = &stk->pool[i]; stk->elem[i]->busaddr = (__u32) (stk->cmd_pool_handle + @@ -255,6 +262,8 @@ scsi_cmd_stack_free(ctlr_info_t *h) pci_free_consistent(h->pdev, size, stk->pool, stk->cmd_pool_handle); stk->pool = NULL; cciss_free_sg_chain_blocks(sa->cmd_sg_list, CMD_STACK_SIZE); + kfree(stk->elem); + stk->elem = NULL; } #if 0 -- GitLab From 805f6b5e1cbfedfb9b3d354013e7f4b13a79270f Mon Sep 17 00:00:00 2001 From: Tao Ma Date: Fri, 11 Mar 2011 20:11:59 +0100 Subject: [PATCH 0619/2822] blktrace: Use rq->cmd_flags directly in blk_add_trace_rq. In blk_add_trace_rq, we only chose the minor 2 bits from request's cmd_flags and did some check for discard. so most of other flags(e.g, REQ_SYNC) are missing. For example, with a sync write after blkparse we get: 8,16 1 1 0.001776503 7509 A WS 1349632 + 1024 <- (8,17) 1347584 8,16 1 2 0.001776813 7509 Q WS 1349632 + 1024 [dd] 8,16 1 3 0.001780395 7509 G WS 1349632 + 1024 [dd] 8,16 1 5 0.001783186 7509 I W 1349632 + 1024 [dd] 8,16 1 11 0.001816987 7509 D W 1349632 + 1024 [dd] 8,16 0 2 0.006218192 0 C W 1349632 + 1024 [0] Since now we have integrated the flags of both bio and request, it is safe to pass rq->cmd_flags directly to __blk_add_trace. With this patch, after a sync write we get: 8,16 1 1 0.001776900 5425 A WS 1189888 + 1024 <- (8,17) 1187840 8,16 1 2 0.001777179 5425 Q WS 1189888 + 1024 [dd] 8,16 1 3 0.001780797 5425 G WS 1189888 + 1024 [dd] 8,16 1 5 0.001783402 5425 I WS 1189888 + 1024 [dd] 8,16 1 11 0.001817468 5425 D WS 1189888 + 1024 [dd] 8,16 0 2 0.005640709 0 C WS 1189888 + 1024 [0] Signed-off-by: Tao Ma Acked-by: Jeff Moyer Signed-off-by: Jens Axboe --- kernel/trace/blktrace.c | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/kernel/trace/blktrace.c b/kernel/trace/blktrace.c index cbafed7d4f386..7aa40f8e182d5 100644 --- a/kernel/trace/blktrace.c +++ b/kernel/trace/blktrace.c @@ -703,28 +703,21 @@ void blk_trace_shutdown(struct request_queue *q) * **/ static void blk_add_trace_rq(struct request_queue *q, struct request *rq, - u32 what) + u32 what) { struct blk_trace *bt = q->blk_trace; - int rw = rq->cmd_flags & 0x03; if (likely(!bt)) return; - if (rq->cmd_flags & REQ_DISCARD) - rw |= REQ_DISCARD; - - if (rq->cmd_flags & REQ_SECURE) - rw |= REQ_SECURE; - if (rq->cmd_type == REQ_TYPE_BLOCK_PC) { what |= BLK_TC_ACT(BLK_TC_PC); - __blk_add_trace(bt, 0, blk_rq_bytes(rq), rw, + __blk_add_trace(bt, 0, blk_rq_bytes(rq), rq->cmd_flags, what, rq->errors, rq->cmd_len, rq->cmd); } else { what |= BLK_TC_ACT(BLK_TC_FS); - __blk_add_trace(bt, blk_rq_pos(rq), blk_rq_bytes(rq), rw, - what, rq->errors, 0, NULL); + __blk_add_trace(bt, blk_rq_pos(rq), blk_rq_bytes(rq), + rq->cmd_flags, what, rq->errors, 0, NULL); } } -- GitLab From eba2ed9c9636d9e7ed203a2498ed230b48341709 Mon Sep 17 00:00:00 2001 From: Tao Ma Date: Fri, 11 Mar 2011 20:13:54 +0100 Subject: [PATCH 0620/2822] block: remove obsolete comments for blkdev_issue_zeroout. barrier is already removed, so remove the obsolete comments in blkdev_issue_zeroout. Cc: Jens Axboe Signed-off-by: Tao Ma Signed-off-by: Jens Axboe --- block/blk-lib.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/block/blk-lib.c b/block/blk-lib.c index eec78becb3550..cb56c4e5b4949 100644 --- a/block/blk-lib.c +++ b/block/blk-lib.c @@ -140,8 +140,6 @@ static void bio_batch_end_io(struct bio *bio, int err) * * Description: * Generate and issue number of bios with zerofiled pages. - * Send barrier at the beginning and at the end if requested. This guarantie - * correct request ordering. Empty barrier allow us to avoid post queue flush. */ int blkdev_issue_zeroout(struct block_device *bdev, sector_t sector, -- GitLab From 1f940bdfc0d03265d178d9dfd840d854819f797d Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Fri, 11 Mar 2011 20:17:08 +0100 Subject: [PATCH 0621/2822] block: fixup plugging stubs for !CONFIG_BLOCK They used an older prototype, fix it up. Reported-by: Randy Dunlap Signed-off-by: Jens Axboe --- include/linux/blkdev.h | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index 91fa428fa2c15..16a902f099ac0 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -1297,15 +1297,18 @@ static inline long nr_blockdev_pages(void) return 0; } -static inline void blk_start_plug(struct list_head *list) +struct blk_plug { +}; + +static inline void blk_start_plug(struct blk_plug *plug) { } -static inline void blk_finish_plug(struct list_head *list) +static inline void blk_finish_plug(struct blk_plug *plug) { } -static inline void blk_flush_plug(struct task_struct *tsk) +static inline void blk_flush_plug(struct task_struct *task) { } -- GitLab From 0c9ba97318fc9a905bcc1419b6966de061203a70 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Fri, 11 Mar 2011 12:39:51 +0000 Subject: [PATCH 0622/2822] xfs: don't name variables "panic" The new xfs_alert_tag() used a variable named "panic", and that is to be avoided. Rename it. Signed-off-by: Alex Elder Reviewed-by: Dave Chinner --- fs/xfs/linux-2.6/xfs_message.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/fs/xfs/linux-2.6/xfs_message.c b/fs/xfs/linux-2.6/xfs_message.c index 8fe8cf69d809d..508e06fd7d1e6 100644 --- a/fs/xfs/linux-2.6/xfs_message.c +++ b/fs/xfs/linux-2.6/xfs_message.c @@ -96,13 +96,13 @@ xfs_alert_tag( { struct va_format vaf; va_list args; - int panic = 0; - int r; + int do_panic = 0; + int r; if (xfs_panic_mask && (xfs_panic_mask & panic_tag)) { xfs_printk(KERN_ALERT, mp, "XFS: Transforming an alert into a BUG."); - panic = 1; + do_panic = 1; } va_start(args, fmt); @@ -113,7 +113,7 @@ xfs_alert_tag( r = __xfs_printk(KERN_ALERT, mp, &vaf); va_end(args); - BUG_ON(panic); + BUG_ON(do_panic); return r; } -- GitLab From b203bd3f6b9c3db3b1979c2ff79bb2b9be8f03a3 Mon Sep 17 00:00:00 2001 From: Ira Snyder Date: Thu, 3 Mar 2011 07:54:53 +0000 Subject: [PATCH 0623/2822] dmatest: fix automatic buffer unmap type The dmatest code relies on the DMAEngine API to automatically call dma_unmap_single() on src buffers. The flags it passes are incorrect, fix them. Signed-off-by: Ira W. Snyder Signed-off-by: Dan Williams --- drivers/dma/dmatest.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/dma/dmatest.c b/drivers/dma/dmatest.c index 5589358b684d7..7e1b0aa0ca508 100644 --- a/drivers/dma/dmatest.c +++ b/drivers/dma/dmatest.c @@ -285,7 +285,12 @@ static int dmatest_func(void *data) set_user_nice(current, 10); - flags = DMA_CTRL_ACK | DMA_COMPL_SKIP_DEST_UNMAP | DMA_PREP_INTERRUPT; + /* + * src buffers are freed by the DMAEngine code with dma_unmap_single() + * dst buffers are freed by ourselves below + */ + flags = DMA_CTRL_ACK | DMA_PREP_INTERRUPT + | DMA_COMPL_SKIP_DEST_UNMAP | DMA_COMPL_SRC_UNMAP_SINGLE; while (!kthread_should_stop() && !(iterations && total_tests >= iterations)) { -- GitLab From e8bd84df27c5921a9ac866aef06e044590ac118f Mon Sep 17 00:00:00 2001 From: Ira Snyder Date: Thu, 3 Mar 2011 07:54:54 +0000 Subject: [PATCH 0624/2822] fsldma: move related helper functions near each other This is a purely cosmetic cleanup. It is nice to have related functions right next to each other in the code. Signed-off-by: Ira W. Snyder Signed-off-by: Dan Williams --- drivers/dma/fsldma.c | 116 ++++++++++++++++++++++++------------------- 1 file changed, 64 insertions(+), 52 deletions(-) diff --git a/drivers/dma/fsldma.c b/drivers/dma/fsldma.c index 4de947a450fce..2e1af4555b0f4 100644 --- a/drivers/dma/fsldma.c +++ b/drivers/dma/fsldma.c @@ -39,33 +39,9 @@ static const char msg_ld_oom[] = "No free memory for link descriptor\n"; -static void dma_init(struct fsldma_chan *chan) -{ - /* Reset the channel */ - DMA_OUT(chan, &chan->regs->mr, 0, 32); - - switch (chan->feature & FSL_DMA_IP_MASK) { - case FSL_DMA_IP_85XX: - /* Set the channel to below modes: - * EIE - Error interrupt enable - * EOSIE - End of segments interrupt enable (basic mode) - * EOLNIE - End of links interrupt enable - * BWC - Bandwidth sharing among channels - */ - DMA_OUT(chan, &chan->regs->mr, FSL_DMA_MR_BWC - | FSL_DMA_MR_EIE | FSL_DMA_MR_EOLNIE - | FSL_DMA_MR_EOSIE, 32); - break; - case FSL_DMA_IP_83XX: - /* Set the channel to below modes: - * EOTIE - End-of-transfer interrupt enable - * PRC_RM - PCI read multiple - */ - DMA_OUT(chan, &chan->regs->mr, FSL_DMA_MR_EOTIE - | FSL_DMA_MR_PRC_RM, 32); - break; - } -} +/* + * Register Helpers + */ static void set_sr(struct fsldma_chan *chan, u32 val) { @@ -77,6 +53,30 @@ static u32 get_sr(struct fsldma_chan *chan) return DMA_IN(chan, &chan->regs->sr, 32); } +static void set_cdar(struct fsldma_chan *chan, dma_addr_t addr) +{ + DMA_OUT(chan, &chan->regs->cdar, addr | FSL_DMA_SNEN, 64); +} + +static dma_addr_t get_cdar(struct fsldma_chan *chan) +{ + return DMA_IN(chan, &chan->regs->cdar, 64) & ~FSL_DMA_SNEN; +} + +static dma_addr_t get_ndar(struct fsldma_chan *chan) +{ + return DMA_IN(chan, &chan->regs->ndar, 64); +} + +static u32 get_bcr(struct fsldma_chan *chan) +{ + return DMA_IN(chan, &chan->regs->bcr, 32); +} + +/* + * Descriptor Helpers + */ + static void set_desc_cnt(struct fsldma_chan *chan, struct fsl_dma_ld_hw *hw, u32 count) { @@ -113,24 +113,49 @@ static void set_desc_next(struct fsldma_chan *chan, hw->next_ln_addr = CPU_TO_DMA(chan, snoop_bits | next, 64); } -static void set_cdar(struct fsldma_chan *chan, dma_addr_t addr) +static void set_ld_eol(struct fsldma_chan *chan, + struct fsl_desc_sw *desc) { - DMA_OUT(chan, &chan->regs->cdar, addr | FSL_DMA_SNEN, 64); -} + u64 snoop_bits; -static dma_addr_t get_cdar(struct fsldma_chan *chan) -{ - return DMA_IN(chan, &chan->regs->cdar, 64) & ~FSL_DMA_SNEN; -} + snoop_bits = ((chan->feature & FSL_DMA_IP_MASK) == FSL_DMA_IP_83XX) + ? FSL_DMA_SNEN : 0; -static dma_addr_t get_ndar(struct fsldma_chan *chan) -{ - return DMA_IN(chan, &chan->regs->ndar, 64); + desc->hw.next_ln_addr = CPU_TO_DMA(chan, + DMA_TO_CPU(chan, desc->hw.next_ln_addr, 64) | FSL_DMA_EOL + | snoop_bits, 64); } -static u32 get_bcr(struct fsldma_chan *chan) +/* + * DMA Engine Hardware Control Helpers + */ + +static void dma_init(struct fsldma_chan *chan) { - return DMA_IN(chan, &chan->regs->bcr, 32); + /* Reset the channel */ + DMA_OUT(chan, &chan->regs->mr, 0, 32); + + switch (chan->feature & FSL_DMA_IP_MASK) { + case FSL_DMA_IP_85XX: + /* Set the channel to below modes: + * EIE - Error interrupt enable + * EOSIE - End of segments interrupt enable (basic mode) + * EOLNIE - End of links interrupt enable + * BWC - Bandwidth sharing among channels + */ + DMA_OUT(chan, &chan->regs->mr, FSL_DMA_MR_BWC + | FSL_DMA_MR_EIE | FSL_DMA_MR_EOLNIE + | FSL_DMA_MR_EOSIE, 32); + break; + case FSL_DMA_IP_83XX: + /* Set the channel to below modes: + * EOTIE - End-of-transfer interrupt enable + * PRC_RM - PCI read multiple + */ + DMA_OUT(chan, &chan->regs->mr, FSL_DMA_MR_EOTIE + | FSL_DMA_MR_PRC_RM, 32); + break; + } } static int dma_is_idle(struct fsldma_chan *chan) @@ -185,19 +210,6 @@ static void dma_halt(struct fsldma_chan *chan) dev_err(chan->dev, "DMA halt timeout!\n"); } -static void set_ld_eol(struct fsldma_chan *chan, - struct fsl_desc_sw *desc) -{ - u64 snoop_bits; - - snoop_bits = ((chan->feature & FSL_DMA_IP_MASK) == FSL_DMA_IP_83XX) - ? FSL_DMA_SNEN : 0; - - desc->hw.next_ln_addr = CPU_TO_DMA(chan, - DMA_TO_CPU(chan, desc->hw.next_ln_addr, 64) | FSL_DMA_EOL - | snoop_bits, 64); -} - /** * fsl_chan_set_src_loop_size - Set source address hold transfer size * @chan : Freescale DMA channel -- GitLab From b158471ef63bf399165db96e945a828096502d9d Mon Sep 17 00:00:00 2001 From: Ira Snyder Date: Thu, 3 Mar 2011 07:54:55 +0000 Subject: [PATCH 0625/2822] fsldma: use channel name in printk output This makes debugging the driver much easier when multiple channels are running concurrently. In addition, you can see how much descriptor memory each channel has allocated via the dmapool API in sysfs. Signed-off-by: Ira W. Snyder Signed-off-by: Dan Williams --- drivers/dma/fsldma.c | 69 ++++++++++++++++++++++---------------------- drivers/dma/fsldma.h | 1 + 2 files changed, 36 insertions(+), 34 deletions(-) diff --git a/drivers/dma/fsldma.c b/drivers/dma/fsldma.c index 2e1af4555b0f4..e535cd13f7cc7 100644 --- a/drivers/dma/fsldma.c +++ b/drivers/dma/fsldma.c @@ -37,7 +37,12 @@ #include "fsldma.h" -static const char msg_ld_oom[] = "No free memory for link descriptor\n"; +#define chan_dbg(chan, fmt, arg...) \ + dev_dbg(chan->dev, "%s: " fmt, chan->name, ##arg) +#define chan_err(chan, fmt, arg...) \ + dev_err(chan->dev, "%s: " fmt, chan->name, ##arg) + +static const char msg_ld_oom[] = "No free memory for link descriptor"; /* * Register Helpers @@ -207,7 +212,7 @@ static void dma_halt(struct fsldma_chan *chan) } if (!dma_is_idle(chan)) - dev_err(chan->dev, "DMA halt timeout!\n"); + chan_err(chan, "DMA halt timeout!\n"); } /** @@ -405,7 +410,7 @@ static struct fsl_desc_sw *fsl_dma_alloc_descriptor( desc = dma_pool_alloc(chan->desc_pool, GFP_ATOMIC, &pdesc); if (!desc) { - dev_dbg(chan->dev, "out of memory for link desc\n"); + chan_dbg(chan, "out of memory for link descriptor\n"); return NULL; } @@ -439,13 +444,11 @@ static int fsl_dma_alloc_chan_resources(struct dma_chan *dchan) * We need the descriptor to be aligned to 32bytes * for meeting FSL DMA specification requirement. */ - chan->desc_pool = dma_pool_create("fsl_dma_engine_desc_pool", - chan->dev, + chan->desc_pool = dma_pool_create(chan->name, chan->dev, sizeof(struct fsl_desc_sw), __alignof__(struct fsl_desc_sw), 0); if (!chan->desc_pool) { - dev_err(chan->dev, "unable to allocate channel %d " - "descriptor pool\n", chan->id); + chan_err(chan, "unable to allocate descriptor pool\n"); return -ENOMEM; } @@ -491,7 +494,7 @@ static void fsl_dma_free_chan_resources(struct dma_chan *dchan) struct fsldma_chan *chan = to_fsl_chan(dchan); unsigned long flags; - dev_dbg(chan->dev, "Free all channel resources.\n"); + chan_dbg(chan, "free all channel resources\n"); spin_lock_irqsave(&chan->desc_lock, flags); fsldma_free_desc_list(chan, &chan->ld_pending); fsldma_free_desc_list(chan, &chan->ld_running); @@ -514,7 +517,7 @@ fsl_dma_prep_interrupt(struct dma_chan *dchan, unsigned long flags) new = fsl_dma_alloc_descriptor(chan); if (!new) { - dev_err(chan->dev, msg_ld_oom); + chan_err(chan, "%s\n", msg_ld_oom); return NULL; } @@ -551,11 +554,11 @@ static struct dma_async_tx_descriptor *fsl_dma_prep_memcpy( /* Allocate the link descriptor from DMA pool */ new = fsl_dma_alloc_descriptor(chan); if (!new) { - dev_err(chan->dev, msg_ld_oom); + chan_err(chan, "%s\n", msg_ld_oom); goto fail; } #ifdef FSL_DMA_LD_DEBUG - dev_dbg(chan->dev, "new link desc alloc %p\n", new); + chan_dbg(chan, "new link desc alloc %p\n", new); #endif copy = min(len, (size_t)FSL_DMA_BCR_MAX_CNT); @@ -639,11 +642,11 @@ static struct dma_async_tx_descriptor *fsl_dma_prep_sg(struct dma_chan *dchan, /* allocate and populate the descriptor */ new = fsl_dma_alloc_descriptor(chan); if (!new) { - dev_err(chan->dev, msg_ld_oom); + chan_err(chan, "%s\n", msg_ld_oom); goto fail; } #ifdef FSL_DMA_LD_DEBUG - dev_dbg(chan->dev, "new link desc alloc %p\n", new); + chan_dbg(chan, "new link desc alloc %p\n", new); #endif set_desc_cnt(chan, &new->hw, len); @@ -815,7 +818,7 @@ static void fsl_dma_update_completed_cookie(struct fsldma_chan *chan) spin_lock_irqsave(&chan->desc_lock, flags); if (list_empty(&chan->ld_running)) { - dev_dbg(chan->dev, "no running descriptors\n"); + chan_dbg(chan, "no running descriptors\n"); goto out_unlock; } @@ -863,7 +866,7 @@ static void fsl_chan_ld_cleanup(struct fsldma_chan *chan) spin_lock_irqsave(&chan->desc_lock, flags); - dev_dbg(chan->dev, "chan completed_cookie = %d\n", chan->completed_cookie); + chan_dbg(chan, "chan completed_cookie = %d\n", chan->completed_cookie); list_for_each_entry_safe(desc, _desc, &chan->ld_running, node) { dma_async_tx_callback callback; void *callback_param; @@ -879,7 +882,7 @@ static void fsl_chan_ld_cleanup(struct fsldma_chan *chan) callback_param = desc->async_tx.callback_param; if (callback) { spin_unlock_irqrestore(&chan->desc_lock, flags); - dev_dbg(chan->dev, "LD %p callback\n", desc); + chan_dbg(chan, "LD %p callback\n", desc); callback(callback_param); spin_lock_irqsave(&chan->desc_lock, flags); } @@ -913,7 +916,7 @@ static void fsl_chan_xfer_ld_queue(struct fsldma_chan *chan) * don't need to do any work at all */ if (list_empty(&chan->ld_pending)) { - dev_dbg(chan->dev, "no pending LDs\n"); + chan_dbg(chan, "no pending LDs\n"); goto out_unlock; } @@ -923,7 +926,7 @@ static void fsl_chan_xfer_ld_queue(struct fsldma_chan *chan) * at the end of the current transaction */ if (!dma_is_idle(chan)) { - dev_dbg(chan->dev, "DMA controller still busy\n"); + chan_dbg(chan, "DMA controller still busy\n"); goto out_unlock; } @@ -1003,14 +1006,14 @@ static irqreturn_t fsldma_chan_irq(int irq, void *data) /* save and clear the status register */ stat = get_sr(chan); set_sr(chan, stat); - dev_dbg(chan->dev, "irq: channel %d, stat = 0x%x\n", chan->id, stat); + chan_dbg(chan, "irq: stat = 0x%x\n", stat); stat &= ~(FSL_DMA_SR_CB | FSL_DMA_SR_CH); if (!stat) return IRQ_NONE; if (stat & FSL_DMA_SR_TE) - dev_err(chan->dev, "Transfer Error!\n"); + chan_err(chan, "Transfer Error!\n"); /* * Programming Error @@ -1018,7 +1021,7 @@ static irqreturn_t fsldma_chan_irq(int irq, void *data) * triger a PE interrupt. */ if (stat & FSL_DMA_SR_PE) { - dev_dbg(chan->dev, "irq: Programming Error INT\n"); + chan_dbg(chan, "irq: Programming Error INT\n"); if (get_bcr(chan) == 0) { /* BCR register is 0, this is a DMA_INTERRUPT async_tx. * Now, update the completed cookie, and continue the @@ -1035,8 +1038,8 @@ static irqreturn_t fsldma_chan_irq(int irq, void *data) * we will recycle the used descriptor. */ if (stat & FSL_DMA_SR_EOSI) { - dev_dbg(chan->dev, "irq: End-of-segments INT\n"); - dev_dbg(chan->dev, "irq: clndar 0x%llx, nlndar 0x%llx\n", + chan_dbg(chan, "irq: End-of-segments INT\n"); + chan_dbg(chan, "irq: clndar 0x%llx, nlndar 0x%llx\n", (unsigned long long)get_cdar(chan), (unsigned long long)get_ndar(chan)); stat &= ~FSL_DMA_SR_EOSI; @@ -1048,7 +1051,7 @@ static irqreturn_t fsldma_chan_irq(int irq, void *data) * and start the next transfer if it exist. */ if (stat & FSL_DMA_SR_EOCDI) { - dev_dbg(chan->dev, "irq: End-of-Chain link INT\n"); + chan_dbg(chan, "irq: End-of-Chain link INT\n"); stat &= ~FSL_DMA_SR_EOCDI; update_cookie = 1; xfer_ld_q = 1; @@ -1060,7 +1063,7 @@ static irqreturn_t fsldma_chan_irq(int irq, void *data) * prepare next transfer. */ if (stat & FSL_DMA_SR_EOLNI) { - dev_dbg(chan->dev, "irq: End-of-link INT\n"); + chan_dbg(chan, "irq: End-of-link INT\n"); stat &= ~FSL_DMA_SR_EOLNI; xfer_ld_q = 1; } @@ -1070,9 +1073,9 @@ static irqreturn_t fsldma_chan_irq(int irq, void *data) if (xfer_ld_q) fsl_chan_xfer_ld_queue(chan); if (stat) - dev_dbg(chan->dev, "irq: unhandled sr 0x%02x\n", stat); + chan_dbg(chan, "irq: unhandled sr 0x%08x\n", stat); - dev_dbg(chan->dev, "irq: Exit\n"); + chan_dbg(chan, "irq: Exit\n"); tasklet_schedule(&chan->tasklet); return IRQ_HANDLED; } @@ -1128,7 +1131,7 @@ static void fsldma_free_irqs(struct fsldma_device *fdev) for (i = 0; i < FSL_DMA_MAX_CHANS_PER_DEVICE; i++) { chan = fdev->chan[i]; if (chan && chan->irq != NO_IRQ) { - dev_dbg(fdev->dev, "free channel %d IRQ\n", chan->id); + chan_dbg(chan, "free per-channel IRQ\n"); free_irq(chan->irq, chan); } } @@ -1155,19 +1158,16 @@ static int fsldma_request_irqs(struct fsldma_device *fdev) continue; if (chan->irq == NO_IRQ) { - dev_err(fdev->dev, "no interrupts property defined for " - "DMA channel %d. Please fix your " - "device tree\n", chan->id); + chan_err(chan, "interrupts property missing in device tree\n"); ret = -ENODEV; goto out_unwind; } - dev_dbg(fdev->dev, "request channel %d IRQ\n", chan->id); + chan_dbg(chan, "request per-channel IRQ\n"); ret = request_irq(chan->irq, fsldma_chan_irq, IRQF_SHARED, "fsldma-chan", chan); if (ret) { - dev_err(fdev->dev, "unable to request IRQ for DMA " - "channel %d\n", chan->id); + chan_err(chan, "unable to request per-channel IRQ\n"); goto out_unwind; } } @@ -1242,6 +1242,7 @@ static int __devinit fsl_dma_chan_probe(struct fsldma_device *fdev, fdev->chan[chan->id] = chan; tasklet_init(&chan->tasklet, dma_do_tasklet, (unsigned long)chan); + snprintf(chan->name, sizeof(chan->name), "chan%d", chan->id); /* Initialize the channel */ dma_init(chan); diff --git a/drivers/dma/fsldma.h b/drivers/dma/fsldma.h index ba9f403c0fbe9..113e7134010b9 100644 --- a/drivers/dma/fsldma.h +++ b/drivers/dma/fsldma.h @@ -135,6 +135,7 @@ struct fsldma_device { #define FSL_DMA_CHAN_START_EXT 0x00002000 struct fsldma_chan { + char name[8]; /* Channel name */ struct fsldma_chan_regs __iomem *regs; dma_cookie_t completed_cookie; /* The maximum cookie completed */ spinlock_t desc_lock; /* Descriptor operation lock */ -- GitLab From 0ab09c36818ca88f65c88f4d8c6d067fbf10578d Mon Sep 17 00:00:00 2001 From: Ira Snyder Date: Thu, 3 Mar 2011 07:54:56 +0000 Subject: [PATCH 0626/2822] fsldma: improve link descriptor debugging This adds better tracking to link descriptor allocations, callbacks, and frees. This makes it much easier to track errors with link descriptors. Signed-off-by: Ira W. Snyder Signed-off-by: Dan Williams --- drivers/dma/fsldma.c | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/drivers/dma/fsldma.c b/drivers/dma/fsldma.c index e535cd13f7cc7..82b8e9f9c7bf1 100644 --- a/drivers/dma/fsldma.c +++ b/drivers/dma/fsldma.c @@ -420,6 +420,10 @@ static struct fsl_desc_sw *fsl_dma_alloc_descriptor( desc->async_tx.tx_submit = fsl_dma_tx_submit; desc->async_tx.phys = pdesc; +#ifdef FSL_DMA_LD_DEBUG + chan_dbg(chan, "LD %p allocated\n", desc); +#endif + return desc; } @@ -470,6 +474,9 @@ static void fsldma_free_desc_list(struct fsldma_chan *chan, list_for_each_entry_safe(desc, _desc, list, node) { list_del(&desc->node); +#ifdef FSL_DMA_LD_DEBUG + chan_dbg(chan, "LD %p free\n", desc); +#endif dma_pool_free(chan->desc_pool, desc, desc->async_tx.phys); } } @@ -481,6 +488,9 @@ static void fsldma_free_desc_list_reverse(struct fsldma_chan *chan, list_for_each_entry_safe_reverse(desc, _desc, list, node) { list_del(&desc->node); +#ifdef FSL_DMA_LD_DEBUG + chan_dbg(chan, "LD %p free\n", desc); +#endif dma_pool_free(chan->desc_pool, desc, desc->async_tx.phys); } } @@ -557,9 +567,6 @@ static struct dma_async_tx_descriptor *fsl_dma_prep_memcpy( chan_err(chan, "%s\n", msg_ld_oom); goto fail; } -#ifdef FSL_DMA_LD_DEBUG - chan_dbg(chan, "new link desc alloc %p\n", new); -#endif copy = min(len, (size_t)FSL_DMA_BCR_MAX_CNT); @@ -645,9 +652,6 @@ static struct dma_async_tx_descriptor *fsl_dma_prep_sg(struct dma_chan *dchan, chan_err(chan, "%s\n", msg_ld_oom); goto fail; } -#ifdef FSL_DMA_LD_DEBUG - chan_dbg(chan, "new link desc alloc %p\n", new); -#endif set_desc_cnt(chan, &new->hw, len); set_desc_src(chan, &new->hw, src); @@ -882,13 +886,18 @@ static void fsl_chan_ld_cleanup(struct fsldma_chan *chan) callback_param = desc->async_tx.callback_param; if (callback) { spin_unlock_irqrestore(&chan->desc_lock, flags); +#ifdef FSL_DMA_LD_DEBUG chan_dbg(chan, "LD %p callback\n", desc); +#endif callback(callback_param); spin_lock_irqsave(&chan->desc_lock, flags); } /* Run any dependencies, then free the descriptor */ dma_run_dependencies(&desc->async_tx); +#ifdef FSL_DMA_LD_DEBUG + chan_dbg(chan, "LD %p free\n", desc); +#endif dma_pool_free(chan->desc_pool, desc, desc->async_tx.phys); } -- GitLab From 31f4306c83a2daa3e348056b720de511bffe5a9b Mon Sep 17 00:00:00 2001 From: Ira Snyder Date: Thu, 3 Mar 2011 07:54:57 +0000 Subject: [PATCH 0627/2822] fsldma: minor codingstyle and consistency fixes This fixes some minor violations of the coding style. It also changes the style of the device_prep_dma_*() function definitions so they are identical. Signed-off-by: Ira W. Snyder Signed-off-by: Dan Williams --- drivers/dma/fsldma.c | 29 +++++++++++++---------------- drivers/dma/fsldma.h | 4 ++-- 2 files changed, 15 insertions(+), 18 deletions(-) diff --git a/drivers/dma/fsldma.c b/drivers/dma/fsldma.c index 82b8e9f9c7bf1..5da1a4a817e3e 100644 --- a/drivers/dma/fsldma.c +++ b/drivers/dma/fsldma.c @@ -89,7 +89,7 @@ static void set_desc_cnt(struct fsldma_chan *chan, } static void set_desc_src(struct fsldma_chan *chan, - struct fsl_dma_ld_hw *hw, dma_addr_t src) + struct fsl_dma_ld_hw *hw, dma_addr_t src) { u64 snoop_bits; @@ -99,7 +99,7 @@ static void set_desc_src(struct fsldma_chan *chan, } static void set_desc_dst(struct fsldma_chan *chan, - struct fsl_dma_ld_hw *hw, dma_addr_t dst) + struct fsl_dma_ld_hw *hw, dma_addr_t dst) { u64 snoop_bits; @@ -109,7 +109,7 @@ static void set_desc_dst(struct fsldma_chan *chan, } static void set_desc_next(struct fsldma_chan *chan, - struct fsl_dma_ld_hw *hw, dma_addr_t next) + struct fsl_dma_ld_hw *hw, dma_addr_t next) { u64 snoop_bits; @@ -118,8 +118,7 @@ static void set_desc_next(struct fsldma_chan *chan, hw->next_ln_addr = CPU_TO_DMA(chan, snoop_bits | next, 64); } -static void set_ld_eol(struct fsldma_chan *chan, - struct fsl_desc_sw *desc) +static void set_ld_eol(struct fsldma_chan *chan, struct fsl_desc_sw *desc) { u64 snoop_bits; @@ -338,8 +337,7 @@ static void fsl_chan_toggle_ext_start(struct fsldma_chan *chan, int enable) chan->feature &= ~FSL_DMA_CHAN_START_EXT; } -static void append_ld_queue(struct fsldma_chan *chan, - struct fsl_desc_sw *desc) +static void append_ld_queue(struct fsldma_chan *chan, struct fsl_desc_sw *desc) { struct fsl_desc_sw *tail = to_fsl_desc(chan->ld_pending.prev); @@ -380,8 +378,8 @@ static dma_cookie_t fsl_dma_tx_submit(struct dma_async_tx_descriptor *tx) cookie = chan->common.cookie; list_for_each_entry(child, &desc->tx_list, node) { cookie++; - if (cookie < 0) - cookie = 1; + if (cookie < DMA_MIN_COOKIE) + cookie = DMA_MIN_COOKIE; child->async_tx.cookie = cookie; } @@ -402,8 +400,7 @@ static dma_cookie_t fsl_dma_tx_submit(struct dma_async_tx_descriptor *tx) * * Return - The descriptor allocated. NULL for failed. */ -static struct fsl_desc_sw *fsl_dma_alloc_descriptor( - struct fsldma_chan *chan) +static struct fsl_desc_sw *fsl_dma_alloc_descriptor(struct fsldma_chan *chan) { struct fsl_desc_sw *desc; dma_addr_t pdesc; @@ -427,7 +424,6 @@ static struct fsl_desc_sw *fsl_dma_alloc_descriptor( return desc; } - /** * fsl_dma_alloc_chan_resources - Allocate resources for DMA channel. * @chan : Freescale DMA channel @@ -537,14 +533,15 @@ fsl_dma_prep_interrupt(struct dma_chan *dchan, unsigned long flags) /* Insert the link descriptor to the LD ring */ list_add_tail(&new->node, &new->tx_list); - /* Set End-of-link to the last link descriptor of new list*/ + /* Set End-of-link to the last link descriptor of new list */ set_ld_eol(chan, new); return &new->async_tx; } -static struct dma_async_tx_descriptor *fsl_dma_prep_memcpy( - struct dma_chan *dchan, dma_addr_t dma_dst, dma_addr_t dma_src, +static struct dma_async_tx_descriptor * +fsl_dma_prep_memcpy(struct dma_chan *dchan, + dma_addr_t dma_dst, dma_addr_t dma_src, size_t len, unsigned long flags) { struct fsldma_chan *chan; @@ -594,7 +591,7 @@ static struct dma_async_tx_descriptor *fsl_dma_prep_memcpy( new->async_tx.flags = flags; /* client is in control of this ack */ new->async_tx.cookie = -EBUSY; - /* Set End-of-link to the last link descriptor of new list*/ + /* Set End-of-link to the last link descriptor of new list */ set_ld_eol(chan, new); return &first->async_tx; diff --git a/drivers/dma/fsldma.h b/drivers/dma/fsldma.h index 113e7134010b9..49189dacd5f46 100644 --- a/drivers/dma/fsldma.h +++ b/drivers/dma/fsldma.h @@ -102,8 +102,8 @@ struct fsl_desc_sw { } __attribute__((aligned(32))); struct fsldma_chan_regs { - u32 mr; /* 0x00 - Mode Register */ - u32 sr; /* 0x04 - Status Register */ + u32 mr; /* 0x00 - Mode Register */ + u32 sr; /* 0x04 - Status Register */ u64 cdar; /* 0x08 - Current descriptor address register */ u64 sar; /* 0x10 - Source Address Register */ u64 dar; /* 0x18 - Destination Address Register */ -- GitLab From f04cd40701deace2efb9edd7120e59366bda2118 Mon Sep 17 00:00:00 2001 From: Ira Snyder Date: Thu, 3 Mar 2011 07:54:58 +0000 Subject: [PATCH 0628/2822] fsldma: fix controller lockups Enabling poisoning in the dmapool API quickly showed that the DMA controller was fetching descriptors that should not have been in use. This has caused intermittent controller lockups during testing. I have been unable to figure out the exact set of conditions which cause this to happen. However, I believe it is related to the driver using the hardware registers to track whether the controller is busy or not. The code can incorrectly decide that the hardware is idle due to lag between register writes and the hardware actually becoming busy. To fix this, the driver has been reworked to explicitly track the state of the hardware, rather than try to guess what it is doing based on the register values. This has passed dmatest with 10 threads per channel, 100000 iterations per thread several times without error. Previously, this would fail within a few seconds. Signed-off-by: Ira W. Snyder Signed-off-by: Dan Williams --- drivers/dma/fsldma.c | 220 +++++++++++++++++++------------------------ drivers/dma/fsldma.h | 1 + 2 files changed, 99 insertions(+), 122 deletions(-) diff --git a/drivers/dma/fsldma.c b/drivers/dma/fsldma.c index 5da1a4a817e3e..6e9ad6edc4af6 100644 --- a/drivers/dma/fsldma.c +++ b/drivers/dma/fsldma.c @@ -68,11 +68,6 @@ static dma_addr_t get_cdar(struct fsldma_chan *chan) return DMA_IN(chan, &chan->regs->cdar, 64) & ~FSL_DMA_SNEN; } -static dma_addr_t get_ndar(struct fsldma_chan *chan) -{ - return DMA_IN(chan, &chan->regs->ndar, 64); -} - static u32 get_bcr(struct fsldma_chan *chan) { return DMA_IN(chan, &chan->regs->bcr, 32); @@ -143,13 +138,11 @@ static void dma_init(struct fsldma_chan *chan) case FSL_DMA_IP_85XX: /* Set the channel to below modes: * EIE - Error interrupt enable - * EOSIE - End of segments interrupt enable (basic mode) * EOLNIE - End of links interrupt enable * BWC - Bandwidth sharing among channels */ DMA_OUT(chan, &chan->regs->mr, FSL_DMA_MR_BWC - | FSL_DMA_MR_EIE | FSL_DMA_MR_EOLNIE - | FSL_DMA_MR_EOSIE, 32); + | FSL_DMA_MR_EIE | FSL_DMA_MR_EOLNIE, 32); break; case FSL_DMA_IP_83XX: /* Set the channel to below modes: @@ -168,25 +161,32 @@ static int dma_is_idle(struct fsldma_chan *chan) return (!(sr & FSL_DMA_SR_CB)) || (sr & FSL_DMA_SR_CH); } +/* + * Start the DMA controller + * + * Preconditions: + * - the CDAR register must point to the start descriptor + * - the MRn[CS] bit must be cleared + */ static void dma_start(struct fsldma_chan *chan) { u32 mode; mode = DMA_IN(chan, &chan->regs->mr, 32); - if ((chan->feature & FSL_DMA_IP_MASK) == FSL_DMA_IP_85XX) { - if (chan->feature & FSL_DMA_CHAN_PAUSE_EXT) { - DMA_OUT(chan, &chan->regs->bcr, 0, 32); - mode |= FSL_DMA_MR_EMP_EN; - } else { - mode &= ~FSL_DMA_MR_EMP_EN; - } + if (chan->feature & FSL_DMA_CHAN_PAUSE_EXT) { + DMA_OUT(chan, &chan->regs->bcr, 0, 32); + mode |= FSL_DMA_MR_EMP_EN; + } else { + mode &= ~FSL_DMA_MR_EMP_EN; } - if (chan->feature & FSL_DMA_CHAN_START_EXT) + if (chan->feature & FSL_DMA_CHAN_START_EXT) { mode |= FSL_DMA_MR_EMS_EN; - else + } else { + mode &= ~FSL_DMA_MR_EMS_EN; mode |= FSL_DMA_MR_CS; + } DMA_OUT(chan, &chan->regs->mr, mode, 32); } @@ -760,14 +760,15 @@ static int fsl_dma_device_control(struct dma_chan *dchan, switch (cmd) { case DMA_TERMINATE_ALL: + spin_lock_irqsave(&chan->desc_lock, flags); + /* Halt the DMA engine */ dma_halt(chan); - spin_lock_irqsave(&chan->desc_lock, flags); - /* Remove and free all of the descriptors in the LD queue */ fsldma_free_desc_list(chan, &chan->ld_pending); fsldma_free_desc_list(chan, &chan->ld_running); + chan->idle = true; spin_unlock_irqrestore(&chan->desc_lock, flags); return 0; @@ -805,76 +806,43 @@ static int fsl_dma_device_control(struct dma_chan *dchan, } /** - * fsl_dma_update_completed_cookie - Update the completed cookie. + * fsl_chan_ld_cleanup - Clean up link descriptors * @chan : Freescale DMA channel * - * CONTEXT: hardirq + * This function is run after the queue of running descriptors has been + * executed by the DMA engine. It will run any callbacks, and then free + * the descriptors. + * + * HARDWARE STATE: idle */ -static void fsl_dma_update_completed_cookie(struct fsldma_chan *chan) +static void fsl_chan_ld_cleanup(struct fsldma_chan *chan) { - struct fsl_desc_sw *desc; + struct fsl_desc_sw *desc, *_desc; unsigned long flags; - dma_cookie_t cookie; spin_lock_irqsave(&chan->desc_lock, flags); + /* if the ld_running list is empty, there is nothing to do */ if (list_empty(&chan->ld_running)) { - chan_dbg(chan, "no running descriptors\n"); + chan_dbg(chan, "no descriptors to cleanup\n"); goto out_unlock; } - /* Get the last descriptor, update the cookie to that */ + /* + * Get the last descriptor, update the cookie to it + * + * This is done before callbacks run so that clients can check the + * status of their DMA transfer inside the callback. + */ desc = to_fsl_desc(chan->ld_running.prev); - if (dma_is_idle(chan)) - cookie = desc->async_tx.cookie; - else { - cookie = desc->async_tx.cookie - 1; - if (unlikely(cookie < DMA_MIN_COOKIE)) - cookie = DMA_MAX_COOKIE; - } - - chan->completed_cookie = cookie; - -out_unlock: - spin_unlock_irqrestore(&chan->desc_lock, flags); -} - -/** - * fsldma_desc_status - Check the status of a descriptor - * @chan: Freescale DMA channel - * @desc: DMA SW descriptor - * - * This function will return the status of the given descriptor - */ -static enum dma_status fsldma_desc_status(struct fsldma_chan *chan, - struct fsl_desc_sw *desc) -{ - return dma_async_is_complete(desc->async_tx.cookie, - chan->completed_cookie, - chan->common.cookie); -} - -/** - * fsl_chan_ld_cleanup - Clean up link descriptors - * @chan : Freescale DMA channel - * - * This function clean up the ld_queue of DMA channel. - */ -static void fsl_chan_ld_cleanup(struct fsldma_chan *chan) -{ - struct fsl_desc_sw *desc, *_desc; - unsigned long flags; - - spin_lock_irqsave(&chan->desc_lock, flags); + chan->completed_cookie = desc->async_tx.cookie; + chan_dbg(chan, "completed_cookie = %d\n", chan->completed_cookie); - chan_dbg(chan, "chan completed_cookie = %d\n", chan->completed_cookie); + /* Run the callback for each descriptor, in order */ list_for_each_entry_safe(desc, _desc, &chan->ld_running, node) { dma_async_tx_callback callback; void *callback_param; - if (fsldma_desc_status(chan, desc) == DMA_IN_PROGRESS) - break; - /* Remove from the list of running transactions */ list_del(&desc->node); @@ -898,6 +866,7 @@ static void fsl_chan_ld_cleanup(struct fsldma_chan *chan) dma_pool_free(chan->desc_pool, desc, desc->async_tx.phys); } +out_unlock: spin_unlock_irqrestore(&chan->desc_lock, flags); } @@ -905,10 +874,7 @@ static void fsl_chan_ld_cleanup(struct fsldma_chan *chan) * fsl_chan_xfer_ld_queue - transfer any pending transactions * @chan : Freescale DMA channel * - * This will make sure that any pending transactions will be run. - * If the DMA controller is idle, it will be started. Otherwise, - * the DMA controller's interrupt handler will start any pending - * transactions when it becomes idle. + * HARDWARE STATE: idle */ static void fsl_chan_xfer_ld_queue(struct fsldma_chan *chan) { @@ -927,22 +893,15 @@ static void fsl_chan_xfer_ld_queue(struct fsldma_chan *chan) } /* - * The DMA controller is not idle, which means the interrupt - * handler will start any queued transactions when it runs - * at the end of the current transaction + * The DMA controller is not idle, which means that the interrupt + * handler will start any queued transactions when it runs after + * this transaction finishes */ - if (!dma_is_idle(chan)) { + if (!chan->idle) { chan_dbg(chan, "DMA controller still busy\n"); goto out_unlock; } - /* - * TODO: - * make sure the dma_halt() function really un-wedges the - * controller as much as possible - */ - dma_halt(chan); - /* * If there are some link descriptors which have not been * transferred, we need to start the controller @@ -952,15 +911,32 @@ static void fsl_chan_xfer_ld_queue(struct fsldma_chan *chan) * Move all elements from the queue of pending transactions * onto the list of running transactions */ + chan_dbg(chan, "idle, starting controller\n"); desc = list_first_entry(&chan->ld_pending, struct fsl_desc_sw, node); list_splice_tail_init(&chan->ld_pending, &chan->ld_running); + /* + * The 85xx DMA controller doesn't clear the channel start bit + * automatically at the end of a transfer. Therefore we must clear + * it in software before starting the transfer. + */ + if ((chan->feature & FSL_DMA_IP_MASK) == FSL_DMA_IP_85XX) { + u32 mode; + + mode = DMA_IN(chan, &chan->regs->mr, 32); + mode &= ~FSL_DMA_MR_CS; + DMA_OUT(chan, &chan->regs->mr, mode, 32); + } + /* * Program the descriptor's address into the DMA controller, * then start the DMA transaction */ set_cdar(chan, desc->async_tx.phys); + get_cdar(chan); + dma_start(chan); + chan->idle = false; out_unlock: spin_unlock_irqrestore(&chan->desc_lock, flags); @@ -985,16 +961,18 @@ static enum dma_status fsl_tx_status(struct dma_chan *dchan, struct dma_tx_state *txstate) { struct fsldma_chan *chan = to_fsl_chan(dchan); - dma_cookie_t last_used; dma_cookie_t last_complete; + dma_cookie_t last_used; + unsigned long flags; - fsl_chan_ld_cleanup(chan); + spin_lock_irqsave(&chan->desc_lock, flags); - last_used = dchan->cookie; last_complete = chan->completed_cookie; + last_used = dchan->cookie; - dma_set_tx_state(txstate, last_complete, last_used, 0); + spin_unlock_irqrestore(&chan->desc_lock, flags); + dma_set_tx_state(txstate, last_complete, last_used, 0); return dma_async_is_complete(cookie, last_complete, last_used); } @@ -1005,8 +983,6 @@ static enum dma_status fsl_tx_status(struct dma_chan *dchan, static irqreturn_t fsldma_chan_irq(int irq, void *data) { struct fsldma_chan *chan = data; - int update_cookie = 0; - int xfer_ld_q = 0; u32 stat; /* save and clear the status register */ @@ -1014,6 +990,7 @@ static irqreturn_t fsldma_chan_irq(int irq, void *data) set_sr(chan, stat); chan_dbg(chan, "irq: stat = 0x%x\n", stat); + /* check that this was really our device */ stat &= ~(FSL_DMA_SR_CB | FSL_DMA_SR_CH); if (!stat) return IRQ_NONE; @@ -1028,28 +1005,9 @@ static irqreturn_t fsldma_chan_irq(int irq, void *data) */ if (stat & FSL_DMA_SR_PE) { chan_dbg(chan, "irq: Programming Error INT\n"); - if (get_bcr(chan) == 0) { - /* BCR register is 0, this is a DMA_INTERRUPT async_tx. - * Now, update the completed cookie, and continue the - * next uncompleted transfer. - */ - update_cookie = 1; - xfer_ld_q = 1; - } stat &= ~FSL_DMA_SR_PE; - } - - /* - * If the link descriptor segment transfer finishes, - * we will recycle the used descriptor. - */ - if (stat & FSL_DMA_SR_EOSI) { - chan_dbg(chan, "irq: End-of-segments INT\n"); - chan_dbg(chan, "irq: clndar 0x%llx, nlndar 0x%llx\n", - (unsigned long long)get_cdar(chan), - (unsigned long long)get_ndar(chan)); - stat &= ~FSL_DMA_SR_EOSI; - update_cookie = 1; + if (get_bcr(chan) != 0) + chan_err(chan, "Programming Error!\n"); } /* @@ -1059,8 +1017,6 @@ static irqreturn_t fsldma_chan_irq(int irq, void *data) if (stat & FSL_DMA_SR_EOCDI) { chan_dbg(chan, "irq: End-of-Chain link INT\n"); stat &= ~FSL_DMA_SR_EOCDI; - update_cookie = 1; - xfer_ld_q = 1; } /* @@ -1071,25 +1027,44 @@ static irqreturn_t fsldma_chan_irq(int irq, void *data) if (stat & FSL_DMA_SR_EOLNI) { chan_dbg(chan, "irq: End-of-link INT\n"); stat &= ~FSL_DMA_SR_EOLNI; - xfer_ld_q = 1; } - if (update_cookie) - fsl_dma_update_completed_cookie(chan); - if (xfer_ld_q) - fsl_chan_xfer_ld_queue(chan); + /* check that the DMA controller is really idle */ + if (!dma_is_idle(chan)) + chan_err(chan, "irq: controller not idle!\n"); + + /* check that we handled all of the bits */ if (stat) - chan_dbg(chan, "irq: unhandled sr 0x%08x\n", stat); + chan_err(chan, "irq: unhandled sr 0x%08x\n", stat); - chan_dbg(chan, "irq: Exit\n"); + /* + * Schedule the tasklet to handle all cleanup of the current + * transaction. It will start a new transaction if there is + * one pending. + */ tasklet_schedule(&chan->tasklet); + chan_dbg(chan, "irq: Exit\n"); return IRQ_HANDLED; } static void dma_do_tasklet(unsigned long data) { struct fsldma_chan *chan = (struct fsldma_chan *)data; + unsigned long flags; + + chan_dbg(chan, "tasklet entry\n"); + + /* run all callbacks, free all used descriptors */ fsl_chan_ld_cleanup(chan); + + /* the channel is now idle */ + spin_lock_irqsave(&chan->desc_lock, flags); + chan->idle = true; + spin_unlock_irqrestore(&chan->desc_lock, flags); + + /* start any pending transactions automatically */ + fsl_chan_xfer_ld_queue(chan); + chan_dbg(chan, "tasklet exit\n"); } static irqreturn_t fsldma_ctrl_irq(int irq, void *data) @@ -1269,6 +1244,7 @@ static int __devinit fsl_dma_chan_probe(struct fsldma_device *fdev, spin_lock_init(&chan->desc_lock); INIT_LIST_HEAD(&chan->ld_pending); INIT_LIST_HEAD(&chan->ld_running); + chan->idle = true; chan->common.device = &fdev->common; diff --git a/drivers/dma/fsldma.h b/drivers/dma/fsldma.h index 49189dacd5f46..9cb5aa57c677e 100644 --- a/drivers/dma/fsldma.h +++ b/drivers/dma/fsldma.h @@ -148,6 +148,7 @@ struct fsldma_chan { int id; /* Raw id of this channel */ struct tasklet_struct tasklet; u32 feature; + bool idle; /* DMA controller is idle */ void (*toggle_ext_pause)(struct fsldma_chan *fsl_chan, int enable); void (*toggle_ext_start)(struct fsldma_chan *fsl_chan, int enable); -- GitLab From 9c4d1e7bdeb1ed4dc0c3341d40662a6fbc5f2dc2 Mon Sep 17 00:00:00 2001 From: Ira Snyder Date: Thu, 3 Mar 2011 07:54:59 +0000 Subject: [PATCH 0629/2822] fsldma: support async_tx dependencies and automatic unmapping Previous to this patch, the dma_run_dependencies() function has been called while holding desc_lock. This function can call tx_submit() for other descriptors, which may try to re-grab the lock. Avoid this by moving the descriptors to be cleaned up to a temporary list, and dropping the lock before cleanup. At the same time, add support for automatic unmapping of src and dst buffers, as offered by the DMAEngine API. Signed-off-by: Ira W. Snyder Signed-off-by: Dan Williams --- drivers/dma/fsldma.c | 131 +++++++++++++++++++++++++++++++------------ 1 file changed, 95 insertions(+), 36 deletions(-) diff --git a/drivers/dma/fsldma.c b/drivers/dma/fsldma.c index 6e9ad6edc4af6..526579df60338 100644 --- a/drivers/dma/fsldma.c +++ b/drivers/dma/fsldma.c @@ -83,6 +83,11 @@ static void set_desc_cnt(struct fsldma_chan *chan, hw->count = CPU_TO_DMA(chan, count, 32); } +static u32 get_desc_cnt(struct fsldma_chan *chan, struct fsl_desc_sw *desc) +{ + return DMA_TO_CPU(chan, desc->hw.count, 32); +} + static void set_desc_src(struct fsldma_chan *chan, struct fsl_dma_ld_hw *hw, dma_addr_t src) { @@ -93,6 +98,16 @@ static void set_desc_src(struct fsldma_chan *chan, hw->src_addr = CPU_TO_DMA(chan, snoop_bits | src, 64); } +static dma_addr_t get_desc_src(struct fsldma_chan *chan, + struct fsl_desc_sw *desc) +{ + u64 snoop_bits; + + snoop_bits = ((chan->feature & FSL_DMA_IP_MASK) == FSL_DMA_IP_85XX) + ? ((u64)FSL_DMA_SATR_SREADTYPE_SNOOP_READ << 32) : 0; + return DMA_TO_CPU(chan, desc->hw.src_addr, 64) & ~snoop_bits; +} + static void set_desc_dst(struct fsldma_chan *chan, struct fsl_dma_ld_hw *hw, dma_addr_t dst) { @@ -103,6 +118,16 @@ static void set_desc_dst(struct fsldma_chan *chan, hw->dst_addr = CPU_TO_DMA(chan, snoop_bits | dst, 64); } +static dma_addr_t get_desc_dst(struct fsldma_chan *chan, + struct fsl_desc_sw *desc) +{ + u64 snoop_bits; + + snoop_bits = ((chan->feature & FSL_DMA_IP_MASK) == FSL_DMA_IP_85XX) + ? ((u64)FSL_DMA_DATR_DWRITETYPE_SNOOP_WRITE << 32) : 0; + return DMA_TO_CPU(chan, desc->hw.dst_addr, 64) & ~snoop_bits; +} + static void set_desc_next(struct fsldma_chan *chan, struct fsl_dma_ld_hw *hw, dma_addr_t next) { @@ -805,6 +830,57 @@ static int fsl_dma_device_control(struct dma_chan *dchan, return 0; } +/** + * fsldma_cleanup_descriptor - cleanup and free a single link descriptor + * @chan: Freescale DMA channel + * @desc: descriptor to cleanup and free + * + * This function is used on a descriptor which has been executed by the DMA + * controller. It will run any callbacks, submit any dependencies, and then + * free the descriptor. + */ +static void fsldma_cleanup_descriptor(struct fsldma_chan *chan, + struct fsl_desc_sw *desc) +{ + struct dma_async_tx_descriptor *txd = &desc->async_tx; + struct device *dev = chan->common.device->dev; + dma_addr_t src = get_desc_src(chan, desc); + dma_addr_t dst = get_desc_dst(chan, desc); + u32 len = get_desc_cnt(chan, desc); + + /* Run the link descriptor callback function */ + if (txd->callback) { +#ifdef FSL_DMA_LD_DEBUG + chan_dbg(chan, "LD %p callback\n", desc); +#endif + txd->callback(txd->callback_param); + } + + /* Run any dependencies */ + dma_run_dependencies(txd); + + /* Unmap the dst buffer, if requested */ + if (!(txd->flags & DMA_COMPL_SKIP_DEST_UNMAP)) { + if (txd->flags & DMA_COMPL_DEST_UNMAP_SINGLE) + dma_unmap_single(dev, dst, len, DMA_FROM_DEVICE); + else + dma_unmap_page(dev, dst, len, DMA_FROM_DEVICE); + } + + /* Unmap the src buffer, if requested */ + if (!(txd->flags & DMA_COMPL_SKIP_SRC_UNMAP)) { + if (txd->flags & DMA_COMPL_SRC_UNMAP_SINGLE) + dma_unmap_single(dev, src, len, DMA_TO_DEVICE); + else + dma_unmap_page(dev, src, len, DMA_TO_DEVICE); + } + +#ifdef FSL_DMA_LD_DEBUG + chan_dbg(chan, "LD %p free\n", desc); +#endif + dma_pool_free(chan->desc_pool, desc, txd->phys); +} + /** * fsl_chan_ld_cleanup - Clean up link descriptors * @chan : Freescale DMA channel @@ -818,56 +894,39 @@ static int fsl_dma_device_control(struct dma_chan *dchan, static void fsl_chan_ld_cleanup(struct fsldma_chan *chan) { struct fsl_desc_sw *desc, *_desc; + LIST_HEAD(ld_cleanup); unsigned long flags; spin_lock_irqsave(&chan->desc_lock, flags); - /* if the ld_running list is empty, there is nothing to do */ - if (list_empty(&chan->ld_running)) { - chan_dbg(chan, "no descriptors to cleanup\n"); - goto out_unlock; + /* update the cookie if we have some descriptors to cleanup */ + if (!list_empty(&chan->ld_running)) { + dma_cookie_t cookie; + + desc = to_fsl_desc(chan->ld_running.prev); + cookie = desc->async_tx.cookie; + + chan->completed_cookie = cookie; + chan_dbg(chan, "completed cookie=%d\n", cookie); } /* - * Get the last descriptor, update the cookie to it - * - * This is done before callbacks run so that clients can check the - * status of their DMA transfer inside the callback. + * move the descriptors to a temporary list so we can drop the lock + * during the entire cleanup operation */ - desc = to_fsl_desc(chan->ld_running.prev); - chan->completed_cookie = desc->async_tx.cookie; - chan_dbg(chan, "completed_cookie = %d\n", chan->completed_cookie); + list_splice_tail_init(&chan->ld_running, &ld_cleanup); + + spin_unlock_irqrestore(&chan->desc_lock, flags); /* Run the callback for each descriptor, in order */ - list_for_each_entry_safe(desc, _desc, &chan->ld_running, node) { - dma_async_tx_callback callback; - void *callback_param; + list_for_each_entry_safe(desc, _desc, &ld_cleanup, node) { - /* Remove from the list of running transactions */ + /* Remove from the list of transactions */ list_del(&desc->node); - /* Run the link descriptor callback function */ - callback = desc->async_tx.callback; - callback_param = desc->async_tx.callback_param; - if (callback) { - spin_unlock_irqrestore(&chan->desc_lock, flags); -#ifdef FSL_DMA_LD_DEBUG - chan_dbg(chan, "LD %p callback\n", desc); -#endif - callback(callback_param); - spin_lock_irqsave(&chan->desc_lock, flags); - } - - /* Run any dependencies, then free the descriptor */ - dma_run_dependencies(&desc->async_tx); -#ifdef FSL_DMA_LD_DEBUG - chan_dbg(chan, "LD %p free\n", desc); -#endif - dma_pool_free(chan->desc_pool, desc, desc->async_tx.phys); + /* Run all cleanup for this descriptor */ + fsldma_cleanup_descriptor(chan, desc); } - -out_unlock: - spin_unlock_irqrestore(&chan->desc_lock, flags); } /** -- GitLab From dc8d4091575ba81e886ebcdfd1e559c981f82f86 Mon Sep 17 00:00:00 2001 From: Ira Snyder Date: Thu, 3 Mar 2011 07:55:00 +0000 Subject: [PATCH 0630/2822] fsldma: reduce locking during descriptor cleanup This merges the fsl_chan_ld_cleanup() function into the dma_do_tasklet() function to reduce locking overhead. In the best case, we will be able to keep the DMA controller busy while we are freeing used descriptors. In all cases, the spinlock is grabbed two times fewer than before on each transaction. Signed-off-by: Ira W. Snyder Signed-off-by: Dan Williams --- drivers/dma/fsldma.c | 108 ++++++++++++++++++------------------------- 1 file changed, 46 insertions(+), 62 deletions(-) diff --git a/drivers/dma/fsldma.c b/drivers/dma/fsldma.c index 526579df60338..d300de456c905 100644 --- a/drivers/dma/fsldma.c +++ b/drivers/dma/fsldma.c @@ -881,66 +881,16 @@ static void fsldma_cleanup_descriptor(struct fsldma_chan *chan, dma_pool_free(chan->desc_pool, desc, txd->phys); } -/** - * fsl_chan_ld_cleanup - Clean up link descriptors - * @chan : Freescale DMA channel - * - * This function is run after the queue of running descriptors has been - * executed by the DMA engine. It will run any callbacks, and then free - * the descriptors. - * - * HARDWARE STATE: idle - */ -static void fsl_chan_ld_cleanup(struct fsldma_chan *chan) -{ - struct fsl_desc_sw *desc, *_desc; - LIST_HEAD(ld_cleanup); - unsigned long flags; - - spin_lock_irqsave(&chan->desc_lock, flags); - - /* update the cookie if we have some descriptors to cleanup */ - if (!list_empty(&chan->ld_running)) { - dma_cookie_t cookie; - - desc = to_fsl_desc(chan->ld_running.prev); - cookie = desc->async_tx.cookie; - - chan->completed_cookie = cookie; - chan_dbg(chan, "completed cookie=%d\n", cookie); - } - - /* - * move the descriptors to a temporary list so we can drop the lock - * during the entire cleanup operation - */ - list_splice_tail_init(&chan->ld_running, &ld_cleanup); - - spin_unlock_irqrestore(&chan->desc_lock, flags); - - /* Run the callback for each descriptor, in order */ - list_for_each_entry_safe(desc, _desc, &ld_cleanup, node) { - - /* Remove from the list of transactions */ - list_del(&desc->node); - - /* Run all cleanup for this descriptor */ - fsldma_cleanup_descriptor(chan, desc); - } -} - /** * fsl_chan_xfer_ld_queue - transfer any pending transactions * @chan : Freescale DMA channel * * HARDWARE STATE: idle + * LOCKING: must hold chan->desc_lock */ static void fsl_chan_xfer_ld_queue(struct fsldma_chan *chan) { struct fsl_desc_sw *desc; - unsigned long flags; - - spin_lock_irqsave(&chan->desc_lock, flags); /* * If the list of pending descriptors is empty, then we @@ -948,7 +898,7 @@ static void fsl_chan_xfer_ld_queue(struct fsldma_chan *chan) */ if (list_empty(&chan->ld_pending)) { chan_dbg(chan, "no pending LDs\n"); - goto out_unlock; + return; } /* @@ -958,7 +908,7 @@ static void fsl_chan_xfer_ld_queue(struct fsldma_chan *chan) */ if (!chan->idle) { chan_dbg(chan, "DMA controller still busy\n"); - goto out_unlock; + return; } /* @@ -996,9 +946,6 @@ static void fsl_chan_xfer_ld_queue(struct fsldma_chan *chan) dma_start(chan); chan->idle = false; - -out_unlock: - spin_unlock_irqrestore(&chan->desc_lock, flags); } /** @@ -1008,7 +955,11 @@ out_unlock: static void fsl_dma_memcpy_issue_pending(struct dma_chan *dchan) { struct fsldma_chan *chan = to_fsl_chan(dchan); + unsigned long flags; + + spin_lock_irqsave(&chan->desc_lock, flags); fsl_chan_xfer_ld_queue(chan); + spin_unlock_irqrestore(&chan->desc_lock, flags); } /** @@ -1109,20 +1060,53 @@ static irqreturn_t fsldma_chan_irq(int irq, void *data) static void dma_do_tasklet(unsigned long data) { struct fsldma_chan *chan = (struct fsldma_chan *)data; + struct fsl_desc_sw *desc, *_desc; + LIST_HEAD(ld_cleanup); unsigned long flags; chan_dbg(chan, "tasklet entry\n"); - /* run all callbacks, free all used descriptors */ - fsl_chan_ld_cleanup(chan); - - /* the channel is now idle */ spin_lock_irqsave(&chan->desc_lock, flags); + + /* update the cookie if we have some descriptors to cleanup */ + if (!list_empty(&chan->ld_running)) { + dma_cookie_t cookie; + + desc = to_fsl_desc(chan->ld_running.prev); + cookie = desc->async_tx.cookie; + + chan->completed_cookie = cookie; + chan_dbg(chan, "completed_cookie=%d\n", cookie); + } + + /* + * move the descriptors to a temporary list so we can drop the lock + * during the entire cleanup operation + */ + list_splice_tail_init(&chan->ld_running, &ld_cleanup); + + /* the hardware is now idle and ready for more */ chan->idle = true; - spin_unlock_irqrestore(&chan->desc_lock, flags); - /* start any pending transactions automatically */ + /* + * Start any pending transactions automatically + * + * In the ideal case, we keep the DMA controller busy while we go + * ahead and free the descriptors below. + */ fsl_chan_xfer_ld_queue(chan); + spin_unlock_irqrestore(&chan->desc_lock, flags); + + /* Run the callback for each descriptor, in order */ + list_for_each_entry_safe(desc, _desc, &ld_cleanup, node) { + + /* Remove from the list of transactions */ + list_del(&desc->node); + + /* Run all cleanup for this descriptor */ + fsldma_cleanup_descriptor(chan, desc); + } + chan_dbg(chan, "tasklet exit\n"); } -- GitLab From a00ae34ac8bc8a5897d9b6b9b685c39b955b14b9 Mon Sep 17 00:00:00 2001 From: Ira Snyder Date: Thu, 3 Mar 2011 07:55:01 +0000 Subject: [PATCH 0631/2822] fsldma: make halt behave nicely on all supported controllers The original dma_halt() function set the CA (channel abort) bit on both the 83xx and 85xx controllers. This is incorrect on the 83xx, where this bit means TEM (transfer error mask) instead. The 83xx doesn't support channel abort, so we only do this operation on 85xx. Signed-off-by: Ira W. Snyder Signed-off-by: Dan Williams --- drivers/dma/fsldma.c | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/drivers/dma/fsldma.c b/drivers/dma/fsldma.c index d300de456c905..8670a50121221 100644 --- a/drivers/dma/fsldma.c +++ b/drivers/dma/fsldma.c @@ -221,13 +221,26 @@ static void dma_halt(struct fsldma_chan *chan) u32 mode; int i; + /* read the mode register */ mode = DMA_IN(chan, &chan->regs->mr, 32); - mode |= FSL_DMA_MR_CA; - DMA_OUT(chan, &chan->regs->mr, mode, 32); - mode &= ~(FSL_DMA_MR_CS | FSL_DMA_MR_EMS_EN | FSL_DMA_MR_CA); + /* + * The 85xx controller supports channel abort, which will stop + * the current transfer. On 83xx, this bit is the transfer error + * mask bit, which should not be changed. + */ + if ((chan->feature & FSL_DMA_IP_MASK) == FSL_DMA_IP_85XX) { + mode |= FSL_DMA_MR_CA; + DMA_OUT(chan, &chan->regs->mr, mode, 32); + + mode &= ~FSL_DMA_MR_CA; + } + + /* stop the DMA controller */ + mode &= ~(FSL_DMA_MR_CS | FSL_DMA_MR_EMS_EN); DMA_OUT(chan, &chan->regs->mr, mode, 32); + /* wait for the DMA controller to become idle */ for (i = 0; i < 100; i++) { if (dma_is_idle(chan)) return; -- GitLab From 4a765046553a88e4ec80ad84d2131b9e69ab4ab0 Mon Sep 17 00:00:00 2001 From: "Stephen M. Cameron" Date: Sat, 12 Mar 2011 10:02:11 +0100 Subject: [PATCH 0632/2822] cciss: hoist tag masking out of loop In process_nonindexed_cmd, hoist figuring of masked tag out of loop since it is the same throughout. Signed-off-by: Stephen M. Cameron Signed-off-by: Jens Axboe --- drivers/block/cciss.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c index eeed7aeb0b83a..0a296c1eff4ff 100644 --- a/drivers/block/cciss.c +++ b/drivers/block/cciss.c @@ -3433,14 +3433,12 @@ static inline u32 process_indexed_cmd(ctlr_info_t *h, u32 raw_tag) /* process completion of a non-indexed command */ static inline u32 process_nonindexed_cmd(ctlr_info_t *h, u32 raw_tag) { - u32 tag; CommandList_struct *c = NULL; __u32 busaddr_masked, tag_masked; - tag = cciss_tag_discard_error_bits(raw_tag); + tag_masked = cciss_tag_discard_error_bits(raw_tag); list_for_each_entry(c, &h->cmpQ, list) { busaddr_masked = cciss_tag_discard_error_bits(c->busaddr); - tag_masked = cciss_tag_discard_error_bits(tag); if (busaddr_masked == tag_masked) { finish_cmd(h, c, raw_tag); return next_command(h); -- GitLab From 0498cc2a9e81de97674adde8ced8a1462a397013 Mon Sep 17 00:00:00 2001 From: "Stephen M. Cameron" Date: Sat, 12 Mar 2011 10:02:16 +0100 Subject: [PATCH 0633/2822] cciss: Inform controller we are using 32-bit tags. Controller will DMA only 32-bits of the tag per command on completion if it knows we are only using 32-bit tags. Signed-off-by: Stephen M. Cameron Signed-off-by: Jens Axboe --- drivers/block/cciss.c | 25 +++++++++++++++---------- drivers/block/cciss_cmd.h | 1 + 2 files changed, 16 insertions(+), 10 deletions(-) diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c index 0a296c1eff4ff..27b04a32b0c5f 100644 --- a/drivers/block/cciss.c +++ b/drivers/block/cciss.c @@ -231,7 +231,7 @@ static const struct block_device_operations cciss_fops = { */ static void set_performant_mode(ctlr_info_t *h, CommandList_struct *c) { - if (likely(h->transMethod == CFGTBL_Trans_Performant)) + if (likely(h->transMethod & CFGTBL_Trans_Performant)) c->busaddr |= 1 | (h->blockFetchTable[c->Header.SGList] << 1); } @@ -3175,10 +3175,13 @@ static inline u32 cciss_tag_to_index(u32 tag) return tag >> DIRECT_LOOKUP_SHIFT; } -static inline u32 cciss_tag_discard_error_bits(u32 tag) +static inline u32 cciss_tag_discard_error_bits(ctlr_info_t *h, u32 tag) { -#define CCISS_ERROR_BITS 0x03 - return tag & ~CCISS_ERROR_BITS; +#define CCISS_PERF_ERROR_BITS ((1 << DIRECT_LOOKUP_SHIFT) - 1) +#define CCISS_SIMPLE_ERROR_BITS 0x03 + if (likely(h->transMethod & CFGTBL_Trans_Performant)) + return tag & ~CCISS_PERF_ERROR_BITS; + return tag & ~CCISS_SIMPLE_ERROR_BITS; } static inline void cciss_mark_tag_indexed(u32 *tag) @@ -3398,7 +3401,7 @@ static inline u32 next_command(ctlr_info_t *h) { u32 a; - if (unlikely(h->transMethod != CFGTBL_Trans_Performant)) + if (unlikely(!(h->transMethod & CFGTBL_Trans_Performant))) return h->access.command_completed(h); if ((*(h->reply_pool_head) & 1) == (h->reply_pool_wraparound)) { @@ -3436,9 +3439,9 @@ static inline u32 process_nonindexed_cmd(ctlr_info_t *h, u32 raw_tag) CommandList_struct *c = NULL; __u32 busaddr_masked, tag_masked; - tag_masked = cciss_tag_discard_error_bits(raw_tag); + tag_masked = cciss_tag_discard_error_bits(h, raw_tag); list_for_each_entry(c, &h->cmpQ, list) { - busaddr_masked = cciss_tag_discard_error_bits(c->busaddr); + busaddr_masked = cciss_tag_discard_error_bits(h, c->busaddr); if (busaddr_masked == tag_masked) { finish_cmd(h, c, raw_tag); return next_command(h); @@ -3790,7 +3793,8 @@ static void __devinit cciss_wait_for_mode_change_ack(ctlr_info_t *h) } } -static __devinit void cciss_enter_performant_mode(ctlr_info_t *h) +static __devinit void cciss_enter_performant_mode(ctlr_info_t *h, + u32 use_short_tags) { /* This is a bit complicated. There are 8 registers on * the controller which we write to to tell it 8 different @@ -3845,7 +3849,7 @@ static __devinit void cciss_enter_performant_mode(ctlr_info_t *h) writel(0, &h->transtable->RepQCtrAddrHigh32); writel(h->reply_pool_dhandle, &h->transtable->RepQAddr0Low32); writel(0, &h->transtable->RepQAddr0High32); - writel(CFGTBL_Trans_Performant, + writel(CFGTBL_Trans_Performant | use_short_tags, &(h->cfgtable->HostWrite.TransportRequest)); writel(CFGTBL_ChangeReq, h->vaddr + SA5_DOORBELL); @@ -3892,7 +3896,8 @@ static void __devinit cciss_put_controller_into_performant_mode(ctlr_info_t *h) if ((h->reply_pool == NULL) || (h->blockFetchTable == NULL)) goto clean_up; - cciss_enter_performant_mode(h); + cciss_enter_performant_mode(h, + trans_support & CFGTBL_Trans_use_short_tags); /* Change the access methods to the performant access methods */ h->access = SA5_performant_access; diff --git a/drivers/block/cciss_cmd.h b/drivers/block/cciss_cmd.h index 35463d2f0ee7c..cd441bef031f1 100644 --- a/drivers/block/cciss_cmd.h +++ b/drivers/block/cciss_cmd.h @@ -56,6 +56,7 @@ #define CFGTBL_Trans_Simple 0x00000002l #define CFGTBL_Trans_Performant 0x00000004l +#define CFGTBL_Trans_use_short_tags 0x20000000l #define CFGTBL_BusType_Ultra2 0x00000001l #define CFGTBL_BusType_Ultra3 0x00000002l -- GitLab From 16011131ced8bdb317e1bf03324ca78a27fa0a1c Mon Sep 17 00:00:00 2001 From: "Stephen M. Cameron" Date: Sat, 12 Mar 2011 10:02:21 +0100 Subject: [PATCH 0634/2822] cciss: Mask off error bits of c->busaddr in cmd_special_free when calling pci_free_consistent Signed-off-by: Stephen M. Cameron Signed-off-by: Jens Axboe --- drivers/block/cciss.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c index 27b04a32b0c5f..f21116cb8b82f 100644 --- a/drivers/block/cciss.c +++ b/drivers/block/cciss.c @@ -193,7 +193,7 @@ static int __devinit cciss_find_cfg_addrs(struct pci_dev *pdev, u64 *cfg_offset); static int __devinit cciss_pci_find_memory_BAR(struct pci_dev *pdev, unsigned long *memory_bar); - +static inline u32 cciss_tag_discard_error_bits(ctlr_info_t *h, u32 tag); /* performant mode helper functions */ static void calc_bucket_map(int *bucket, int num_buckets, int nsgs, @@ -1012,8 +1012,8 @@ static void cmd_special_free(ctlr_info_t *h, CommandList_struct *c) temp64.val32.upper = c->ErrDesc.Addr.upper; pci_free_consistent(h->pdev, sizeof(ErrorInfo_struct), c->err_info, (dma_addr_t) temp64.val); - pci_free_consistent(h->pdev, sizeof(CommandList_struct), - c, (dma_addr_t) c->busaddr); + pci_free_consistent(h->pdev, sizeof(CommandList_struct), c, + (dma_addr_t) cciss_tag_discard_error_bits(h, (u32) c->busaddr)); } static inline ctlr_info_t *get_host(struct gendisk *disk) -- GitLab From fcab1c112ade881d884cd7b8161f7543194d12e1 Mon Sep 17 00:00:00 2001 From: "Stephen M. Cameron" Date: Sat, 12 Mar 2011 10:02:24 +0100 Subject: [PATCH 0635/2822] cciss: remove unnecessary casts Signed-off-by: Stephen M. Cameron Signed-off-by: Jens Axboe --- drivers/block/cciss.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c index f21116cb8b82f..25267e92ce31c 100644 --- a/drivers/block/cciss.c +++ b/drivers/block/cciss.c @@ -1529,8 +1529,7 @@ static int cciss_bigpassthru(ctlr_info_t *h, void __user *argp) return -EINVAL; if (!capable(CAP_SYS_RAWIO)) return -EPERM; - ioc = (BIG_IOCTL_Command_struct *) - kmalloc(sizeof(*ioc), GFP_KERNEL); + ioc = kmalloc(sizeof(*ioc), GFP_KERNEL); if (!ioc) { status = -ENOMEM; goto cleanup1; -- GitLab From 6d9a4f9e21486fa83526a9a9fdf88b9b2cdfd299 Mon Sep 17 00:00:00 2001 From: "Stephen M. Cameron" Date: Sat, 12 Mar 2011 10:02:30 +0100 Subject: [PATCH 0636/2822] cciss: fix missed command status value CMD_UNABORTABLE and fix a nearby typo, "do" that should have been "due" Signed-off-by: Stephen M. Cameron Signed-off-by: Jens Axboe --- drivers/block/cciss.c | 11 +++++++++++ drivers/block/cciss_scsi.c | 13 +++++++++++-- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c index 25267e92ce31c..9bf13988f1a2f 100644 --- a/drivers/block/cciss.c +++ b/drivers/block/cciss.c @@ -2691,6 +2691,10 @@ static int process_sendcmd_error(ctlr_info_t *h, CommandList_struct *c) c->Request.CDB[0]); return_status = IO_NEEDS_RETRY; break; + case CMD_UNABORTABLE: + dev_warn(&h->pdev->dev, "cmd unabortable\n"); + return_status = IO_ERROR; + break; default: dev_warn(&h->pdev->dev, "cmd 0x%02x returned " "unknown status %x\n", c->Request.CDB[0], @@ -3141,6 +3145,13 @@ static inline void complete_command(ctlr_info_t *h, CommandList_struct *cmd, (cmd->rq->cmd_type == REQ_TYPE_BLOCK_PC) ? DID_PASSTHROUGH : DID_ERROR); break; + case CMD_UNABORTABLE: + dev_warn(&h->pdev->dev, "cmd %p unabortable\n", cmd); + rq->errors = make_status_bytes(SAM_STAT_GOOD, + cmd->err_info->CommandStatus, DRIVER_OK, + cmd->rq->cmd_type == REQ_TYPE_BLOCK_PC ? + DID_PASSTHROUGH : DID_ERROR); + break; default: dev_warn(&h->pdev->dev, "cmd %p returned " "unknown status %x\n", cmd, diff --git a/drivers/block/cciss_scsi.c b/drivers/block/cciss_scsi.c index 3bfbde8b4013a..8fa2a2e90b9f4 100644 --- a/drivers/block/cciss_scsi.c +++ b/drivers/block/cciss_scsi.c @@ -833,13 +833,18 @@ static void complete_scsi_command(CommandList_struct *c, int timeout, break; case CMD_UNSOLICITED_ABORT: cmd->result = DID_ABORT << 16; - dev_warn(&h->pdev->dev, "%p aborted do to an " + dev_warn(&h->pdev->dev, "%p aborted due to an " "unsolicited abort\n", c); break; case CMD_TIMEOUT: cmd->result = DID_TIME_OUT << 16; dev_warn(&h->pdev->dev, "%p timedout\n", c); break; + case CMD_UNABORTABLE: + cmd->result = DID_ERROR << 16; + dev_warn(&h->pdev->dev, "c %p command " + "unabortable\n", c); + break; default: cmd->result = DID_ERROR << 16; dev_warn(&h->pdev->dev, @@ -1016,11 +1021,15 @@ cciss_scsi_interpret_error(ctlr_info_t *h, CommandList_struct *c) break; case CMD_UNSOLICITED_ABORT: dev_warn(&h->pdev->dev, - "%p aborted do to an unsolicited abort\n", c); + "%p aborted due to an unsolicited abort\n", c); break; case CMD_TIMEOUT: dev_warn(&h->pdev->dev, "%p timedout\n", c); break; + case CMD_UNABORTABLE: + dev_warn(&h->pdev->dev, + "%p unabortable\n", c); + break; default: dev_warn(&h->pdev->dev, "%p returned unknown status %x\n", -- GitLab From b66538014f7eae121afa99ca18488fd67536a1bf Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Sat, 12 Mar 2011 13:47:51 +0100 Subject: [PATCH 0637/2822] Revert "cciss: Add missing allocation in scsi_cmd_stack_setup and corresponding deallocation" This reverts commit 978eb516a4e1a1b47163518d6f5d5e81ab27a583. The commit was broken, relying on other changes that have not been committed yet. Signed-off-by: Jens Axboe --- drivers/block/cciss_scsi.c | 9 --------- 1 file changed, 9 deletions(-) diff --git a/drivers/block/cciss_scsi.c b/drivers/block/cciss_scsi.c index 8fa2a2e90b9f4..df793803f5ae5 100644 --- a/drivers/block/cciss_scsi.c +++ b/drivers/block/cciss_scsi.c @@ -226,13 +226,6 @@ scsi_cmd_stack_setup(ctlr_info_t *h, struct cciss_scsi_adapter_data_t *sa) return -ENOMEM; } - stk->elem = kmalloc(sizeof(stk->elem[0]) * stk->nelems, GFP_KERNEL); - if (!stk->elem) { - pci_free_consistent(h->pdev, size, stk->pool, - stk->cmd_pool_handle); - return -1; - } - for (i=0; ielem[i] = &stk->pool[i]; stk->elem[i]->busaddr = (__u32) (stk->cmd_pool_handle + @@ -262,8 +255,6 @@ scsi_cmd_stack_free(ctlr_info_t *h) pci_free_consistent(h->pdev, size, stk->pool, stk->cmd_pool_handle); stk->pool = NULL; cciss_free_sg_chain_blocks(sa->cmd_sg_list, CMD_STACK_SIZE); - kfree(stk->elem); - stk->elem = NULL; } #if 0 -- GitLab From 167400d34070ebbc408dc0f447c4ddb4bf837360 Mon Sep 17 00:00:00 2001 From: Justin TerAvest Date: Sat, 12 Mar 2011 16:54:00 +0100 Subject: [PATCH 0638/2822] blk-cgroup: Add unaccounted time to timeslice_used. There are two kind of times that tasks are not charged for: the first seek and the extra time slice used over the allocated timeslice. Both of these exported as a new unaccounted_time stat. I think it would be good to have this reported in 'time' as well, but that is probably a separate discussion. Signed-off-by: Justin TerAvest Signed-off-by: Jens Axboe --- block/blk-cgroup.c | 16 +++++++++++++++- block/blk-cgroup.h | 12 ++++++++++-- block/cfq-iosched.c | 21 +++++++++++++-------- block/cfq.h | 6 +++--- 4 files changed, 41 insertions(+), 14 deletions(-) diff --git a/block/blk-cgroup.c b/block/blk-cgroup.c index 455768a3eb9e8..77ee3c1ec1a7a 100644 --- a/block/blk-cgroup.c +++ b/block/blk-cgroup.c @@ -371,12 +371,14 @@ void blkiocg_update_io_remove_stats(struct blkio_group *blkg, } EXPORT_SYMBOL_GPL(blkiocg_update_io_remove_stats); -void blkiocg_update_timeslice_used(struct blkio_group *blkg, unsigned long time) +void blkiocg_update_timeslice_used(struct blkio_group *blkg, unsigned long time, + unsigned long unaccounted_time) { unsigned long flags; spin_lock_irqsave(&blkg->stats_lock, flags); blkg->stats.time += time; + blkg->stats.unaccounted_time += unaccounted_time; spin_unlock_irqrestore(&blkg->stats_lock, flags); } EXPORT_SYMBOL_GPL(blkiocg_update_timeslice_used); @@ -603,6 +605,9 @@ static uint64_t blkio_get_stat(struct blkio_group *blkg, if (type == BLKIO_STAT_SECTORS) return blkio_fill_stat(key_str, MAX_KEY_LEN - 1, blkg->stats.sectors, cb, dev); + if (type == BLKIO_STAT_UNACCOUNTED_TIME) + return blkio_fill_stat(key_str, MAX_KEY_LEN - 1, + blkg->stats.unaccounted_time, cb, dev); #ifdef CONFIG_DEBUG_BLK_CGROUP if (type == BLKIO_STAT_AVG_QUEUE_SIZE) { uint64_t sum = blkg->stats.avg_queue_size_sum; @@ -1106,6 +1111,9 @@ static int blkiocg_file_read_map(struct cgroup *cgrp, struct cftype *cft, case BLKIO_PROP_sectors: return blkio_read_blkg_stats(blkcg, cft, cb, BLKIO_STAT_SECTORS, 0); + case BLKIO_PROP_unaccounted_time: + return blkio_read_blkg_stats(blkcg, cft, cb, + BLKIO_STAT_UNACCOUNTED_TIME, 0); case BLKIO_PROP_io_service_bytes: return blkio_read_blkg_stats(blkcg, cft, cb, BLKIO_STAT_SERVICE_BYTES, 1); @@ -1261,6 +1269,12 @@ struct cftype blkio_files[] = { BLKIO_PROP_sectors), .read_map = blkiocg_file_read_map, }, + { + .name = "unaccounted_time", + .private = BLKIOFILE_PRIVATE(BLKIO_POLICY_PROP, + BLKIO_PROP_unaccounted_time), + .read_map = blkiocg_file_read_map, + }, { .name = "io_service_bytes", .private = BLKIOFILE_PRIVATE(BLKIO_POLICY_PROP, diff --git a/block/blk-cgroup.h b/block/blk-cgroup.h index 57e7234c5ae5b..10919fae2d3aa 100644 --- a/block/blk-cgroup.h +++ b/block/blk-cgroup.h @@ -49,6 +49,8 @@ enum stat_type { /* All the single valued stats go below this */ BLKIO_STAT_TIME, BLKIO_STAT_SECTORS, + /* Time not charged to this cgroup */ + BLKIO_STAT_UNACCOUNTED_TIME, #ifdef CONFIG_DEBUG_BLK_CGROUP BLKIO_STAT_AVG_QUEUE_SIZE, BLKIO_STAT_IDLE_TIME, @@ -81,6 +83,7 @@ enum blkcg_file_name_prop { BLKIO_PROP_io_serviced, BLKIO_PROP_time, BLKIO_PROP_sectors, + BLKIO_PROP_unaccounted_time, BLKIO_PROP_io_service_time, BLKIO_PROP_io_wait_time, BLKIO_PROP_io_merged, @@ -114,6 +117,8 @@ struct blkio_group_stats { /* total disk time and nr sectors dispatched by this group */ uint64_t time; uint64_t sectors; + /* Time not charged to this cgroup */ + uint64_t unaccounted_time; uint64_t stat_arr[BLKIO_STAT_QUEUED + 1][BLKIO_STAT_TOTAL]; #ifdef CONFIG_DEBUG_BLK_CGROUP /* Sum of number of IOs queued across all samples */ @@ -293,7 +298,8 @@ extern int blkiocg_del_blkio_group(struct blkio_group *blkg); extern struct blkio_group *blkiocg_lookup_group(struct blkio_cgroup *blkcg, void *key); void blkiocg_update_timeslice_used(struct blkio_group *blkg, - unsigned long time); + unsigned long time, + unsigned long unaccounted_time); void blkiocg_update_dispatch_stats(struct blkio_group *blkg, uint64_t bytes, bool direction, bool sync); void blkiocg_update_completion_stats(struct blkio_group *blkg, @@ -319,7 +325,9 @@ blkiocg_del_blkio_group(struct blkio_group *blkg) { return 0; } static inline struct blkio_group * blkiocg_lookup_group(struct blkio_cgroup *blkcg, void *key) { return NULL; } static inline void blkiocg_update_timeslice_used(struct blkio_group *blkg, - unsigned long time) {} + unsigned long time, + unsigned long unaccounted_time) +{} static inline void blkiocg_update_dispatch_stats(struct blkio_group *blkg, uint64_t bytes, bool direction, bool sync) {} static inline void blkiocg_update_completion_stats(struct blkio_group *blkg, diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c index c826ef81c6794..89e0d1cc14bab 100644 --- a/block/cfq-iosched.c +++ b/block/cfq-iosched.c @@ -899,7 +899,8 @@ cfq_group_service_tree_del(struct cfq_data *cfqd, struct cfq_group *cfqg) cfq_blkiocg_update_dequeue_stats(&cfqg->blkg, 1); } -static inline unsigned int cfq_cfqq_slice_usage(struct cfq_queue *cfqq) +static inline unsigned int cfq_cfqq_slice_usage(struct cfq_queue *cfqq, + unsigned int *unaccounted_time) { unsigned int slice_used; @@ -918,8 +919,13 @@ static inline unsigned int cfq_cfqq_slice_usage(struct cfq_queue *cfqq) 1); } else { slice_used = jiffies - cfqq->slice_start; - if (slice_used > cfqq->allocated_slice) + if (slice_used > cfqq->allocated_slice) { + *unaccounted_time = slice_used - cfqq->allocated_slice; slice_used = cfqq->allocated_slice; + } + if (time_after(cfqq->slice_start, cfqq->dispatch_start)) + *unaccounted_time += cfqq->slice_start - + cfqq->dispatch_start; } return slice_used; @@ -929,12 +935,12 @@ static void cfq_group_served(struct cfq_data *cfqd, struct cfq_group *cfqg, struct cfq_queue *cfqq) { struct cfq_rb_root *st = &cfqd->grp_service_tree; - unsigned int used_sl, charge; + unsigned int used_sl, charge, unaccounted_sl = 0; int nr_sync = cfqg->nr_cfqq - cfqg_busy_async_queues(cfqd, cfqg) - cfqg->service_tree_idle.count; BUG_ON(nr_sync < 0); - used_sl = charge = cfq_cfqq_slice_usage(cfqq); + used_sl = charge = cfq_cfqq_slice_usage(cfqq, &unaccounted_sl); if (iops_mode(cfqd)) charge = cfqq->slice_dispatch; @@ -960,7 +966,8 @@ static void cfq_group_served(struct cfq_data *cfqd, struct cfq_group *cfqg, cfq_log_cfqq(cfqq->cfqd, cfqq, "sl_used=%u disp=%u charge=%u iops=%u" " sect=%u", used_sl, cfqq->slice_dispatch, charge, iops_mode(cfqd), cfqq->nr_sectors); - cfq_blkiocg_update_timeslice_used(&cfqg->blkg, used_sl); + cfq_blkiocg_update_timeslice_used(&cfqg->blkg, used_sl, + unaccounted_sl); cfq_blkiocg_set_start_empty_time(&cfqg->blkg); } @@ -3296,9 +3303,7 @@ static void cfq_preempt_queue(struct cfq_data *cfqd, struct cfq_queue *cfqq) BUG_ON(!cfq_cfqq_on_rr(cfqq)); cfq_service_tree_add(cfqd, cfqq, 1); - - cfqq->slice_end = 0; - cfq_mark_cfqq_slice_new(cfqq); + __cfq_set_active_queue(cfqd, cfqq); } /* diff --git a/block/cfq.h b/block/cfq.h index 54a6d90f8e8c9..2a155927e37ce 100644 --- a/block/cfq.h +++ b/block/cfq.h @@ -16,9 +16,9 @@ static inline void cfq_blkiocg_update_dequeue_stats(struct blkio_group *blkg, } static inline void cfq_blkiocg_update_timeslice_used(struct blkio_group *blkg, - unsigned long time) + unsigned long time, unsigned long unaccounted_time) { - blkiocg_update_timeslice_used(blkg, time); + blkiocg_update_timeslice_used(blkg, time, unaccounted_time); } static inline void cfq_blkiocg_set_start_empty_time(struct blkio_group *blkg) @@ -85,7 +85,7 @@ static inline void cfq_blkiocg_update_dequeue_stats(struct blkio_group *blkg, unsigned long dequeue) {} static inline void cfq_blkiocg_update_timeslice_used(struct blkio_group *blkg, - unsigned long time) {} + unsigned long time, unsigned long unaccounted_time) {} static inline void cfq_blkiocg_set_start_empty_time(struct blkio_group *blkg) {} static inline void cfq_blkiocg_update_io_remove_stats(struct blkio_group *blkg, bool direction, bool sync) {} -- GitLab From 4fc193814b3a269c1ea89aefdb56d4f957680d44 Mon Sep 17 00:00:00 2001 From: Ping Cheng Date: Sat, 12 Mar 2011 20:33:33 -0800 Subject: [PATCH 0639/2822] Input: wacom - do not send 2FGT Tablet PC events in TAP format 2FGT Tablet PC touch events were processed in _TAP_ format. Remove them so we can change to _MT_ format. Signed-off-by: Ping Cheng Signed-off-by: Dmitry Torokhov --- drivers/input/tablet/wacom_wac.c | 84 +++----------------------------- drivers/input/tablet/wacom_wac.h | 5 +- 2 files changed, 10 insertions(+), 79 deletions(-) diff --git a/drivers/input/tablet/wacom_wac.c b/drivers/input/tablet/wacom_wac.c index 367fa82a607e8..5488c6172621c 100644 --- a/drivers/input/tablet/wacom_wac.c +++ b/drivers/input/tablet/wacom_wac.c @@ -675,40 +675,6 @@ static int wacom_intuos_irq(struct wacom_wac *wacom) return 1; } - -static void wacom_tpc_finger_in(struct wacom_wac *wacom, char *data, int idx) -{ - struct input_dev *input = wacom->input; - int finger = idx + 1; - int x = le16_to_cpup((__le16 *)&data[finger * 2]) & 0x7fff; - int y = le16_to_cpup((__le16 *)&data[4 + finger * 2]) & 0x7fff; - - /* - * Work around input core suppressing "duplicate" events since - * we are abusing ABS_X/ABS_Y to transmit multi-finger data. - * This should go away once we switch to true multitouch - * protocol. - */ - if (wacom->last_finger != finger) { - if (x == input_abs_get_val(input, ABS_X)) - x++; - - if (y == input_abs_get_val(input, ABS_Y)) - y++; - } - - input_report_abs(input, ABS_X, x); - input_report_abs(input, ABS_Y, y); - input_report_abs(input, ABS_MISC, wacom->id[0]); - input_report_key(input, wacom->tool[finger], 1); - if (!idx) - input_report_key(input, BTN_TOUCH, 1); - input_event(input, EV_MSC, MSC_SERIAL, finger); - input_sync(input); - - wacom->last_finger = finger; -} - static void wacom_tpc_touch_out(struct wacom_wac *wacom, int idx) { struct input_dev *input = wacom->input; @@ -731,7 +697,6 @@ static void wacom_tpc_touch_in(struct wacom_wac *wacom, size_t len) wacom->tool[1] = BTN_TOOL_DOUBLETAP; wacom->id[0] = TOUCH_DEVICE_ID; - wacom->tool[2] = BTN_TOOL_TRIPLETAP; if (len != WACOM_PKGLEN_TPC1FG) { @@ -746,18 +711,6 @@ static void wacom_tpc_touch_in(struct wacom_wac *wacom, size_t len) input_report_key(input, wacom->tool[1], 1); input_sync(input); break; - - case WACOM_REPORT_TPC2FG: - if (data[1] & 0x01) - wacom_tpc_finger_in(wacom, data, 0); - else if (wacom->id[1] & 0x01) - wacom_tpc_touch_out(wacom, 0); - - if (data[1] & 0x02) - wacom_tpc_finger_in(wacom, data, 1); - else if (wacom->id[1] & 0x02) - wacom_tpc_touch_out(wacom, 1); - break; } } else { input_report_abs(input, ABS_X, get_unaligned_le16(&data[1])); @@ -779,47 +732,26 @@ static int wacom_tpc_irq(struct wacom_wac *wacom, size_t len) dbg("wacom_tpc_irq: received report #%d", data[0]); - if (len == WACOM_PKGLEN_TPC1FG || /* single touch */ - data[0] == WACOM_REPORT_TPC1FG || /* single touch */ - data[0] == WACOM_REPORT_TPC2FG) { /* 2FG touch */ + if (len == WACOM_PKGLEN_TPC1FG || + data[0] == WACOM_REPORT_TPC1FG) { /* single touch */ if (wacom->shared->stylus_in_proximity) { if (wacom->id[1] & 0x01) wacom_tpc_touch_out(wacom, 0); - if (wacom->id[1] & 0x02) - wacom_tpc_touch_out(wacom, 1); - wacom->id[1] = 0; return 0; } - if (len == WACOM_PKGLEN_TPC1FG) { /* with touch */ + if (len == WACOM_PKGLEN_TPC1FG) prox = data[0] & 0x01; - } else { /* with capacity */ - if (data[0] == WACOM_REPORT_TPC1FG) - /* single touch */ - prox = data[1] & 0x01; - else - /* 2FG touch data */ - prox = data[1] & 0x03; - } + else /* with capacity */ + prox = data[1] & 0x01; - if (prox) { - if (!wacom->id[1]) - wacom->last_finger = 1; + if (prox) wacom_tpc_touch_in(wacom, len); - } else { - if (data[0] == WACOM_REPORT_TPC2FG) { - /* 2FGT out-prox */ - if (wacom->id[1] & 0x01) - wacom_tpc_touch_out(wacom, 0); - - if (wacom->id[1] & 0x02) - wacom_tpc_touch_out(wacom, 1); - } else - /* one finger touch */ - wacom_tpc_touch_out(wacom, 0); + else { + wacom_tpc_touch_out(wacom, 0); wacom->id[0] = 0; } diff --git a/drivers/input/tablet/wacom_wac.h b/drivers/input/tablet/wacom_wac.h index b1310ec9720c0..8f747dd1214e3 100644 --- a/drivers/input/tablet/wacom_wac.h +++ b/drivers/input/tablet/wacom_wac.h @@ -93,10 +93,9 @@ struct wacom_shared { struct wacom_wac { char name[64]; unsigned char *data; - int tool[3]; - int id[3]; + int tool[2]; + int id[2]; __u32 serial[2]; - int last_finger; struct wacom_features features; struct wacom_shared *shared; struct input_dev *input; -- GitLab From 8aa9a9ac89baa0e423da0211e0883d28165697e0 Mon Sep 17 00:00:00 2001 From: Ping Cheng Date: Sat, 12 Mar 2011 20:34:11 -0800 Subject: [PATCH 0640/2822] Input: wacom - process pen data in its own routine So it would be easier for patch reviewers to follow the data path. Reviewed-by: Henrik Rydberg Reviewed-by: Chris Bagwell Signed-off-by: Ping Cheng Signed-off-by: Dmitry Torokhov --- drivers/input/tablet/wacom_wac.c | 73 +++++++++++++++++--------------- 1 file changed, 40 insertions(+), 33 deletions(-) diff --git a/drivers/input/tablet/wacom_wac.c b/drivers/input/tablet/wacom_wac.c index 5488c6172621c..15bab99a4c7ed 100644 --- a/drivers/input/tablet/wacom_wac.c +++ b/drivers/input/tablet/wacom_wac.c @@ -722,13 +722,47 @@ static void wacom_tpc_touch_in(struct wacom_wac *wacom, size_t len) } } -static int wacom_tpc_irq(struct wacom_wac *wacom, size_t len) +static int wacom_tpc_pen(struct wacom_wac *wacom) { struct wacom_features *features = &wacom->features; char *data = wacom->data; struct input_dev *input = wacom->input; - int prox = 0, pressure; - int retval = 0; + int prox, pressure; + + prox = data[1] & 0x20; + + if (!wacom->shared->stylus_in_proximity) { /* first in prox */ + /* Going into proximity select tool */ + wacom->tool[0] = (data[1] & 0x0c) ? BTN_TOOL_RUBBER : BTN_TOOL_PEN; + if (wacom->tool[0] == BTN_TOOL_PEN) + wacom->id[0] = STYLUS_DEVICE_ID; + else + wacom->id[0] = ERASER_DEVICE_ID; + + wacom->shared->stylus_in_proximity = true; + } + input_report_key(input, BTN_STYLUS, data[1] & 0x02); + input_report_key(input, BTN_STYLUS2, data[1] & 0x10); + input_report_abs(input, ABS_X, le16_to_cpup((__le16 *)&data[2])); + input_report_abs(input, ABS_Y, le16_to_cpup((__le16 *)&data[4])); + pressure = ((data[7] & 0x01) << 8) | data[6]; + if (pressure < 0) + pressure = features->pressure_max + pressure + 1; + input_report_abs(input, ABS_PRESSURE, pressure); + input_report_key(input, BTN_TOUCH, data[1] & 0x05); + if (!prox) { /* out-prox */ + wacom->id[0] = 0; + wacom->shared->stylus_in_proximity = false; + } + input_report_key(input, wacom->tool[0], prox); + + return 1; +} + +static int wacom_tpc_irq(struct wacom_wac *wacom, size_t len) +{ + char *data = wacom->data; + int prox = 0; dbg("wacom_tpc_irq: received report #%d", data[0]); @@ -757,37 +791,10 @@ static int wacom_tpc_irq(struct wacom_wac *wacom, size_t len) } /* keep prox bit to send proper out-prox event */ wacom->id[1] = prox; - } else if (data[0] == WACOM_REPORT_PENABLED) { /* Penabled */ - prox = data[1] & 0x20; - - if (!wacom->shared->stylus_in_proximity) { /* first in prox */ - /* Going into proximity select tool */ - wacom->tool[0] = (data[1] & 0x0c) ? BTN_TOOL_RUBBER : BTN_TOOL_PEN; - if (wacom->tool[0] == BTN_TOOL_PEN) - wacom->id[0] = STYLUS_DEVICE_ID; - else - wacom->id[0] = ERASER_DEVICE_ID; + } else if (data[0] == WACOM_REPORT_PENABLED) + return wacom_tpc_pen(wacom); - wacom->shared->stylus_in_proximity = true; - } - input_report_key(input, BTN_STYLUS, data[1] & 0x02); - input_report_key(input, BTN_STYLUS2, data[1] & 0x10); - input_report_abs(input, ABS_X, le16_to_cpup((__le16 *)&data[2])); - input_report_abs(input, ABS_Y, le16_to_cpup((__le16 *)&data[4])); - pressure = ((data[7] & 0x01) << 8) | data[6]; - if (pressure < 0) - pressure = features->pressure_max + pressure + 1; - input_report_abs(input, ABS_PRESSURE, pressure); - input_report_key(input, BTN_TOUCH, data[1] & 0x05); - if (!prox) { /* out-prox */ - wacom->id[0] = 0; - wacom->shared->stylus_in_proximity = false; - } - input_report_key(input, wacom->tool[0], prox); - input_report_abs(input, ABS_MISC, wacom->id[0]); - retval = 1; - } - return retval; + return 0; } static int wacom_bpt_touch(struct wacom_wac *wacom) -- GitLab From a43c7c53835ba1ff4e488806d0f8b98e9dce9b0e Mon Sep 17 00:00:00 2001 From: Ping Cheng Date: Sat, 12 Mar 2011 20:34:42 -0800 Subject: [PATCH 0641/2822] Input: wacom - support one finger touch the touchscreen way There are two types of 1FGT devices supported in wacom_wac.c. Changing them to follow the existing touchscreen format, i.e., only report BTN_TOUCH as a valid tool type. Touch data will be ignored if pen is in proximity. This requires a touch up event sent if touch was down when pen comes in. The touch up event should be sent before any pen events are emitted. Otherwise, two pointers would race for the cursor. However, we can not send a touch up inside wacom_tpc_pen since pen and touch are on different logical port. That is why we have to check if touch is up before sending pen events. Reviewed-by: Henrik Rydberg Reviewed-by: Chris Bagwell Signed-off-by: Ping Cheng Signed-off-by: Dmitry Torokhov --- drivers/input/tablet/wacom_wac.c | 139 +++++++++++-------------------- drivers/input/tablet/wacom_wac.h | 1 + 2 files changed, 50 insertions(+), 90 deletions(-) diff --git a/drivers/input/tablet/wacom_wac.c b/drivers/input/tablet/wacom_wac.c index 15bab99a4c7ed..adf8946e8f0d0 100644 --- a/drivers/input/tablet/wacom_wac.c +++ b/drivers/input/tablet/wacom_wac.c @@ -675,51 +675,37 @@ static int wacom_intuos_irq(struct wacom_wac *wacom) return 1; } -static void wacom_tpc_touch_out(struct wacom_wac *wacom, int idx) -{ - struct input_dev *input = wacom->input; - int finger = idx + 1; - - input_report_abs(input, ABS_X, 0); - input_report_abs(input, ABS_Y, 0); - input_report_abs(input, ABS_MISC, 0); - input_report_key(input, wacom->tool[finger], 0); - if (!idx) - input_report_key(input, BTN_TOUCH, 0); - input_event(input, EV_MSC, MSC_SERIAL, finger); - input_sync(input); -} - -static void wacom_tpc_touch_in(struct wacom_wac *wacom, size_t len) +static int wacom_tpc_single_touch(struct wacom_wac *wacom, size_t len) { char *data = wacom->data; struct input_dev *input = wacom->input; + bool prox; + int x = 0, y = 0; - wacom->tool[1] = BTN_TOOL_DOUBLETAP; - wacom->id[0] = TOUCH_DEVICE_ID; + if (!wacom->shared->stylus_in_proximity) { + if (len == WACOM_PKGLEN_TPC1FG) { + prox = data[0] & 0x01; + x = get_unaligned_le16(&data[1]); + y = get_unaligned_le16(&data[3]); + } else { /* with capacity */ + prox = data[1] & 0x01; + x = le16_to_cpup((__le16 *)&data[2]); + y = le16_to_cpup((__le16 *)&data[4]); + } + } else + /* force touch out when pen is in prox */ + prox = 0; - if (len != WACOM_PKGLEN_TPC1FG) { + if (prox) { + input_report_abs(input, ABS_X, x); + input_report_abs(input, ABS_Y, y); + } + input_report_key(input, BTN_TOUCH, prox); - switch (data[0]) { + /* keep touch state for pen events */ + wacom->shared->touch_down = prox; - case WACOM_REPORT_TPC1FG: - input_report_abs(input, ABS_X, le16_to_cpup((__le16 *)&data[2])); - input_report_abs(input, ABS_Y, le16_to_cpup((__le16 *)&data[4])); - input_report_abs(input, ABS_PRESSURE, le16_to_cpup((__le16 *)&data[6])); - input_report_key(input, BTN_TOUCH, le16_to_cpup((__le16 *)&data[6])); - input_report_abs(input, ABS_MISC, wacom->id[0]); - input_report_key(input, wacom->tool[1], 1); - input_sync(input); - break; - } - } else { - input_report_abs(input, ABS_X, get_unaligned_le16(&data[1])); - input_report_abs(input, ABS_Y, get_unaligned_le16(&data[3])); - input_report_key(input, BTN_TOUCH, 1); - input_report_abs(input, ABS_MISC, wacom->id[1]); - input_report_key(input, wacom->tool[1], 1); - input_sync(input); - } + return 1; } static int wacom_tpc_pen(struct wacom_wac *wacom) @@ -727,71 +713,43 @@ static int wacom_tpc_pen(struct wacom_wac *wacom) struct wacom_features *features = &wacom->features; char *data = wacom->data; struct input_dev *input = wacom->input; - int prox, pressure; - - prox = data[1] & 0x20; + int pressure; + bool prox = data[1] & 0x20; - if (!wacom->shared->stylus_in_proximity) { /* first in prox */ + if (!wacom->shared->stylus_in_proximity) /* first in prox */ /* Going into proximity select tool */ wacom->tool[0] = (data[1] & 0x0c) ? BTN_TOOL_RUBBER : BTN_TOOL_PEN; - if (wacom->tool[0] == BTN_TOOL_PEN) - wacom->id[0] = STYLUS_DEVICE_ID; - else - wacom->id[0] = ERASER_DEVICE_ID; - wacom->shared->stylus_in_proximity = true; - } - input_report_key(input, BTN_STYLUS, data[1] & 0x02); - input_report_key(input, BTN_STYLUS2, data[1] & 0x10); - input_report_abs(input, ABS_X, le16_to_cpup((__le16 *)&data[2])); - input_report_abs(input, ABS_Y, le16_to_cpup((__le16 *)&data[4])); - pressure = ((data[7] & 0x01) << 8) | data[6]; - if (pressure < 0) - pressure = features->pressure_max + pressure + 1; - input_report_abs(input, ABS_PRESSURE, pressure); - input_report_key(input, BTN_TOUCH, data[1] & 0x05); - if (!prox) { /* out-prox */ - wacom->id[0] = 0; - wacom->shared->stylus_in_proximity = false; + /* keep pen state for touch events */ + wacom->shared->stylus_in_proximity = prox; + + /* send pen events only when touch is up or forced out */ + if (!wacom->shared->touch_down) { + input_report_key(input, BTN_STYLUS, data[1] & 0x02); + input_report_key(input, BTN_STYLUS2, data[1] & 0x10); + input_report_abs(input, ABS_X, le16_to_cpup((__le16 *)&data[2])); + input_report_abs(input, ABS_Y, le16_to_cpup((__le16 *)&data[4])); + pressure = ((data[7] & 0x01) << 8) | data[6]; + if (pressure < 0) + pressure = features->pressure_max + pressure + 1; + input_report_abs(input, ABS_PRESSURE, pressure); + input_report_key(input, BTN_TOUCH, data[1] & 0x05); + input_report_key(input, wacom->tool[0], prox); + return 1; } - input_report_key(input, wacom->tool[0], prox); - return 1; + return 0; } static int wacom_tpc_irq(struct wacom_wac *wacom, size_t len) { char *data = wacom->data; - int prox = 0; dbg("wacom_tpc_irq: received report #%d", data[0]); - if (len == WACOM_PKGLEN_TPC1FG || - data[0] == WACOM_REPORT_TPC1FG) { /* single touch */ - - if (wacom->shared->stylus_in_proximity) { - if (wacom->id[1] & 0x01) - wacom_tpc_touch_out(wacom, 0); - - wacom->id[1] = 0; - return 0; - } - - if (len == WACOM_PKGLEN_TPC1FG) - prox = data[0] & 0x01; - else /* with capacity */ - prox = data[1] & 0x01; - - if (prox) - wacom_tpc_touch_in(wacom, len); - else { - wacom_tpc_touch_out(wacom, 0); - - wacom->id[0] = 0; - } - /* keep prox bit to send proper out-prox event */ - wacom->id[1] = prox; - } else if (data[0] == WACOM_REPORT_PENABLED) + if (len == WACOM_PKGLEN_TPC1FG || data[0] == WACOM_REPORT_TPC1FG) + return wacom_tpc_single_touch(wacom, len); + else if (data[0] == WACOM_REPORT_PENABLED) return wacom_tpc_pen(wacom); return 0; @@ -1172,6 +1130,8 @@ void wacom_setup_input_capabilities(struct input_dev *input_dev, /* fall through */ case TABLETPC: + __clear_bit(ABS_MISC, input_dev->absbit); + if (features->device_type == BTN_TOOL_DOUBLETAP || features->device_type == BTN_TOOL_TRIPLETAP) { input_abs_set_res(input_dev, ABS_X, @@ -1180,7 +1140,6 @@ void wacom_setup_input_capabilities(struct input_dev *input_dev, input_abs_set_res(input_dev, ABS_Y, wacom_calculate_touch_res(features->y_max, features->y_phy)); - __set_bit(BTN_TOOL_DOUBLETAP, input_dev->keybit); } if (features->device_type != BTN_TOOL_PEN) diff --git a/drivers/input/tablet/wacom_wac.h b/drivers/input/tablet/wacom_wac.h index 8f747dd1214e3..835f756b150c1 100644 --- a/drivers/input/tablet/wacom_wac.h +++ b/drivers/input/tablet/wacom_wac.h @@ -88,6 +88,7 @@ struct wacom_features { struct wacom_shared { bool stylus_in_proximity; + bool touch_down; }; struct wacom_wac { -- GitLab From 84eb5aa6ccb2a62c40722b8c5fb1338ea12155a3 Mon Sep 17 00:00:00 2001 From: Ping Cheng Date: Sat, 12 Mar 2011 20:35:18 -0800 Subject: [PATCH 0642/2822] Input: wacom - support 2FGT in MT format Reviewed-by: Henrik Rydberg Reviewed-by: Chris Bagwell Signed-off-by: Ping Cheng Signed-off-by: Dmitry Torokhov --- drivers/input/tablet/wacom_sys.c | 12 +++---- drivers/input/tablet/wacom_wac.c | 59 +++++++++++++++++++++++++------- 2 files changed, 53 insertions(+), 18 deletions(-) diff --git a/drivers/input/tablet/wacom_sys.c b/drivers/input/tablet/wacom_sys.c index fc381498b7987..b97665f9765e3 100644 --- a/drivers/input/tablet/wacom_sys.c +++ b/drivers/input/tablet/wacom_sys.c @@ -193,16 +193,16 @@ static int wacom_parse_hid(struct usb_interface *intf, struct hid_descriptor *hi case HID_USAGE_X: if (usage == WCM_DESKTOP) { if (finger) { - features->device_type = BTN_TOOL_DOUBLETAP; + features->device_type = BTN_TOOL_FINGER; if (features->type == TABLETPC2FG) { /* need to reset back */ features->pktlen = WACOM_PKGLEN_TPC2FG; - features->device_type = BTN_TOOL_TRIPLETAP; + features->device_type = BTN_TOOL_DOUBLETAP; } if (features->type == BAMBOO_PT) { /* need to reset back */ features->pktlen = WACOM_PKGLEN_BBTOUCH; - features->device_type = BTN_TOOL_TRIPLETAP; + features->device_type = BTN_TOOL_DOUBLETAP; features->x_phy = get_unaligned_le16(&report[i + 5]); features->x_max = @@ -241,11 +241,11 @@ static int wacom_parse_hid(struct usb_interface *intf, struct hid_descriptor *hi case HID_USAGE_Y: if (usage == WCM_DESKTOP) { if (finger) { - features->device_type = BTN_TOOL_DOUBLETAP; + features->device_type = BTN_TOOL_FINGER; if (features->type == TABLETPC2FG) { /* need to reset back */ features->pktlen = WACOM_PKGLEN_TPC2FG; - features->device_type = BTN_TOOL_TRIPLETAP; + features->device_type = BTN_TOOL_DOUBLETAP; features->y_max = get_unaligned_le16(&report[i + 3]); features->y_phy = @@ -254,7 +254,7 @@ static int wacom_parse_hid(struct usb_interface *intf, struct hid_descriptor *hi } else if (features->type == BAMBOO_PT) { /* need to reset back */ features->pktlen = WACOM_PKGLEN_BBTOUCH; - features->device_type = BTN_TOOL_TRIPLETAP; + features->device_type = BTN_TOOL_DOUBLETAP; features->y_phy = get_unaligned_le16(&report[i + 3]); features->y_max = diff --git a/drivers/input/tablet/wacom_wac.c b/drivers/input/tablet/wacom_wac.c index adf8946e8f0d0..5597637cfd418 100644 --- a/drivers/input/tablet/wacom_wac.c +++ b/drivers/input/tablet/wacom_wac.c @@ -675,6 +675,37 @@ static int wacom_intuos_irq(struct wacom_wac *wacom) return 1; } +static int wacom_tpc_mt_touch(struct wacom_wac *wacom) +{ + struct input_dev *input = wacom->input; + unsigned char *data = wacom->data; + int contact_with_no_pen_down_count = 0; + int i; + + for (i = 0; i < 2; i++) { + int p = data[1] & (1 << i); + bool touch = p && !wacom->shared->stylus_in_proximity; + + input_mt_slot(input, i); + input_mt_report_slot_state(input, MT_TOOL_FINGER, touch); + if (touch) { + int x = le16_to_cpup((__le16 *)&data[i * 2 + 2]) & 0x7fff; + int y = le16_to_cpup((__le16 *)&data[i * 2 + 6]) & 0x7fff; + + input_report_abs(input, ABS_MT_POSITION_X, x); + input_report_abs(input, ABS_MT_POSITION_Y, y); + contact_with_no_pen_down_count++; + } + } + + /* keep touch state for pen event */ + wacom->shared->touch_down = (contact_with_no_pen_down_count > 0); + + input_mt_report_pointer_emulation(input, true); + + return 1; +} + static int wacom_tpc_single_touch(struct wacom_wac *wacom, size_t len) { char *data = wacom->data; @@ -749,6 +780,8 @@ static int wacom_tpc_irq(struct wacom_wac *wacom, size_t len) if (len == WACOM_PKGLEN_TPC1FG || data[0] == WACOM_REPORT_TPC1FG) return wacom_tpc_single_touch(wacom, len); + else if (data[0] == WACOM_REPORT_TPC2FG) + return wacom_tpc_mt_touch(wacom); else if (data[0] == WACOM_REPORT_PENABLED) return wacom_tpc_pen(wacom); @@ -975,7 +1008,7 @@ void wacom_setup_device_quirks(struct wacom_features *features) { /* touch device found but size is not defined. use default */ - if (features->device_type == BTN_TOOL_DOUBLETAP && !features->x_max) { + if (features->device_type == BTN_TOOL_FINGER && !features->x_max) { features->x_max = 1023; features->y_max = 1023; } @@ -987,7 +1020,7 @@ void wacom_setup_device_quirks(struct wacom_features *features) /* quirks for bamboo touch */ if (features->type == BAMBOO_PT && - features->device_type == BTN_TOOL_TRIPLETAP) { + features->device_type == BTN_TOOL_DOUBLETAP) { features->x_max <<= 5; features->y_max <<= 5; features->x_fuzz <<= 5; @@ -1123,28 +1156,30 @@ void wacom_setup_input_capabilities(struct input_dev *input_dev, break; case TABLETPC2FG: - if (features->device_type == BTN_TOOL_TRIPLETAP) { - __set_bit(BTN_TOOL_TRIPLETAP, input_dev->keybit); - input_set_capability(input_dev, EV_MSC, MSC_SERIAL); + if (features->device_type == BTN_TOOL_DOUBLETAP) { + + input_mt_init_slots(input_dev, 2); + input_set_abs_params(input_dev, ABS_MT_TOOL_TYPE, + 0, MT_TOOL_MAX, 0, 0); + input_set_abs_params(input_dev, ABS_MT_POSITION_X, + 0, features->x_max, 0, 0); + input_set_abs_params(input_dev, ABS_MT_POSITION_Y, + 0, features->y_max, 0, 0); } /* fall through */ case TABLETPC: __clear_bit(ABS_MISC, input_dev->absbit); - if (features->device_type == BTN_TOOL_DOUBLETAP || - features->device_type == BTN_TOOL_TRIPLETAP) { + if (features->device_type != BTN_TOOL_PEN) { input_abs_set_res(input_dev, ABS_X, wacom_calculate_touch_res(features->x_max, features->x_phy)); input_abs_set_res(input_dev, ABS_Y, wacom_calculate_touch_res(features->y_max, features->y_phy)); - } - - if (features->device_type != BTN_TOOL_PEN) break; /* no need to process stylus stuff */ - + } /* fall through */ case PL: @@ -1162,7 +1197,7 @@ void wacom_setup_input_capabilities(struct input_dev *input_dev, case BAMBOO_PT: __clear_bit(ABS_MISC, input_dev->absbit); - if (features->device_type == BTN_TOOL_TRIPLETAP) { + if (features->device_type == BTN_TOOL_DOUBLETAP) { __set_bit(BTN_LEFT, input_dev->keybit); __set_bit(BTN_FORWARD, input_dev->keybit); __set_bit(BTN_BACK, input_dev->keybit); -- GitLab From 47340bd9fefb571888836da942b5aee0e85e959c Mon Sep 17 00:00:00 2001 From: Andy Botting Date: Sat, 12 Mar 2011 20:27:22 -0800 Subject: [PATCH 0643/2822] Input: bcm5974 - add support for MacBookPro8 This patch add multitouch support for the MacBookPro8,1 and MacBookPro8,2 models. Cc: stable@kernel.org Signed-off-by: Andy Botting Signed-off-by: Henrik Rydberg Acked-by: Jiri Kosina Signed-off-by: Dmitry Torokhov --- drivers/hid/hid-apple.c | 6 ++++++ drivers/hid/hid-core.c | 6 ++++++ drivers/hid/hid-ids.h | 3 +++ drivers/input/mouse/bcm5974.c | 20 ++++++++++++++++++++ 4 files changed, 35 insertions(+) diff --git a/drivers/hid/hid-apple.c b/drivers/hid/hid-apple.c index 61aa712333927..b85744fe84647 100644 --- a/drivers/hid/hid-apple.c +++ b/drivers/hid/hid-apple.c @@ -481,6 +481,12 @@ static const struct hid_device_id apple_devices[] = { .driver_data = APPLE_HAS_FN | APPLE_ISO_KEYBOARD }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4A_JIS), .driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5_ANSI), + .driver_data = APPLE_HAS_FN }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5_ISO), + .driver_data = APPLE_HAS_FN | APPLE_ISO_KEYBOARD }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5_JIS), + .driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS }, { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ANSI), .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN }, { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ISO), diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index d678cf3d33d5e..48a0a2f3e0721 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -1302,6 +1302,9 @@ static const struct hid_device_id hid_have_special_driver[] = { { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4A_ANSI) }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4A_ISO) }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4A_JIS) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5_ANSI) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5_ISO) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5_JIS) }, { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ANSI) }, { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ISO) }, { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_JIS) }, @@ -1801,6 +1804,9 @@ static const struct hid_device_id hid_mouse_ignore_list[] = { { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4A_ANSI) }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4A_ISO) }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4A_JIS) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5_ANSI) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5_ISO) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5_JIS) }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY) }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY) }, { } diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index 92a0d61a7379c..ca32ecbdce067 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -103,6 +103,9 @@ #define USB_DEVICE_ID_APPLE_WELLSPRING4A_ANSI 0x0242 #define USB_DEVICE_ID_APPLE_WELLSPRING4A_ISO 0x0243 #define USB_DEVICE_ID_APPLE_WELLSPRING4A_JIS 0x0244 +#define USB_DEVICE_ID_APPLE_WELLSPRING5_ANSI 0x0245 +#define USB_DEVICE_ID_APPLE_WELLSPRING5_ISO 0x0246 +#define USB_DEVICE_ID_APPLE_WELLSPRING5_JIS 0x0247 #define USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ANSI 0x0239 #define USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ISO 0x023a #define USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_JIS 0x023b diff --git a/drivers/input/mouse/bcm5974.c b/drivers/input/mouse/bcm5974.c index ee82851afe3ee..318531424848f 100644 --- a/drivers/input/mouse/bcm5974.c +++ b/drivers/input/mouse/bcm5974.c @@ -63,6 +63,10 @@ #define USB_DEVICE_ID_APPLE_WELLSPRING4A_ANSI 0x0242 #define USB_DEVICE_ID_APPLE_WELLSPRING4A_ISO 0x0243 #define USB_DEVICE_ID_APPLE_WELLSPRING4A_JIS 0x0244 +/* Macbook8 (unibody, March 2011) */ +#define USB_DEVICE_ID_APPLE_WELLSPRING5_ANSI 0x0245 +#define USB_DEVICE_ID_APPLE_WELLSPRING5_ISO 0x0246 +#define USB_DEVICE_ID_APPLE_WELLSPRING5_JIS 0x0247 #define BCM5974_DEVICE(prod) { \ .match_flags = (USB_DEVICE_ID_MATCH_DEVICE | \ @@ -96,6 +100,10 @@ static const struct usb_device_id bcm5974_table[] = { BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING4A_ANSI), BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING4A_ISO), BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING4A_JIS), + /* MacbookPro8 */ + BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING5_ANSI), + BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING5_ISO), + BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING5_JIS), /* Terminating entry */ {} }; @@ -274,6 +282,18 @@ static const struct bcm5974_config bcm5974_config_table[] = { { DIM_X, DIM_X / SN_COORD, -4616, 5112 }, { DIM_Y, DIM_Y / SN_COORD, -142, 5234 } }, + { + USB_DEVICE_ID_APPLE_WELLSPRING5_ANSI, + USB_DEVICE_ID_APPLE_WELLSPRING5_ISO, + USB_DEVICE_ID_APPLE_WELLSPRING5_JIS, + HAS_INTEGRATED_BUTTON, + 0x84, sizeof(struct bt_data), + 0x81, TYPE2, FINGER_TYPE2, FINGER_TYPE2 + SIZEOF_ALL_FINGERS, + { DIM_PRESSURE, DIM_PRESSURE / SN_PRESSURE, 0, 300 }, + { DIM_WIDTH, DIM_WIDTH / SN_WIDTH, 0, 2048 }, + { DIM_X, DIM_X / SN_COORD, -4415, 5050 }, + { DIM_Y, DIM_Y / SN_COORD, -55, 6680 } + }, {} }; -- GitLab From 23c483d29fcbc35591131019660b2630cc6629ae Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Sat, 12 Mar 2011 20:48:34 -0800 Subject: [PATCH 0644/2822] Input: wm831x-ts - default pressure measurements on tslib expects pressure measurements so enable them by default for better compatibility. Signed-off-by: Mark Brown Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/wm831x-ts.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/input/touchscreen/wm831x-ts.c b/drivers/input/touchscreen/wm831x-ts.c index 1022f715d3c25..3db0c29f3b054 100644 --- a/drivers/input/touchscreen/wm831x-ts.c +++ b/drivers/input/touchscreen/wm831x-ts.c @@ -225,7 +225,10 @@ static __devinit int wm831x_ts_probe(struct platform_device *pdev) else wm831x_ts->pd_irq = platform_get_irq_byname(pdev, "TCHPD"); - wm831x_ts->pressure = pdata && pdata->pressure; + if (pdata) + wm831x_ts->pressure = pdata->pressure; + else + wm831x_ts->pressure = true; /* Five wire touchscreens can't report pressure */ if (pdata && pdata->fivewire) { -- GitLab From cfbdab951369f15de890597530076bf0119361be Mon Sep 17 00:00:00 2001 From: Jason Wang Date: Mon, 17 Jan 2011 16:10:59 +0800 Subject: [PATCH 0645/2822] vhost-net: check the support of mergeable buffer outside the receive loop No need to check the support of mergeable buffer inside the recevie loop as the whole handle_rx()_xx is in the read critical region. So this patch move it ahead of the receiving loop. Signed-off-by: Jason Wang Signed-off-by: Michael S. Tsirkin --- drivers/vhost/net.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/vhost/net.c b/drivers/vhost/net.c index 59dad9fe52ddc..9f57cd45fe8ff 100644 --- a/drivers/vhost/net.c +++ b/drivers/vhost/net.c @@ -411,7 +411,7 @@ static void handle_rx_mergeable(struct vhost_net *net) .hdr.gso_type = VIRTIO_NET_HDR_GSO_NONE }; size_t total_len = 0; - int err, headcount; + int err, headcount, mergeable; size_t vhost_hlen, sock_hlen; size_t vhost_len, sock_len; /* TODO: check that we are running from vhost_worker? */ @@ -427,6 +427,7 @@ static void handle_rx_mergeable(struct vhost_net *net) vq_log = unlikely(vhost_has_feature(&net->dev, VHOST_F_LOG_ALL)) ? vq->log : NULL; + mergeable = vhost_has_feature(&net->dev, VIRTIO_NET_F_MRG_RXBUF); while ((sock_len = peek_head_len(sock->sk))) { sock_len += sock_hlen; @@ -476,7 +477,7 @@ static void handle_rx_mergeable(struct vhost_net *net) break; } /* TODO: Should check and handle checksum. */ - if (vhost_has_feature(&net->dev, VIRTIO_NET_F_MRG_RXBUF) && + if (likely(mergeable) && memcpy_toiovecend(vq->hdr, (unsigned char *)&headcount, offsetof(typeof(hdr), num_buffers), sizeof hdr.num_buffers)) { -- GitLab From 94249369e9930276e30087da205349a55478cbb5 Mon Sep 17 00:00:00 2001 From: Jason Wang Date: Mon, 17 Jan 2011 16:11:08 +0800 Subject: [PATCH 0646/2822] vhost-net: Unify the code of mergeable and big buffer handling Codes duplication were found between the handling of mergeable and big buffers, so this patch tries to unify them. This could be easily done by adding a quota to the get_rx_bufs() which is used to limit the number of buffers it returns (for mergeable buffer, the quota is simply UIO_MAXIOV, for big buffers, the quota is just 1), and then the previous handle_rx_mergeable() could be resued also for big buffers. Signed-off-by: Jason Wang Signed-off-by: Michael S. Tsirkin --- drivers/vhost/net.c | 128 +++----------------------------------------- 1 file changed, 7 insertions(+), 121 deletions(-) diff --git a/drivers/vhost/net.c b/drivers/vhost/net.c index 9f57cd45fe8ff..0329c411bbf10 100644 --- a/drivers/vhost/net.c +++ b/drivers/vhost/net.c @@ -229,6 +229,7 @@ static int peek_head_len(struct sock *sk) * @iovcount - returned count of io vectors we fill * @log - vhost log * @log_num - log offset + * @quota - headcount quota, 1 for big buffer * returns number of buffer heads allocated, negative on error */ static int get_rx_bufs(struct vhost_virtqueue *vq, @@ -236,7 +237,8 @@ static int get_rx_bufs(struct vhost_virtqueue *vq, int datalen, unsigned *iovcount, struct vhost_log *log, - unsigned *log_num) + unsigned *log_num, + unsigned int quota) { unsigned int out, in; int seg = 0; @@ -244,7 +246,7 @@ static int get_rx_bufs(struct vhost_virtqueue *vq, unsigned d; int r, nlogs = 0; - while (datalen > 0) { + while (datalen > 0 && headcount < quota) { if (unlikely(seg >= UIO_MAXIOV)) { r = -ENOBUFS; goto err; @@ -284,116 +286,7 @@ err: /* Expects to be always run from workqueue - which acts as * read-size critical section for our kind of RCU. */ -static void handle_rx_big(struct vhost_net *net) -{ - struct vhost_virtqueue *vq = &net->dev.vqs[VHOST_NET_VQ_RX]; - unsigned out, in, log, s; - int head; - struct vhost_log *vq_log; - struct msghdr msg = { - .msg_name = NULL, - .msg_namelen = 0, - .msg_control = NULL, /* FIXME: get and handle RX aux data. */ - .msg_controllen = 0, - .msg_iov = vq->iov, - .msg_flags = MSG_DONTWAIT, - }; - struct virtio_net_hdr hdr = { - .flags = 0, - .gso_type = VIRTIO_NET_HDR_GSO_NONE - }; - size_t len, total_len = 0; - int err; - size_t hdr_size; - /* TODO: check that we are running from vhost_worker? */ - struct socket *sock = rcu_dereference_check(vq->private_data, 1); - - if (!sock || skb_queue_empty(&sock->sk->sk_receive_queue)) - return; - - mutex_lock(&vq->mutex); - vhost_disable_notify(vq); - hdr_size = vq->vhost_hlen; - - vq_log = unlikely(vhost_has_feature(&net->dev, VHOST_F_LOG_ALL)) ? - vq->log : NULL; - - for (;;) { - head = vhost_get_vq_desc(&net->dev, vq, vq->iov, - ARRAY_SIZE(vq->iov), - &out, &in, - vq_log, &log); - /* On error, stop handling until the next kick. */ - if (unlikely(head < 0)) - break; - /* OK, now we need to know about added descriptors. */ - if (head == vq->num) { - if (unlikely(vhost_enable_notify(vq))) { - /* They have slipped one in as we were - * doing that: check again. */ - vhost_disable_notify(vq); - continue; - } - /* Nothing new? Wait for eventfd to tell us - * they refilled. */ - break; - } - /* We don't need to be notified again. */ - if (out) { - vq_err(vq, "Unexpected descriptor format for RX: " - "out %d, int %d\n", - out, in); - break; - } - /* Skip header. TODO: support TSO/mergeable rx buffers. */ - s = move_iovec_hdr(vq->iov, vq->hdr, hdr_size, in); - msg.msg_iovlen = in; - len = iov_length(vq->iov, in); - /* Sanity check */ - if (!len) { - vq_err(vq, "Unexpected header len for RX: " - "%zd expected %zd\n", - iov_length(vq->hdr, s), hdr_size); - break; - } - err = sock->ops->recvmsg(NULL, sock, &msg, - len, MSG_DONTWAIT | MSG_TRUNC); - /* TODO: Check specific error and bomb out unless EAGAIN? */ - if (err < 0) { - vhost_discard_vq_desc(vq, 1); - break; - } - /* TODO: Should check and handle checksum. */ - if (err > len) { - pr_debug("Discarded truncated rx packet: " - " len %d > %zd\n", err, len); - vhost_discard_vq_desc(vq, 1); - continue; - } - len = err; - err = memcpy_toiovec(vq->hdr, (unsigned char *)&hdr, hdr_size); - if (err) { - vq_err(vq, "Unable to write vnet_hdr at addr %p: %d\n", - vq->iov->iov_base, err); - break; - } - len += hdr_size; - vhost_add_used_and_signal(&net->dev, vq, head, len); - if (unlikely(vq_log)) - vhost_log_write(vq, vq_log, log, len); - total_len += len; - if (unlikely(total_len >= VHOST_NET_WEIGHT)) { - vhost_poll_queue(&vq->poll); - break; - } - } - - mutex_unlock(&vq->mutex); -} - -/* Expects to be always run from workqueue - which acts as - * read-size critical section for our kind of RCU. */ -static void handle_rx_mergeable(struct vhost_net *net) +static void handle_rx(struct vhost_net *net) { struct vhost_virtqueue *vq = &net->dev.vqs[VHOST_NET_VQ_RX]; unsigned uninitialized_var(in), log; @@ -433,7 +326,8 @@ static void handle_rx_mergeable(struct vhost_net *net) sock_len += sock_hlen; vhost_len = sock_len + vhost_hlen; headcount = get_rx_bufs(vq, vq->heads, vhost_len, - &in, vq_log, &log); + &in, vq_log, &log, + likely(mergeable) ? UIO_MAXIOV : 1); /* On error, stop handling until the next kick. */ if (unlikely(headcount < 0)) break; @@ -499,14 +393,6 @@ static void handle_rx_mergeable(struct vhost_net *net) mutex_unlock(&vq->mutex); } -static void handle_rx(struct vhost_net *net) -{ - if (vhost_has_feature(&net->dev, VIRTIO_NET_F_MRG_RXBUF)) - handle_rx_mergeable(net); - else - handle_rx_big(net); -} - static void handle_tx_kick(struct vhost_work *work) { struct vhost_virtqueue *vq = container_of(work, struct vhost_virtqueue, -- GitLab From 783e3988544b94ff3918666b9f36866ac547fba1 Mon Sep 17 00:00:00 2001 From: Jason Wang Date: Mon, 17 Jan 2011 16:11:17 +0800 Subject: [PATCH 0647/2822] vhost: lock receive queue, not the socket vhost takes a sock lock to try and prevent the skb from being pulled from the receive queue after skb_peek. However this is not the right lock to use for that, sk_receive_queue.lock is. Fix that up. Signed-off-by: Michael S. Tsirkin --- drivers/vhost/net.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/vhost/net.c b/drivers/vhost/net.c index 0329c411bbf10..57203014c4577 100644 --- a/drivers/vhost/net.c +++ b/drivers/vhost/net.c @@ -213,12 +213,13 @@ static int peek_head_len(struct sock *sk) { struct sk_buff *head; int len = 0; + unsigned long flags; - lock_sock(sk); + spin_lock_irqsave(&sk->sk_receive_queue.lock, flags); head = skb_peek(&sk->sk_receive_queue); - if (head) + if (likely(head)) len = head->len; - release_sock(sk); + spin_unlock_irqrestore(&sk->sk_receive_queue.lock, flags); return len; } -- GitLab From de4d768a428d9de943dd6dc82bcd61742955cb6e Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Sun, 13 Mar 2011 23:00:52 +0200 Subject: [PATCH 0648/2822] vhost-net: remove unlocked use of receive_queue Use of skb_queue_empty(&sock->sk->sk_receive_queue) without taking the sk_receive_queue.lock is unsafe or useless. Take it out. Reported-by: Eric Dumazet Signed-off-by: Michael S. Tsirkin --- drivers/vhost/net.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/vhost/net.c b/drivers/vhost/net.c index 57203014c4577..2f7c76a85e532 100644 --- a/drivers/vhost/net.c +++ b/drivers/vhost/net.c @@ -311,7 +311,7 @@ static void handle_rx(struct vhost_net *net) /* TODO: check that we are running from vhost_worker? */ struct socket *sock = rcu_dereference_check(vq->private_data, 1); - if (!sock || skb_queue_empty(&sock->sk->sk_receive_queue)) + if (!sock) return; mutex_lock(&vq->mutex); -- GitLab From bd7e4e85f3b8e5c7ea2f09d0b3350b264e339a14 Mon Sep 17 00:00:00 2001 From: Bo Shen Date: Sun, 13 Mar 2011 23:34:59 -0700 Subject: [PATCH 0649/2822] Input: add Atmel AT42QT1070 keypad driver The AT42QT1070 QTouch sensor supports up to 7 keys. The driver has been tested on Atmel AT91SAM9M10-G45-EK board, and it should work fine on other platforms. Signed-off-by: Bo Shen Signed-off-by: Dmitry Torokhov --- drivers/input/keyboard/Kconfig | 10 ++ drivers/input/keyboard/Makefile | 1 + drivers/input/keyboard/qt1070.c | 276 ++++++++++++++++++++++++++++++++ 3 files changed, 287 insertions(+) create mode 100644 drivers/input/keyboard/qt1070.c diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig index c7a92028f4509..b16bed038f724 100644 --- a/drivers/input/keyboard/Kconfig +++ b/drivers/input/keyboard/Kconfig @@ -112,6 +112,16 @@ config KEYBOARD_ATKBD_RDI_KEYCODES right-hand column will be interpreted as the key shown in the left-hand column. +config KEYBOARD_QT1070 + tristate "Atmel AT42QT1070 Touch Sensor Chip" + depends on I2C + help + Say Y here if you want to use Atmel AT42QT1070 QTouch + Sensor chip as input device. + + To compile this driver as a module, choose M here: + the module will be called qt1070 + config KEYBOARD_QT2160 tristate "Atmel AT42QT2160 Touch Sensor Chip" depends on I2C && EXPERIMENTAL diff --git a/drivers/input/keyboard/Makefile b/drivers/input/keyboard/Makefile index 468c627a28447..878e6c20deb0e 100644 --- a/drivers/input/keyboard/Makefile +++ b/drivers/input/keyboard/Makefile @@ -34,6 +34,7 @@ obj-$(CONFIG_KEYBOARD_OMAP4) += omap4-keypad.o obj-$(CONFIG_KEYBOARD_OPENCORES) += opencores-kbd.o obj-$(CONFIG_KEYBOARD_PXA27x) += pxa27x_keypad.o obj-$(CONFIG_KEYBOARD_PXA930_ROTARY) += pxa930_rotary.o +obj-$(CONFIG_KEYBOARD_QT1070) += qt1070.o obj-$(CONFIG_KEYBOARD_QT2160) += qt2160.o obj-$(CONFIG_KEYBOARD_SAMSUNG) += samsung-keypad.o obj-$(CONFIG_KEYBOARD_SH_KEYSC) += sh_keysc.o diff --git a/drivers/input/keyboard/qt1070.c b/drivers/input/keyboard/qt1070.c new file mode 100644 index 0000000000000..fba8404c72975 --- /dev/null +++ b/drivers/input/keyboard/qt1070.c @@ -0,0 +1,276 @@ +/* + * Atmel AT42QT1070 QTouch Sensor Controller + * + * Copyright (C) 2011 Atmel + * + * Authors: Bo Shen + * + * Base on AT42QT2160 driver by: + * Raphael Derosso Pereira + * Copyright (C) 2009 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Address for each register */ +#define CHIP_ID 0x00 +#define QT1070_CHIP_ID 0x2E + +#define FW_VERSION 0x01 +#define QT1070_FW_VERSION 0x15 + +#define DET_STATUS 0x02 + +#define KEY_STATUS 0x03 + +/* Calibrate */ +#define CALIBRATE_CMD 0x38 +#define QT1070_CAL_TIME 200 + +/* Reset */ +#define RESET 0x39 +#define QT1070_RESET_TIME 255 + +/* AT42QT1070 support up to 7 keys */ +static const unsigned short qt1070_key2code[] = { + KEY_0, KEY_1, KEY_2, KEY_3, + KEY_4, KEY_5, KEY_6, +}; + +struct qt1070_data { + struct i2c_client *client; + struct input_dev *input; + unsigned int irq; + unsigned short keycodes[ARRAY_SIZE(qt1070_key2code)]; + u8 last_keys; +}; + +static int qt1070_read(struct i2c_client *client, u8 reg) +{ + int ret; + + ret = i2c_smbus_read_byte_data(client, reg); + if (ret < 0) + dev_err(&client->dev, + "can not read register, returned %d\n", ret); + + return ret; +} + +static int qt1070_write(struct i2c_client *client, u8 reg, u8 data) +{ + int ret; + + ret = i2c_smbus_write_byte_data(client, reg, data); + if (ret < 0) + dev_err(&client->dev, + "can not write register, returned %d\n", ret); + + return ret; +} + +static bool __devinit qt1070_identify(struct i2c_client *client) +{ + int id, ver; + + /* Read Chip ID */ + id = qt1070_read(client, CHIP_ID); + if (id != QT1070_CHIP_ID) { + dev_err(&client->dev, "ID %d not supported\n", id); + return false; + } + + /* Read firmware version */ + ver = qt1070_read(client, FW_VERSION); + if (ver < 0) { + dev_err(&client->dev, "could not read the firmware version\n"); + return false; + } + + dev_info(&client->dev, "AT42QT1070 firmware version %x\n", ver); + + return true; +} + +static irqreturn_t qt1070_interrupt(int irq, void *dev_id) +{ + struct qt1070_data *data = dev_id; + struct i2c_client *client = data->client; + struct input_dev *input = data->input; + int i; + u8 new_keys, keyval, mask = 0x01; + + /* Read the detected status register, thus clearing interrupt */ + qt1070_read(client, DET_STATUS); + + /* Read which key changed */ + new_keys = qt1070_read(client, KEY_STATUS); + + for (i = 0; i < ARRAY_SIZE(qt1070_key2code); i++) { + keyval = new_keys & mask; + if ((data->last_keys & mask) != keyval) + input_report_key(input, data->keycodes[i], keyval); + mask <<= 1; + } + input_sync(input); + + data->last_keys = new_keys; + return IRQ_HANDLED; +} + +static int __devinit qt1070_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct qt1070_data *data; + struct input_dev *input; + int i; + int err; + + err = i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE); + if (!err) { + dev_err(&client->dev, "%s adapter not supported\n", + dev_driver_string(&client->adapter->dev)); + return -ENODEV; + } + + if (!client->irq) { + dev_err(&client->dev, "please assign the irq to this device\n"); + return -EINVAL; + } + + /* Identify the qt1070 chip */ + if (!qt1070_identify(client)) + return -ENODEV; + + data = kzalloc(sizeof(struct qt1070_data), GFP_KERNEL); + input = input_allocate_device(); + if (!data || !input) { + dev_err(&client->dev, "insufficient memory\n"); + err = -ENOMEM; + goto err_free_mem; + } + + data->client = client; + data->input = input; + data->irq = client->irq; + + input->name = "AT42QT1070 QTouch Sensor"; + input->dev.parent = &client->dev; + input->id.bustype = BUS_I2C; + + /* Add the keycode */ + input->keycode = data->keycodes; + input->keycodesize = sizeof(data->keycodes[0]); + input->keycodemax = ARRAY_SIZE(qt1070_key2code); + + __set_bit(EV_KEY, input->evbit); + + for (i = 0; i < ARRAY_SIZE(qt1070_key2code); i++) { + data->keycodes[i] = qt1070_key2code[i]; + __set_bit(qt1070_key2code[i], input->keybit); + } + + /* Calibrate device */ + qt1070_write(client, CALIBRATE_CMD, 1); + msleep(QT1070_CAL_TIME); + + /* Soft reset */ + qt1070_write(client, RESET, 1); + msleep(QT1070_RESET_TIME); + + err = request_threaded_irq(client->irq, NULL, qt1070_interrupt, + IRQF_TRIGGER_NONE, client->dev.driver->name, data); + if (err) { + dev_err(&client->dev, "fail to request irq\n"); + goto err_free_mem; + } + + /* Register the input device */ + err = input_register_device(data->input); + if (err) { + dev_err(&client->dev, "Failed to register input device\n"); + goto err_free_irq; + } + + i2c_set_clientdata(client, data); + + /* Read to clear the chang line */ + qt1070_read(client, DET_STATUS); + + return 0; + +err_free_irq: + free_irq(client->irq, data); +err_free_mem: + input_free_device(input); + kfree(data); + return err; +} + +static int __devexit qt1070_remove(struct i2c_client *client) +{ + struct qt1070_data *data = i2c_get_clientdata(client); + + /* Release IRQ */ + free_irq(client->irq, data); + + input_unregister_device(data->input); + kfree(data); + + i2c_set_clientdata(client, NULL); + + return 0; +} + +static const struct i2c_device_id qt1070_id[] = { + { "qt1070", 0 }, + { }, +}; + +static struct i2c_driver qt1070_driver = { + .driver = { + .name = "qt1070", + .owner = THIS_MODULE, + }, + .id_table = qt1070_id, + .probe = qt1070_probe, + .remove = __devexit_p(qt1070_remove), +}; + +static int __init qt1070_init(void) +{ + return i2c_add_driver(&qt1070_driver); +} +module_init(qt1070_init); + +static void __exit qt1070_exit(void) +{ + i2c_del_driver(&qt1070_driver); +} +module_exit(qt1070_exit); + +MODULE_AUTHOR("Bo Shen "); +MODULE_DESCRIPTION("Driver for AT42QT1070 QTouch sensor"); +MODULE_LICENSE("GPL"); -- GitLab From ba02fa37de80bea10d706f39f076dd848348320a Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Fri, 11 Mar 2011 09:28:06 +0200 Subject: [PATCH 0650/2822] HACK: OMAP: DSS2: VENC: disable VENC on OMAP4 to prevent crash Something seems to be wrong with OMAP4 & VENC, and register access fails in omap_venchw_probe(). This patch skips venc driver registration on OMAP4, thus circumventing the problem for now. Signed-off-by: Tomi Valkeinen --- drivers/video/omap2/dss/venc.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/video/omap2/dss/venc.c b/drivers/video/omap2/dss/venc.c index 43009e57cd3e1..8e35a5bae429c 100644 --- a/drivers/video/omap2/dss/venc.c +++ b/drivers/video/omap2/dss/venc.c @@ -769,10 +769,16 @@ static struct platform_driver omap_venchw_driver = { int venc_init_platform_driver(void) { + if (cpu_is_omap44xx()) + return 0; + return platform_driver_register(&omap_venchw_driver); } void venc_uninit_platform_driver(void) { + if (cpu_is_omap44xx()) + return; + return platform_driver_unregister(&omap_venchw_driver); } -- GitLab From b6258fc1feabda868694ad5fdc7ca8edf3ef30ec Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Sat, 26 Feb 2011 15:08:35 +0100 Subject: [PATCH 0651/2822] firewire: ohci: omit IntEvent.busReset check rom AT queueing Since commit 82b662dc4102 "flush AT contexts after bus reset for OHCI 1.2", the driver takes care of any AT packets that were enqueued during a bus reset phase. The check from commit 76f73ca1b291 is therefore no longer necessary and the MMIO read can be avoided. Signed-off-by: Stefan Richter --- drivers/firewire/ohci.c | 17 ++--------------- 1 file changed, 2 insertions(+), 15 deletions(-) diff --git a/drivers/firewire/ohci.c b/drivers/firewire/ohci.c index c0572283b93ed..8f1e3ce930d6a 100644 --- a/drivers/firewire/ohci.c +++ b/drivers/firewire/ohci.c @@ -1329,21 +1329,8 @@ static int at_context_queue_packet(struct context *ctx, DESCRIPTOR_IRQ_ALWAYS | DESCRIPTOR_BRANCH_ALWAYS); - /* - * If the controller and packet generations don't match, we need to - * bail out and try again. If IntEvent.busReset is set, the AT context - * is halted, so appending to the context and trying to run it is - * futile. Most controllers do the right thing and just flush the AT - * queue (per section 7.2.3.2 of the OHCI 1.1 specification), but - * some controllers (like a JMicron JMB381 PCI-e) misbehave and wind - * up stalling out. So we just bail out in software and try again - * later, and everyone is happy. - * FIXME: Test of IntEvent.busReset may no longer be necessary since we - * flush AT queues in bus_reset_tasklet. - * FIXME: Document how the locking works. - */ - if (ohci->generation != packet->generation || - reg_read(ohci, OHCI1394_IntEventSet) & OHCI1394_busReset) { + /* FIXME: Document how the locking works. */ + if (ohci->generation != packet->generation) { if (packet->payload_mapped) dma_unmap_single(ohci->card.device, payload_bus, packet->payload_length, DMA_TO_DEVICE); -- GitLab From d838d2c09af0820e306e3e9e31f97e873823b0b4 Mon Sep 17 00:00:00 2001 From: Oleg Drokin Date: Fri, 11 Mar 2011 04:17:27 +0300 Subject: [PATCH 0652/2822] firewire: ohci: Misleading kfree in ohci.c::pci_probe/remove It seems drivers/firewire/ohci.c is making some optimistic assumptions about struct fw_ohci and that member "card" will always remain the first member of the struct. Plus it's probably going to confuse a lot of static code analyzers too. So I wonder if there is a good reason not to free the ohci struct just like it was allocated instead of the tricky &ohci->card way? Signed-off-by: Oleg Drokin It is perhaps just a rudiment from before mainline submission of the driver. Signed-off-by: Stefan Richter --- drivers/firewire/ohci.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/firewire/ohci.c b/drivers/firewire/ohci.c index 8f1e3ce930d6a..f903d7b6f34a9 100644 --- a/drivers/firewire/ohci.c +++ b/drivers/firewire/ohci.c @@ -3309,7 +3309,7 @@ static int __devinit pci_probe(struct pci_dev *dev, fail_disable: pci_disable_device(dev); fail_free: - kfree(&ohci->card); + kfree(ohci); pmac_ohci_off(dev); fail: if (err == -ENOMEM) @@ -3353,7 +3353,7 @@ static void pci_remove(struct pci_dev *dev) pci_iounmap(dev, ohci->registers); pci_release_region(dev, 0); pci_disable_device(dev); - kfree(&ohci->card); + kfree(ohci); pmac_ohci_off(dev); fw_notify("Removed fw-ohci device.\n"); -- GitLab From 0a5e5f122c756d1c1a6ca712eda76ea8664e5fd9 Mon Sep 17 00:00:00 2001 From: "J. Bruce Fields" Date: Mon, 14 Mar 2011 20:57:44 -0400 Subject: [PATCH 0653/2822] nfsd: fix compile error "fs/built-in.o: In function `supported_enctypes_show': nfsctl.c:(.text+0x7beb0): undefined reference to `gss_mech_get_by_name' nfsctl.c:(.text+0x7bebc): undefined reference to `gss_mech_put' " Reported-by: Guennadi Liakhovetski Signed-off-by: J. Bruce Fields --- fs/nfsd/nfsctl.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c index 35dcfa8eba219..1f5eae40f34ef 100644 --- a/fs/nfsd/nfsctl.c +++ b/fs/nfsd/nfsctl.c @@ -189,6 +189,7 @@ static struct file_operations export_features_operations = { .release = single_release, }; +#ifdef CONFIG_SUNRPC_GSS static int supported_enctypes_show(struct seq_file *m, void *v) { struct gss_api_mech *k5mech; @@ -214,6 +215,7 @@ static struct file_operations supported_enctypes_ops = { .llseek = seq_lseek, .release = single_release, }; +#endif /* CONFIG_SUNRPC_GSS */ extern int nfsd_pool_stats_open(struct inode *inode, struct file *file); extern int nfsd_pool_stats_release(struct inode *inode, struct file *file); @@ -1425,7 +1427,9 @@ static int nfsd_fill_super(struct super_block * sb, void * data, int silent) [NFSD_Versions] = {"versions", &transaction_ops, S_IWUSR|S_IRUSR}, [NFSD_Ports] = {"portlist", &transaction_ops, S_IWUSR|S_IRUGO}, [NFSD_MaxBlkSize] = {"max_block_size", &transaction_ops, S_IWUSR|S_IRUGO}, +#ifdef CONFIG_SUNRPC_GSS [NFSD_SupportedEnctypes] = {"supported_krb5_enctypes", &supported_enctypes_ops, S_IRUGO}, +#endif /* CONFIG_SUNRPC_GSS */ #ifdef CONFIG_NFSD_V4 [NFSD_Leasetime] = {"nfsv4leasetime", &transaction_ops, S_IWUSR|S_IRUSR}, [NFSD_Gracetime] = {"nfsv4gracetime", &transaction_ops, S_IWUSR|S_IRUSR}, -- GitLab From e7cbb90ad244b9d3ba5c6d57aec05d6c73df0a98 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Mon, 14 Mar 2011 21:39:09 -0700 Subject: [PATCH 0654/2822] Input: wm831x-ts - ensure the controller is in a known state on open Explicitly set all the enable bits when opening the device just in case something left the device in an unexpected state. Signed-off-by: Mark Brown Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/wm831x-ts.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/input/touchscreen/wm831x-ts.c b/drivers/input/touchscreen/wm831x-ts.c index 3db0c29f3b054..6ae054f8e0aa5 100644 --- a/drivers/input/touchscreen/wm831x-ts.c +++ b/drivers/input/touchscreen/wm831x-ts.c @@ -167,7 +167,9 @@ static int wm831x_ts_input_open(struct input_dev *idev) struct wm831x *wm831x = wm831x_ts->wm831x; wm831x_set_bits(wm831x, WM831X_TOUCH_CONTROL_1, - WM831X_TCH_ENA, WM831X_TCH_ENA); + WM831X_TCH_ENA | WM831X_TCH_CVT_ENA | + WM831X_TCH_X_ENA | WM831X_TCH_Y_ENA | + WM831X_TCH_Z_ENA, WM831X_TCH_ENA); wm831x_set_bits(wm831x, WM831X_TOUCH_CONTROL_1, WM831X_TCH_CVT_ENA, WM831X_TCH_CVT_ENA); -- GitLab From 979a72dad9c6649486e35a84324af8e81936af03 Mon Sep 17 00:00:00 2001 From: Joonyoung Shim Date: Mon, 14 Mar 2011 21:41:34 -0700 Subject: [PATCH 0655/2822] Input: atmel_mxt_ts - remove firmware version check Atmel touchscreen chips have different firmware version with each chip, so we cannot distinguish attribute of chip by firmware version. Signed-off-by: Joonyoung Shim Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/atmel_mxt_ts.c | 21 +++++---------------- 1 file changed, 5 insertions(+), 16 deletions(-) diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c index 6264ba80c38cc..0986fa46e9dfb 100644 --- a/drivers/input/touchscreen/atmel_mxt_ts.c +++ b/drivers/input/touchscreen/atmel_mxt_ts.c @@ -60,11 +60,11 @@ #define MXT_PROCG_NOISE 22 #define MXT_PROCI_ONETOUCH 24 #define MXT_PROCI_TWOTOUCH 27 -#define MXT_SPT_COMMSCONFIG 18 /* firmware ver 21 over */ +#define MXT_SPT_COMMSCONFIG 18 #define MXT_SPT_GPIOPWM 19 #define MXT_SPT_SELFTEST 25 #define MXT_SPT_CTECONFIG 28 -#define MXT_SPT_USERDATA 38 /* firmware ver 21 over */ +#define MXT_SPT_USERDATA 38 /* MXT_GEN_COMMAND field */ #define MXT_COMMAND_RESET 0 @@ -115,7 +115,7 @@ #define MXT_TOUCH_XEDGEDIST 27 #define MXT_TOUCH_YEDGECTRL 28 #define MXT_TOUCH_YEDGEDIST 29 -#define MXT_TOUCH_JUMPLIMIT 30 /* firmware ver 22 over */ +#define MXT_TOUCH_JUMPLIMIT 30 /* MXT_PROCI_GRIPFACE field */ #define MXT_GRIPFACE_CTRL 0 @@ -157,7 +157,7 @@ #define MXT_CTE_MODE 2 #define MXT_CTE_IDLEGCAFDEPTH 3 #define MXT_CTE_ACTVGCAFDEPTH 4 -#define MXT_CTE_VOLTAGE 5 /* firmware ver 21 over */ +#define MXT_CTE_VOLTAGE 5 #define MXT_VOLTAGE_DEFAULT 2700000 #define MXT_VOLTAGE_STEP 10000 @@ -686,7 +686,7 @@ static void mxt_handle_pdata(struct mxt_data *data) MXT_TOUCH_YRANGE_MSB, (pdata->y_size - 1) >> 8); /* Set touchscreen voltage */ - if (data->info.version >= MXT_VER_21 && pdata->voltage) { + if (pdata->voltage) { if (pdata->voltage < MXT_VOLTAGE_DEFAULT) { voltage = (MXT_VOLTAGE_DEFAULT - pdata->voltage) / MXT_VOLTAGE_STEP; @@ -951,19 +951,8 @@ static ssize_t mxt_update_fw_store(struct device *dev, const char *buf, size_t count) { struct mxt_data *data = dev_get_drvdata(dev); - unsigned int version; int error; - if (sscanf(buf, "%u", &version) != 1) { - dev_err(dev, "Invalid values\n"); - return -EINVAL; - } - - if (data->info.version < MXT_VER_21 || version < MXT_VER_21) { - dev_err(dev, "FW update supported starting with version 21\n"); - return -EINVAL; - } - disable_irq(data->irq); error = mxt_load_fw(dev, MXT_FW_NAME); -- GitLab From 4c75de32eb9fcaa14925e2e444748f8b71e4f6fc Mon Sep 17 00:00:00 2001 From: Joonyoung Shim Date: Mon, 14 Mar 2011 21:41:40 -0700 Subject: [PATCH 0656/2822] Input: atmel_mxt_ts - add objects of mXT1386 chip Atmel mXT1386 chip is operated by atmel_mxt_ts driver and it has some different objects. Signed-off-by: Joonyoung Shim Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/atmel_mxt_ts.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c index 0986fa46e9dfb..4012436633b18 100644 --- a/drivers/input/touchscreen/atmel_mxt_ts.c +++ b/drivers/input/touchscreen/atmel_mxt_ts.c @@ -60,11 +60,15 @@ #define MXT_PROCG_NOISE 22 #define MXT_PROCI_ONETOUCH 24 #define MXT_PROCI_TWOTOUCH 27 +#define MXT_PROCI_GRIP 40 +#define MXT_PROCI_PALM 41 #define MXT_SPT_COMMSCONFIG 18 #define MXT_SPT_GPIOPWM 19 #define MXT_SPT_SELFTEST 25 #define MXT_SPT_CTECONFIG 28 #define MXT_SPT_USERDATA 38 +#define MXT_SPT_DIGITIZER 43 +#define MXT_SPT_MESSAGECOUNT 44 /* MXT_GEN_COMMAND field */ #define MXT_COMMAND_RESET 0 @@ -258,6 +262,8 @@ static bool mxt_object_readable(unsigned int type) case MXT_PROCG_NOISE: case MXT_PROCI_ONETOUCH: case MXT_PROCI_TWOTOUCH: + case MXT_PROCI_GRIP: + case MXT_PROCI_PALM: case MXT_SPT_COMMSCONFIG: case MXT_SPT_GPIOPWM: case MXT_SPT_SELFTEST: @@ -282,6 +288,8 @@ static bool mxt_object_writable(unsigned int type) case MXT_PROCG_NOISE: case MXT_PROCI_ONETOUCH: case MXT_PROCI_TWOTOUCH: + case MXT_PROCI_GRIP: + case MXT_PROCI_PALM: case MXT_SPT_GPIOPWM: case MXT_SPT_SELFTEST: case MXT_SPT_CTECONFIG: -- GitLab From 235e7dba0264d4c6e56ee217fc7ef6d80da5eb67 Mon Sep 17 00:00:00 2001 From: "Taneja, Archit" Date: Mon, 14 Mar 2011 23:28:21 -0500 Subject: [PATCH 0657/2822] OMAP2PLUS: DSS2: FEATURES: Fix usage of dss_reg_field and dss_clk_source_name The structures dss_reg_field and dss_clk_source_name have enum members which specify the register field and the clock source respectively. These members are not used to choose the correct result in the corresponding feature functions. Remove these members and change the features array declaration to incorporate these enums. The structure dss_clk_source_name without the enum member is just a pointer to an string. Remove the structure and use a character pointer directly. Signed-off-by: Archit Taneja Signed-off-by: Tomi Valkeinen --- drivers/video/omap2/dss/dss.c | 10 ++-- drivers/video/omap2/dss/dss.h | 6 -- drivers/video/omap2/dss/dss_features.c | 77 +++++++++++++------------- 3 files changed, 43 insertions(+), 50 deletions(-) diff --git a/drivers/video/omap2/dss/dss.c b/drivers/video/omap2/dss/dss.c index aed9345e8adad..06ad312908530 100644 --- a/drivers/video/omap2/dss/dss.c +++ b/drivers/video/omap2/dss/dss.c @@ -82,10 +82,10 @@ static struct { u32 ctx[DSS_SZ_REGS / sizeof(u32)]; } dss; -static const struct dss_clk_source_name dss_generic_clk_source_names[] = { - { DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC, "DSI_PLL_HSDIV_DISPC" }, - { DSS_CLK_SRC_DSI_PLL_HSDIV_DSI, "DSI_PLL_HSDIV_DSI" }, - { DSS_CLK_SRC_FCK, "DSS_FCK" }, +static const char * const dss_generic_clk_source_names[] = { + [DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC] = "DSI_PLL_HSDIV_DISPC", + [DSS_CLK_SRC_DSI_PLL_HSDIV_DSI] = "DSI_PLL_HSDIV_DSI", + [DSS_CLK_SRC_FCK] = "DSS_FCK", }; static void dss_clk_enable_all_no_ctx(void); @@ -232,7 +232,7 @@ void dss_sdi_disable(void) const char *dss_get_generic_clk_source_name(enum dss_clk_source clk_src) { - return dss_generic_clk_source_names[clk_src].clksrc_name; + return dss_generic_clk_source_names[clk_src]; } void dss_dump_clocks(struct seq_file *s) diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h index b845468d97062..26a43c93e4893 100644 --- a/drivers/video/omap2/dss/dss.h +++ b/drivers/video/omap2/dss/dss.h @@ -126,12 +126,6 @@ enum dss_clk_source { * OMAP4: DSS_FCLK */ }; -/* Correlates clock source name and dss_clk_source member */ -struct dss_clk_source_name { - enum dss_clk_source clksrc; - const char *clksrc_name; -}; - struct dss_clock_info { /* rates that we get with dividers below */ unsigned long fck; diff --git a/drivers/video/omap2/dss/dss_features.c b/drivers/video/omap2/dss/dss_features.c index 6eb6ec62a0002..8de3344842d7e 100644 --- a/drivers/video/omap2/dss/dss_features.c +++ b/drivers/video/omap2/dss/dss_features.c @@ -30,7 +30,6 @@ /* Defines a generic omap register field */ struct dss_reg_field { - enum dss_feat_reg_field id; u8 start, end; }; @@ -45,43 +44,43 @@ struct omap_dss_features { const unsigned long max_dss_fck; const enum omap_display_type *supported_displays; const enum omap_color_mode *supported_color_modes; - const struct dss_clk_source_name *clksrc_names; + const char * const *clksrc_names; }; /* This struct is assigned to one of the below during initialization */ static struct omap_dss_features *omap_current_dss_features; static const struct dss_reg_field omap2_dss_reg_fields[] = { - { FEAT_REG_FIRHINC, 11, 0 }, - { FEAT_REG_FIRVINC, 27, 16 }, - { FEAT_REG_FIFOLOWTHRESHOLD, 8, 0 }, - { FEAT_REG_FIFOHIGHTHRESHOLD, 24, 16 }, - { FEAT_REG_FIFOSIZE, 8, 0 }, - { FEAT_REG_HORIZONTALACCU, 9, 0 }, - { FEAT_REG_VERTICALACCU, 25, 16 }, - { FEAT_REG_DISPC_CLK_SWITCH, 0, 0 }, + [FEAT_REG_FIRHINC] = { 11, 0 }, + [FEAT_REG_FIRVINC] = { 27, 16 }, + [FEAT_REG_FIFOLOWTHRESHOLD] = { 8, 0 }, + [FEAT_REG_FIFOHIGHTHRESHOLD] = { 24, 16 }, + [FEAT_REG_FIFOSIZE] = { 8, 0 }, + [FEAT_REG_HORIZONTALACCU] = { 9, 0 }, + [FEAT_REG_VERTICALACCU] = { 25, 16 }, + [FEAT_REG_DISPC_CLK_SWITCH] = { 0, 0 }, }; static const struct dss_reg_field omap3_dss_reg_fields[] = { - { FEAT_REG_FIRHINC, 12, 0 }, - { FEAT_REG_FIRVINC, 28, 16 }, - { FEAT_REG_FIFOLOWTHRESHOLD, 11, 0 }, - { FEAT_REG_FIFOHIGHTHRESHOLD, 27, 16 }, - { FEAT_REG_FIFOSIZE, 10, 0 }, - { FEAT_REG_HORIZONTALACCU, 9, 0 }, - { FEAT_REG_VERTICALACCU, 25, 16 }, - { FEAT_REG_DISPC_CLK_SWITCH, 0, 0 }, + [FEAT_REG_FIRHINC] = { 12, 0 }, + [FEAT_REG_FIRVINC] = { 28, 16 }, + [FEAT_REG_FIFOLOWTHRESHOLD] = { 11, 0 }, + [FEAT_REG_FIFOHIGHTHRESHOLD] = { 27, 16 }, + [FEAT_REG_FIFOSIZE] = { 10, 0 }, + [FEAT_REG_HORIZONTALACCU] = { 9, 0 }, + [FEAT_REG_VERTICALACCU] = { 25, 16 }, + [FEAT_REG_DISPC_CLK_SWITCH] = { 0, 0 }, }; static const struct dss_reg_field omap4_dss_reg_fields[] = { - { FEAT_REG_FIRHINC, 12, 0 }, - { FEAT_REG_FIRVINC, 28, 16 }, - { FEAT_REG_FIFOLOWTHRESHOLD, 15, 0 }, - { FEAT_REG_FIFOHIGHTHRESHOLD, 31, 16 }, - { FEAT_REG_FIFOSIZE, 15, 0 }, - { FEAT_REG_HORIZONTALACCU, 10, 0 }, - { FEAT_REG_VERTICALACCU, 26, 16 }, - { FEAT_REG_DISPC_CLK_SWITCH, 9, 8 }, + [FEAT_REG_FIRHINC] = { 12, 0 }, + [FEAT_REG_FIRVINC] = { 28, 16 }, + [FEAT_REG_FIFOLOWTHRESHOLD] = { 15, 0 }, + [FEAT_REG_FIFOHIGHTHRESHOLD] = { 31, 16 }, + [FEAT_REG_FIFOSIZE] = { 15, 0 }, + [FEAT_REG_HORIZONTALACCU] = { 10, 0 }, + [FEAT_REG_VERTICALACCU] = { 26, 16 }, + [FEAT_REG_DISPC_CLK_SWITCH] = { 9, 8 }, }; static const enum omap_display_type omap2_dss_supported_displays[] = { @@ -162,22 +161,22 @@ static const enum omap_color_mode omap3_dss_supported_color_modes[] = { OMAP_DSS_COLOR_RGBA32 | OMAP_DSS_COLOR_RGBX32, }; -static const struct dss_clk_source_name omap2_dss_clk_source_names[] = { - { DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC, "N/A" }, - { DSS_CLK_SRC_DSI_PLL_HSDIV_DSI, "N/A" }, - { DSS_CLK_SRC_FCK, "DSS_FCLK1" }, +static const char * const omap2_dss_clk_source_names[] = { + [DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC] = "N/A", + [DSS_CLK_SRC_DSI_PLL_HSDIV_DSI] = "N/A", + [DSS_CLK_SRC_FCK] = "DSS_FCLK1", }; -static const struct dss_clk_source_name omap3_dss_clk_source_names[] = { - { DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC, "DSI1_PLL_FCLK" }, - { DSS_CLK_SRC_DSI_PLL_HSDIV_DSI, "DSI2_PLL_FCLK" }, - { DSS_CLK_SRC_FCK, "DSS1_ALWON_FCLK" }, +static const char * const omap3_dss_clk_source_names[] = { + [DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC] = "DSI1_PLL_FCLK", + [DSS_CLK_SRC_DSI_PLL_HSDIV_DSI] = "DSI2_PLL_FCLK", + [DSS_CLK_SRC_FCK] = "DSS1_ALWON_FCLK", }; -static const struct dss_clk_source_name omap4_dss_clk_source_names[] = { - { DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC, "PLL1_CLK1" }, - { DSS_CLK_SRC_DSI_PLL_HSDIV_DSI, "PLL1_CLK2" }, - { DSS_CLK_SRC_FCK, "DSS_FCLK" }, +static const char * const omap4_dss_clk_source_names[] = { + [DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC] = "PLL1_CLK1", + [DSS_CLK_SRC_DSI_PLL_HSDIV_DSI] = "PLL1_CLK2", + [DSS_CLK_SRC_FCK] = "DSS_FCLK", }; /* OMAP2 DSS Features */ @@ -290,7 +289,7 @@ bool dss_feat_color_mode_supported(enum omap_plane plane, const char *dss_feat_get_clk_source_name(enum dss_clk_source id) { - return omap_current_dss_features->clksrc_names[id].clksrc_name; + return omap_current_dss_features->clksrc_names[id]; } /* DSS has_feature check */ -- GitLab From 31ef82377f1e0f1bc7d308ae4312e6cc5a431885 Mon Sep 17 00:00:00 2001 From: "Taneja, Archit" Date: Mon, 14 Mar 2011 23:28:22 -0500 Subject: [PATCH 0658/2822] OMAP: DSS2: FEATURES: Functions to return min and max values of parameters Create 2 functions dss_feat_get_param_min() and dss_feat_get_param_max() which return the minimum and maximum value of a parameter. Introduce a enum in dss_features called dss_range_param which contains parameters whose ranges we are interested in. Replace this with dss_feat_get_max_dss_fck() which is specific to the parameter DSS_FCK. Signed-off-by: Archit Taneja Signed-off-by: Tomi Valkeinen --- drivers/video/omap2/dss/dsi.c | 2 +- drivers/video/omap2/dss/dss.c | 2 +- drivers/video/omap2/dss/dss_features.c | 36 ++++++++++++++++++++------ drivers/video/omap2/dss/dss_features.h | 7 ++++- 4 files changed, 36 insertions(+), 11 deletions(-) diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c index be7694ff7ca7d..6e7f468281486 100644 --- a/drivers/video/omap2/dss/dsi.c +++ b/drivers/video/omap2/dss/dsi.c @@ -864,7 +864,7 @@ int dsi_pll_calc_clock_div_pck(bool is_tft, unsigned long req_pck, dss_sys_clk = dss_clk_get_rate(DSS_CLK_SYSCK); - max_dss_fck = dss_feat_get_max_dss_fck(); + max_dss_fck = dss_feat_get_param_max(FEAT_PARAM_DSS_FCK); if (req_pck == dsi.cache_req_pck && dsi.cache_cinfo.clkin == dss_sys_clk) { diff --git a/drivers/video/omap2/dss/dss.c b/drivers/video/omap2/dss/dss.c index 06ad312908530..562d8d28d4f2d 100644 --- a/drivers/video/omap2/dss/dss.c +++ b/drivers/video/omap2/dss/dss.c @@ -457,7 +457,7 @@ int dss_calc_clock_div(bool is_tft, unsigned long req_pck, prate = dss_get_dpll4_rate(); - max_dss_fck = dss_feat_get_max_dss_fck(); + max_dss_fck = dss_feat_get_param_max(FEAT_PARAM_DSS_FCK); fck = dss_clk_get_rate(DSS_CLK_FCK); if (req_pck == dss.cache_req_pck && diff --git a/drivers/video/omap2/dss/dss_features.c b/drivers/video/omap2/dss/dss_features.c index 8de3344842d7e..4c8b32af496c3 100644 --- a/drivers/video/omap2/dss/dss_features.c +++ b/drivers/video/omap2/dss/dss_features.c @@ -33,6 +33,10 @@ struct dss_reg_field { u8 start, end; }; +struct dss_param_range { + int min, max; +}; + struct omap_dss_features { const struct dss_reg_field *reg_fields; const int num_reg_fields; @@ -41,10 +45,10 @@ struct omap_dss_features { const int num_mgrs; const int num_ovls; - const unsigned long max_dss_fck; const enum omap_display_type *supported_displays; const enum omap_color_mode *supported_color_modes; const char * const *clksrc_names; + const struct dss_param_range *dss_params; }; /* This struct is assigned to one of the below during initialization */ @@ -179,6 +183,18 @@ static const char * const omap4_dss_clk_source_names[] = { [DSS_CLK_SRC_FCK] = "DSS_FCLK", }; +static const struct dss_param_range omap2_dss_param_range[] = { + [FEAT_PARAM_DSS_FCK] = { 0, 173000000 }, +}; + +static const struct dss_param_range omap3_dss_param_range[] = { + [FEAT_PARAM_DSS_FCK] = { 0, 173000000 }, +}; + +static const struct dss_param_range omap4_dss_param_range[] = { + [FEAT_PARAM_DSS_FCK] = { 0, 186000000 }, +}; + /* OMAP2 DSS Features */ static struct omap_dss_features omap2_dss_features = { .reg_fields = omap2_dss_reg_fields, @@ -191,10 +207,10 @@ static struct omap_dss_features omap2_dss_features = { .num_mgrs = 2, .num_ovls = 3, - .max_dss_fck = 173000000, .supported_displays = omap2_dss_supported_displays, .supported_color_modes = omap2_dss_supported_color_modes, .clksrc_names = omap2_dss_clk_source_names, + .dss_params = omap2_dss_param_range, }; /* OMAP3 DSS Features */ @@ -210,10 +226,10 @@ static struct omap_dss_features omap3430_dss_features = { .num_mgrs = 2, .num_ovls = 3, - .max_dss_fck = 173000000, .supported_displays = omap3430_dss_supported_displays, .supported_color_modes = omap3_dss_supported_color_modes, .clksrc_names = omap3_dss_clk_source_names, + .dss_params = omap3_dss_param_range, }; static struct omap_dss_features omap3630_dss_features = { @@ -229,10 +245,10 @@ static struct omap_dss_features omap3630_dss_features = { .num_mgrs = 2, .num_ovls = 3, - .max_dss_fck = 173000000, .supported_displays = omap3630_dss_supported_displays, .supported_color_modes = omap3_dss_supported_color_modes, .clksrc_names = omap3_dss_clk_source_names, + .dss_params = omap3_dss_param_range, }; /* OMAP4 DSS Features */ @@ -247,10 +263,10 @@ static struct omap_dss_features omap4_dss_features = { .num_mgrs = 3, .num_ovls = 3, - .max_dss_fck = 186000000, .supported_displays = omap4_dss_supported_displays, .supported_color_modes = omap3_dss_supported_color_modes, .clksrc_names = omap4_dss_clk_source_names, + .dss_params = omap4_dss_param_range, }; /* Functions returning values related to a DSS feature */ @@ -264,10 +280,14 @@ int dss_feat_get_num_ovls(void) return omap_current_dss_features->num_ovls; } -/* Max supported DSS FCK in Hz */ -unsigned long dss_feat_get_max_dss_fck(void) +unsigned long dss_feat_get_param_min(enum dss_range_param param) +{ + return omap_current_dss_features->dss_params[param].min; +} + +unsigned long dss_feat_get_param_max(enum dss_range_param param) { - return omap_current_dss_features->max_dss_fck; + return omap_current_dss_features->dss_params[param].max; } enum omap_display_type dss_feat_get_supported_displays(enum omap_channel channel) diff --git a/drivers/video/omap2/dss/dss_features.h b/drivers/video/omap2/dss/dss_features.h index 729b5f19fa2e4..da63bbf38e902 100644 --- a/drivers/video/omap2/dss/dss_features.h +++ b/drivers/video/omap2/dss/dss_features.h @@ -54,10 +54,15 @@ enum dss_feat_reg_field { FEAT_REG_DISPC_CLK_SWITCH, }; +enum dss_range_param { + FEAT_PARAM_DSS_FCK, +}; + /* DSS Feature Functions */ int dss_feat_get_num_mgrs(void); int dss_feat_get_num_ovls(void); -unsigned long dss_feat_get_max_dss_fck(void); +unsigned long dss_feat_get_param_min(enum dss_range_param param); +unsigned long dss_feat_get_param_max(enum dss_range_param param); enum omap_display_type dss_feat_get_supported_displays(enum omap_channel channel); enum omap_color_mode dss_feat_get_supported_color_modes(enum omap_plane plane); bool dss_feat_color_mode_supported(enum omap_plane plane, -- GitLab From 49641116392ad7522fa0efad53f7ed63f811bd88 Mon Sep 17 00:00:00 2001 From: "Taneja, Archit" Date: Mon, 14 Mar 2011 23:28:23 -0500 Subject: [PATCH 0659/2822] OMAP: DSS2: FEATURES: DSI PLL parameter cleanup The DSI PLL parameters (regm, regn, regm_dispc, regm_dsi, fint) have different fields and also different Max values on OMAP3 and OMAP4. Use dss features to calculate the register fields and min/max values based on current OMAP revision. Signed-off-by: Archit Taneja Signed-off-by: Tomi Valkeinen --- drivers/video/omap2/dss/dsi.c | 69 ++++++++++++++------- drivers/video/omap2/dss/dss_features.c | 84 +++++++++++++++++--------- drivers/video/omap2/dss/dss_features.h | 10 +++ 3 files changed, 113 insertions(+), 50 deletions(-) diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c index 6e7f468281486..7a4b4404a9764 100644 --- a/drivers/video/omap2/dss/dsi.c +++ b/drivers/video/omap2/dss/dsi.c @@ -185,14 +185,6 @@ struct dsi_reg { u16 idx; }; #define DSI_DT_RX_SHORT_READ_1 0x21 #define DSI_DT_RX_SHORT_READ_2 0x22 -#define FINT_MAX 2100000 -#define FINT_MIN 750000 -#define REGN_MAX (1 << 7) -#define REGM_MAX ((1 << 11) - 1) -#define REGM_DISPC_MAX (1 << 4) -#define REGM_DSI_MAX (1 << 4) -#define LP_DIV_MAX ((1 << 13) - 1) - enum fifo_size { DSI_FIFO_SIZE_0 = 0, DSI_FIFO_SIZE_32 = 1, @@ -277,6 +269,11 @@ static struct spinlock_t irq_stats_lock; struct dsi_irq_stats irq_stats; #endif + /* DSI PLL Parameter Ranges */ + unsigned long regm_max, regn_max; + unsigned long regm_dispc_max, regm_dsi_max; + unsigned long fint_min, fint_max; + unsigned long lpdiv_max; } dsi; #ifdef DEBUG @@ -751,7 +748,7 @@ static int dsi_set_lp_clk_divisor(struct omap_dss_device *dssdev) lp_clk_div = dssdev->phy.dsi.div.lp_clk_div; - if (lp_clk_div == 0 || lp_clk_div > LP_DIV_MAX) + if (lp_clk_div == 0 || lp_clk_div > dsi.lpdiv_max) return -EINVAL; dsi_fclk = dsi_fclk_rate(); @@ -801,16 +798,16 @@ static int dsi_pll_power(enum dsi_pll_power_state state) static int dsi_calc_clock_rates(struct omap_dss_device *dssdev, struct dsi_clock_info *cinfo) { - if (cinfo->regn == 0 || cinfo->regn > REGN_MAX) + if (cinfo->regn == 0 || cinfo->regn > dsi.regn_max) return -EINVAL; - if (cinfo->regm == 0 || cinfo->regm > REGM_MAX) + if (cinfo->regm == 0 || cinfo->regm > dsi.regm_max) return -EINVAL; - if (cinfo->regm_dispc > REGM_DISPC_MAX) + if (cinfo->regm_dispc > dsi.regm_dispc_max) return -EINVAL; - if (cinfo->regm_dsi > REGM_DSI_MAX) + if (cinfo->regm_dsi > dsi.regm_dsi_max) return -EINVAL; if (cinfo->use_sys_clk) { @@ -829,7 +826,7 @@ static int dsi_calc_clock_rates(struct omap_dss_device *dssdev, cinfo->fint = cinfo->clkin / (cinfo->regn * (cinfo->highfreq ? 2 : 1)); - if (cinfo->fint > FINT_MAX || cinfo->fint < FINT_MIN) + if (cinfo->fint > dsi.fint_max || cinfo->fint < dsi.fint_min) return -EINVAL; cinfo->clkin4ddr = 2 * cinfo->regm * cinfo->fint; @@ -899,17 +896,17 @@ retry: /* no highfreq: 0.75MHz < Fint = clkin / regn < 2.1MHz */ /* highfreq: 0.75MHz < Fint = clkin / (2*regn) < 2.1MHz */ /* To reduce PLL lock time, keep Fint high (around 2 MHz) */ - for (cur.regn = 1; cur.regn < REGN_MAX; ++cur.regn) { + for (cur.regn = 1; cur.regn < dsi.regn_max; ++cur.regn) { if (cur.highfreq == 0) cur.fint = cur.clkin / cur.regn; else cur.fint = cur.clkin / (2 * cur.regn); - if (cur.fint > FINT_MAX || cur.fint < FINT_MIN) + if (cur.fint > dsi.fint_max || cur.fint < dsi.fint_min) continue; /* DSIPHY(MHz) = (2 * regm / regn) * (clkin / (highfreq + 1)) */ - for (cur.regm = 1; cur.regm < REGM_MAX; ++cur.regm) { + for (cur.regm = 1; cur.regm < dsi.regm_max; ++cur.regm) { unsigned long a, b; a = 2 * cur.regm * (cur.clkin/1000); @@ -921,7 +918,7 @@ retry: /* dsi_pll_hsdiv_dispc_clk(MHz) = * DSIPHY(MHz) / regm_dispc < 173MHz/186Mhz */ - for (cur.regm_dispc = 1; cur.regm_dispc < REGM_DISPC_MAX; + for (cur.regm_dispc = 1; cur.regm_dispc < dsi.regm_dispc_max; ++cur.regm_dispc) { struct dispc_clock_info cur_dispc; cur.dsi_pll_hsdiv_dispc_clk = @@ -994,6 +991,8 @@ int dsi_pll_set_clock_div(struct dsi_clock_info *cinfo) int r = 0; u32 l; int f; + u8 regn_start, regn_end, regm_start, regm_end; + u8 regm_dispc_start, regm_dispc_end, regm_dsi_start, regm_dsi_end; DSSDBGF(); @@ -1038,19 +1037,30 @@ int dsi_pll_set_clock_div(struct dsi_clock_info *cinfo) dss_feat_get_clk_source_name(DSS_CLK_SRC_DSI_PLL_HSDIV_DSI), cinfo->dsi_pll_hsdiv_dsi_clk); + dss_feat_get_reg_field(FEAT_REG_DSIPLL_REGN, ®n_start, ®n_end); + dss_feat_get_reg_field(FEAT_REG_DSIPLL_REGM, ®m_start, ®m_end); + dss_feat_get_reg_field(FEAT_REG_DSIPLL_REGM_DISPC, ®m_dispc_start, + ®m_dispc_end); + dss_feat_get_reg_field(FEAT_REG_DSIPLL_REGM_DSI, ®m_dsi_start, + ®m_dsi_end); + REG_FLD_MOD(DSI_PLL_CONTROL, 0, 0, 0); /* DSI_PLL_AUTOMODE = manual */ l = dsi_read_reg(DSI_PLL_CONFIGURATION1); l = FLD_MOD(l, 1, 0, 0); /* DSI_PLL_STOPMODE */ - l = FLD_MOD(l, cinfo->regn - 1, 7, 1); /* DSI_PLL_REGN */ - l = FLD_MOD(l, cinfo->regm, 18, 8); /* DSI_PLL_REGM */ + /* DSI_PLL_REGN */ + l = FLD_MOD(l, cinfo->regn - 1, regn_start, regn_end); + /* DSI_PLL_REGM */ + l = FLD_MOD(l, cinfo->regm, regm_start, regm_end); + /* DSI_CLOCK_DIV */ l = FLD_MOD(l, cinfo->regm_dispc > 0 ? cinfo->regm_dispc - 1 : 0, - 22, 19); /* DSI_CLOCK_DIV */ + regm_dispc_start, regm_dispc_end); + /* DSIPROTO_CLOCK_DIV */ l = FLD_MOD(l, cinfo->regm_dsi > 0 ? cinfo->regm_dsi - 1 : 0, - 26, 23); /* DSIPROTO_CLOCK_DIV */ + regm_dsi_start, regm_dsi_end); dsi_write_reg(DSI_PLL_CONFIGURATION1, l); - BUG_ON(cinfo->fint < 750000 || cinfo->fint > 2100000); + BUG_ON(cinfo->fint < dsi.fint_min || cinfo->fint > dsi.fint_max); if (cinfo->fint < 1000000) f = 0x3; else if (cinfo->fint < 1250000) @@ -3333,6 +3343,17 @@ void dsi_wait_pll_hsdiv_dsi_active(void) dss_feat_get_clk_source_name(DSS_CLK_SRC_DSI_PLL_HSDIV_DSI)); } +static void dsi_calc_clock_param_ranges(void) +{ + dsi.regn_max = dss_feat_get_param_max(FEAT_PARAM_DSIPLL_REGN); + dsi.regm_max = dss_feat_get_param_max(FEAT_PARAM_DSIPLL_REGM); + dsi.regm_dispc_max = dss_feat_get_param_max(FEAT_PARAM_DSIPLL_REGM_DISPC); + dsi.regm_dsi_max = dss_feat_get_param_max(FEAT_PARAM_DSIPLL_REGM_DSI); + dsi.fint_min = dss_feat_get_param_min(FEAT_PARAM_DSIPLL_FINT); + dsi.fint_max = dss_feat_get_param_max(FEAT_PARAM_DSIPLL_FINT); + dsi.lpdiv_max = dss_feat_get_param_max(FEAT_PARAM_DSIPLL_LPDIV); +} + static int dsi_init(struct platform_device *pdev) { u32 rev; @@ -3397,6 +3418,8 @@ static int dsi_init(struct platform_device *pdev) dsi.vc[i].vc_id = 0; } + dsi_calc_clock_param_ranges(); + enable_clocks(1); rev = dsi_read_reg(DSI_REVISION); diff --git a/drivers/video/omap2/dss/dss_features.c b/drivers/video/omap2/dss/dss_features.c index 4c8b32af496c3..06b18f73449b0 100644 --- a/drivers/video/omap2/dss/dss_features.c +++ b/drivers/video/omap2/dss/dss_features.c @@ -55,36 +55,48 @@ struct omap_dss_features { static struct omap_dss_features *omap_current_dss_features; static const struct dss_reg_field omap2_dss_reg_fields[] = { - [FEAT_REG_FIRHINC] = { 11, 0 }, - [FEAT_REG_FIRVINC] = { 27, 16 }, - [FEAT_REG_FIFOLOWTHRESHOLD] = { 8, 0 }, - [FEAT_REG_FIFOHIGHTHRESHOLD] = { 24, 16 }, - [FEAT_REG_FIFOSIZE] = { 8, 0 }, - [FEAT_REG_HORIZONTALACCU] = { 9, 0 }, - [FEAT_REG_VERTICALACCU] = { 25, 16 }, - [FEAT_REG_DISPC_CLK_SWITCH] = { 0, 0 }, + [FEAT_REG_FIRHINC] = { 11, 0 }, + [FEAT_REG_FIRVINC] = { 27, 16 }, + [FEAT_REG_FIFOLOWTHRESHOLD] = { 8, 0 }, + [FEAT_REG_FIFOHIGHTHRESHOLD] = { 24, 16 }, + [FEAT_REG_FIFOSIZE] = { 8, 0 }, + [FEAT_REG_HORIZONTALACCU] = { 9, 0 }, + [FEAT_REG_VERTICALACCU] = { 25, 16 }, + [FEAT_REG_DISPC_CLK_SWITCH] = { 0, 0 }, + [FEAT_REG_DSIPLL_REGN] = { 0, 0 }, + [FEAT_REG_DSIPLL_REGM] = { 0, 0 }, + [FEAT_REG_DSIPLL_REGM_DISPC] = { 0, 0 }, + [FEAT_REG_DSIPLL_REGM_DSI] = { 0, 0 }, }; static const struct dss_reg_field omap3_dss_reg_fields[] = { - [FEAT_REG_FIRHINC] = { 12, 0 }, - [FEAT_REG_FIRVINC] = { 28, 16 }, - [FEAT_REG_FIFOLOWTHRESHOLD] = { 11, 0 }, - [FEAT_REG_FIFOHIGHTHRESHOLD] = { 27, 16 }, - [FEAT_REG_FIFOSIZE] = { 10, 0 }, - [FEAT_REG_HORIZONTALACCU] = { 9, 0 }, - [FEAT_REG_VERTICALACCU] = { 25, 16 }, - [FEAT_REG_DISPC_CLK_SWITCH] = { 0, 0 }, + [FEAT_REG_FIRHINC] = { 12, 0 }, + [FEAT_REG_FIRVINC] = { 28, 16 }, + [FEAT_REG_FIFOLOWTHRESHOLD] = { 11, 0 }, + [FEAT_REG_FIFOHIGHTHRESHOLD] = { 27, 16 }, + [FEAT_REG_FIFOSIZE] = { 10, 0 }, + [FEAT_REG_HORIZONTALACCU] = { 9, 0 }, + [FEAT_REG_VERTICALACCU] = { 25, 16 }, + [FEAT_REG_DISPC_CLK_SWITCH] = { 0, 0 }, + [FEAT_REG_DSIPLL_REGN] = { 7, 1 }, + [FEAT_REG_DSIPLL_REGM] = { 18, 8 }, + [FEAT_REG_DSIPLL_REGM_DISPC] = { 22, 19 }, + [FEAT_REG_DSIPLL_REGM_DSI] = { 26, 23 }, }; static const struct dss_reg_field omap4_dss_reg_fields[] = { - [FEAT_REG_FIRHINC] = { 12, 0 }, - [FEAT_REG_FIRVINC] = { 28, 16 }, - [FEAT_REG_FIFOLOWTHRESHOLD] = { 15, 0 }, - [FEAT_REG_FIFOHIGHTHRESHOLD] = { 31, 16 }, - [FEAT_REG_FIFOSIZE] = { 15, 0 }, - [FEAT_REG_HORIZONTALACCU] = { 10, 0 }, - [FEAT_REG_VERTICALACCU] = { 26, 16 }, - [FEAT_REG_DISPC_CLK_SWITCH] = { 9, 8 }, + [FEAT_REG_FIRHINC] = { 12, 0 }, + [FEAT_REG_FIRVINC] = { 28, 16 }, + [FEAT_REG_FIFOLOWTHRESHOLD] = { 15, 0 }, + [FEAT_REG_FIFOHIGHTHRESHOLD] = { 31, 16 }, + [FEAT_REG_FIFOSIZE] = { 15, 0 }, + [FEAT_REG_HORIZONTALACCU] = { 10, 0 }, + [FEAT_REG_VERTICALACCU] = { 26, 16 }, + [FEAT_REG_DISPC_CLK_SWITCH] = { 9, 8 }, + [FEAT_REG_DSIPLL_REGN] = { 8, 1 }, + [FEAT_REG_DSIPLL_REGM] = { 20, 9 }, + [FEAT_REG_DSIPLL_REGM_DISPC] = { 25, 21 }, + [FEAT_REG_DSIPLL_REGM_DSI] = { 30, 26 }, }; static const enum omap_display_type omap2_dss_supported_displays[] = { @@ -184,15 +196,33 @@ static const char * const omap4_dss_clk_source_names[] = { }; static const struct dss_param_range omap2_dss_param_range[] = { - [FEAT_PARAM_DSS_FCK] = { 0, 173000000 }, + [FEAT_PARAM_DSS_FCK] = { 0, 173000000 }, + [FEAT_PARAM_DSIPLL_REGN] = { 0, 0 }, + [FEAT_PARAM_DSIPLL_REGM] = { 0, 0 }, + [FEAT_PARAM_DSIPLL_REGM_DISPC] = { 0, 0 }, + [FEAT_PARAM_DSIPLL_REGM_DSI] = { 0, 0 }, + [FEAT_PARAM_DSIPLL_FINT] = { 0, 0 }, + [FEAT_PARAM_DSIPLL_LPDIV] = { 0, 0 }, }; static const struct dss_param_range omap3_dss_param_range[] = { - [FEAT_PARAM_DSS_FCK] = { 0, 173000000 }, + [FEAT_PARAM_DSS_FCK] = { 0, 173000000 }, + [FEAT_PARAM_DSIPLL_REGN] = { 0, (1 << 7) - 1 }, + [FEAT_PARAM_DSIPLL_REGM] = { 0, (1 << 11) - 1 }, + [FEAT_PARAM_DSIPLL_REGM_DISPC] = { 0, (1 << 4) - 1 }, + [FEAT_PARAM_DSIPLL_REGM_DSI] = { 0, (1 << 4) - 1 }, + [FEAT_PARAM_DSIPLL_FINT] = { 750000, 2100000 }, + [FEAT_PARAM_DSIPLL_LPDIV] = { 1, (1 << 13) - 1}, }; static const struct dss_param_range omap4_dss_param_range[] = { - [FEAT_PARAM_DSS_FCK] = { 0, 186000000 }, + [FEAT_PARAM_DSS_FCK] = { 0, 186000000 }, + [FEAT_PARAM_DSIPLL_REGN] = { 0, (1 << 8) - 1 }, + [FEAT_PARAM_DSIPLL_REGM] = { 0, (1 << 12) - 1 }, + [FEAT_PARAM_DSIPLL_REGM_DISPC] = { 0, (1 << 5) - 1 }, + [FEAT_PARAM_DSIPLL_REGM_DSI] = { 0, (1 << 5) - 1 }, + [FEAT_PARAM_DSIPLL_FINT] = { 500000, 2500000 }, + [FEAT_PARAM_DSIPLL_LPDIV] = { 0, (1 << 13) - 1 }, }; /* OMAP2 DSS Features */ diff --git a/drivers/video/omap2/dss/dss_features.h b/drivers/video/omap2/dss/dss_features.h index da63bbf38e902..12e9c4ef0dec4 100644 --- a/drivers/video/omap2/dss/dss_features.h +++ b/drivers/video/omap2/dss/dss_features.h @@ -52,10 +52,20 @@ enum dss_feat_reg_field { FEAT_REG_HORIZONTALACCU, FEAT_REG_VERTICALACCU, FEAT_REG_DISPC_CLK_SWITCH, + FEAT_REG_DSIPLL_REGN, + FEAT_REG_DSIPLL_REGM, + FEAT_REG_DSIPLL_REGM_DISPC, + FEAT_REG_DSIPLL_REGM_DSI, }; enum dss_range_param { FEAT_PARAM_DSS_FCK, + FEAT_PARAM_DSIPLL_REGN, + FEAT_PARAM_DSIPLL_REGM, + FEAT_PARAM_DSIPLL_REGM_DISPC, + FEAT_PARAM_DSIPLL_REGM_DSI, + FEAT_PARAM_DSIPLL_FINT, + FEAT_PARAM_DSIPLL_LPDIV, }; /* DSS Feature Functions */ -- GitLab From 69b281a61442f97e8df14babc9bb6a28624886b1 Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Wed, 2 Mar 2011 14:44:27 +0200 Subject: [PATCH 0660/2822] OMAP: DSS2: DSI: Restructure IRQ handler Clean up the IRQ handler a bit by separating collection of IRQ stats and handling of IRQ errors to separate functions. Signed-off-by: Tomi Valkeinen --- drivers/video/omap2/dss/dsi.c | 123 ++++++++++++++++++++-------------- 1 file changed, 73 insertions(+), 50 deletions(-) diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c index 7a4b4404a9764..b6c08a6f2da15 100644 --- a/drivers/video/omap2/dss/dsi.c +++ b/drivers/video/omap2/dss/dsi.c @@ -477,26 +477,33 @@ static void print_irq_status_cio(u32 status) printk("\n"); } -static int debug_irq; - -/* called from dss */ -static irqreturn_t omap_dsi_irq_handler(int irq, void *arg) +#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS +static void dsi_collect_irq_stats(u32 irqstatus, u32 *vcstatus, u32 ciostatus) { - u32 irqstatus, vcstatus, ciostatus; int i; - irqstatus = dsi_read_reg(DSI_IRQSTATUS); - - /* IRQ is not for us */ - if (!irqstatus) - return IRQ_NONE; - -#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS spin_lock(&dsi.irq_stats_lock); + dsi.irq_stats.irq_count++; dss_collect_irq_stats(irqstatus, dsi.irq_stats.dsi_irqs); + + for (i = 0; i < 4; ++i) + dss_collect_irq_stats(vcstatus[i], dsi.irq_stats.vc_irqs[i]); + + dss_collect_irq_stats(ciostatus, dsi.irq_stats.cio_irqs); + + spin_unlock(&dsi.irq_stats_lock); +} +#else +#define dsi_collect_irq_stats(irqstatus, vcstatus, ciostatus) #endif +static int debug_irq; + +static void dsi_handle_irq_errors(u32 irqstatus, u32 *vcstatus, u32 ciostatus) +{ + int i; + if (irqstatus & DSI_IRQ_ERROR_MASK) { DSSERR("DSI error, irqstatus %x\n", irqstatus); print_irq_status(irqstatus); @@ -507,37 +514,48 @@ static irqreturn_t omap_dsi_irq_handler(int irq, void *arg) print_irq_status(irqstatus); } -#ifdef DSI_CATCH_MISSING_TE - if (irqstatus & DSI_IRQ_TE_TRIGGER) - del_timer(&dsi.te_timer); -#endif - for (i = 0; i < 4; ++i) { - if ((irqstatus & (1< Date: Wed, 2 Mar 2011 14:47:04 +0200 Subject: [PATCH 0661/2822] OMAP: DSS2: DSI: Add ISR support Add generic ISR support for DSI interrupts. ISRs can be used instead of custom hooks in the interrupt handler. Signed-off-by: Tomi Valkeinen --- drivers/video/omap2/dss/dsi.c | 329 +++++++++++++++++++++++++++++++--- 1 file changed, 304 insertions(+), 25 deletions(-) diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c index b6c08a6f2da15..8613ec4894103 100644 --- a/drivers/video/omap2/dss/dsi.c +++ b/drivers/video/omap2/dss/dsi.c @@ -185,6 +185,16 @@ struct dsi_reg { u16 idx; }; #define DSI_DT_RX_SHORT_READ_1 0x21 #define DSI_DT_RX_SHORT_READ_2 0x22 +typedef void (*omap_dsi_isr_t) (void *arg, u32 mask); + +#define DSI_MAX_NR_ISRS 2 + +struct dsi_isr_data { + omap_dsi_isr_t isr; + void *arg; + u32 mask; +}; + enum fifo_size { DSI_FIFO_SIZE_0 = 0, DSI_FIFO_SIZE_32 = 1, @@ -211,6 +221,12 @@ struct dsi_irq_stats { unsigned cio_irqs[32]; }; +struct dsi_isr_tables { + struct dsi_isr_data isr_table[DSI_MAX_NR_ISRS]; + struct dsi_isr_data isr_table_vc[4][DSI_MAX_NR_ISRS]; + struct dsi_isr_data isr_table_cio[DSI_MAX_NR_ISRS]; +}; + static struct { struct platform_device *pdev; @@ -236,6 +252,11 @@ static struct struct completion bta_completion; void (*bta_callback)(void); + spinlock_t irq_lock; + struct dsi_isr_tables isr_tables; + /* space for a copy used by the interrupt handler */ + struct dsi_isr_tables isr_tables_copy; + int update_channel; struct dsi_update_region update_region; @@ -532,16 +553,56 @@ static void dsi_handle_irq_errors(u32 irqstatus, u32 *vcstatus, u32 ciostatus) } } +static void dsi_call_isrs(struct dsi_isr_data *isr_array, + unsigned isr_array_size, u32 irqstatus) +{ + struct dsi_isr_data *isr_data; + int i; + + for (i = 0; i < isr_array_size; i++) { + isr_data = &isr_array[i]; + if (isr_data->isr && isr_data->mask & irqstatus) + isr_data->isr(isr_data->arg, irqstatus); + } +} + +static void dsi_handle_isrs(struct dsi_isr_tables *isr_tables, + u32 irqstatus, u32 *vcstatus, u32 ciostatus) +{ + int i; + + dsi_call_isrs(isr_tables->isr_table, + ARRAY_SIZE(isr_tables->isr_table), + irqstatus); + + for (i = 0; i < 4; ++i) { + if (vcstatus[i] == 0) + continue; + dsi_call_isrs(isr_tables->isr_table_vc[i], + ARRAY_SIZE(isr_tables->isr_table_vc[i]), + vcstatus[i]); + } + + if (ciostatus != 0) + dsi_call_isrs(isr_tables->isr_table_cio, + ARRAY_SIZE(isr_tables->isr_table_cio), + ciostatus); +} + static irqreturn_t omap_dsi_irq_handler(int irq, void *arg) { u32 irqstatus, vcstatus[4], ciostatus; int i; + spin_lock(&dsi.irq_lock); + irqstatus = dsi_read_reg(DSI_IRQSTATUS); /* IRQ is not for us */ - if (!irqstatus) + if (!irqstatus) { + spin_unlock(&dsi.irq_lock); return IRQ_NONE; + } dsi_write_reg(DSI_IRQSTATUS, irqstatus & ~DSI_IRQ_CHANNEL_MASK); /* flush posted write */ @@ -587,6 +648,14 @@ static irqreturn_t omap_dsi_irq_handler(int irq, void *arg) } } + /* make a copy and unlock, so that isrs can unregister + * themselves */ + memcpy(&dsi.isr_tables_copy, &dsi.isr_tables, sizeof(dsi.isr_tables)); + + spin_unlock(&dsi.irq_lock); + + dsi_handle_isrs(&dsi.isr_tables_copy, irqstatus, vcstatus, ciostatus); + dsi_handle_irq_errors(irqstatus, vcstatus, ciostatus); dsi_collect_irq_stats(irqstatus, vcstatus, ciostatus); @@ -594,42 +663,251 @@ static irqreturn_t omap_dsi_irq_handler(int irq, void *arg) return IRQ_HANDLED; } -static void _dsi_initialize_irq(void) +/* dsi.irq_lock has to be locked by the caller */ +static void _omap_dsi_configure_irqs(struct dsi_isr_data *isr_array, + unsigned isr_array_size, u32 default_mask, + const struct dsi_reg enable_reg, + const struct dsi_reg status_reg) { - u32 l; + struct dsi_isr_data *isr_data; + u32 mask; + u32 old_mask; int i; - /* disable all interrupts */ - dsi_write_reg(DSI_IRQENABLE, 0); - for (i = 0; i < 4; ++i) - dsi_write_reg(DSI_VC_IRQENABLE(i), 0); - dsi_write_reg(DSI_COMPLEXIO_IRQ_ENABLE, 0); + mask = default_mask; - /* clear interrupt status */ - l = dsi_read_reg(DSI_IRQSTATUS); - dsi_write_reg(DSI_IRQSTATUS, l & ~DSI_IRQ_CHANNEL_MASK); + for (i = 0; i < isr_array_size; i++) { + isr_data = &isr_array[i]; - for (i = 0; i < 4; ++i) { - l = dsi_read_reg(DSI_VC_IRQSTATUS(i)); - dsi_write_reg(DSI_VC_IRQSTATUS(i), l); + if (isr_data->isr == NULL) + continue; + + mask |= isr_data->mask; } - l = dsi_read_reg(DSI_COMPLEXIO_IRQ_STATUS); - dsi_write_reg(DSI_COMPLEXIO_IRQ_STATUS, l); + old_mask = dsi_read_reg(enable_reg); + /* clear the irqstatus for newly enabled irqs */ + dsi_write_reg(status_reg, (mask ^ old_mask) & mask); + dsi_write_reg(enable_reg, mask); + + /* flush posted writes */ + dsi_read_reg(enable_reg); + dsi_read_reg(status_reg); +} - /* enable error irqs */ - l = DSI_IRQ_ERROR_MASK; +/* dsi.irq_lock has to be locked by the caller */ +static void _omap_dsi_set_irqs(void) +{ + u32 mask = DSI_IRQ_ERROR_MASK; #ifdef DSI_CATCH_MISSING_TE - l |= DSI_IRQ_TE_TRIGGER; + mask |= DSI_IRQ_TE_TRIGGER; #endif - dsi_write_reg(DSI_IRQENABLE, l); + _omap_dsi_configure_irqs(dsi.isr_tables.isr_table, + ARRAY_SIZE(dsi.isr_tables.isr_table), mask, + DSI_IRQENABLE, DSI_IRQSTATUS); +} - l = DSI_VC_IRQ_ERROR_MASK; - for (i = 0; i < 4; ++i) - dsi_write_reg(DSI_VC_IRQENABLE(i), l); +/* dsi.irq_lock has to be locked by the caller */ +static void _omap_dsi_set_irqs_vc(int vc) +{ + _omap_dsi_configure_irqs(dsi.isr_tables.isr_table_vc[vc], + ARRAY_SIZE(dsi.isr_tables.isr_table_vc[vc]), + DSI_VC_IRQ_ERROR_MASK, + DSI_VC_IRQENABLE(vc), DSI_VC_IRQSTATUS(vc)); +} + +/* dsi.irq_lock has to be locked by the caller */ +static void _omap_dsi_set_irqs_cio(void) +{ + _omap_dsi_configure_irqs(dsi.isr_tables.isr_table_cio, + ARRAY_SIZE(dsi.isr_tables.isr_table_cio), + DSI_CIO_IRQ_ERROR_MASK, + DSI_COMPLEXIO_IRQ_ENABLE, DSI_COMPLEXIO_IRQ_STATUS); +} + +static void _dsi_initialize_irq(void) +{ + unsigned long flags; + int vc; + + spin_lock_irqsave(&dsi.irq_lock, flags); + + memset(&dsi.isr_tables, 0, sizeof(dsi.isr_tables)); + + _omap_dsi_set_irqs(); + for (vc = 0; vc < 4; ++vc) + _omap_dsi_set_irqs_vc(vc); + _omap_dsi_set_irqs_cio(); + + spin_unlock_irqrestore(&dsi.irq_lock, flags); +} - l = DSI_CIO_IRQ_ERROR_MASK; - dsi_write_reg(DSI_COMPLEXIO_IRQ_ENABLE, l); +static int _dsi_register_isr(omap_dsi_isr_t isr, void *arg, u32 mask, + struct dsi_isr_data *isr_array, unsigned isr_array_size) +{ + struct dsi_isr_data *isr_data; + int free_idx; + int i; + + BUG_ON(isr == NULL); + + /* check for duplicate entry and find a free slot */ + free_idx = -1; + for (i = 0; i < isr_array_size; i++) { + isr_data = &isr_array[i]; + + if (isr_data->isr == isr && isr_data->arg == arg && + isr_data->mask == mask) { + return -EINVAL; + } + + if (isr_data->isr == NULL && free_idx == -1) + free_idx = i; + } + + if (free_idx == -1) + return -EBUSY; + + isr_data = &isr_array[free_idx]; + isr_data->isr = isr; + isr_data->arg = arg; + isr_data->mask = mask; + + return 0; +} + +static int _dsi_unregister_isr(omap_dsi_isr_t isr, void *arg, u32 mask, + struct dsi_isr_data *isr_array, unsigned isr_array_size) +{ + struct dsi_isr_data *isr_data; + int i; + + for (i = 0; i < isr_array_size; i++) { + isr_data = &isr_array[i]; + if (isr_data->isr != isr || isr_data->arg != arg || + isr_data->mask != mask) + continue; + + isr_data->isr = NULL; + isr_data->arg = NULL; + isr_data->mask = 0; + + return 0; + } + + return -EINVAL; +} + +static int dsi_register_isr(omap_dsi_isr_t isr, void *arg, u32 mask) +{ + unsigned long flags; + int r; + + spin_lock_irqsave(&dsi.irq_lock, flags); + + r = _dsi_register_isr(isr, arg, mask, dsi.isr_tables.isr_table, + ARRAY_SIZE(dsi.isr_tables.isr_table)); + + if (r == 0) + _omap_dsi_set_irqs(); + + spin_unlock_irqrestore(&dsi.irq_lock, flags); + + return r; +} + +static int dsi_unregister_isr(omap_dsi_isr_t isr, void *arg, u32 mask) +{ + unsigned long flags; + int r; + + spin_lock_irqsave(&dsi.irq_lock, flags); + + r = _dsi_unregister_isr(isr, arg, mask, dsi.isr_tables.isr_table, + ARRAY_SIZE(dsi.isr_tables.isr_table)); + + if (r == 0) + _omap_dsi_set_irqs(); + + spin_unlock_irqrestore(&dsi.irq_lock, flags); + + return r; +} + +static int dsi_register_isr_vc(int channel, omap_dsi_isr_t isr, void *arg, + u32 mask) +{ + unsigned long flags; + int r; + + spin_lock_irqsave(&dsi.irq_lock, flags); + + r = _dsi_register_isr(isr, arg, mask, + dsi.isr_tables.isr_table_vc[channel], + ARRAY_SIZE(dsi.isr_tables.isr_table_vc[channel])); + + if (r == 0) + _omap_dsi_set_irqs_vc(channel); + + spin_unlock_irqrestore(&dsi.irq_lock, flags); + + return r; +} + +static int dsi_unregister_isr_vc(int channel, omap_dsi_isr_t isr, void *arg, + u32 mask) +{ + unsigned long flags; + int r; + + spin_lock_irqsave(&dsi.irq_lock, flags); + + r = _dsi_unregister_isr(isr, arg, mask, + dsi.isr_tables.isr_table_vc[channel], + ARRAY_SIZE(dsi.isr_tables.isr_table_vc[channel])); + + if (r == 0) + _omap_dsi_set_irqs_vc(channel); + + spin_unlock_irqrestore(&dsi.irq_lock, flags); + + return r; +} + +static int dsi_register_isr_cio(omap_dsi_isr_t isr, void *arg, u32 mask) +{ + unsigned long flags; + int r; + + spin_lock_irqsave(&dsi.irq_lock, flags); + + r = _dsi_register_isr(isr, arg, mask, dsi.isr_tables.isr_table_cio, + ARRAY_SIZE(dsi.isr_tables.isr_table_cio)); + + if (r == 0) + _omap_dsi_set_irqs_cio(); + + spin_unlock_irqrestore(&dsi.irq_lock, flags); + + return r; +} + +static int dsi_unregister_isr_cio(omap_dsi_isr_t isr, void *arg, u32 mask) +{ + unsigned long flags; + int r; + + spin_lock_irqsave(&dsi.irq_lock, flags); + + r = _dsi_unregister_isr(isr, arg, mask, dsi.isr_tables.isr_table_cio, + ARRAY_SIZE(dsi.isr_tables.isr_table_cio)); + + if (r == 0) + _omap_dsi_set_irqs_cio(); + + spin_unlock_irqrestore(&dsi.irq_lock, flags); + + return r; } static u32 dsi_get_errors(void) @@ -3383,6 +3661,7 @@ static int dsi_init(struct platform_device *pdev) int r, i; struct resource *dsi_mem; + spin_lock_init(&dsi.irq_lock); spin_lock_init(&dsi.errors_lock); dsi.errors = 0; -- GitLab From f36a06e702ef804a99ce3a286514d84610a74db5 Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Wed, 2 Mar 2011 14:48:41 +0200 Subject: [PATCH 0662/2822] OMAP: DSS2: DSI: use ISR in send_bta_sync Remove bta_completion handling from the interrupt handler, and use ISR support instead. Signed-off-by: Tomi Valkeinen --- drivers/video/omap2/dss/dsi.c | 32 ++++++++++++++++++-------------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c index 8613ec4894103..18b72521ee7e9 100644 --- a/drivers/video/omap2/dss/dsi.c +++ b/drivers/video/omap2/dss/dsi.c @@ -249,7 +249,6 @@ static struct unsigned pll_locked; - struct completion bta_completion; void (*bta_callback)(void); spinlock_t irq_lock; @@ -338,6 +337,11 @@ static bool dsi_bus_is_locked(void) return dsi.bus_lock.count == 0; } +static void dsi_completion_handler(void *data, u32 mask) +{ + complete((struct completion *)data); +} + static inline int wait_for_bit_change(const struct dsi_reg idx, int bitnum, int value) { @@ -641,8 +645,6 @@ static irqreturn_t omap_dsi_irq_handler(int irq, void *arg) continue; if (vcstatus[i] & DSI_VC_IRQ_BTA) { - complete(&dsi.bta_completion); - if (dsi.bta_callback) dsi.bta_callback(); } @@ -2263,33 +2265,37 @@ static int dsi_vc_send_bta(int channel) int dsi_vc_send_bta_sync(int channel) { + DECLARE_COMPLETION_ONSTACK(completion); int r = 0; u32 err; - INIT_COMPLETION(dsi.bta_completion); - - dsi_vc_enable_bta_irq(channel); + r = dsi_register_isr_vc(channel, dsi_completion_handler, + &completion, DSI_VC_IRQ_BTA); + if (r) + goto err0; r = dsi_vc_send_bta(channel); if (r) - goto err; + goto err1; - if (wait_for_completion_timeout(&dsi.bta_completion, + if (wait_for_completion_timeout(&completion, msecs_to_jiffies(500)) == 0) { DSSERR("Failed to receive BTA\n"); r = -EIO; - goto err; + goto err1; } err = dsi_get_errors(); if (err) { DSSERR("Error while sending BTA: %x\n", err); r = -EIO; - goto err; + goto err1; } -err: - dsi_vc_disable_bta_irq(channel); +err1: + dsi_unregister_isr_vc(channel, dsi_completion_handler, + &completion, DSI_VC_IRQ_BTA); +err0: return r; } EXPORT_SYMBOL(dsi_vc_send_bta_sync); @@ -3670,8 +3676,6 @@ static int dsi_init(struct platform_device *pdev) dsi.irq_stats.last_reset = jiffies; #endif - init_completion(&dsi.bta_completion); - mutex_init(&dsi.lock); sema_init(&dsi.bus_lock, 1); -- GitLab From f34bd465cae57bcce11fb7f953cfcbb18222b99e Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Wed, 2 Mar 2011 14:52:48 +0200 Subject: [PATCH 0663/2822] OMAP: DSS2: DSI: use ISR for BTA in framedone Remove bta_callback from the interrupt handler, and use ISR support instead. Signed-off-by: Tomi Valkeinen --- drivers/video/omap2/dss/dsi.c | 57 +++++++++-------------------------- 1 file changed, 15 insertions(+), 42 deletions(-) diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c index 18b72521ee7e9..cd872e9d79898 100644 --- a/drivers/video/omap2/dss/dsi.c +++ b/drivers/video/omap2/dss/dsi.c @@ -249,8 +249,6 @@ static struct unsigned pll_locked; - void (*bta_callback)(void); - spinlock_t irq_lock; struct dsi_isr_tables isr_tables; /* space for a copy used by the interrupt handler */ @@ -640,16 +638,6 @@ static irqreturn_t omap_dsi_irq_handler(int irq, void *arg) del_timer(&dsi.te_timer); #endif - for (i = 0; i < 4; ++i) { - if (vcstatus[i] == 0) - continue; - - if (vcstatus[i] & DSI_VC_IRQ_BTA) { - if (dsi.bta_callback) - dsi.bta_callback(); - } - } - /* make a copy and unlock, so that isrs can unregister * themselves */ memcpy(&dsi.isr_tables_copy, &dsi.isr_tables, sizeof(dsi.isr_tables)); @@ -923,26 +911,6 @@ static u32 dsi_get_errors(void) return e; } -static void dsi_vc_enable_bta_irq(int channel) -{ - u32 l; - - dsi_write_reg(DSI_VC_IRQSTATUS(channel), DSI_VC_IRQ_BTA); - - l = dsi_read_reg(DSI_VC_IRQENABLE(channel)); - l |= DSI_VC_IRQ_BTA; - dsi_write_reg(DSI_VC_IRQENABLE(channel), l); -} - -static void dsi_vc_disable_bta_irq(int channel) -{ - u32 l; - - l = dsi_read_reg(DSI_VC_IRQENABLE(channel)); - l &= ~DSI_VC_IRQ_BTA; - dsi_write_reg(DSI_VC_IRQENABLE(channel), l); -} - /* DSI func clock. this could also be dsi_pll_hsdiv_dsi_clk */ static inline void enable_clocks(bool enable) { @@ -3109,19 +3077,20 @@ static void dsi_te_timeout(unsigned long arg) } #endif +static void dsi_framedone_bta_callback(void *data, u32 mask); + static void dsi_handle_framedone(int error) { const int channel = dsi.update_channel; - cancel_delayed_work(&dsi.framedone_timeout_work); + dsi_unregister_isr_vc(channel, dsi_framedone_bta_callback, + NULL, DSI_VC_IRQ_BTA); - dsi_vc_disable_bta_irq(channel); + cancel_delayed_work(&dsi.framedone_timeout_work); /* SIDLEMODE back to smart-idle */ dispc_enable_sidle(); - dsi.bta_callback = NULL; - if (dsi.te_enabled) { /* enable LP_RX_TO again after the TE */ REG_FLD_MOD(DSI_TIMING2, 1, 15, 15); /* LP_RX_TO */ @@ -3155,7 +3124,7 @@ static void dsi_framedone_timeout_work_callback(struct work_struct *work) dsi_handle_framedone(-ETIMEDOUT); } -static void dsi_framedone_bta_callback(void) +static void dsi_framedone_bta_callback(void *data, u32 mask) { dsi_handle_framedone(0); @@ -3195,15 +3164,19 @@ static void dsi_framedone_irq_callback(void *data, u32 mask) * asynchronously. * */ - dsi.bta_callback = dsi_framedone_bta_callback; - - barrier(); - - dsi_vc_enable_bta_irq(channel); + r = dsi_register_isr_vc(channel, dsi_framedone_bta_callback, + NULL, DSI_VC_IRQ_BTA); + if (r) { + DSSERR("Failed to register BTA ISR\n"); + dsi_handle_framedone(-EIO); + return; + } r = dsi_vc_send_bta(channel); if (r) { DSSERR("BTA after framedone failed\n"); + dsi_unregister_isr_vc(channel, dsi_framedone_bta_callback, + NULL, DSI_VC_IRQ_BTA); dsi_handle_framedone(-EIO); } } -- GitLab From 773b30b22f8c5ac4ccc52775c17809cc5826cb86 Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Fri, 8 Oct 2010 16:15:25 +0300 Subject: [PATCH 0664/2822] OMAP: DSS2: DSI: catch DSI errors in send_bta_sync dsi_vc_send_bta_sync() waits for BTA interrupt with a 500ms timeout. If a DSI error happens, no BTA is received and the timeout triggers. This could be handled much faster by listening to DSI errors also. This patch uses the ISR support to notice DSI errors while waiting for the BTA, thus speeding up the fail-path considerably. Signed-off-by: Tomi Valkeinen --- drivers/video/omap2/dss/dsi.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c index cd872e9d79898..37226628bc0fe 100644 --- a/drivers/video/omap2/dss/dsi.c +++ b/drivers/video/omap2/dss/dsi.c @@ -2242,24 +2242,31 @@ int dsi_vc_send_bta_sync(int channel) if (r) goto err0; - r = dsi_vc_send_bta(channel); + r = dsi_register_isr(dsi_completion_handler, &completion, + DSI_IRQ_ERROR_MASK); if (r) goto err1; + r = dsi_vc_send_bta(channel); + if (r) + goto err2; + if (wait_for_completion_timeout(&completion, msecs_to_jiffies(500)) == 0) { DSSERR("Failed to receive BTA\n"); r = -EIO; - goto err1; + goto err2; } err = dsi_get_errors(); if (err) { DSSERR("Error while sending BTA: %x\n", err); r = -EIO; - goto err1; + goto err2; } - +err2: + dsi_unregister_isr(dsi_completion_handler, &completion, + DSI_IRQ_ERROR_MASK); err1: dsi_unregister_isr_vc(channel, dsi_completion_handler, &completion, DSI_VC_IRQ_BTA); -- GitLab From d80d499ed926e70b429d309360f5910d5ad54788 Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Wed, 2 Mar 2011 15:53:07 +0200 Subject: [PATCH 0665/2822] OMAP: DSS2: DSI: fix IRQ debug prints print_irq_status functions can be called with empty irq status when full irq debugging is enabled. This patch makes print_irq_status functions return immediately when given an empty irq status to lessen the debug spam slightly. Signed-off-by: Tomi Valkeinen --- drivers/video/omap2/dss/dsi.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c index 37226628bc0fe..0a7f1a47f8e3b 100644 --- a/drivers/video/omap2/dss/dsi.c +++ b/drivers/video/omap2/dss/dsi.c @@ -409,6 +409,9 @@ static void dsi_perf_show(const char *name) static void print_irq_status(u32 status) { + if (status == 0) + return; + #ifndef VERBOSE_IRQ if ((status & ~DSI_IRQ_CHANNEL_MASK) == 0) return; @@ -444,6 +447,9 @@ static void print_irq_status(u32 status) static void print_irq_status_vc(int channel, u32 status) { + if (status == 0) + return; + #ifndef VERBOSE_IRQ if ((status & ~DSI_VC_IRQ_PACKET_SENT) == 0) return; @@ -470,6 +476,9 @@ static void print_irq_status_vc(int channel, u32 status) static void print_irq_status_cio(u32 status) { + if (status == 0) + return; + printk(KERN_DEBUG "DSI CIO IRQ 0x%x: ", status); #define PIS(x) \ -- GitLab From 2c722c9a47d1369e2685b85288e78c469a081238 Mon Sep 17 00:00:00 2001 From: Tobias Klauser Date: Thu, 9 Dec 2010 15:55:21 +0100 Subject: [PATCH 0666/2822] exofs: Remove redundant unlikely() IS_ERR() already implies unlikely(), so it can be omitted here. Signed-off-by: Tobias Klauser --- fs/exofs/super.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/exofs/super.c b/fs/exofs/super.c index 8c6c4669b3816..78f5ad633d3b4 100644 --- a/fs/exofs/super.c +++ b/fs/exofs/super.c @@ -495,7 +495,7 @@ static int exofs_read_lookup_dev_table(struct exofs_sb_info **psbi, } od = osduld_info_lookup(&odi); - if (unlikely(IS_ERR(od))) { + if (IS_ERR(od)) { ret = PTR_ERR(od); EXOFS_ERR("ERROR: device requested is not found " "osd_name-%s =>%d\n", odi.osdname, ret); -- GitLab From 0a935519cca83f26dc15e7577fa6c2b39606a4ac Mon Sep 17 00:00:00 2001 From: Boaz Harrosh Date: Tue, 26 Oct 2010 17:52:41 +0200 Subject: [PATCH 0667/2822] exofs: Trivial: fix some indentation and debug prints I stumbled on some of these prints in log files so, might just submit the fixes. * All i_ino prints in exofs should be hex * All OSD_ERR prints should end with a "\n" Signed-off-by: Boaz Harrosh --- fs/exofs/dir.c | 33 ++++++++++++++++++--------------- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/fs/exofs/dir.c b/fs/exofs/dir.c index dcc941d82d67d..d0941c6a1f72e 100644 --- a/fs/exofs/dir.c +++ b/fs/exofs/dir.c @@ -124,7 +124,7 @@ out: Ebadsize: EXOFS_ERR("ERROR [exofs_check_page]: " - "size of directory #%lu is not a multiple of chunk size", + "size of directory(0x%lx) is not a multiple of chunk size\n", dir->i_ino ); goto fail; @@ -142,8 +142,8 @@ Espan: goto bad_entry; bad_entry: EXOFS_ERR( - "ERROR [exofs_check_page]: bad entry in directory #%lu: %s - " - "offset=%lu, inode=%llu, rec_len=%d, name_len=%d", + "ERROR [exofs_check_page]: bad entry in directory(0x%lx): %s - " + "offset=%lu, inode=0x%llu, rec_len=%d, name_len=%d\n", dir->i_ino, error, (page->index<inode_no)), rec_len, p->name_len); @@ -151,8 +151,8 @@ bad_entry: Eend: p = (struct exofs_dir_entry *)(kaddr + offs); EXOFS_ERR("ERROR [exofs_check_page]: " - "entry in directory #%lu spans the page boundary" - "offset=%lu, inode=%llu", + "entry in directory(0x%lx) spans the page boundary" + "offset=%lu, inode=0x%llx\n", dir->i_ino, (page->index<inode_no))); fail: @@ -261,9 +261,8 @@ exofs_readdir(struct file *filp, void *dirent, filldir_t filldir) struct page *page = exofs_get_page(inode, n); if (IS_ERR(page)) { - EXOFS_ERR("ERROR: " - "bad page in #%lu", - inode->i_ino); + EXOFS_ERR("ERROR: bad page in directory(0x%lx)\n", + inode->i_ino); filp->f_pos += PAGE_CACHE_SIZE - offset; return PTR_ERR(page); } @@ -283,7 +282,8 @@ exofs_readdir(struct file *filp, void *dirent, filldir_t filldir) for (; (char *)de <= limit; de = exofs_next_entry(de)) { if (de->rec_len == 0) { EXOFS_ERR("ERROR: " - "zero-length directory entry"); + "zero-length entry in directory(0x%lx)\n", + inode->i_ino); exofs_put_page(page); return -EIO; } @@ -342,9 +342,9 @@ struct exofs_dir_entry *exofs_find_entry(struct inode *dir, kaddr += exofs_last_byte(dir, n) - reclen; while ((char *) de <= kaddr) { if (de->rec_len == 0) { - EXOFS_ERR( - "ERROR: exofs_find_entry: " - "zero-length directory entry"); + EXOFS_ERR("ERROR: zero-length entry in " + "directory(0x%lx)\n", + dir->i_ino); exofs_put_page(page); goto out; } @@ -472,7 +472,8 @@ int exofs_add_link(struct dentry *dentry, struct inode *inode) } if (de->rec_len == 0) { EXOFS_ERR("ERROR: exofs_add_link: " - "zero-length directory entry"); + "zero-length entry in directory(0x%lx)\n", + inode->i_ino); err = -EIO; goto out_unlock; } @@ -491,7 +492,8 @@ int exofs_add_link(struct dentry *dentry, struct inode *inode) exofs_put_page(page); } - EXOFS_ERR("exofs_add_link: BAD dentry=%p or inode=%p", dentry, inode); + EXOFS_ERR("exofs_add_link: BAD dentry=%p or inode=0x%lx\n", + dentry, inode->i_ino); return -EINVAL; got_it: @@ -542,7 +544,8 @@ int exofs_delete_entry(struct exofs_dir_entry *dir, struct page *page) while (de < dir) { if (de->rec_len == 0) { EXOFS_ERR("ERROR: exofs_delete_entry:" - "zero-length directory entry"); + "zero-length entry in directory(0x%lx)\n", + inode->i_ino); err = -EIO; goto out; } -- GitLab From a8f1418f9e9bd4c487a7b703ff26c5dd5ceb2bf3 Mon Sep 17 00:00:00 2001 From: Boaz Harrosh Date: Mon, 22 Nov 2010 18:02:45 +0200 Subject: [PATCH 0668/2822] exofs: Optimize read_4_write Don't attempt a read passed i_size, just zero the page and be done with it. Signed-off-by: Boaz Harrosh --- fs/exofs/inode.c | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/fs/exofs/inode.c b/fs/exofs/inode.c index a7555238c41aa..c8f58a96e5978 100644 --- a/fs/exofs/inode.c +++ b/fs/exofs/inode.c @@ -350,8 +350,10 @@ static int readpage_strip(void *data, struct page *page) if (!pcol->read_4_write) unlock_page(page); - EXOFS_DBGMSG("readpage_strip(0x%lx, 0x%lx) empty page," - " splitting\n", inode->i_ino, page->index); + EXOFS_DBGMSG("readpage_strip(0x%lx) empty page len=%zx " + "read_4_write=%d index=0x%lx end_index=0x%lx " + "splitting\n", inode->i_ino, len, + pcol->read_4_write, page->index, end_index); return read_exec(pcol); } @@ -722,11 +724,28 @@ int exofs_write_begin(struct file *file, struct address_space *mapping, /* read modify write */ if (!PageUptodate(page) && (len != PAGE_CACHE_SIZE)) { + loff_t i_size = i_size_read(mapping->host); + pgoff_t end_index = i_size >> PAGE_CACHE_SHIFT; + size_t rlen; + + if (page->index < end_index) + rlen = PAGE_CACHE_SIZE; + else if (page->index == end_index) + rlen = i_size & ~PAGE_CACHE_MASK; + else + rlen = 0; + + if (!rlen) { + clear_highpage(page); + SetPageUptodate(page); + goto out; + } + ret = _readpage(page, true); if (ret) { /*SetPageError was done by _readpage. Is it ok?*/ unlock_page(page); - EXOFS_DBGMSG("__readpage_filler failed\n"); + EXOFS_DBGMSG("__readpage failed\n"); } } out: -- GitLab From 97178b7b6c84bd14660b89474d27931a1ea65c66 Mon Sep 17 00:00:00 2001 From: Nick Piggin Date: Thu, 25 Nov 2010 12:47:15 +0200 Subject: [PATCH 0669/2822] exofs: simple fsync race fix It is incorrect to test inode dirty bits without participating in the inode writeback protocol. Inode writeback sets I_SYNC and clears I_DIRTY_?, then writes out the particular bits, then clears I_SYNC when it is done. BTW. it may not completely write all pages out, so I_DIRTY_PAGES would get set again. This is a standard pattern used throughout the kernel's writeback caches (I_SYNC ~= I_WRITEBACK, if that makes it clearer). And so it is not possible to determine an inode's dirty status just by checking I_DIRTY bits. Especially not for the purpose of data integrity syncs. Missing the check for these bits means that fsync can complete while writeback to the inode is underway. Inode writeback functions get this right, so call into them rather than try to shortcut things by testing dirty state improperly. Signed-off-by: Nick Piggin Signed-off-by: Boaz Harrosh --- fs/exofs/file.c | 5 ----- fs/exofs/inode.c | 3 ++- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/fs/exofs/file.c b/fs/exofs/file.c index b905c79b4f0af..4c0d6bac91433 100644 --- a/fs/exofs/file.c +++ b/fs/exofs/file.c @@ -48,11 +48,6 @@ static int exofs_file_fsync(struct file *filp, int datasync) struct inode *inode = filp->f_mapping->host; struct super_block *sb; - if (!(inode->i_state & I_DIRTY)) - return 0; - if (datasync && !(inode->i_state & I_DIRTY_DATASYNC)) - return 0; - ret = sync_inode_metadata(inode, 1); /* This is a good place to write the sb */ diff --git a/fs/exofs/inode.c b/fs/exofs/inode.c index c8f58a96e5978..fb9d380561037 100644 --- a/fs/exofs/inode.c +++ b/fs/exofs/inode.c @@ -1290,7 +1290,8 @@ out: int exofs_write_inode(struct inode *inode, struct writeback_control *wbc) { - return exofs_update_inode(inode, wbc->sync_mode == WB_SYNC_ALL); + /* FIXME: fix fsync and use wbc->sync_mode == WB_SYNC_ALL */ + return exofs_update_inode(inode, 1); } /* -- GitLab From 66cd6cad4919f980dd21307d0150ff251762a264 Mon Sep 17 00:00:00 2001 From: "bharrosh@panasas.com" Date: Thu, 7 Oct 2010 14:28:18 -0400 Subject: [PATCH 0670/2822] exofs: Override read-ahead to align on stripe_size * Set all inode->i_mapping->backing_dev_info to point to the per super-block sb->s_bdi. * Calculating a read_ahead that is: - preferable 2 stripes long (Future patch will add a mount option to override this) - Minimum 128K aligned up to stripe-size - Caped to maximum-IO-sizes round down to stripe_size. (Max sizes are governed by max bio-size that fits in a page times number-of-devices) CC: Marc Dionne Signed-off-by: Boaz Harrosh --- fs/exofs/exofs.h | 2 ++ fs/exofs/inode.c | 19 +++++++++++++++---- fs/exofs/super.c | 18 ++++++++++++++++++ 3 files changed, 35 insertions(+), 4 deletions(-) diff --git a/fs/exofs/exofs.h b/fs/exofs/exofs.h index 2dc925fa10106..99fcb9126a970 100644 --- a/fs/exofs/exofs.h +++ b/fs/exofs/exofs.h @@ -256,6 +256,8 @@ static inline int exofs_oi_read(struct exofs_i_info *oi, } /* inode.c */ +unsigned exofs_max_io_pages(struct exofs_layout *layout, + unsigned expected_pages); int exofs_setattr(struct dentry *, struct iattr *); int exofs_write_begin(struct file *file, struct address_space *mapping, loff_t pos, unsigned len, unsigned flags, diff --git a/fs/exofs/inode.c b/fs/exofs/inode.c index fb9d380561037..681b3cb9b4d8b 100644 --- a/fs/exofs/inode.c +++ b/fs/exofs/inode.c @@ -43,6 +43,17 @@ enum { BIO_MAX_PAGES_KMALLOC = PAGE_SIZE / sizeof(struct page *), }; +unsigned exofs_max_io_pages(struct exofs_layout *layout, + unsigned expected_pages) +{ + unsigned pages = min_t(unsigned, expected_pages, MAX_PAGES_KMALLOC); + + /* TODO: easily support bio chaining */ + pages = min_t(unsigned, pages, + layout->group_width * BIO_MAX_PAGES_KMALLOC); + return pages; +} + struct page_collect { struct exofs_sb_info *sbi; struct inode *inode; @@ -97,8 +108,7 @@ static void _pcol_reset(struct page_collect *pcol) static int pcol_try_alloc(struct page_collect *pcol) { - unsigned pages = min_t(unsigned, pcol->expected_pages, - MAX_PAGES_KMALLOC); + unsigned pages; if (!pcol->ios) { /* First time allocate io_state */ int ret = exofs_get_io_state(&pcol->sbi->layout, &pcol->ios); @@ -108,8 +118,7 @@ static int pcol_try_alloc(struct page_collect *pcol) } /* TODO: easily support bio chaining */ - pages = min_t(unsigned, pages, - pcol->sbi->layout.group_width * BIO_MAX_PAGES_KMALLOC); + pages = exofs_max_io_pages(&pcol->sbi->layout, pcol->expected_pages); for (; pages; pages >>= 1) { pcol->pages = kmalloc(pages * sizeof(struct page *), @@ -1049,6 +1058,7 @@ struct inode *exofs_iget(struct super_block *sb, unsigned long ino) memcpy(oi->i_data, fcb.i_data, sizeof(fcb.i_data)); } + inode->i_mapping->backing_dev_info = sb->s_bdi; if (S_ISREG(inode->i_mode)) { inode->i_op = &exofs_file_inode_operations; inode->i_fop = &exofs_file_operations; @@ -1149,6 +1159,7 @@ struct inode *exofs_new_inode(struct inode *dir, int mode) sbi = sb->s_fs_info; + inode->i_mapping->backing_dev_info = sb->s_bdi; sb->s_dirt = 1; inode_init_owner(inode, dir, mode); inode->i_ino = sbi->s_nextid++; diff --git a/fs/exofs/super.c b/fs/exofs/super.c index 78f5ad633d3b4..e87510f4749e4 100644 --- a/fs/exofs/super.c +++ b/fs/exofs/super.c @@ -390,6 +390,23 @@ static int _read_and_match_data_map(struct exofs_sb_info *sbi, unsigned numdevs, return 0; } +static unsigned __ra_pages(struct exofs_layout *layout) +{ + const unsigned _MIN_RA = 32; /* min 128K read-ahead */ + unsigned ra_pages = layout->group_width * layout->stripe_unit / + PAGE_SIZE; + unsigned max_io_pages = exofs_max_io_pages(layout, ~0); + + ra_pages *= 2; /* two stripes */ + if (ra_pages < _MIN_RA) + ra_pages = roundup(_MIN_RA, ra_pages / 2); + + if (ra_pages > max_io_pages) + ra_pages = max_io_pages; + + return ra_pages; +} + /* @odi is valid only as long as @fscb_dev is valid */ static int exofs_devs_2_odi(struct exofs_dt_device_info *dt_dev, struct osd_dev_info *odi) @@ -623,6 +640,7 @@ static int exofs_fill_super(struct super_block *sb, void *data, int silent) } /* set up operation vectors */ + sbi->bdi.ra_pages = __ra_pages(&sbi->layout); sb->s_bdi = &sbi->bdi; sb->s_fs_info = sbi; sb->s_op = &exofs_sops; -- GitLab From 9ed96484311b89360b80a4181d856cbdb21630fd Mon Sep 17 00:00:00 2001 From: Boaz Harrosh Date: Mon, 31 Jan 2011 14:32:14 +0200 Subject: [PATCH 0671/2822] exofs: Add option to mount by osdname If /dev/osd* devices are shuffled because more devices where added, and/or login order has changed. It is hard to mount the FS you want. Add an option to mount by osdname. osdname is any osd-device's osdname as specified to the mkfs.exofs command when formatting the osd-devices. The new mount format is: OPT="osdname=$UUID0,pid=$PID,_netdev" mount -t exofs -o $OPT $DEV_OSD0 $MOUNTDIR if "osdname=" is specified in options above $DEV_OSD0 is ignored and can be empty. Also while at it: Removed some old unused Opt_* enums. Signed-off-by: Boaz Harrosh --- Documentation/filesystems/exofs.txt | 10 +++++++++- fs/exofs/super.c | 31 +++++++++++++++++++++++++---- 2 files changed, 36 insertions(+), 5 deletions(-) diff --git a/Documentation/filesystems/exofs.txt b/Documentation/filesystems/exofs.txt index abd2a9b5b787c..23583a136975c 100644 --- a/Documentation/filesystems/exofs.txt +++ b/Documentation/filesystems/exofs.txt @@ -104,7 +104,15 @@ Where: exofs specific options: Options are separated by commas (,) pid= - The partition number to mount/create as container of the filesystem. - This option is mandatory. + This option is mandatory. integer can be + Hex by pre-pending an 0x to the number. + osdname= - Mount by a device's osdname. + osdname is usually a 36 character uuid of the + form "d2683732-c906-4ee1-9dbd-c10c27bb40df". + It is one of the device's uuid specified in the + mkfs.exofs format command. + If this option is specified then the /dev/osdX + above can be empty and is ignored. to= - Timeout in ticks for a single command. default is (60 * HZ) [for debugging only] diff --git a/fs/exofs/super.c b/fs/exofs/super.c index e87510f4749e4..474989eeb7d64 100644 --- a/fs/exofs/super.c +++ b/fs/exofs/super.c @@ -48,6 +48,7 @@ * struct to hold what we get from mount options */ struct exofs_mountopt { + bool is_osdname; const char *dev_name; uint64_t pid; int timeout; @@ -56,7 +57,7 @@ struct exofs_mountopt { /* * exofs-specific mount-time options. */ -enum { Opt_pid, Opt_to, Opt_mkfs, Opt_format, Opt_err }; +enum { Opt_name, Opt_pid, Opt_to, Opt_err }; /* * Our mount-time options. These should ideally be 64-bit unsigned, but the @@ -64,6 +65,7 @@ enum { Opt_pid, Opt_to, Opt_mkfs, Opt_format, Opt_err }; * sufficient for most applications now. */ static match_table_t tokens = { + {Opt_name, "osdname=%s"}, {Opt_pid, "pid=%u"}, {Opt_to, "to=%u"}, {Opt_err, NULL} @@ -94,6 +96,14 @@ static int parse_options(char *options, struct exofs_mountopt *opts) token = match_token(p, tokens, args); switch (token) { + case Opt_name: + opts->dev_name = match_strdup(&args[0]); + if (unlikely(!opts->dev_name)) { + EXOFS_ERR("Error allocating dev_name"); + return -ENOMEM; + } + opts->is_osdname = true; + break; case Opt_pid: if (0 == match_strlcpy(str, &args[0], sizeof(str))) return -EINVAL; @@ -575,9 +585,17 @@ static int exofs_fill_super(struct super_block *sb, void *data, int silent) goto free_bdi; /* use mount options to fill superblock */ - od = osduld_path_lookup(opts->dev_name); + if (opts->is_osdname) { + struct osd_dev_info odi = {.systemid_len = 0}; + + odi.osdname_len = strlen(opts->dev_name); + odi.osdname = (u8 *)opts->dev_name; + od = osduld_info_lookup(&odi); + } else { + od = osduld_path_lookup(opts->dev_name); + } if (IS_ERR(od)) { - ret = PTR_ERR(od); + ret = -EINVAL; goto free_sbi; } @@ -670,6 +688,8 @@ static int exofs_fill_super(struct super_block *sb, void *data, int silent) _exofs_print_device("Mounting", opts->dev_name, sbi->layout.s_ods[0], sbi->layout.s_pid); + if (opts->is_osdname) + kfree(opts->dev_name); return 0; free_sbi: @@ -678,6 +698,8 @@ free_bdi: EXOFS_ERR("Unable to mount exofs on %s pid=0x%llx err=%d\n", opts->dev_name, sbi->layout.s_pid, ret); exofs_free_sbi(sbi); + if (opts->is_osdname) + kfree(opts->dev_name); return ret; } @@ -695,7 +717,8 @@ static struct dentry *exofs_mount(struct file_system_type *type, if (ret) return ERR_PTR(ret); - opts.dev_name = dev_name; + if (!opts.dev_name) + opts.dev_name = dev_name; return mount_nodev(type, flags, &opts, exofs_fill_super); } -- GitLab From 1cea312ad49d9cb964179a784fedb1fcfe396283 Mon Sep 17 00:00:00 2001 From: Boaz Harrosh Date: Thu, 3 Feb 2011 17:53:25 +0200 Subject: [PATCH 0672/2822] exofs: Write sbi->s_nextid as part of the Create command Before when creating a new inode, we'd set the sb->s_dirt flag, and sometime later the system would write out s_nextid as part of the sb_info. Also on inode sync we would force the sb sync as well. Define the s_nextid as a new partition attribute and set it every time we create a new object. At mount we read it from it's new place. We now never set sb->s_dirt anywhere in exofs. write_super is actually never called. The call to exofs_write_super from exofs_put_super is also removed because the VFS always calls ->sync_fs before calling ->put_super twice. To stay backward-and-forward compatible we also write the old s_nextid in the super_block object at unmount, and support zero length attribute on mount. This also fixes a BUG where in layouts when group_width was not a divisor of EXOFS_SUPER_ID (0x10000) the s_nextid was not read from the device it was written to. Because of the sliding window layout trick, and because the read was always done from the 0 device but the write was done via the raid engine that might slide the device view. Now we read and write through the raid engine. Signed-off-by: Boaz Harrosh --- fs/exofs/common.h | 18 ++++++- fs/exofs/exofs.h | 4 +- fs/exofs/file.c | 11 +--- fs/exofs/inode.c | 4 +- fs/exofs/super.c | 135 ++++++++++++++++++++++++++++++++++++++++------ 5 files changed, 141 insertions(+), 31 deletions(-) diff --git a/fs/exofs/common.h b/fs/exofs/common.h index f0d520312d8b6..5e74ad3d40090 100644 --- a/fs/exofs/common.h +++ b/fs/exofs/common.h @@ -53,10 +53,14 @@ #define EXOFS_ROOT_ID 0x10002 /* object ID for root directory */ /* exofs Application specific page/attribute */ +/* Inode attrs */ # define EXOFS_APAGE_FS_DATA (OSD_APAGE_APP_DEFINED_FIRST + 3) # define EXOFS_ATTR_INODE_DATA 1 # define EXOFS_ATTR_INODE_FILE_LAYOUT 2 # define EXOFS_ATTR_INODE_DIR_LAYOUT 3 +/* Partition attrs */ +# define EXOFS_APAGE_SB_DATA (0xF0000000U + 3) +# define EXOFS_ATTR_SB_STATS 1 /* * The maximum number of files we can have is limited by the size of the @@ -86,8 +90,8 @@ enum { */ enum {EXOFS_FSCB_VER = 1, EXOFS_DT_VER = 1}; struct exofs_fscb { - __le64 s_nextid; /* Highest object ID used */ - __le64 s_numfiles; /* Number of files on fs */ + __le64 s_nextid; /* Only used after mkfs */ + __le64 s_numfiles; /* Only used after mkfs */ __le32 s_version; /* == EXOFS_FSCB_VER */ __le16 s_magic; /* Magic signature */ __le16 s_newfs; /* Non-zero if this is a new fs */ @@ -97,6 +101,16 @@ struct exofs_fscb { __le64 s_dev_table_count; /* == 0 means no dev_table */ } __packed; +/* + * This struct is set on the FS partition's attributes. + * [EXOFS_APAGE_SB_DATA, EXOFS_ATTR_SB_STATS] and is written together + * with the create command, to atomically persist the sb writeable information. + */ +struct exofs_sb_stats { + __le64 s_nextid; /* Highest object ID used */ + __le64 s_numfiles; /* Number of files on fs */ +} __packed; + /* * Describes the raid used in the FS. It is part of the device table. * This here is taken from the pNFS-objects definition. In exofs we diff --git a/fs/exofs/exofs.h b/fs/exofs/exofs.h index 99fcb9126a970..c965806c2821c 100644 --- a/fs/exofs/exofs.h +++ b/fs/exofs/exofs.h @@ -77,7 +77,7 @@ struct exofs_layout { * our extension to the in-memory superblock */ struct exofs_sb_info { - struct exofs_fscb s_fscb; /* Written often, pre-allocate*/ + struct exofs_sb_stats s_ess; /* Written often, pre-allocate*/ int s_timeout; /* timeout for OSD operations */ uint64_t s_nextid; /* highest object ID used */ uint32_t s_numfiles; /* number of files on fs */ @@ -281,7 +281,7 @@ int exofs_set_link(struct inode *, struct exofs_dir_entry *, struct page *, struct inode *); /* super.c */ -int exofs_sync_fs(struct super_block *sb, int wait); +int exofs_sbi_write_stats(struct exofs_sb_info *sbi); /********************* * operation vectors * diff --git a/fs/exofs/file.c b/fs/exofs/file.c index 4c0d6bac91433..45ca323d83634 100644 --- a/fs/exofs/file.c +++ b/fs/exofs/file.c @@ -45,17 +45,8 @@ static int exofs_release_file(struct inode *inode, struct file *filp) static int exofs_file_fsync(struct file *filp, int datasync) { int ret; - struct inode *inode = filp->f_mapping->host; - struct super_block *sb; - - ret = sync_inode_metadata(inode, 1); - - /* This is a good place to write the sb */ - /* TODO: Sechedule an sb-sync on create */ - sb = inode->i_sb; - if (sb->s_dirt) - exofs_sync_fs(sb, 1); + ret = sync_inode_metadata(filp->f_mapping->host, 1); return ret; } diff --git a/fs/exofs/inode.c b/fs/exofs/inode.c index 681b3cb9b4d8b..0c713cfbebf06 100644 --- a/fs/exofs/inode.c +++ b/fs/exofs/inode.c @@ -1102,6 +1102,7 @@ int __exofs_wait_obj_created(struct exofs_i_info *oi) } return unlikely(is_bad_inode(&oi->vfs_inode)) ? -EIO : 0; } + /* * Callback function from exofs_new_inode(). The important thing is that we * set the obj_created flag so that other methods know that the object exists on @@ -1160,7 +1161,6 @@ struct inode *exofs_new_inode(struct inode *dir, int mode) sbi = sb->s_fs_info; inode->i_mapping->backing_dev_info = sb->s_bdi; - sb->s_dirt = 1; inode_init_owner(inode, dir, mode); inode->i_ino = sbi->s_nextid++; inode->i_blkbits = EXOFS_BLKSHIFT; @@ -1171,6 +1171,8 @@ struct inode *exofs_new_inode(struct inode *dir, int mode) spin_unlock(&sbi->s_next_gen_lock); insert_inode_hash(inode); + exofs_sbi_write_stats(sbi); /* Make sure new sbi->s_nextid is on disk */ + mark_inode_dirty(inode); ret = exofs_get_io_state(&sbi->layout, &ios); diff --git a/fs/exofs/super.c b/fs/exofs/super.c index 474989eeb7d64..5eb0851e54810 100644 --- a/fs/exofs/super.c +++ b/fs/exofs/super.c @@ -213,6 +213,101 @@ static void destroy_inodecache(void) static const struct super_operations exofs_sops; static const struct export_operations exofs_export_ops; +static const struct osd_attr g_attr_sb_stats = ATTR_DEF( + EXOFS_APAGE_SB_DATA, + EXOFS_ATTR_SB_STATS, + sizeof(struct exofs_sb_stats)); + +static int __sbi_read_stats(struct exofs_sb_info *sbi) +{ + struct osd_attr attrs[] = { + [0] = g_attr_sb_stats, + }; + struct exofs_io_state *ios; + int ret; + + ret = exofs_get_io_state(&sbi->layout, &ios); + if (unlikely(ret)) { + EXOFS_ERR("%s: exofs_get_io_state failed.\n", __func__); + return ret; + } + + ios->cred = sbi->s_cred; + + ios->in_attr = attrs; + ios->in_attr_len = ARRAY_SIZE(attrs); + + ret = exofs_sbi_read(ios); + if (unlikely(ret)) { + EXOFS_ERR("Error reading super_block stats => %d\n", ret); + goto out; + } + + ret = extract_attr_from_ios(ios, &attrs[0]); + if (ret) { + EXOFS_ERR("%s: extract_attr of sb_stats failed\n", __func__); + goto out; + } + if (attrs[0].len) { + struct exofs_sb_stats *ess; + + if (unlikely(attrs[0].len != sizeof(*ess))) { + EXOFS_ERR("%s: Wrong version of exofs_sb_stats " + "size(%d) != expected(%zd)\n", + __func__, attrs[0].len, sizeof(*ess)); + goto out; + } + + ess = attrs[0].val_ptr; + sbi->s_nextid = le64_to_cpu(ess->s_nextid); + sbi->s_numfiles = le32_to_cpu(ess->s_numfiles); + } + +out: + exofs_put_io_state(ios); + return ret; +} + +static void stats_done(struct exofs_io_state *ios, void *p) +{ + exofs_put_io_state(ios); + /* Good thanks nothing to do anymore */ +} + +/* Asynchronously write the stats attribute */ +int exofs_sbi_write_stats(struct exofs_sb_info *sbi) +{ + struct osd_attr attrs[] = { + [0] = g_attr_sb_stats, + }; + struct exofs_io_state *ios; + int ret; + + ret = exofs_get_io_state(&sbi->layout, &ios); + if (unlikely(ret)) { + EXOFS_ERR("%s: exofs_get_io_state failed.\n", __func__); + return ret; + } + + sbi->s_ess.s_nextid = cpu_to_le64(sbi->s_nextid); + sbi->s_ess.s_numfiles = cpu_to_le64(sbi->s_numfiles); + attrs[0].val_ptr = &sbi->s_ess; + + ios->cred = sbi->s_cred; + ios->done = stats_done; + ios->private = sbi; + ios->out_attr = attrs; + ios->out_attr_len = ARRAY_SIZE(attrs); + + ret = exofs_sbi_write(ios); + if (unlikely(ret)) { + EXOFS_ERR("%s: exofs_sbi_write failed.\n", __func__); + exofs_put_io_state(ios); + } + + return ret; +} + /* * Write the superblock to the OSD */ @@ -223,18 +318,25 @@ int exofs_sync_fs(struct super_block *sb, int wait) struct exofs_io_state *ios; int ret = -ENOMEM; - lock_super(sb); + fscb = kmalloc(sizeof(*fscb), GFP_KERNEL); + if (unlikely(!fscb)) + return -ENOMEM; + sbi = sb->s_fs_info; - fscb = &sbi->s_fscb; + /* NOTE: We no longer dirty the super_block anywhere in exofs. The + * reason we write the fscb here on unmount is so we can stay backwards + * compatible with fscb->s_version == 1. (What we are not compatible + * with is if a new version FS crashed and then we try to mount an old + * version). Otherwise the exofs_fscb is read-only from mkfs time. All + * the writeable info is set in exofs_sbi_write_stats() above. + */ ret = exofs_get_io_state(&sbi->layout, &ios); - if (ret) + if (unlikely(ret)) goto out; - /* Note: We only write the changing part of the fscb. .i.e upto the - * the fscb->s_dev_table_oid member. There is no read-modify-write - * here. - */ + lock_super(sb); + ios->length = offsetof(struct exofs_fscb, s_dev_table_oid); memset(fscb, 0, ios->length); fscb->s_nextid = cpu_to_le64(sbi->s_nextid); @@ -249,16 +351,17 @@ int exofs_sync_fs(struct super_block *sb, int wait) ios->cred = sbi->s_cred; ret = exofs_sbi_write(ios); - if (unlikely(ret)) { + if (unlikely(ret)) EXOFS_ERR("%s: exofs_sbi_write failed.\n", __func__); - goto out; - } - sb->s_dirt = 0; + else + sb->s_dirt = 0; + + unlock_super(sb); out: EXOFS_DBGMSG("s_nextid=0x%llx ret=%d\n", _LLU(sbi->s_nextid), ret); exofs_put_io_state(ios); - unlock_super(sb); + kfree(fscb); return ret; } @@ -302,9 +405,6 @@ static void exofs_put_super(struct super_block *sb) int num_pend; struct exofs_sb_info *sbi = sb->s_fs_info; - if (sb->s_dirt) - exofs_write_super(sb); - /* make sure there are no pending commands */ for (num_pend = atomic_read(&sbi->s_curr_pending); num_pend > 0; num_pend = atomic_read(&sbi->s_curr_pending)) { @@ -629,6 +729,7 @@ static int exofs_fill_super(struct super_block *sb, void *data, int silent) goto free_sbi; sb->s_magic = le16_to_cpu(fscb.s_magic); + /* NOTE: we read below to be backward compatible with old versions */ sbi->s_nextid = le64_to_cpu(fscb.s_nextid); sbi->s_numfiles = le32_to_cpu(fscb.s_numfiles); @@ -639,7 +740,7 @@ static int exofs_fill_super(struct super_block *sb, void *data, int silent) ret = -EINVAL; goto free_sbi; } - if (le32_to_cpu(fscb.s_version) != EXOFS_FSCB_VER) { + if (le32_to_cpu(fscb.s_version) > EXOFS_FSCB_VER) { EXOFS_ERR("ERROR: Bad FSCB version expected-%d got-%d\n", EXOFS_FSCB_VER, le32_to_cpu(fscb.s_version)); ret = -EINVAL; @@ -657,6 +758,8 @@ static int exofs_fill_super(struct super_block *sb, void *data, int silent) goto free_sbi; } + __sbi_read_stats(sbi); + /* set up operation vectors */ sbi->bdi.ra_pages = __ra_pages(&sbi->layout); sb->s_bdi = &sbi->bdi; -- GitLab From a49fb4c3d035ab516507b31ec3bd49263caee14d Mon Sep 17 00:00:00 2001 From: Boaz Harrosh Date: Mon, 7 Feb 2011 18:12:15 +0200 Subject: [PATCH 0673/2822] exofs: deprecate the commands pending counter One leftover from the days of IBM's original code, is an SB counter that counts in-flight asynchronous commands. And a piece of code that waits for the counter to reach zero at unmount. I guess it might have been needed then, cause of some reference missing or something. I'm not removing it yet but am putting a warning message if ever this counter triggers at unmount. If I'll never see it triggers or reported I'll remove the counter for good. (I had this print as a debug output for a long time and never had it trigger) Signed-off-by: Boaz Harrosh --- fs/exofs/super.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/fs/exofs/super.c b/fs/exofs/super.c index 5eb0851e54810..06065bd37fc33 100644 --- a/fs/exofs/super.c +++ b/fs/exofs/super.c @@ -409,6 +409,10 @@ static void exofs_put_super(struct super_block *sb) for (num_pend = atomic_read(&sbi->s_curr_pending); num_pend > 0; num_pend = atomic_read(&sbi->s_curr_pending)) { wait_queue_head_t wq; + + printk(KERN_NOTICE "%s: !!Pending operations in flight. " + "This is a BUG. please report to osd-dev@open-osd.org\n", + __func__); init_waitqueue_head(&wq); wait_event_timeout(wq, (atomic_read(&sbi->s_curr_pending) == 0), -- GitLab From b09734b1f4abd86e046777f0f268215b4ef1b523 Mon Sep 17 00:00:00 2001 From: Tommi Virtanen Date: Wed, 2 Feb 2011 11:39:32 -0800 Subject: [PATCH 0674/2822] libceph: Fix base64-decoding when input ends in newline. It used to return -EINVAL because it thought the end was not aligned to 4 bytes. Clean up superfluous src < end test in if, the while itself guarantees that. Signed-off-by: Tommi Virtanen Signed-off-by: Sage Weil --- net/ceph/armor.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/net/ceph/armor.c b/net/ceph/armor.c index eb2a666b0be70..1fc1ee11dfa28 100644 --- a/net/ceph/armor.c +++ b/net/ceph/armor.c @@ -78,8 +78,10 @@ int ceph_unarmor(char *dst, const char *src, const char *end) while (src < end) { int a, b, c, d; - if (src < end && src[0] == '\n') + if (src[0] == '\n') { src++; + continue; + } if (src + 4 > end) return -EINVAL; a = decode_bits(src[0]); -- GitLab From 09adc80c611bb8902daa8ccfe34dbbc009d6befe Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Fri, 4 Feb 2011 21:38:47 -0800 Subject: [PATCH 0675/2822] ceph: preserve I_COMPLETE across rename d_move puts the renamed dentry at the end of d_subdirs, screwing with our cached dentry directory offsets. We were just clearing I_COMPLETE to avoid any possibility of trouble. However, assigning the renamed dentry an offset at the end of the directory (to match it's new d_subdirs position) is sufficient to maintain correct behavior and hold onto I_COMPLETE. This is especially important for workloads like rsync, which renames files into place. Before, we would lose I_COMPLETE and do MDS lookups for each file. With this patch we only talk to the MDS on create and rename. Signed-off-by: Sage Weil --- fs/ceph/inode.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/fs/ceph/inode.c b/fs/ceph/inode.c index 193bfa5e9cbd7..60456361e07d3 100644 --- a/fs/ceph/inode.c +++ b/fs/ceph/inode.c @@ -1030,9 +1030,6 @@ int ceph_fill_trace(struct super_block *sb, struct ceph_mds_request *req, dout("fill_trace doing d_move %p -> %p\n", req->r_old_dentry, dn); - /* d_move screws up d_subdirs order */ - ceph_i_clear(dir, CEPH_I_COMPLETE); - d_move(req->r_old_dentry, dn); dout(" src %p '%.*s' dst %p '%.*s'\n", req->r_old_dentry, @@ -1044,12 +1041,15 @@ int ceph_fill_trace(struct super_block *sb, struct ceph_mds_request *req, rehashing bug in vfs_rename_dir */ ceph_invalidate_dentry_lease(dn); - /* take overwritten dentry's readdir offset */ - dout("dn %p gets %p offset %lld (old offset %lld)\n", - req->r_old_dentry, dn, ceph_dentry(dn)->offset, + /* + * d_move() puts the renamed dentry at the end of + * d_subdirs. We need to assign it an appropriate + * directory offset so we can behave when holding + * I_COMPLETE. + */ + ceph_set_dentry_offset(req->r_old_dentry); + dout("dn %p gets new offset %lld\n", req->r_old_dentry, ceph_dentry(req->r_old_dentry)->offset); - ceph_dentry(req->r_old_dentry)->offset = - ceph_dentry(dn)->offset; dn = req->r_old_dentry; /* use old_dentry */ in = dn->d_inode; -- GitLab From 709de99df0ecf3102e7728fbd876a3591859f423 Mon Sep 17 00:00:00 2001 From: Chuanxiao Dong Date: Sat, 22 Jan 2011 04:09:41 +0800 Subject: [PATCH 0676/2822] mmc: export eMMC4.4 enhanced area details to sysfs Enhanced area feature is a new feature defined in eMMC4.4 standard. This user data area provides higher performance/reliability, at the expense of using twice the effective media space due to the area using SLC. The MMC driver now reads out the enhanced area offset and size and adds them to the device attributes in sysfs. Enabling the enhanced area can only be done once, and should be done in manufacturing. To use this feature, bit ERASE_GRP_DEF should also be set. Documentation/ABI/testing/sysfs-devices-mmc describes the two new attributes. Signed-off-by: Chuanxiao Dong Reviewed-by: Chris Ball Signed-off-by: Chris Ball --- Documentation/ABI/testing/sysfs-devices-mmc | 21 ++++++ drivers/mmc/core/mmc.c | 74 +++++++++++++++++++++ include/linux/mmc/card.h | 3 + include/linux/mmc/mmc.h | 3 + 4 files changed, 101 insertions(+) create mode 100644 Documentation/ABI/testing/sysfs-devices-mmc diff --git a/Documentation/ABI/testing/sysfs-devices-mmc b/Documentation/ABI/testing/sysfs-devices-mmc new file mode 100644 index 0000000000000..5a50ab6558439 --- /dev/null +++ b/Documentation/ABI/testing/sysfs-devices-mmc @@ -0,0 +1,21 @@ +What: /sys/devices/.../mmc_host/mmcX/mmcX:XXXX/enhanced_area_offset +Date: January 2011 +Contact: Chuanxiao Dong +Description: + Enhanced area is a new feature defined in eMMC4.4 standard. + eMMC4.4 or later card can support such feature. This kind of + area can help to improve the card performance. If the feature + is enabled, this attribute will indicate the start address of + enhanced data area. If not, this attribute will be -EINVAL. + Unit Byte. Format decimal. + +What: /sys/devices/.../mmc_host/mmcX/mmcX:XXXX/enhanced_area_size +Date: January 2011 +Contact: Chuanxiao Dong +Description: + Enhanced area is a new feature defined in eMMC4.4 standard. + eMMC4.4 or later card can support such feature. This kind of + area can help to improve the card performance. If the feature + is enabled, this attribute will indicate the size of enhanced + data area. If not, this attribute will be -EINVAL. + Unit KByte. Format decimal. diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c index 16006ef153fe0..6396c5d98e853 100644 --- a/drivers/mmc/core/mmc.c +++ b/drivers/mmc/core/mmc.c @@ -302,6 +302,44 @@ static int mmc_read_ext_csd(struct mmc_card *card) } if (card->ext_csd.rev >= 4) { + /* + * Enhanced area feature support -- check whether the eMMC + * card has the Enhanced area enabled. If so, export enhanced + * area offset and size to user by adding sysfs interface. + */ + if ((ext_csd[EXT_CSD_PARTITION_SUPPORT] & 0x2) && + (ext_csd[EXT_CSD_PARTITION_ATTRIBUTE] & 0x1)) { + u8 hc_erase_grp_sz = + ext_csd[EXT_CSD_HC_ERASE_GRP_SIZE]; + u8 hc_wp_grp_sz = + ext_csd[EXT_CSD_HC_WP_GRP_SIZE]; + + card->ext_csd.enhanced_area_en = 1; + /* + * calculate the enhanced data area offset, in bytes + */ + card->ext_csd.enhanced_area_offset = + (ext_csd[139] << 24) + (ext_csd[138] << 16) + + (ext_csd[137] << 8) + ext_csd[136]; + if (mmc_card_blockaddr(card)) + card->ext_csd.enhanced_area_offset <<= 9; + /* + * calculate the enhanced data area size, in kilobytes + */ + card->ext_csd.enhanced_area_size = + (ext_csd[142] << 16) + (ext_csd[141] << 8) + + ext_csd[140]; + card->ext_csd.enhanced_area_size *= + (size_t)(hc_erase_grp_sz * hc_wp_grp_sz); + card->ext_csd.enhanced_area_size <<= 9; + } else { + /* + * If the enhanced area is not enabled, disable these + * device attributes. + */ + card->ext_csd.enhanced_area_offset = -EINVAL; + card->ext_csd.enhanced_area_size = -EINVAL; + } card->ext_csd.sec_trim_mult = ext_csd[EXT_CSD_SEC_TRIM_MULT]; card->ext_csd.sec_erase_mult = @@ -336,6 +374,9 @@ MMC_DEV_ATTR(manfid, "0x%06x\n", card->cid.manfid); MMC_DEV_ATTR(name, "%s\n", card->cid.prod_name); MMC_DEV_ATTR(oemid, "0x%04x\n", card->cid.oemid); MMC_DEV_ATTR(serial, "0x%08x\n", card->cid.serial); +MMC_DEV_ATTR(enhanced_area_offset, "%llu\n", + card->ext_csd.enhanced_area_offset); +MMC_DEV_ATTR(enhanced_area_size, "%u\n", card->ext_csd.enhanced_area_size); static struct attribute *mmc_std_attrs[] = { &dev_attr_cid.attr, @@ -349,6 +390,8 @@ static struct attribute *mmc_std_attrs[] = { &dev_attr_name.attr, &dev_attr_oemid.attr, &dev_attr_serial.attr, + &dev_attr_enhanced_area_offset.attr, + &dev_attr_enhanced_area_size.attr, NULL, }; @@ -483,6 +526,37 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr, mmc_set_erase_size(card); } + /* + * If enhanced_area_en is TRUE, host needs to enable ERASE_GRP_DEF + * bit. This bit will be lost everytime after a reset or power off. + */ + if (card->ext_csd.enhanced_area_en) { + err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, + EXT_CSD_ERASE_GROUP_DEF, 1); + + if (err && err != -EBADMSG) + goto free_card; + + if (err) { + err = 0; + /* + * Just disable enhanced area off & sz + * will try to enable ERASE_GROUP_DEF + * during next time reinit + */ + card->ext_csd.enhanced_area_offset = -EINVAL; + card->ext_csd.enhanced_area_size = -EINVAL; + } else { + card->ext_csd.erase_group_def = 1; + /* + * enable ERASE_GRP_DEF successfully. + * This will affect the erase size, so + * here need to reset erase size + */ + mmc_set_erase_size(card); + } + } + /* * Activate high speed (if supported) */ diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h index 8ce082781ccb4..4652cf9c5442d 100644 --- a/include/linux/mmc/card.h +++ b/include/linux/mmc/card.h @@ -54,6 +54,9 @@ struct mmc_ext_csd { unsigned int sec_trim_mult; /* Secure trim multiplier */ unsigned int sec_erase_mult; /* Secure erase multiplier */ unsigned int trim_timeout; /* In milliseconds */ + bool enhanced_area_en; /* enable bit */ + unsigned long long enhanced_area_offset; /* Units: Byte */ + unsigned int enhanced_area_size; /* Units: KB */ }; struct sd_scr { diff --git a/include/linux/mmc/mmc.h b/include/linux/mmc/mmc.h index 612301f85d144..264ba5451e3b9 100644 --- a/include/linux/mmc/mmc.h +++ b/include/linux/mmc/mmc.h @@ -253,6 +253,8 @@ struct _mmc_csd { * EXT_CSD fields */ +#define EXT_CSD_PARTITION_ATTRIBUTE 156 /* R/W */ +#define EXT_CSD_PARTITION_SUPPORT 160 /* RO */ #define EXT_CSD_ERASE_GROUP_DEF 175 /* R/W */ #define EXT_CSD_ERASED_MEM_CONT 181 /* RO */ #define EXT_CSD_BUS_WIDTH 183 /* R/W */ @@ -262,6 +264,7 @@ struct _mmc_csd { #define EXT_CSD_CARD_TYPE 196 /* RO */ #define EXT_CSD_SEC_CNT 212 /* RO, 4 bytes */ #define EXT_CSD_S_A_TIMEOUT 217 /* RO */ +#define EXT_CSD_HC_WP_GRP_SIZE 221 /* RO */ #define EXT_CSD_ERASE_TIMEOUT_MULT 223 /* RO */ #define EXT_CSD_HC_ERASE_GRP_SIZE 224 /* RO */ #define EXT_CSD_SEC_TRIM_MULT 229 /* RO */ -- GitLab From 3362177fe1b7c23ee8497ee720ab4d6f6ba0b840 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20H=C3=A9bert?= Date: Mon, 31 Jan 2011 12:31:24 -0500 Subject: [PATCH 0677/2822] mmc: Fix the block device read only flag While the MMC handled the card's read only flag correctly on open, it did not setup the flag in the allocated disk structure. The consequence being that probing the /sys/class/block/mmcblkX/ro attribute always reported 0. Signed-off-by: Marc-Andre Hebert Reviewed-by: Chris Ball Tested-by: Chris Ball Signed-off-by: Chris Ball --- drivers/mmc/card/block.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c index bfc8a8ae55df2..61d233a7c1180 100644 --- a/drivers/mmc/card/block.c +++ b/drivers/mmc/card/block.c @@ -621,6 +621,7 @@ static struct mmc_blk_data *mmc_blk_alloc(struct mmc_card *card) md->disk->private_data = md; md->disk->queue = md->queue.queue; md->disk->driverfs_dev = &card->dev; + set_disk_ro(md->disk, md->read_only); /* * As discussed on lkml, GENHD_FL_REMOVABLE should: -- GitLab From 732f0e31db03c84005578927ed9d4e996c3c0020 Mon Sep 17 00:00:00 2001 From: Kyungmin Park Date: Sat, 30 Oct 2010 12:58:56 +0900 Subject: [PATCH 0678/2822] mmc: sdhci-s3c: Auto CMD12 support Samsung SDHCI host controller supports the Auto CMD12. Signed-off-by: Kyungmin Park Signed-off-by: Chris Ball --- drivers/mmc/host/sdhci-s3c.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/mmc/host/sdhci-s3c.c b/drivers/mmc/host/sdhci-s3c.c index 5309ab95aada9..69e3ee321eb59 100644 --- a/drivers/mmc/host/sdhci-s3c.c +++ b/drivers/mmc/host/sdhci-s3c.c @@ -499,6 +499,9 @@ static int __devinit sdhci_s3c_probe(struct platform_device *pdev) * SDHCI block, or a missing configuration that needs to be set. */ host->quirks |= SDHCI_QUIRK_NO_BUSY_IRQ; + /* This host supports the Auto CMD12 */ + host->quirks |= SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12; + if (pdata->cd_type == S3C_SDHCI_CD_NONE || pdata->cd_type == S3C_SDHCI_CD_PERMANENT) host->quirks |= SDHCI_QUIRK_BROKEN_CARD_DETECTION; -- GitLab From 54d6b44a5f0da708e8a9e496df304e05e8748ef9 Mon Sep 17 00:00:00 2001 From: Pawel Moll Date: Sun, 6 Feb 2011 15:06:24 -0500 Subject: [PATCH 0679/2822] mmc: mmc_test: Only warn about not waiting for busy if it's supported If the MMC host controller does not support waiting for card signaling busy state (MMC_CAP_WAIT_WHILE_BUSY cap), there is no point in prining the relevant warning message. Signed-off-by: Pawel Moll Reviewed-by: Matt Fleming Signed-off-by: Chris Ball --- drivers/mmc/card/mmc_test.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/mmc/card/mmc_test.c b/drivers/mmc/card/mmc_test.c index 21adc27f41328..0131c6c0d8f6f 100644 --- a/drivers/mmc/card/mmc_test.c +++ b/drivers/mmc/card/mmc_test.c @@ -226,9 +226,10 @@ static int mmc_test_wait_busy(struct mmc_test_card *test) if (!busy && mmc_test_busy(&cmd)) { busy = 1; - printk(KERN_INFO "%s: Warning: Host did not " - "wait for busy state to end.\n", - mmc_hostname(test->card->host)); + if (test->card->host->caps & MMC_CAP_WAIT_WHILE_BUSY) + printk(KERN_INFO "%s: Warning: Host did not " + "wait for busy state to end.\n", + mmc_hostname(test->card->host)); } } while (mmc_test_busy(&cmd)); -- GitLab From 66c036e0142fed2484d58a2d3c7a4d21ba32b6a6 Mon Sep 17 00:00:00 2001 From: Pierre Tardy Date: Sun, 6 Feb 2011 19:02:48 +0100 Subject: [PATCH 0680/2822] mmc: put the led blinking code after clock ungating Since mmc clock gating can also be used as a power gating tip, it's better to put the led blinking after having ungated the clock. Signed-off-by: Pierre Tardy Acked-by: Linus Walleij Signed-off-by: Chris Ball --- drivers/mmc/core/core.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index 150b5f3cd401a..2af2ee1a2265a 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c @@ -167,8 +167,6 @@ mmc_start_request(struct mmc_host *host, struct mmc_request *mrq) WARN_ON(!host->claimed); - led_trigger_event(host->led, LED_FULL); - mrq->cmd->error = 0; mrq->cmd->mrq = mrq; if (mrq->data) { @@ -194,6 +192,7 @@ mmc_start_request(struct mmc_host *host, struct mmc_request *mrq) } } mmc_host_clk_ungate(host); + led_trigger_event(host->led, LED_FULL); host->ops->request(host, mrq); } -- GitLab From 57f0adc7eaaf4315d568e72069dbe48aa7e20995 Mon Sep 17 00:00:00 2001 From: Pierre Tardy Date: Sun, 6 Feb 2011 19:03:46 +0100 Subject: [PATCH 0681/2822] mmc: add per device quirk placeholder Some cards have quirks valid for every platforms using current platform quirk hooks leads to a lot of code and debug duplication. So we inspire a bit from what exists in PCI subsystem and do our own per vendorid/deviceid quirk. We still drop the complexity of the pci quirk system (with special section tables, and so on). That can be added later if needed. Signed-off-by: Pierre Tardy Acked-by: Linus Walleij Acked-by: Ohad Ben-Cohen Signed-off-by: Chris Ball --- drivers/mmc/core/Makefile | 3 +- drivers/mmc/core/core.h | 2 ++ drivers/mmc/core/quirks.c | 61 +++++++++++++++++++++++++++++++++++++++ drivers/mmc/core/sdio.c | 1 + include/linux/mmc/card.h | 2 ++ 5 files changed, 68 insertions(+), 1 deletion(-) create mode 100644 drivers/mmc/core/quirks.c diff --git a/drivers/mmc/core/Makefile b/drivers/mmc/core/Makefile index 86b4791193326..639501970b412 100644 --- a/drivers/mmc/core/Makefile +++ b/drivers/mmc/core/Makefile @@ -6,6 +6,7 @@ obj-$(CONFIG_MMC) += mmc_core.o mmc_core-y := core.o bus.o host.o \ mmc.o mmc_ops.o sd.o sd_ops.o \ sdio.o sdio_ops.o sdio_bus.o \ - sdio_cis.o sdio_io.o sdio_irq.o + sdio_cis.o sdio_io.o sdio_irq.o \ + quirks.o mmc_core-$(CONFIG_DEBUG_FS) += debugfs.o diff --git a/drivers/mmc/core/core.h b/drivers/mmc/core/core.h index ca1fdde29df6c..20b1c0831eac8 100644 --- a/drivers/mmc/core/core.h +++ b/drivers/mmc/core/core.h @@ -61,6 +61,8 @@ int mmc_attach_mmc(struct mmc_host *host); int mmc_attach_sd(struct mmc_host *host); int mmc_attach_sdio(struct mmc_host *host); +void mmc_fixup_device(struct mmc_card *card); + /* Module parameters */ extern int use_spi_crc; diff --git a/drivers/mmc/core/quirks.c b/drivers/mmc/core/quirks.c new file mode 100644 index 0000000000000..e18cb49c12b17 --- /dev/null +++ b/drivers/mmc/core/quirks.c @@ -0,0 +1,61 @@ +/* + * This file contains work-arounds for many known sdio hardware + * bugs. + * + * Copyright (c) 2011 Pierre Tardy + * Inspired from pci fixup code: + * Copyright (c) 1999 Martin Mares + * + */ + +#include +#include +#include +#include + +/* + * The world is not perfect and supplies us with broken mmc/sdio devices. + * For at least a part of these bugs we need a work-around + */ + +struct mmc_fixup { + u16 vendor, device; /* You can use SDIO_ANY_ID here of course */ + void (*vendor_fixup)(struct mmc_card *card, int data); + int data; +}; + +/* + * This hook just adds a quirk unconditionnally + */ +static void __maybe_unused add_quirk(struct mmc_card *card, int data) +{ + card->quirks |= data; +} + +/* + * This hook just removes a quirk unconditionnally + */ +static void __maybe_unused remove_quirk(struct mmc_card *card, int data) +{ + card->quirks &= ~data; +} + +static const struct mmc_fixup mmc_fixup_methods[] = { + { 0 } +}; + +void mmc_fixup_device(struct mmc_card *card) +{ + const struct mmc_fixup *f; + + for (f = mmc_fixup_methods; f->vendor_fixup; f++) { + if ((f->vendor == card->cis.vendor + || f->vendor == (u16) SDIO_ANY_ID) && + (f->device == card->cis.device + || f->device == (u16) SDIO_ANY_ID)) { + dev_dbg(&card->dev, "calling %pF\n", f->vendor_fixup); + f->vendor_fixup(card, f->data); + } + } +} +EXPORT_SYMBOL(mmc_fixup_device); diff --git a/drivers/mmc/core/sdio.c b/drivers/mmc/core/sdio.c index ebc62ad4cc567..c9fbb777440df 100644 --- a/drivers/mmc/core/sdio.c +++ b/drivers/mmc/core/sdio.c @@ -458,6 +458,7 @@ static int mmc_sdio_init_card(struct mmc_host *host, u32 ocr, card = oldcard; } + mmc_fixup_device(card); if (card->type == MMC_TYPE_SD_COMBO) { err = mmc_sd_setup_card(host, card, oldcard != NULL); diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h index 4652cf9c5442d..ad7413854f79f 100644 --- a/include/linux/mmc/card.h +++ b/include/linux/mmc/card.h @@ -151,6 +151,8 @@ struct mmc_card { struct dentry *debugfs_root; }; +void mmc_fixup_device(struct mmc_card *dev); + #define mmc_card_mmc(c) ((c)->type == MMC_TYPE_MMC) #define mmc_card_sd(c) ((c)->type == MMC_TYPE_SD) #define mmc_card_sdio(c) ((c)->type == MMC_TYPE_SDIO) -- GitLab From db9935000d95ae3f9702b7ff6ac0eef2319d8772 Mon Sep 17 00:00:00 2001 From: Pierre Tardy Date: Sun, 6 Feb 2011 19:03:47 +0100 Subject: [PATCH 0682/2822] mmc: add MMC_QUIRK_BROKEN_CLK_GATING Some sdio card are not following sdio standard, and do not work when the sdio bus's clock is gated. To keep functionnality for all legacy driver, we turn this quirk on for every sdio card. Drivers needs to disable the quirk manually when someone verifies that their supported card works with clock gating. Signed-off-by: Pierre Tardy Acked-by: Ohad Ben-Cohen Signed-off-by: Chris Ball --- drivers/mmc/core/host.c | 5 +---- drivers/mmc/core/quirks.c | 13 +++++++++++++ include/linux/mmc/card.h | 1 + 3 files changed, 15 insertions(+), 4 deletions(-) diff --git a/drivers/mmc/core/host.c b/drivers/mmc/core/host.c index b3ac6c5bc5c62..461e6a17fb90e 100644 --- a/drivers/mmc/core/host.c +++ b/drivers/mmc/core/host.c @@ -160,10 +160,7 @@ static bool mmc_host_may_gate_card(struct mmc_card *card) * gate the clock, because there is somebody out there that may still * be using it. */ - if (mmc_card_sdio(card)) - return false; - - return true; + return !(card->quirks & MMC_QUIRK_BROKEN_CLK_GATING); } /** diff --git a/drivers/mmc/core/quirks.c b/drivers/mmc/core/quirks.c index e18cb49c12b17..890843129e3b3 100644 --- a/drivers/mmc/core/quirks.c +++ b/drivers/mmc/core/quirks.c @@ -40,7 +40,20 @@ static void __maybe_unused remove_quirk(struct mmc_card *card, int data) card->quirks &= ~data; } +/* + * This hook just adds a quirk for all sdio devices + */ +static void add_quirk_for_sdio_devices(struct mmc_card *card, int data) +{ + if (mmc_card_sdio(card)) + card->quirks |= data; +} + static const struct mmc_fixup mmc_fixup_methods[] = { + /* by default sdio devices are considered CLK_GATING broken */ + /* good cards will be whitelisted as they are tested */ + { SDIO_ANY_ID, SDIO_ANY_ID, + add_quirk_for_sdio_devices, MMC_QUIRK_BROKEN_CLK_GATING } { 0 } }; diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h index ad7413854f79f..adb4888248be9 100644 --- a/include/linux/mmc/card.h +++ b/include/linux/mmc/card.h @@ -124,6 +124,7 @@ struct mmc_card { /* for byte mode */ #define MMC_QUIRK_NONSTD_SDIO (1<<2) /* non-standard SDIO card attached */ /* (missing CIA registers) */ +#define MMC_QUIRK_BROKEN_CLK_GATING (1<<3) /* clock gating the sdio bus will make card fail */ unsigned int erase_size; /* erase size in sectors */ unsigned int erase_shift; /* if erase unit is power 2 */ -- GitLab From 12f8ef8fb21f3b410b28eb57fc79bfe71232512a Mon Sep 17 00:00:00 2001 From: Pierre Tardy Date: Sun, 6 Feb 2011 19:04:17 +0100 Subject: [PATCH 0683/2822] mmc: remove BROKEN_CLK_GATING quirk for wl1271 This sdio card supports having its sdio clock shutdown. It is also not using the SDIO IRQ, but rather uses a side gpio irq. Signed-off-by: Pierre Tardy Signed-off-by: Chris Ball --- drivers/mmc/core/quirks.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/drivers/mmc/core/quirks.c b/drivers/mmc/core/quirks.c index 890843129e3b3..11118b74eb20d 100644 --- a/drivers/mmc/core/quirks.c +++ b/drivers/mmc/core/quirks.c @@ -49,11 +49,21 @@ static void add_quirk_for_sdio_devices(struct mmc_card *card, int data) card->quirks |= data; } +#ifndef SDIO_VENDOR_ID_TI +#define SDIO_VENDOR_ID_TI 0x0097 +#endif + +#ifndef SDIO_DEVICE_ID_TI_WL1271 +#define SDIO_DEVICE_ID_TI_WL1271 0x4076 +#endif + static const struct mmc_fixup mmc_fixup_methods[] = { /* by default sdio devices are considered CLK_GATING broken */ /* good cards will be whitelisted as they are tested */ { SDIO_ANY_ID, SDIO_ANY_ID, - add_quirk_for_sdio_devices, MMC_QUIRK_BROKEN_CLK_GATING } + add_quirk_for_sdio_devices, MMC_QUIRK_BROKEN_CLK_GATING }, + { SDIO_VENDOR_ID_TI, SDIO_DEVICE_ID_TI_WL1271, + remove_quirk, MMC_QUIRK_BROKEN_CLK_GATING }, { 0 } }; -- GitLab From 0532ff6358ae00615cfba7212f5075356b437c66 Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Tue, 8 Feb 2011 13:41:01 +0200 Subject: [PATCH 0684/2822] mmc: mmc_test: make performance test area size about 4MiB The test area size was set to the preferred erase size but for comparison purposes it is better if it is the same size for different devices. Make it a multiple of preferred erase size that is greater than or equal to 4MiB. Signed-off-by: Adrian Hunter Signed-off-by: Chris Ball --- drivers/mmc/card/mmc_test.c | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/drivers/mmc/card/mmc_test.c b/drivers/mmc/card/mmc_test.c index 0131c6c0d8f6f..ec6060c06ce89 100644 --- a/drivers/mmc/card/mmc_test.c +++ b/drivers/mmc/card/mmc_test.c @@ -1426,28 +1426,29 @@ static int mmc_test_area_cleanup(struct mmc_test_card *test) } /* - * Initialize an area for testing large transfers. The size of the area is the - * preferred erase size which is a good size for optimal transfer speed. Note - * that is typically 4MiB for modern cards. The test area is set to the middle - * of the card because cards may have different charateristics at the front - * (for FAT file system optimization). Optionally, the area is erased (if the - * card supports it) which may improve write performance. Optionally, the area - * is filled with data for subsequent read tests. + * Initialize an area for testing large transfers. The test area is set to the + * middle of the card because cards may have different charateristics at the + * front (for FAT file system optimization). Optionally, the area is erased + * (if the card supports it) which may improve write performance. Optionally, + * the area is filled with data for subsequent read tests. */ static int mmc_test_area_init(struct mmc_test_card *test, int erase, int fill) { struct mmc_test_area *t = &test->area; - unsigned long min_sz = 64 * 1024; + unsigned long min_sz = 64 * 1024, sz; int ret; ret = mmc_test_set_blksize(test, 512); if (ret) return ret; - if (test->card->pref_erase > TEST_AREA_MAX_SIZE >> 9) - t->max_sz = TEST_AREA_MAX_SIZE; - else - t->max_sz = (unsigned long)test->card->pref_erase << 9; + /* Make the test area size about 4MiB */ + sz = (unsigned long)test->card->pref_erase << 9; + t->max_sz = sz; + while (t->max_sz < 4 * 1024 * 1024) + t->max_sz += sz; + while (t->max_sz > TEST_AREA_MAX_SIZE && t->max_sz > sz) + t->max_sz -= sz; t->max_segs = test->card->host->max_segs; t->max_seg_sz = test->card->host->max_seg_size; -- GitLab From b6056d12342f936256cbf64c86459af06f11cd5e Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Tue, 8 Feb 2011 13:41:02 +0200 Subject: [PATCH 0685/2822] mmc: mmc_test: add tests to measure random I/O operations per second Existing performance tests measure single or sequential I/O speed. Add two random I/O tests: 33. Random read performance by transfer size 34. Random write performance by transfer size Signed-off-by: Adrian Hunter Signed-off-by: Chris Ball --- drivers/mmc/card/mmc_test.c | 139 +++++++++++++++++++++++++++++++++--- 1 file changed, 128 insertions(+), 11 deletions(-) diff --git a/drivers/mmc/card/mmc_test.c b/drivers/mmc/card/mmc_test.c index ec6060c06ce89..d1aa57a4d0582 100644 --- a/drivers/mmc/card/mmc_test.c +++ b/drivers/mmc/card/mmc_test.c @@ -88,6 +88,7 @@ struct mmc_test_area { * @sectors: amount of sectors to check in one group * @ts: time values of transfer * @rate: calculated transfer rate + * @iops: I/O operations per second (times 100) */ struct mmc_test_transfer_result { struct list_head link; @@ -95,6 +96,7 @@ struct mmc_test_transfer_result { unsigned int sectors; struct timespec ts; unsigned int rate; + unsigned int iops; }; /** @@ -495,7 +497,7 @@ static unsigned int mmc_test_rate(uint64_t bytes, struct timespec *ts) */ static void mmc_test_save_transfer_result(struct mmc_test_card *test, unsigned int count, unsigned int sectors, struct timespec ts, - unsigned int rate) + unsigned int rate, unsigned int iops) { struct mmc_test_transfer_result *tr; @@ -510,6 +512,7 @@ static void mmc_test_save_transfer_result(struct mmc_test_card *test, tr->sectors = sectors; tr->ts = ts; tr->rate = rate; + tr->iops = iops; list_add_tail(&tr->link, &test->gr->tr_lst); } @@ -520,20 +523,22 @@ static void mmc_test_save_transfer_result(struct mmc_test_card *test, static void mmc_test_print_rate(struct mmc_test_card *test, uint64_t bytes, struct timespec *ts1, struct timespec *ts2) { - unsigned int rate, sectors = bytes >> 9; + unsigned int rate, iops, sectors = bytes >> 9; struct timespec ts; ts = timespec_sub(*ts2, *ts1); rate = mmc_test_rate(bytes, &ts); + iops = mmc_test_rate(100, &ts); /* I/O ops per sec x 100 */ printk(KERN_INFO "%s: Transfer of %u sectors (%u%s KiB) took %lu.%09lu " - "seconds (%u kB/s, %u KiB/s)\n", + "seconds (%u kB/s, %u KiB/s, %u.%02u IOPS)\n", mmc_hostname(test->card->host), sectors, sectors >> 1, (sectors & 1 ? ".5" : ""), (unsigned long)ts.tv_sec, - (unsigned long)ts.tv_nsec, rate / 1000, rate / 1024); + (unsigned long)ts.tv_nsec, rate / 1000, rate / 1024, + iops / 100, iops % 100); - mmc_test_save_transfer_result(test, 1, sectors, ts, rate); + mmc_test_save_transfer_result(test, 1, sectors, ts, rate, iops); } /* @@ -543,22 +548,24 @@ static void mmc_test_print_avg_rate(struct mmc_test_card *test, uint64_t bytes, unsigned int count, struct timespec *ts1, struct timespec *ts2) { - unsigned int rate, sectors = bytes >> 9; + unsigned int rate, iops, sectors = bytes >> 9; uint64_t tot = bytes * count; struct timespec ts; ts = timespec_sub(*ts2, *ts1); rate = mmc_test_rate(tot, &ts); + iops = mmc_test_rate(count * 100, &ts); /* I/O ops per sec x 100 */ printk(KERN_INFO "%s: Transfer of %u x %u sectors (%u x %u%s KiB) took " - "%lu.%09lu seconds (%u kB/s, %u KiB/s)\n", + "%lu.%09lu seconds (%u kB/s, %u KiB/s, " + "%u.%02u IOPS)\n", mmc_hostname(test->card->host), count, sectors, count, sectors >> 1, (sectors & 1 ? ".5" : ""), (unsigned long)ts.tv_sec, (unsigned long)ts.tv_nsec, - rate / 1000, rate / 1024); + rate / 1000, rate / 1024, iops / 100, iops % 100); - mmc_test_save_transfer_result(test, count, sectors, ts, rate); + mmc_test_save_transfer_result(test, count, sectors, ts, rate, iops); } /* @@ -1768,6 +1775,102 @@ static int mmc_test_profile_seq_trim_perf(struct mmc_test_card *test) return 0; } +static unsigned int rnd_next = 1; + +static unsigned int mmc_test_rnd_num(unsigned int rnd_cnt) +{ + uint64_t r; + + rnd_next = rnd_next * 1103515245 + 12345; + r = (rnd_next >> 16) & 0x7fff; + return (r * rnd_cnt) >> 15; +} + +static int mmc_test_rnd_perf(struct mmc_test_card *test, int write, int print, + unsigned long sz) +{ + unsigned int dev_addr, cnt, rnd_addr, range1, range2, last_ea = 0, ea; + unsigned int ssz; + struct timespec ts1, ts2, ts; + int ret; + + ssz = sz >> 9; + + rnd_addr = mmc_test_capacity(test->card) / 4; + range1 = rnd_addr / test->card->pref_erase; + range2 = range1 / ssz; + + getnstimeofday(&ts1); + for (cnt = 0; cnt < UINT_MAX; cnt++) { + getnstimeofday(&ts2); + ts = timespec_sub(ts2, ts1); + if (ts.tv_sec >= 10) + break; + ea = mmc_test_rnd_num(range1); + if (ea == last_ea) + ea -= 1; + last_ea = ea; + dev_addr = rnd_addr + test->card->pref_erase * ea + + ssz * mmc_test_rnd_num(range2); + ret = mmc_test_area_io(test, sz, dev_addr, write, 0, 0); + if (ret) + return ret; + } + if (print) + mmc_test_print_avg_rate(test, sz, cnt, &ts1, &ts2); + return 0; +} + +static int mmc_test_random_perf(struct mmc_test_card *test, int write) +{ + unsigned int next; + unsigned long sz; + int ret; + + for (sz = 512; sz < test->area.max_tfr; sz <<= 1) { + /* + * When writing, try to get more consistent results by running + * the test twice with exactly the same I/O but outputting the + * results only for the 2nd run. + */ + if (write) { + next = rnd_next; + ret = mmc_test_rnd_perf(test, write, 0, sz); + if (ret) + return ret; + rnd_next = next; + } + ret = mmc_test_rnd_perf(test, write, 1, sz); + if (ret) + return ret; + } + sz = test->area.max_tfr; + if (write) { + next = rnd_next; + ret = mmc_test_rnd_perf(test, write, 0, sz); + if (ret) + return ret; + rnd_next = next; + } + return mmc_test_rnd_perf(test, write, 1, sz); +} + +/* + * Random read performance by transfer size. + */ +static int mmc_test_random_read_perf(struct mmc_test_card *test) +{ + return mmc_test_random_perf(test, 0); +} + +/* + * Random write performance by transfer size. + */ +static int mmc_test_random_write_perf(struct mmc_test_card *test) +{ + return mmc_test_random_perf(test, 1); +} + static const struct mmc_test_case mmc_test_cases[] = { { .name = "Basic write (no data verification)", @@ -2007,6 +2110,20 @@ static const struct mmc_test_case mmc_test_cases[] = { .cleanup = mmc_test_area_cleanup, }, + { + .name = "Random read performance by transfer size", + .prepare = mmc_test_area_prepare, + .run = mmc_test_random_read_perf, + .cleanup = mmc_test_area_cleanup, + }, + + { + .name = "Random write performance by transfer size", + .prepare = mmc_test_area_prepare, + .run = mmc_test_random_write_perf, + .cleanup = mmc_test_area_cleanup, + }, + }; static DEFINE_MUTEX(mmc_test_lock); @@ -2150,11 +2267,11 @@ static int mtf_test_show(struct seq_file *sf, void *data) seq_printf(sf, "Test %d: %d\n", gr->testcase + 1, gr->result); list_for_each_entry(tr, &gr->tr_lst, link) { - seq_printf(sf, "%u %d %lu.%09lu %u\n", + seq_printf(sf, "%u %d %lu.%09lu %u %u.%02u\n", tr->count, tr->sectors, (unsigned long)tr->ts.tv_sec, (unsigned long)tr->ts.tv_nsec, - tr->rate); + tr->rate, tr->iops / 100, tr->iops % 100); } } -- GitLab From a803d551d92079beb599cc37fa407c059c82c821 Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Tue, 8 Feb 2011 13:41:03 +0200 Subject: [PATCH 0686/2822] mmc: mmc_test: add tests to measure large sequential I/O performance Add two large sequential I/O performance tests: 35. Large sequential read into scattered pages 36. Large sequential write from scattered pages The tests measure transfer times for 10MiB, 100MiB, 1000MiB. Signed-off-by: Adrian Hunter Signed-off-by: Chris Ball --- drivers/mmc/card/mmc_test.c | 100 ++++++++++++++++++++++++++++++++++++ 1 file changed, 100 insertions(+) diff --git a/drivers/mmc/card/mmc_test.c b/drivers/mmc/card/mmc_test.c index d1aa57a4d0582..5ec8eddfcf6e6 100644 --- a/drivers/mmc/card/mmc_test.c +++ b/drivers/mmc/card/mmc_test.c @@ -1871,6 +1871,92 @@ static int mmc_test_random_write_perf(struct mmc_test_card *test) return mmc_test_random_perf(test, 1); } +static int mmc_test_seq_perf(struct mmc_test_card *test, int write, + unsigned int tot_sz, int max_scatter) +{ + unsigned int dev_addr, i, cnt, sz, ssz; + struct timespec ts1, ts2, ts; + int ret; + + sz = test->area.max_tfr; + /* + * In the case of a maximally scattered transfer, the maximum transfer + * size is further limited by using PAGE_SIZE segments. + */ + if (max_scatter) { + struct mmc_test_area *t = &test->area; + unsigned long max_tfr; + + if (t->max_seg_sz >= PAGE_SIZE) + max_tfr = t->max_segs * PAGE_SIZE; + else + max_tfr = t->max_segs * t->max_seg_sz; + if (sz > max_tfr) + sz = max_tfr; + } + + ssz = sz >> 9; + dev_addr = mmc_test_capacity(test->card) / 4; + if (tot_sz > dev_addr << 9) + tot_sz = dev_addr << 9; + cnt = tot_sz / sz; + dev_addr &= 0xffff0000; /* Round to 64MiB boundary */ + + getnstimeofday(&ts1); + for (i = 0; i < cnt; i++) { + ret = mmc_test_area_io(test, sz, dev_addr, write, + max_scatter, 0); + if (ret) + return ret; + dev_addr += ssz; + } + getnstimeofday(&ts2); + + ts = timespec_sub(ts2, ts1); + mmc_test_print_avg_rate(test, sz, cnt, &ts1, &ts2); + + return 0; +} + +static int mmc_test_large_seq_perf(struct mmc_test_card *test, int write) +{ + int ret, i; + + for (i = 0; i < 10; i++) { + ret = mmc_test_seq_perf(test, write, 10 * 1024 * 1024, 1); + if (ret) + return ret; + } + for (i = 0; i < 5; i++) { + ret = mmc_test_seq_perf(test, write, 100 * 1024 * 1024, 1); + if (ret) + return ret; + } + for (i = 0; i < 3; i++) { + ret = mmc_test_seq_perf(test, write, 1000 * 1024 * 1024, 1); + if (ret) + return ret; + } + + return ret; +} + +/* + * Large sequential read performance. + */ +static int mmc_test_large_seq_read_perf(struct mmc_test_card *test) +{ + return mmc_test_large_seq_perf(test, 0); +} + +/* + * Large sequential write performance. + */ +static int mmc_test_large_seq_write_perf(struct mmc_test_card *test) +{ + return mmc_test_large_seq_perf(test, 1); +} + static const struct mmc_test_case mmc_test_cases[] = { { .name = "Basic write (no data verification)", @@ -2124,6 +2210,20 @@ static const struct mmc_test_case mmc_test_cases[] = { .cleanup = mmc_test_area_cleanup, }, + { + .name = "Large sequential read into scattered pages", + .prepare = mmc_test_area_prepare, + .run = mmc_test_large_seq_read_perf, + .cleanup = mmc_test_area_cleanup, + }, + + { + .name = "Large sequential write from scattered pages", + .prepare = mmc_test_area_prepare, + .run = mmc_test_large_seq_write_perf, + .cleanup = mmc_test_area_cleanup, + }, + }; static DEFINE_MUTEX(mmc_test_lock); -- GitLab From a803d7fbc1ae64244eb8738aa0e4ac491b45d26c Mon Sep 17 00:00:00 2001 From: Simon Horman Date: Wed, 9 Feb 2011 07:25:22 +0900 Subject: [PATCH 0687/2822] mmc: tmio_mmc: Improve readability of the output of pr_debug_status() Reviewed-by: Guennadi Liakhovetski Signed-off-by: Simon Horman Signed-off-by: Chris Ball --- drivers/mmc/host/tmio_mmc.c | 50 ++++++++++++++++++++----------------- 1 file changed, 27 insertions(+), 23 deletions(-) diff --git a/drivers/mmc/host/tmio_mmc.c b/drivers/mmc/host/tmio_mmc.c index e3c6ef2083919..a33f71841dec6 100644 --- a/drivers/mmc/host/tmio_mmc.c +++ b/drivers/mmc/host/tmio_mmc.c @@ -228,36 +228,40 @@ static void tmio_mmc_kunmap_atomic(void *virt, unsigned long *flags) #ifdef CONFIG_MMC_DEBUG -#define STATUS_TO_TEXT(a) \ +#define STATUS_TO_TEXT(a, status, i) \ do { \ - if (status & TMIO_STAT_##a) \ + if (status & TMIO_STAT_##a) { \ + if (i++) \ + printk(" | "); \ printk(#a); \ + } \ } while (0) void pr_debug_status(u32 status) { + int i = 0; printk(KERN_DEBUG "status: %08x = ", status); - STATUS_TO_TEXT(CARD_REMOVE); - STATUS_TO_TEXT(CARD_INSERT); - STATUS_TO_TEXT(SIGSTATE); - STATUS_TO_TEXT(WRPROTECT); - STATUS_TO_TEXT(CARD_REMOVE_A); - STATUS_TO_TEXT(CARD_INSERT_A); - STATUS_TO_TEXT(SIGSTATE_A); - STATUS_TO_TEXT(CMD_IDX_ERR); - STATUS_TO_TEXT(STOPBIT_ERR); - STATUS_TO_TEXT(ILL_FUNC); - STATUS_TO_TEXT(CMD_BUSY); - STATUS_TO_TEXT(CMDRESPEND); - STATUS_TO_TEXT(DATAEND); - STATUS_TO_TEXT(CRCFAIL); - STATUS_TO_TEXT(DATATIMEOUT); - STATUS_TO_TEXT(CMDTIMEOUT); - STATUS_TO_TEXT(RXOVERFLOW); - STATUS_TO_TEXT(TXUNDERRUN); - STATUS_TO_TEXT(RXRDY); - STATUS_TO_TEXT(TXRQ); - STATUS_TO_TEXT(ILL_ACCESS); + STATUS_TO_TEXT(CARD_REMOVE, status, i); + STATUS_TO_TEXT(CARD_INSERT, status, i); + STATUS_TO_TEXT(SIGSTATE, status, i); + STATUS_TO_TEXT(WRPROTECT, status, i); + STATUS_TO_TEXT(CARD_REMOVE_A, status, i); + STATUS_TO_TEXT(CARD_INSERT_A, status, i); + STATUS_TO_TEXT(SIGSTATE_A, status, i); + STATUS_TO_TEXT(CMD_IDX_ERR, status, i); + STATUS_TO_TEXT(STOPBIT_ERR, status, i); + STATUS_TO_TEXT(ILL_FUNC, status, i); + STATUS_TO_TEXT(CMD_BUSY, status, i); + STATUS_TO_TEXT(CMDRESPEND, status, i); + STATUS_TO_TEXT(DATAEND, status, i); + STATUS_TO_TEXT(CRCFAIL, status, i); + STATUS_TO_TEXT(DATATIMEOUT, status, i); + STATUS_TO_TEXT(CMDTIMEOUT, status, i); + STATUS_TO_TEXT(RXOVERFLOW, status, i); + STATUS_TO_TEXT(TXUNDERRUN, status, i); + STATUS_TO_TEXT(RXRDY, status, i); + STATUS_TO_TEXT(TXRQ, status, i); + STATUS_TO_TEXT(ILL_ACCESS, status, i); printk("\n"); } -- GitLab From 170cba8cad5d9350f2c76bbd22013cc31ae26b0f Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Thu, 20 Jan 2011 15:02:59 -0200 Subject: [PATCH 0688/2822] mmc: mmc_mxc: Allow selection only for the correct platforms Currently MMC_MXC driver can be selected by all i.MX devices. Restrict its use only for the appropriate processors. Signed-off-by: Fabio Estevam Acked-by: Sascha Hauer Signed-off-by: Chris Ball --- drivers/mmc/host/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig index afe8c6fa166a7..54b7bd54a52af 100644 --- a/drivers/mmc/host/Kconfig +++ b/drivers/mmc/host/Kconfig @@ -311,7 +311,7 @@ config MMC_MSM config MMC_MXC tristate "Freescale i.MX2/3 Multimedia Card Interface support" - depends on ARCH_MXC + depends on MACH_MX21 || MACH_MX27 || ARCH_MX31 help This selects the Freescale i.MX2/3 Multimedia card Interface. If you have a i.MX platform with a Multimedia Card slot, -- GitLab From dd6c4b9807581b37bf68ba3cd160c6859f070d39 Mon Sep 17 00:00:00 2001 From: Will Newton Date: Thu, 10 Feb 2011 14:37:03 -0500 Subject: [PATCH 0689/2822] mmc: dw_mmc: Run card detect tasklet during slot initialisation. We need to run the card detect tasklet at the end of slot initialisation as it is possible that a card has been inserted prior to boot, so we don't see an insertion interrupt and now the card is sitting there inserted but with no power to it. Signed-off-by: Neil Jones Signed-off-by: Will Newton Reviewed-by: Matt Fleming Signed-off-by: Chris Ball --- drivers/mmc/host/dw_mmc.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c index 2fcc82577c1b1..c01cb8642fb52 100644 --- a/drivers/mmc/host/dw_mmc.c +++ b/drivers/mmc/host/dw_mmc.c @@ -1441,6 +1441,12 @@ static int __init dw_mci_init_slot(struct dw_mci *host, unsigned int id) /* Card initially undetected */ slot->last_detect_state = 0; + /* + * Card may have been plugged in prior to boot so we + * need to run the detect tasklet + */ + tasklet_schedule(&host->card_tasklet); + return 0; } -- GitLab From aadb9f4110096876c6f03073415439f76f0c61ca Mon Sep 17 00:00:00 2001 From: Will Newton Date: Thu, 10 Feb 2011 10:40:57 +0000 Subject: [PATCH 0690/2822] mmc: dw_mmc: Enable low-power mode for the card clock. Setting this bit in the clock enable register will stop the clock when the card is in the IDLE state. Signed-off-by: Will Newton Signed-off-by: Chris Ball --- drivers/mmc/host/dw_mmc.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c index c01cb8642fb52..cd6d8212dacc2 100644 --- a/drivers/mmc/host/dw_mmc.c +++ b/drivers/mmc/host/dw_mmc.c @@ -562,7 +562,8 @@ static void dw_mci_setup_bus(struct dw_mci_slot *slot) SDMMC_CMD_UPD_CLK | SDMMC_CMD_PRV_DAT_WAIT, 0); /* enable clock */ - mci_writel(host, CLKENA, SDMMC_CLKEN_ENABLE); + mci_writel(host, CLKENA, SDMMC_CLKEN_ENABLE | + SDMMC_CLKEN_LOW_PWR); /* inform CIU */ mci_send_cmd(slot, -- GitLab From 50cec37c1ac24e9a02b845242a4712e2fb092b5c Mon Sep 17 00:00:00 2001 From: Will Newton Date: Thu, 10 Feb 2011 10:41:02 +0000 Subject: [PATCH 0691/2822] mmc: Improve MMC_TEST config text. The test file is created under debugfs, not sysfs. Also remove the unnecessary default n. Signed-off-by: Will Newton Reviewed-by: Chris Ball Signed-off-by: Chris Ball --- drivers/mmc/card/Kconfig | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/mmc/card/Kconfig b/drivers/mmc/card/Kconfig index 2a876c4099cd3..3b1f783bf924f 100644 --- a/drivers/mmc/card/Kconfig +++ b/drivers/mmc/card/Kconfig @@ -58,12 +58,11 @@ config SDIO_UART config MMC_TEST tristate "MMC host test driver" - default n help Development driver that performs a series of reads and writes to a memory card in order to expose certain well known bugs in host controllers. The tests are executed by writing to the - "test" file in sysfs under each card. Note that whatever is + "test" file in debugfs under each card. Note that whatever is on your card will be overwritten by these tests. This driver is only of interest to those developing or -- GitLab From ce1014965ae2538e7447b19879bd0e8109690b79 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 10 Feb 2011 10:58:37 +0000 Subject: [PATCH 0692/2822] mmc: Ensure prototypes for SD API are visible in sd.c So we know the implementation and prototypes agree with each other. Signed-off-by: Mark Brown Reviewed-by: Chris Ball Signed-off-by: Chris Ball --- drivers/mmc/core/sd.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c index d18c32bca99ba..6dac89fe0535a 100644 --- a/drivers/mmc/core/sd.c +++ b/drivers/mmc/core/sd.c @@ -21,6 +21,7 @@ #include "core.h" #include "bus.h" #include "mmc_ops.h" +#include "sd.h" #include "sd_ops.h" static const unsigned int tran_exp[] = { -- GitLab From 5fd11c0754fa069b6aba64b65734aa2fb193552d Mon Sep 17 00:00:00 2001 From: Manoj Iyer Date: Fri, 11 Feb 2011 16:25:31 -0600 Subject: [PATCH 0693/2822] mmc: sdhci: Add Ricoh e823 PCI ID Signed-off-by: Manoj Iyer Cc: Signed-off-by: Chris Ball --- drivers/mmc/host/sdhci-pci.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/mmc/host/sdhci-pci.c b/drivers/mmc/host/sdhci-pci.c index 0dc905b20eee1..f7e622c539baa 100644 --- a/drivers/mmc/host/sdhci-pci.c +++ b/drivers/mmc/host/sdhci-pci.c @@ -546,6 +546,14 @@ static const struct pci_device_id pci_ids[] __devinitdata = { .driver_data = (kernel_ulong_t)&sdhci_ricoh_mmc, }, + { + .vendor = PCI_VENDOR_ID_RICOH, + .device = 0xe823, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .driver_data = (kernel_ulong_t)&sdhci_ricoh_mmc, + }, + { .vendor = PCI_VENDOR_ID_ENE, .device = PCI_DEVICE_ID_ENE_CB712_SD, -- GitLab From 266ac3f297adb72fb6c34949a38337c6fad4c7a6 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Thu, 10 Feb 2011 16:08:06 +0100 Subject: [PATCH 0694/2822] mmc: atmel-mci: map DMA sglist on the DMA engine As established for the MMCI, it is proper to map the DMA buffers on the DMA engine which is the one actually performing the DMA. Signed-off-by: Linus Walleij Signed-off-by: Nicolas Ferre Signed-off-by: Chris Ball --- drivers/mmc/host/atmel-mci.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/mmc/host/atmel-mci.c b/drivers/mmc/host/atmel-mci.c index ad2a7a032cdf0..045bdbbe3720a 100644 --- a/drivers/mmc/host/atmel-mci.c +++ b/drivers/mmc/host/atmel-mci.c @@ -578,7 +578,8 @@ static void atmci_dma_cleanup(struct atmel_mci *host) struct mmc_data *data = host->data; if (data) - dma_unmap_sg(&host->pdev->dev, data->sg, data->sg_len, + dma_unmap_sg(host->dma.chan->device->dev, + data->sg, data->sg_len, ((data->flags & MMC_DATA_WRITE) ? DMA_TO_DEVICE : DMA_FROM_DEVICE)); } @@ -684,7 +685,8 @@ atmci_prepare_data_dma(struct atmel_mci *host, struct mmc_data *data) else direction = DMA_TO_DEVICE; - sglen = dma_map_sg(&host->pdev->dev, data->sg, data->sg_len, direction); + sglen = dma_map_sg(chan->device->dev, data->sg, + data->sg_len, direction); if (sglen != data->sg_len) goto unmap_exit; desc = chan->device->device_prep_slave_sg(chan, @@ -699,7 +701,7 @@ atmci_prepare_data_dma(struct atmel_mci *host, struct mmc_data *data) return 0; unmap_exit: - dma_unmap_sg(&host->pdev->dev, data->sg, sglen, direction); + dma_unmap_sg(chan->device->dev, data->sg, sglen, direction); return -ENOMEM; } -- GitLab From 88ce4db313bca1e4e6ef3b448471f85d3e14a854 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Thu, 10 Feb 2011 16:08:16 +0100 Subject: [PATCH 0695/2822] mmc: atmel-mci: conform to DMA-API Fixes the following: - It is perfectly legal for the dma_map_sg() to return fewer entries than were passed in. - Supply the returned numer of (possibly coalesced) entries to the device_pre_slave_sg() function. - Use the proper original sg_len when unmapping the sglist in the error path. Signed-off-by: Linus Walleij Signed-off-by: Nicolas Ferre Signed-off-by: Chris Ball --- drivers/mmc/host/atmel-mci.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/mmc/host/atmel-mci.c b/drivers/mmc/host/atmel-mci.c index 045bdbbe3720a..df5a135423709 100644 --- a/drivers/mmc/host/atmel-mci.c +++ b/drivers/mmc/host/atmel-mci.c @@ -687,10 +687,9 @@ atmci_prepare_data_dma(struct atmel_mci *host, struct mmc_data *data) sglen = dma_map_sg(chan->device->dev, data->sg, data->sg_len, direction); - if (sglen != data->sg_len) - goto unmap_exit; + desc = chan->device->device_prep_slave_sg(chan, - data->sg, data->sg_len, direction, + data->sg, sglen, direction, DMA_PREP_INTERRUPT | DMA_CTRL_ACK); if (!desc) goto unmap_exit; @@ -701,7 +700,7 @@ atmci_prepare_data_dma(struct atmel_mci *host, struct mmc_data *data) return 0; unmap_exit: - dma_unmap_sg(chan->device->dev, data->sg, sglen, direction); + dma_unmap_sg(chan->device->dev, data->sg, data->sg_len, direction); return -ENOMEM; } -- GitLab From 5328906aa2e54a7a5e99e1ba8ee52b387e8be44b Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Thu, 10 Feb 2011 16:08:26 +0100 Subject: [PATCH 0696/2822] mmc: atmel-mci: use dmaengine helper functions Use the new dmaengine helpers to make the code more readable. Signed-off-by: Linus Walleij Signed-off-by: Nicolas Ferre Signed-off-by: Chris Ball --- drivers/mmc/host/atmel-mci.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/mmc/host/atmel-mci.c b/drivers/mmc/host/atmel-mci.c index df5a135423709..80bc9a5c25cc3 100644 --- a/drivers/mmc/host/atmel-mci.c +++ b/drivers/mmc/host/atmel-mci.c @@ -589,7 +589,7 @@ static void atmci_stop_dma(struct atmel_mci *host) struct dma_chan *chan = host->data_chan; if (chan) { - chan->device->device_control(chan, DMA_TERMINATE_ALL, 0); + dmaengine_terminate_all(chan); atmci_dma_cleanup(host); } else { /* Data transfer was stopped by the interrupt handler */ @@ -710,8 +710,8 @@ static void atmci_submit_data(struct atmel_mci *host) struct dma_async_tx_descriptor *desc = host->dma.data_desc; if (chan) { - desc->tx_submit(desc); - chan->device->device_issue_pending(chan); + dmaengine_submit(desc); + dma_async_issue_pending(chan); } } -- GitLab From 1ed828dbb4a90f273b2a3cc70c9c28306427ea7c Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Thu, 10 Feb 2011 16:09:29 +0100 Subject: [PATCH 0697/2822] mmc: sh_mmcif: map DMA buffers on the DMA engine device As established for the MMCI, it is proper to map the DMA buffers on the DMA engine which is the one actually performing the DMA. Signed-off-by: Linus Walleij Signed-off-by: Chris Ball --- drivers/mmc/host/sh_mmcif.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/drivers/mmc/host/sh_mmcif.c b/drivers/mmc/host/sh_mmcif.c index 12884c270171d..8e4aba90d6a49 100644 --- a/drivers/mmc/host/sh_mmcif.c +++ b/drivers/mmc/host/sh_mmcif.c @@ -194,10 +194,12 @@ static void mmcif_dma_complete(void *arg) return; if (host->data->flags & MMC_DATA_READ) - dma_unmap_sg(&host->pd->dev, host->data->sg, host->dma_sglen, + dma_unmap_sg(host->chan_rx->device->dev, + host->data->sg, host->dma_sglen, DMA_FROM_DEVICE); else - dma_unmap_sg(&host->pd->dev, host->data->sg, host->dma_sglen, + dma_unmap_sg(host->chan_tx->device->dev, + host->data->sg, host->dma_sglen, DMA_TO_DEVICE); complete(&host->dma_complete); @@ -211,7 +213,8 @@ static void sh_mmcif_start_dma_rx(struct sh_mmcif_host *host) dma_cookie_t cookie = -EINVAL; int ret; - ret = dma_map_sg(&host->pd->dev, sg, host->data->sg_len, DMA_FROM_DEVICE); + ret = dma_map_sg(chan->device->dev, sg, host->data->sg_len, + DMA_FROM_DEVICE); if (ret > 0) { host->dma_sglen = ret; desc = chan->device->device_prep_slave_sg(chan, sg, ret, @@ -263,7 +266,8 @@ static void sh_mmcif_start_dma_tx(struct sh_mmcif_host *host) dma_cookie_t cookie = -EINVAL; int ret; - ret = dma_map_sg(&host->pd->dev, sg, host->data->sg_len, DMA_TO_DEVICE); + ret = dma_map_sg(chan->device->dev, sg, host->data->sg_len, + DMA_TO_DEVICE); if (ret > 0) { host->dma_sglen = ret; desc = chan->device->device_prep_slave_sg(chan, sg, ret, -- GitLab From 9dc3fb5e4584630c50f7a5405efe9835d321ad44 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Thu, 10 Feb 2011 16:09:40 +0100 Subject: [PATCH 0698/2822] mmc: sh_mmcif: unmap with the proper sglen According to the DMA-API you shall unmap the sglists with the same sglist length as passed into the mapping function, not the returned value from the mapping function. Signed-off-by: Linus Walleij Signed-off-by: Chris Ball --- drivers/mmc/host/sh_mmcif.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/mmc/host/sh_mmcif.c b/drivers/mmc/host/sh_mmcif.c index 8e4aba90d6a49..61ad19ecfbf83 100644 --- a/drivers/mmc/host/sh_mmcif.c +++ b/drivers/mmc/host/sh_mmcif.c @@ -195,11 +195,11 @@ static void mmcif_dma_complete(void *arg) if (host->data->flags & MMC_DATA_READ) dma_unmap_sg(host->chan_rx->device->dev, - host->data->sg, host->dma_sglen, + host->data->sg, host->data->sg_len, DMA_FROM_DEVICE); else dma_unmap_sg(host->chan_tx->device->dev, - host->data->sg, host->dma_sglen, + host->data->sg, host->data->sg_len, DMA_TO_DEVICE); complete(&host->dma_complete); -- GitLab From f38f94c6b226f7c6888bedbcadf0ed2ddca7d029 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Thu, 10 Feb 2011 16:09:50 +0100 Subject: [PATCH 0699/2822] mmc: sh_mmcif: rename and retype activity variable The host_sglen is now actually used to keep track of whether DMA is active or not, so rename and retype it to bool. Signed-off-by: Linus Walleij Signed-off-by: Chris Ball --- drivers/mmc/host/sh_mmcif.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/mmc/host/sh_mmcif.c b/drivers/mmc/host/sh_mmcif.c index 61ad19ecfbf83..e247031f91f71 100644 --- a/drivers/mmc/host/sh_mmcif.c +++ b/drivers/mmc/host/sh_mmcif.c @@ -169,7 +169,7 @@ struct sh_mmcif_host { struct dma_chan *chan_rx; struct dma_chan *chan_tx; struct completion dma_complete; - unsigned int dma_sglen; + bool dma_active; }; static inline void sh_mmcif_bitset(struct sh_mmcif_host *host, @@ -216,7 +216,7 @@ static void sh_mmcif_start_dma_rx(struct sh_mmcif_host *host) ret = dma_map_sg(chan->device->dev, sg, host->data->sg_len, DMA_FROM_DEVICE); if (ret > 0) { - host->dma_sglen = ret; + host->dma_active = true; desc = chan->device->device_prep_slave_sg(chan, sg, ret, DMA_FROM_DEVICE, DMA_PREP_INTERRUPT | DMA_CTRL_ACK); } @@ -241,7 +241,7 @@ static void sh_mmcif_start_dma_rx(struct sh_mmcif_host *host) if (ret >= 0) ret = -EIO; host->chan_rx = NULL; - host->dma_sglen = 0; + host->dma_active = false; dma_release_channel(chan); /* Free the Tx channel too */ chan = host->chan_tx; @@ -269,7 +269,7 @@ static void sh_mmcif_start_dma_tx(struct sh_mmcif_host *host) ret = dma_map_sg(chan->device->dev, sg, host->data->sg_len, DMA_TO_DEVICE); if (ret > 0) { - host->dma_sglen = ret; + host->dma_active = true; desc = chan->device->device_prep_slave_sg(chan, sg, ret, DMA_TO_DEVICE, DMA_PREP_INTERRUPT | DMA_CTRL_ACK); } @@ -294,7 +294,7 @@ static void sh_mmcif_start_dma_tx(struct sh_mmcif_host *host) if (ret >= 0) ret = -EIO; host->chan_tx = NULL; - host->dma_sglen = 0; + host->dma_active = false; dma_release_channel(chan); /* Free the Rx channel too */ chan = host->chan_rx; @@ -321,7 +321,7 @@ static bool sh_mmcif_filter(struct dma_chan *chan, void *arg) static void sh_mmcif_request_dma(struct sh_mmcif_host *host, struct sh_mmcif_plat_data *pdata) { - host->dma_sglen = 0; + host->dma_active = false; /* We can only either use DMA for both Tx and Rx or not use it at all */ if (pdata->dma) { @@ -368,7 +368,7 @@ static void sh_mmcif_release_dma(struct sh_mmcif_host *host) dma_release_channel(chan); } - host->dma_sglen = 0; + host->dma_active = false; } static void sh_mmcif_clock_control(struct sh_mmcif_host *host, unsigned int clk) @@ -757,7 +757,7 @@ static void sh_mmcif_start_cmd(struct sh_mmcif_host *host, } sh_mmcif_get_response(host, cmd); if (host->data) { - if (!host->dma_sglen) { + if (!host->dma_active) { ret = sh_mmcif_data_trans(host, mrq, cmd->opcode); } else { long time = @@ -769,7 +769,7 @@ static void sh_mmcif_start_cmd(struct sh_mmcif_host *host, ret = time; sh_mmcif_bitclr(host, MMCIF_CE_BUF_ACC, BUF_ACC_DMAREN | BUF_ACC_DMAWEN); - host->dma_sglen = 0; + host->dma_active = false; } if (ret < 0) mrq->data->bytes_xfered = 0; -- GitLab From a5ece7d29d09714a690f83f6f0ce395f4374021e Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Thu, 10 Feb 2011 16:10:00 +0100 Subject: [PATCH 0700/2822] mmc: sh_mmcif: use dmaengine helpers, drop submit check Use the new dmaengine helper functions, and drop the error check on the returned cookier from the dmaengine - we recently established that this is really not allowed to fail. Signed-off-by: Linus Walleij Signed-off-by: Chris Ball --- drivers/mmc/host/sh_mmcif.c | 22 ++++++---------------- 1 file changed, 6 insertions(+), 16 deletions(-) diff --git a/drivers/mmc/host/sh_mmcif.c b/drivers/mmc/host/sh_mmcif.c index e247031f91f71..aea86262ed66c 100644 --- a/drivers/mmc/host/sh_mmcif.c +++ b/drivers/mmc/host/sh_mmcif.c @@ -224,14 +224,9 @@ static void sh_mmcif_start_dma_rx(struct sh_mmcif_host *host) if (desc) { desc->callback = mmcif_dma_complete; desc->callback_param = host; - cookie = desc->tx_submit(desc); - if (cookie < 0) { - desc = NULL; - ret = cookie; - } else { - sh_mmcif_bitset(host, MMCIF_CE_BUF_ACC, BUF_ACC_DMAREN); - chan->device->device_issue_pending(chan); - } + cookie = dmaengine_submit(desc); + sh_mmcif_bitset(host, MMCIF_CE_BUF_ACC, BUF_ACC_DMAREN); + dma_async_issue_pending(chan); } dev_dbg(&host->pd->dev, "%s(): mapped %d -> %d, cookie %d\n", __func__, host->data->sg_len, ret, cookie); @@ -277,14 +272,9 @@ static void sh_mmcif_start_dma_tx(struct sh_mmcif_host *host) if (desc) { desc->callback = mmcif_dma_complete; desc->callback_param = host; - cookie = desc->tx_submit(desc); - if (cookie < 0) { - desc = NULL; - ret = cookie; - } else { - sh_mmcif_bitset(host, MMCIF_CE_BUF_ACC, BUF_ACC_DMAWEN); - chan->device->device_issue_pending(chan); - } + cookie = dmaengine_submit(desc); + sh_mmcif_bitset(host, MMCIF_CE_BUF_ACC, BUF_ACC_DMAWEN); + dma_async_issue_pending(chan); } dev_dbg(&host->pd->dev, "%s(): mapped %d -> %d, cookie %d\n", __func__, host->data->sg_len, ret, cookie); -- GitLab From 2dc7ddc1e7e68ee7793dda0ca0d659367d035e3d Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Thu, 10 Feb 2011 16:10:37 +0100 Subject: [PATCH 0701/2822] mmc: tmio_mmc: map DMA buffers on the DMA engine device As established for the MMCI, it is proper to map the DMA buffers on the DMA engine which is the one actually performing the DMA. Signed-off-by: Linus Walleij Signed-off-by: Chris Ball --- drivers/mmc/host/tmio_mmc.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/mmc/host/tmio_mmc.c b/drivers/mmc/host/tmio_mmc.c index a33f71841dec6..0d36fa9c629e0 100644 --- a/drivers/mmc/host/tmio_mmc.c +++ b/drivers/mmc/host/tmio_mmc.c @@ -829,7 +829,7 @@ static void tmio_mmc_start_dma_rx(struct tmio_mmc_host *host) sg = host->sg_ptr; } - ret = dma_map_sg(&host->pdev->dev, sg, host->sg_len, DMA_FROM_DEVICE); + ret = dma_map_sg(chan->device->dev, sg, host->sg_len, DMA_FROM_DEVICE); if (ret > 0) { host->dma_sglen = ret; desc = chan->device->device_prep_slave_sg(chan, sg, ret, @@ -910,7 +910,7 @@ static void tmio_mmc_start_dma_tx(struct tmio_mmc_host *host) sg = host->sg_ptr; } - ret = dma_map_sg(&host->pdev->dev, sg, host->sg_len, DMA_TO_DEVICE); + ret = dma_map_sg(chan->device->dev, sg, host->sg_len, DMA_TO_DEVICE); if (ret > 0) { host->dma_sglen = ret; desc = chan->device->device_prep_slave_sg(chan, sg, ret, @@ -982,10 +982,12 @@ static void tmio_tasklet_fn(unsigned long arg) goto out; if (host->data->flags & MMC_DATA_READ) - dma_unmap_sg(&host->pdev->dev, host->sg_ptr, host->dma_sglen, + dma_unmap_sg(host->chan_rx->device->dev, + host->sg_ptr, host->dma_sglen, DMA_FROM_DEVICE); else - dma_unmap_sg(&host->pdev->dev, host->sg_ptr, host->dma_sglen, + dma_unmap_sg(host->chan_tx->device->dev, + host->sg_ptr, host->dma_sglen, DMA_TO_DEVICE); tmio_mmc_do_data_irq(host); -- GitLab From d7554caa2c3410c07a1889a08c66288edbdc216a Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Thu, 10 Feb 2011 16:10:47 +0100 Subject: [PATCH 0702/2822] mmc: tmio_mmc: unmap with the proper sglen According to the DMA-API you shall unmap the sglists with the same sglist length as passed into the mapping function, not the returned value from the mapping function. Signed-off-by: Linus Walleij Signed-off-by: Chris Ball --- drivers/mmc/host/tmio_mmc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/mmc/host/tmio_mmc.c b/drivers/mmc/host/tmio_mmc.c index 0d36fa9c629e0..1b9fa21c2bdcb 100644 --- a/drivers/mmc/host/tmio_mmc.c +++ b/drivers/mmc/host/tmio_mmc.c @@ -983,11 +983,11 @@ static void tmio_tasklet_fn(unsigned long arg) if (host->data->flags & MMC_DATA_READ) dma_unmap_sg(host->chan_rx->device->dev, - host->sg_ptr, host->dma_sglen, + host->sg_ptr, host->sg_len, DMA_FROM_DEVICE); else dma_unmap_sg(host->chan_tx->device->dev, - host->sg_ptr, host->dma_sglen, + host->sg_ptr, host->sg_len, DMA_TO_DEVICE); tmio_mmc_do_data_irq(host); -- GitLab From 3383433ce70613514593c940a2ae4e6ab19f2b28 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Thu, 10 Feb 2011 16:10:56 +0100 Subject: [PATCH 0703/2822] mmc: tmio_mmc: drop dma_sglen state variable This variable doesn't seem to be used for anything after the other patches so just drop it. Signed-off-by: Linus Walleij Signed-off-by: Chris Ball --- drivers/mmc/host/tmio_mmc.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/drivers/mmc/host/tmio_mmc.c b/drivers/mmc/host/tmio_mmc.c index 1b9fa21c2bdcb..699b6ab209b24 100644 --- a/drivers/mmc/host/tmio_mmc.c +++ b/drivers/mmc/host/tmio_mmc.c @@ -152,7 +152,6 @@ struct tmio_mmc_host { struct tasklet_struct dma_complete; struct tasklet_struct dma_issue; #ifdef CONFIG_TMIO_MMC_DMA - unsigned int dma_sglen; u8 bounce_buf[PAGE_CACHE_SIZE] __attribute__((aligned(MAX_ALIGN))); struct scatterlist bounce_sg; #endif @@ -830,11 +829,9 @@ static void tmio_mmc_start_dma_rx(struct tmio_mmc_host *host) } ret = dma_map_sg(chan->device->dev, sg, host->sg_len, DMA_FROM_DEVICE); - if (ret > 0) { - host->dma_sglen = ret; + if (ret > 0) desc = chan->device->device_prep_slave_sg(chan, sg, ret, DMA_FROM_DEVICE, DMA_PREP_INTERRUPT | DMA_CTRL_ACK); - } if (desc) { desc->callback = tmio_dma_complete; @@ -911,11 +908,9 @@ static void tmio_mmc_start_dma_tx(struct tmio_mmc_host *host) } ret = dma_map_sg(chan->device->dev, sg, host->sg_len, DMA_TO_DEVICE); - if (ret > 0) { - host->dma_sglen = ret; + if (ret > 0) desc = chan->device->device_prep_slave_sg(chan, sg, ret, DMA_TO_DEVICE, DMA_PREP_INTERRUPT | DMA_CTRL_ACK); - } if (desc) { desc->callback = tmio_dma_complete; -- GitLab From 449bdc2d9d62794246351d10dd4534a239bf06b6 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Thu, 10 Feb 2011 16:11:07 +0100 Subject: [PATCH 0704/2822] mmc: tmio_mmc: use dmaengine helpers, drop submit check Use the new dmaengine helper functions, and drop the error check on the returned cookier from the dmaengine - we recently established that this is really not allowed to fail. Signed-off-by: Linus Walleij Signed-off-by: Chris Ball --- drivers/mmc/host/tmio_mmc.c | 17 ++++------------- 1 file changed, 4 insertions(+), 13 deletions(-) diff --git a/drivers/mmc/host/tmio_mmc.c b/drivers/mmc/host/tmio_mmc.c index 699b6ab209b24..0e4998fa6fc5f 100644 --- a/drivers/mmc/host/tmio_mmc.c +++ b/drivers/mmc/host/tmio_mmc.c @@ -836,13 +836,8 @@ static void tmio_mmc_start_dma_rx(struct tmio_mmc_host *host) if (desc) { desc->callback = tmio_dma_complete; desc->callback_param = host; - cookie = desc->tx_submit(desc); - if (cookie < 0) { - desc = NULL; - ret = cookie; - } else { - chan->device->device_issue_pending(chan); - } + cookie = dmaengine_submit(desc); + dma_async_issue_pending(chan); } dev_dbg(&host->pdev->dev, "%s(): mapped %d -> %d, cookie %d, rq %p\n", __func__, host->sg_len, ret, cookie, host->mrq); @@ -915,11 +910,7 @@ static void tmio_mmc_start_dma_tx(struct tmio_mmc_host *host) if (desc) { desc->callback = tmio_dma_complete; desc->callback_param = host; - cookie = desc->tx_submit(desc); - if (cookie < 0) { - desc = NULL; - ret = cookie; - } + cookie = dmaengine_submit(desc); } dev_dbg(&host->pdev->dev, "%s(): mapped %d -> %d, cookie %d, rq %p\n", __func__, host->sg_len, ret, cookie, host->mrq); @@ -963,7 +954,7 @@ static void tmio_issue_tasklet_fn(unsigned long priv) struct tmio_mmc_host *host = (struct tmio_mmc_host *)priv; struct dma_chan *chan = host->chan_tx; - chan->device->device_issue_pending(chan); + dma_async_issue_pending(chan); } static void tmio_tasklet_fn(unsigned long arg) -- GitLab From 37b7785e3ac5128809340eaeb791ca7a471c4e32 Mon Sep 17 00:00:00 2001 From: Jaehoon Chung Date: Thu, 17 Feb 2011 13:09:04 +0900 Subject: [PATCH 0705/2822] mmc: dw_mmc: modify quirks bit-shift control If we need some quirks, maybe add quirks in future But now, quirks value set to integer..later we should be confused.. So I think that need bit-shift control. And If we need not any quirks, we didn't set anything.. (Need not DW_MCI_QUIRK_NONE) Signed-off-by: Jaehoon Chung Acked-by: Will Newton Signed-off-by: Chris Ball --- include/linux/mmc/dw_mmc.h | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/include/linux/mmc/dw_mmc.h b/include/linux/mmc/dw_mmc.h index 16b0261763ed5..3f22c201ee3a0 100644 --- a/include/linux/mmc/dw_mmc.h +++ b/include/linux/mmc/dw_mmc.h @@ -165,14 +165,12 @@ struct dw_mci_dma_ops { }; /* IP Quirks/flags. */ -/* No special quirks or flags to cater for */ -#define DW_MCI_QUIRK_NONE 0 /* DTO fix for command transmission with IDMAC configured */ -#define DW_MCI_QUIRK_IDMAC_DTO 1 +#define DW_MCI_QUIRK_IDMAC_DTO BIT(0) /* delay needed between retries on some 2.11a implementations */ -#define DW_MCI_QUIRK_RETRY_DELAY 2 +#define DW_MCI_QUIRK_RETRY_DELAY BIT(1) /* High Speed Capable - Supports HS cards (upto 50MHz) */ -#define DW_MCI_QUIRK_HIGHSPEED 4 +#define DW_MCI_QUIRK_HIGHSPEED BIT(2) struct dma_pdata; -- GitLab From c9b2a06fb0efda37241861915a8639c27bddaa85 Mon Sep 17 00:00:00 2001 From: Jaehoon Chung Date: Thu, 17 Feb 2011 16:12:38 +0900 Subject: [PATCH 0706/2822] mmc: dw_mmc: support 8-bit buswidth This patch adds support for 8-bit buswidth. dw_mmc can use 8-bit buswidth and set to CTYPE_8BIT in card-type register. Signed-off-by: Jaehoon Chung Signed-off-by: Kyungmin Park Acked-by: Will Newton Signed-off-by: Chris Ball --- drivers/mmc/host/dw_mmc.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c index cd6d8212dacc2..62c8440ff04b9 100644 --- a/drivers/mmc/host/dw_mmc.c +++ b/drivers/mmc/host/dw_mmc.c @@ -673,6 +673,9 @@ static void dw_mci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) case MMC_BUS_WIDTH_4: slot->ctype = SDMMC_CTYPE_4BIT; break; + case MMC_BUS_WIDTH_8: + slot->ctype = SDMMC_CTYPE_8BIT; + break; } if (ios->clock) { -- GitLab From f53fbde48ef0a5ce7733fbc84da18014d0a11cf0 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Fri, 18 Feb 2011 10:21:09 +0100 Subject: [PATCH 0707/2822] mmc: mxcmmc: use dmaengine API This switches the mxcmmc driver to use the dmaengine API. Unlike the old one this one is always present in the tree, even if no DMA is implemented, hence we can remove all the #ifdefs in from the driver. The driver automatically switches to PIO mode if no DMA support or no suitable channel is available. Signed-off-by: Sascha Hauer Acked-by: Arnd Bergmann Signed-off-by: Chris Ball --- drivers/mmc/host/mxcmmc.c | 181 ++++++++++++++++++++++---------------- 1 file changed, 104 insertions(+), 77 deletions(-) diff --git a/drivers/mmc/host/mxcmmc.c b/drivers/mmc/host/mxcmmc.c index 4428594261c52..cc20e02593259 100644 --- a/drivers/mmc/host/mxcmmc.c +++ b/drivers/mmc/host/mxcmmc.c @@ -32,16 +32,14 @@ #include #include #include +#include #include #include #include #include -#ifdef CONFIG_ARCH_MX2 -#include -#define HAS_DMA -#endif +#include #define DRIVER_NAME "mxc-mmc" @@ -118,7 +116,8 @@ struct mxcmci_host { void __iomem *base; int irq; int detect_irq; - int dma; + struct dma_chan *dma; + struct dma_async_tx_descriptor *desc; int do_dma; int default_irq_mask; int use_sdio; @@ -129,7 +128,6 @@ struct mxcmci_host { struct mmc_command *cmd; struct mmc_data *data; - unsigned int dma_nents; unsigned int datasize; unsigned int dma_dir; @@ -144,6 +142,11 @@ struct mxcmci_host { spinlock_t lock; struct regulator *vcc; + + int burstlen; + int dmareq; + struct dma_slave_config dma_slave_config; + struct imx_dma_data dma_data; }; static void mxcmci_set_clk_rate(struct mxcmci_host *host, unsigned int clk_ios); @@ -206,17 +209,16 @@ static void mxcmci_softreset(struct mxcmci_host *host) writew(0xff, host->base + MMC_REG_RES_TO); } +static int mxcmci_setup_dma(struct mmc_host *mmc); static int mxcmci_setup_data(struct mxcmci_host *host, struct mmc_data *data) { unsigned int nob = data->blocks; unsigned int blksz = data->blksz; unsigned int datasize = nob * blksz; -#ifdef HAS_DMA struct scatterlist *sg; - int i; - int ret; -#endif + int i, nents; + if (data->flags & MMC_DATA_STREAM) nob = 0xffff; @@ -227,7 +229,9 @@ static int mxcmci_setup_data(struct mxcmci_host *host, struct mmc_data *data) writew(blksz, host->base + MMC_REG_BLK_LEN); host->datasize = datasize; -#ifdef HAS_DMA + if (!mxcmci_use_dma(host)) + return 0; + for_each_sg(data->sg, sg, data->sg_len, i) { if (sg->offset & 3 || sg->length & 3) { host->do_dma = 0; @@ -235,34 +239,30 @@ static int mxcmci_setup_data(struct mxcmci_host *host, struct mmc_data *data) } } - if (data->flags & MMC_DATA_READ) { + if (data->flags & MMC_DATA_READ) host->dma_dir = DMA_FROM_DEVICE; - host->dma_nents = dma_map_sg(mmc_dev(host->mmc), data->sg, - data->sg_len, host->dma_dir); - - ret = imx_dma_setup_sg(host->dma, data->sg, host->dma_nents, - datasize, - host->res->start + MMC_REG_BUFFER_ACCESS, - DMA_MODE_READ); - } else { + else host->dma_dir = DMA_TO_DEVICE; - host->dma_nents = dma_map_sg(mmc_dev(host->mmc), data->sg, - data->sg_len, host->dma_dir); - ret = imx_dma_setup_sg(host->dma, data->sg, host->dma_nents, - datasize, - host->res->start + MMC_REG_BUFFER_ACCESS, - DMA_MODE_WRITE); - } + nents = dma_map_sg(host->dma->device->dev, data->sg, + data->sg_len, host->dma_dir); + if (nents != data->sg_len) + return -EINVAL; + + host->desc = host->dma->device->device_prep_slave_sg(host->dma, + data->sg, data->sg_len, host->dma_dir, + DMA_PREP_INTERRUPT | DMA_CTRL_ACK); - if (ret) { - dev_err(mmc_dev(host->mmc), "failed to setup DMA : %d\n", ret); - return ret; + if (!host->desc) { + dma_unmap_sg(host->dma->device->dev, data->sg, data->sg_len, + host->dma_dir); + host->do_dma = 0; + return 0; /* Fall back to PIO */ } wmb(); - imx_dma_enable(host->dma); -#endif /* HAS_DMA */ + dmaengine_submit(host->desc); + return 0; } @@ -337,13 +337,11 @@ static int mxcmci_finish_data(struct mxcmci_host *host, unsigned int stat) struct mmc_data *data = host->data; int data_error; -#ifdef HAS_DMA if (mxcmci_use_dma(host)) { - imx_dma_disable(host->dma); - dma_unmap_sg(mmc_dev(host->mmc), data->sg, host->dma_nents, + dmaengine_terminate_all(host->dma); + dma_unmap_sg(host->dma->device->dev, data->sg, data->sg_len, host->dma_dir); } -#endif if (stat & STATUS_ERR_MASK) { dev_dbg(mmc_dev(host->mmc), "request failed. status: 0x%08x\n", @@ -545,7 +543,6 @@ static void mxcmci_datawork(struct work_struct *work) } } -#ifdef HAS_DMA static void mxcmci_data_done(struct mxcmci_host *host, unsigned int stat) { struct mmc_data *data = host->data; @@ -568,7 +565,6 @@ static void mxcmci_data_done(struct mxcmci_host *host, unsigned int stat) mxcmci_finish_request(host, host->req); } } -#endif /* HAS_DMA */ static void mxcmci_cmd_done(struct mxcmci_host *host, unsigned int stat) { @@ -606,12 +602,10 @@ static irqreturn_t mxcmci_irq(int irq, void *devid) sdio_irq = (stat & STATUS_SDIO_INT_ACTIVE) && host->use_sdio; spin_unlock_irqrestore(&host->lock, flags); -#ifdef HAS_DMA if (mxcmci_use_dma(host) && (stat & (STATUS_READ_OP_DONE | STATUS_WRITE_OP_DONE))) writel(STATUS_READ_OP_DONE | STATUS_WRITE_OP_DONE, host->base + MMC_REG_STATUS); -#endif if (sdio_irq) { writel(STATUS_SDIO_INT_ACTIVE, host->base + MMC_REG_STATUS); @@ -621,14 +615,14 @@ static irqreturn_t mxcmci_irq(int irq, void *devid) if (stat & STATUS_END_CMD_RESP) mxcmci_cmd_done(host, stat); -#ifdef HAS_DMA if (mxcmci_use_dma(host) && (stat & (STATUS_DATA_TRANS_DONE | STATUS_WRITE_OP_DONE))) mxcmci_data_done(host, stat); -#endif + if (host->default_irq_mask && (stat & (STATUS_CARD_INSERTION | STATUS_CARD_REMOVAL))) mmc_detect_change(host->mmc, msecs_to_jiffies(200)); + return IRQ_HANDLED; } @@ -642,9 +636,10 @@ static void mxcmci_request(struct mmc_host *mmc, struct mmc_request *req) host->req = req; host->cmdat &= ~CMD_DAT_CONT_INIT; -#ifdef HAS_DMA - host->do_dma = 1; -#endif + + if (host->dma) + host->do_dma = 1; + if (req->data) { error = mxcmci_setup_data(host, req->data); if (error) { @@ -660,6 +655,7 @@ static void mxcmci_request(struct mmc_host *mmc, struct mmc_request *req) } error = mxcmci_start_cmd(host, req->cmd, cmdat); + out: if (error) mxcmci_finish_request(host, req); @@ -698,22 +694,46 @@ static void mxcmci_set_clk_rate(struct mxcmci_host *host, unsigned int clk_ios) prescaler, divider, clk_in, clk_ios); } +static int mxcmci_setup_dma(struct mmc_host *mmc) +{ + struct mxcmci_host *host = mmc_priv(mmc); + struct dma_slave_config *config = &host->dma_slave_config; + + config->dst_addr = host->res->start + MMC_REG_BUFFER_ACCESS; + config->src_addr = host->res->start + MMC_REG_BUFFER_ACCESS; + config->dst_addr_width = 4; + config->src_addr_width = 4; + config->dst_maxburst = host->burstlen; + config->src_maxburst = host->burstlen; + + return dmaengine_slave_config(host->dma, config); +} + static void mxcmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) { struct mxcmci_host *host = mmc_priv(mmc); -#ifdef HAS_DMA - unsigned int blen; + int burstlen, ret; + /* * use burstlen of 64 in 4 bit mode (--> reg value 0) * use burstlen of 16 in 1 bit mode (--> reg value 16) */ if (ios->bus_width == MMC_BUS_WIDTH_4) - blen = 0; + burstlen = 64; else - blen = 16; + burstlen = 16; + + if (mxcmci_use_dma(host) && burstlen != host->burstlen) { + host->burstlen = burstlen; + ret = mxcmci_setup_dma(mmc); + if (ret) { + dev_err(mmc_dev(host->mmc), + "failed to config DMA channel. Falling back to PIO\n"); + dma_release_channel(host->dma); + host->do_dma = 0; + } + } - imx_dma_config_burstlen(host->dma, blen); -#endif if (ios->bus_width == MMC_BUS_WIDTH_4) host->cmdat |= CMD_DAT_CONT_BUS_WIDTH_4; else @@ -794,6 +814,18 @@ static void mxcmci_init_card(struct mmc_host *host, struct mmc_card *card) host->caps |= MMC_CAP_4_BIT_DATA; } +static bool filter(struct dma_chan *chan, void *param) +{ + struct mxcmci_host *host = param; + + if (!imx_dma_is_general_purpose(chan)) + return false; + + chan->private = &host->dma_data; + + return true; +} + static const struct mmc_host_ops mxcmci_ops = { .request = mxcmci_request, .set_ios = mxcmci_set_ios, @@ -808,6 +840,7 @@ static int mxcmci_probe(struct platform_device *pdev) struct mxcmci_host *host = NULL; struct resource *iores, *r; int ret = 0, irq; + dma_cap_mask_t mask; printk(KERN_INFO "i.MX SDHC driver\n"); @@ -883,29 +916,23 @@ static int mxcmci_probe(struct platform_device *pdev) writel(host->default_irq_mask, host->base + MMC_REG_INT_CNTR); -#ifdef HAS_DMA - host->dma = imx_dma_request_by_prio(DRIVER_NAME, DMA_PRIO_LOW); - if (host->dma < 0) { - dev_err(mmc_dev(host->mmc), "imx_dma_request_by_prio failed\n"); - ret = -EBUSY; - goto out_clk_put; - } - r = platform_get_resource(pdev, IORESOURCE_DMA, 0); - if (!r) { - ret = -EINVAL; - goto out_free_dma; + if (r) { + host->dmareq = r->start; + host->dma_data.peripheral_type = IMX_DMATYPE_SDHC; + host->dma_data.priority = DMA_PRIO_LOW; + host->dma_data.dma_request = host->dmareq; + dma_cap_zero(mask); + dma_cap_set(DMA_SLAVE, mask); + host->dma = dma_request_channel(mask, filter, host); + if (host->dma) + mmc->max_seg_size = dma_get_max_seg_size( + host->dma->device->dev); } - ret = imx_dma_config_channel(host->dma, - IMX_DMA_MEMSIZE_32 | IMX_DMA_TYPE_FIFO, - IMX_DMA_MEMSIZE_32 | IMX_DMA_TYPE_LINEAR, - r->start, 0); - if (ret) { - dev_err(mmc_dev(host->mmc), "failed to config DMA channel\n"); - goto out_free_dma; - } -#endif + if (!host->dma) + dev_info(mmc_dev(host->mmc), "dma not available. Using PIO\n"); + INIT_WORK(&host->datawork, mxcmci_datawork); ret = request_irq(host->irq, mxcmci_irq, 0, DRIVER_NAME, host); @@ -928,9 +955,8 @@ static int mxcmci_probe(struct platform_device *pdev) out_free_irq: free_irq(host->irq, host); out_free_dma: -#ifdef HAS_DMA - imx_dma_free(host->dma); -#endif + if (host->dma) + dma_release_channel(host->dma); out_clk_put: clk_disable(host->clk); clk_put(host->clk); @@ -960,9 +986,10 @@ static int mxcmci_remove(struct platform_device *pdev) free_irq(host->irq, host); iounmap(host->base); -#ifdef HAS_DMA - imx_dma_free(host->dma); -#endif + + if (host->dma) + dma_release_channel(host->dma); + clk_disable(host->clk); clk_put(host->clk); -- GitLab From 8154b5756d3cb850f846ff38cf35cbbb7c2b45fe Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Thu, 10 Feb 2011 18:07:30 +0100 Subject: [PATCH 0708/2822] mmc: sdhci-tegra: free irq on error and remove Signed-off-by: Wolfram Sang Acked-by: Olof Johansson Signed-off-by: Chris Ball --- drivers/mmc/host/sdhci-tegra.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/mmc/host/sdhci-tegra.c b/drivers/mmc/host/sdhci-tegra.c index 4823ee94a63fe..f7e1f964395fd 100644 --- a/drivers/mmc/host/sdhci-tegra.c +++ b/drivers/mmc/host/sdhci-tegra.c @@ -169,7 +169,7 @@ static int tegra_sdhci_pltfm_init(struct sdhci_host *host, if (rc) { dev_err(mmc_dev(host->mmc), "failed to allocate wp gpio\n"); - goto out_cd; + goto out_irq; } tegra_gpio_enable(plat->wp_gpio); gpio_direction_input(plat->wp_gpio); @@ -195,6 +195,9 @@ out_wp: gpio_free(plat->wp_gpio); } +out_irq: + if (gpio_is_valid(plat->cd_gpio)) + free_irq(gpio_to_irq(plat->cd_gpio), host); out_cd: if (gpio_is_valid(plat->cd_gpio)) { tegra_gpio_disable(plat->cd_gpio); @@ -225,6 +228,7 @@ static void tegra_sdhci_pltfm_exit(struct sdhci_host *host) } if (gpio_is_valid(plat->cd_gpio)) { + free_irq(gpio_to_irq(plat->cd_gpio), host); tegra_gpio_disable(plat->cd_gpio); gpio_free(plat->cd_gpio); } -- GitLab From e4243f13d10e5fbe2b84e211dcac3bc6e0792167 Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Mon, 21 Feb 2011 18:35:28 +0800 Subject: [PATCH 0709/2822] mmc: mxs-mmc: add mmc host driver for i.MX23/28 This adds the mmc host driver for Freescale MXS-based SoC i.MX23/28. The driver calls into mxs-dma via generic dmaengine api for both pio and data transfer. Thanks Chris Ball for the indentation patch. Signed-off-by: Shawn Guo Reviewed-by: Arnd Bergmann Tested-by: Wolfram Sang Signed-off-by: Chris Ball --- arch/arm/mach-mxs/include/mach/mmc.h | 18 + drivers/mmc/host/Kconfig | 9 + drivers/mmc/host/Makefile | 1 + drivers/mmc/host/mxs-mmc.c | 874 +++++++++++++++++++++++++++ 4 files changed, 902 insertions(+) create mode 100644 arch/arm/mach-mxs/include/mach/mmc.h create mode 100644 drivers/mmc/host/mxs-mmc.c diff --git a/arch/arm/mach-mxs/include/mach/mmc.h b/arch/arm/mach-mxs/include/mach/mmc.h new file mode 100644 index 0000000000000..211547a055648 --- /dev/null +++ b/arch/arm/mach-mxs/include/mach/mmc.h @@ -0,0 +1,18 @@ +/* + * Copyright 2011 Freescale Semiconductor, Inc. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef __MACH_MXS_MMC_H__ +#define __MACH_MXS_MMC_H__ + +struct mxs_mmc_platform_data { + int wp_gpio; /* write protect pin */ + unsigned int flags; +#define SLOTF_4_BIT_CAPABLE (1 << 0) +#define SLOTF_8_BIT_CAPABLE (1 << 1) +}; +#endif /* __MACH_MXS_MMC_H__ */ diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig index 54b7bd54a52af..398d7d54c52a5 100644 --- a/drivers/mmc/host/Kconfig +++ b/drivers/mmc/host/Kconfig @@ -319,6 +319,15 @@ config MMC_MXC If unsure, say N. +config MMC_MXS + tristate "Freescale MXS Multimedia Card Interface support" + depends on ARCH_MXS && MXS_DMA + help + This selects the Freescale SSP MMC controller found on MXS based + platforms like mx23/28. + + If unsure, say N. + config MMC_TIFM_SD tristate "TI Flash Media MMC/SD Interface support (EXPERIMENTAL)" depends on EXPERIMENTAL && PCI diff --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile index e834fb223e9a8..30aa6867745f4 100644 --- a/drivers/mmc/host/Makefile +++ b/drivers/mmc/host/Makefile @@ -6,6 +6,7 @@ obj-$(CONFIG_MMC_ARMMMCI) += mmci.o obj-$(CONFIG_MMC_PXA) += pxamci.o obj-$(CONFIG_MMC_IMX) += imxmmc.o obj-$(CONFIG_MMC_MXC) += mxcmmc.o +obj-$(CONFIG_MMC_MXS) += mxs-mmc.o obj-$(CONFIG_MMC_SDHCI) += sdhci.o obj-$(CONFIG_MMC_SDHCI_PCI) += sdhci-pci.o obj-$(CONFIG_MMC_SDHCI_PXA) += sdhci-pxa.o diff --git a/drivers/mmc/host/mxs-mmc.c b/drivers/mmc/host/mxs-mmc.c new file mode 100644 index 0000000000000..99d39a6a1032d --- /dev/null +++ b/drivers/mmc/host/mxs-mmc.c @@ -0,0 +1,874 @@ +/* + * Portions copyright (C) 2003 Russell King, PXA MMCI Driver + * Portions copyright (C) 2004-2005 Pierre Ossman, W83L51xD SD/MMC driver + * + * Copyright 2008 Embedded Alley Solutions, Inc. + * Copyright 2009-2011 Freescale Semiconductor, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#define DRIVER_NAME "mxs-mmc" + +/* card detect polling timeout */ +#define MXS_MMC_DETECT_TIMEOUT (HZ/2) + +#define SSP_VERSION_LATEST 4 +#define ssp_is_old() (host->version < SSP_VERSION_LATEST) + +/* SSP registers */ +#define HW_SSP_CTRL0 0x000 +#define BM_SSP_CTRL0_RUN (1 << 29) +#define BM_SSP_CTRL0_SDIO_IRQ_CHECK (1 << 28) +#define BM_SSP_CTRL0_IGNORE_CRC (1 << 26) +#define BM_SSP_CTRL0_READ (1 << 25) +#define BM_SSP_CTRL0_DATA_XFER (1 << 24) +#define BP_SSP_CTRL0_BUS_WIDTH (22) +#define BM_SSP_CTRL0_BUS_WIDTH (0x3 << 22) +#define BM_SSP_CTRL0_WAIT_FOR_IRQ (1 << 21) +#define BM_SSP_CTRL0_LONG_RESP (1 << 19) +#define BM_SSP_CTRL0_GET_RESP (1 << 17) +#define BM_SSP_CTRL0_ENABLE (1 << 16) +#define BP_SSP_CTRL0_XFER_COUNT (0) +#define BM_SSP_CTRL0_XFER_COUNT (0xffff) +#define HW_SSP_CMD0 0x010 +#define BM_SSP_CMD0_DBL_DATA_RATE_EN (1 << 25) +#define BM_SSP_CMD0_SLOW_CLKING_EN (1 << 22) +#define BM_SSP_CMD0_CONT_CLKING_EN (1 << 21) +#define BM_SSP_CMD0_APPEND_8CYC (1 << 20) +#define BP_SSP_CMD0_BLOCK_SIZE (16) +#define BM_SSP_CMD0_BLOCK_SIZE (0xf << 16) +#define BP_SSP_CMD0_BLOCK_COUNT (8) +#define BM_SSP_CMD0_BLOCK_COUNT (0xff << 8) +#define BP_SSP_CMD0_CMD (0) +#define BM_SSP_CMD0_CMD (0xff) +#define HW_SSP_CMD1 0x020 +#define HW_SSP_XFER_SIZE 0x030 +#define HW_SSP_BLOCK_SIZE 0x040 +#define BP_SSP_BLOCK_SIZE_BLOCK_COUNT (4) +#define BM_SSP_BLOCK_SIZE_BLOCK_COUNT (0xffffff << 4) +#define BP_SSP_BLOCK_SIZE_BLOCK_SIZE (0) +#define BM_SSP_BLOCK_SIZE_BLOCK_SIZE (0xf) +#define HW_SSP_TIMING (ssp_is_old() ? 0x050 : 0x070) +#define BP_SSP_TIMING_TIMEOUT (16) +#define BM_SSP_TIMING_TIMEOUT (0xffff << 16) +#define BP_SSP_TIMING_CLOCK_DIVIDE (8) +#define BM_SSP_TIMING_CLOCK_DIVIDE (0xff << 8) +#define BP_SSP_TIMING_CLOCK_RATE (0) +#define BM_SSP_TIMING_CLOCK_RATE (0xff) +#define HW_SSP_CTRL1 (ssp_is_old() ? 0x060 : 0x080) +#define BM_SSP_CTRL1_SDIO_IRQ (1 << 31) +#define BM_SSP_CTRL1_SDIO_IRQ_EN (1 << 30) +#define BM_SSP_CTRL1_RESP_ERR_IRQ (1 << 29) +#define BM_SSP_CTRL1_RESP_ERR_IRQ_EN (1 << 28) +#define BM_SSP_CTRL1_RESP_TIMEOUT_IRQ (1 << 27) +#define BM_SSP_CTRL1_RESP_TIMEOUT_IRQ_EN (1 << 26) +#define BM_SSP_CTRL1_DATA_TIMEOUT_IRQ (1 << 25) +#define BM_SSP_CTRL1_DATA_TIMEOUT_IRQ_EN (1 << 24) +#define BM_SSP_CTRL1_DATA_CRC_IRQ (1 << 23) +#define BM_SSP_CTRL1_DATA_CRC_IRQ_EN (1 << 22) +#define BM_SSP_CTRL1_FIFO_UNDERRUN_IRQ (1 << 21) +#define BM_SSP_CTRL1_FIFO_UNDERRUN_IRQ_EN (1 << 20) +#define BM_SSP_CTRL1_RECV_TIMEOUT_IRQ (1 << 17) +#define BM_SSP_CTRL1_RECV_TIMEOUT_IRQ_EN (1 << 16) +#define BM_SSP_CTRL1_FIFO_OVERRUN_IRQ (1 << 15) +#define BM_SSP_CTRL1_FIFO_OVERRUN_IRQ_EN (1 << 14) +#define BM_SSP_CTRL1_DMA_ENABLE (1 << 13) +#define BM_SSP_CTRL1_POLARITY (1 << 9) +#define BP_SSP_CTRL1_WORD_LENGTH (4) +#define BM_SSP_CTRL1_WORD_LENGTH (0xf << 4) +#define BP_SSP_CTRL1_SSP_MODE (0) +#define BM_SSP_CTRL1_SSP_MODE (0xf) +#define HW_SSP_SDRESP0 (ssp_is_old() ? 0x080 : 0x0a0) +#define HW_SSP_SDRESP1 (ssp_is_old() ? 0x090 : 0x0b0) +#define HW_SSP_SDRESP2 (ssp_is_old() ? 0x0a0 : 0x0c0) +#define HW_SSP_SDRESP3 (ssp_is_old() ? 0x0b0 : 0x0d0) +#define HW_SSP_STATUS (ssp_is_old() ? 0x0c0 : 0x100) +#define BM_SSP_STATUS_CARD_DETECT (1 << 28) +#define BM_SSP_STATUS_SDIO_IRQ (1 << 17) +#define HW_SSP_VERSION (cpu_is_mx23() ? 0x110 : 0x130) +#define BP_SSP_VERSION_MAJOR (24) + +#define BF_SSP(value, field) (((value) << BP_SSP_##field) & BM_SSP_##field) + +#define MXS_MMC_IRQ_BITS (BM_SSP_CTRL1_SDIO_IRQ | \ + BM_SSP_CTRL1_RESP_ERR_IRQ | \ + BM_SSP_CTRL1_RESP_TIMEOUT_IRQ | \ + BM_SSP_CTRL1_DATA_TIMEOUT_IRQ | \ + BM_SSP_CTRL1_DATA_CRC_IRQ | \ + BM_SSP_CTRL1_FIFO_UNDERRUN_IRQ | \ + BM_SSP_CTRL1_RECV_TIMEOUT_IRQ | \ + BM_SSP_CTRL1_FIFO_OVERRUN_IRQ) + +#define SSP_PIO_NUM 3 + +struct mxs_mmc_host { + struct mmc_host *mmc; + struct mmc_request *mrq; + struct mmc_command *cmd; + struct mmc_data *data; + + void __iomem *base; + int irq; + struct resource *res; + struct resource *dma_res; + struct clk *clk; + unsigned int clk_rate; + + struct dma_chan *dmach; + struct mxs_dma_data dma_data; + unsigned int dma_dir; + u32 ssp_pio_words[SSP_PIO_NUM]; + + unsigned int version; + unsigned char bus_width; + spinlock_t lock; + int sdio_irq_en; +}; + +static int mxs_mmc_get_ro(struct mmc_host *mmc) +{ + struct mxs_mmc_host *host = mmc_priv(mmc); + struct mxs_mmc_platform_data *pdata = + mmc_dev(host->mmc)->platform_data; + + if (!pdata) + return -EFAULT; + + if (!gpio_is_valid(pdata->wp_gpio)) + return -EINVAL; + + return gpio_get_value(pdata->wp_gpio); +} + +static int mxs_mmc_get_cd(struct mmc_host *mmc) +{ + struct mxs_mmc_host *host = mmc_priv(mmc); + + return !(readl(host->base + HW_SSP_STATUS) & + BM_SSP_STATUS_CARD_DETECT); +} + +static void mxs_mmc_reset(struct mxs_mmc_host *host) +{ + u32 ctrl0, ctrl1; + + mxs_reset_block(host->base); + + ctrl0 = BM_SSP_CTRL0_IGNORE_CRC; + ctrl1 = BF_SSP(0x3, CTRL1_SSP_MODE) | + BF_SSP(0x7, CTRL1_WORD_LENGTH) | + BM_SSP_CTRL1_DMA_ENABLE | + BM_SSP_CTRL1_POLARITY | + BM_SSP_CTRL1_RECV_TIMEOUT_IRQ_EN | + BM_SSP_CTRL1_DATA_CRC_IRQ_EN | + BM_SSP_CTRL1_DATA_TIMEOUT_IRQ_EN | + BM_SSP_CTRL1_RESP_TIMEOUT_IRQ_EN | + BM_SSP_CTRL1_RESP_ERR_IRQ_EN; + + writel(BF_SSP(0xffff, TIMING_TIMEOUT) | + BF_SSP(2, TIMING_CLOCK_DIVIDE) | + BF_SSP(0, TIMING_CLOCK_RATE), + host->base + HW_SSP_TIMING); + + if (host->sdio_irq_en) { + ctrl0 |= BM_SSP_CTRL0_SDIO_IRQ_CHECK; + ctrl1 |= BM_SSP_CTRL1_SDIO_IRQ_EN; + } + + writel(ctrl0, host->base + HW_SSP_CTRL0); + writel(ctrl1, host->base + HW_SSP_CTRL1); +} + +static void mxs_mmc_start_cmd(struct mxs_mmc_host *host, + struct mmc_command *cmd); + +static void mxs_mmc_request_done(struct mxs_mmc_host *host) +{ + struct mmc_command *cmd = host->cmd; + struct mmc_data *data = host->data; + struct mmc_request *mrq = host->mrq; + + if (mmc_resp_type(cmd) & MMC_RSP_PRESENT) { + if (mmc_resp_type(cmd) & MMC_RSP_136) { + cmd->resp[3] = readl(host->base + HW_SSP_SDRESP0); + cmd->resp[2] = readl(host->base + HW_SSP_SDRESP1); + cmd->resp[1] = readl(host->base + HW_SSP_SDRESP2); + cmd->resp[0] = readl(host->base + HW_SSP_SDRESP3); + } else { + cmd->resp[0] = readl(host->base + HW_SSP_SDRESP0); + } + } + + if (data) { + dma_unmap_sg(mmc_dev(host->mmc), data->sg, + data->sg_len, host->dma_dir); + /* + * If there was an error on any block, we mark all + * data blocks as being in error. + */ + if (!data->error) + data->bytes_xfered = data->blocks * data->blksz; + else + data->bytes_xfered = 0; + + host->data = NULL; + if (mrq->stop) { + mxs_mmc_start_cmd(host, mrq->stop); + return; + } + } + + host->mrq = NULL; + mmc_request_done(host->mmc, mrq); +} + +static void mxs_mmc_dma_irq_callback(void *param) +{ + struct mxs_mmc_host *host = param; + + mxs_mmc_request_done(host); +} + +static irqreturn_t mxs_mmc_irq_handler(int irq, void *dev_id) +{ + struct mxs_mmc_host *host = dev_id; + struct mmc_command *cmd = host->cmd; + struct mmc_data *data = host->data; + u32 stat; + + spin_lock(&host->lock); + + stat = readl(host->base + HW_SSP_CTRL1); + writel(stat & MXS_MMC_IRQ_BITS, + host->base + HW_SSP_CTRL1 + MXS_CLR_ADDR); + + if ((stat & BM_SSP_CTRL1_SDIO_IRQ) && (stat & BM_SSP_CTRL1_SDIO_IRQ_EN)) + mmc_signal_sdio_irq(host->mmc); + + spin_unlock(&host->lock); + + if (stat & BM_SSP_CTRL1_RESP_TIMEOUT_IRQ) + cmd->error = -ETIMEDOUT; + else if (stat & BM_SSP_CTRL1_RESP_ERR_IRQ) + cmd->error = -EIO; + + if (data) { + if (stat & (BM_SSP_CTRL1_DATA_TIMEOUT_IRQ | + BM_SSP_CTRL1_RECV_TIMEOUT_IRQ)) + data->error = -ETIMEDOUT; + else if (stat & BM_SSP_CTRL1_DATA_CRC_IRQ) + data->error = -EILSEQ; + else if (stat & (BM_SSP_CTRL1_FIFO_UNDERRUN_IRQ | + BM_SSP_CTRL1_FIFO_OVERRUN_IRQ)) + data->error = -EIO; + } + + return IRQ_HANDLED; +} + +static struct dma_async_tx_descriptor *mxs_mmc_prep_dma( + struct mxs_mmc_host *host, unsigned int append) +{ + struct dma_async_tx_descriptor *desc; + struct mmc_data *data = host->data; + struct scatterlist * sgl; + unsigned int sg_len; + + if (data) { + /* data */ + dma_map_sg(mmc_dev(host->mmc), data->sg, + data->sg_len, host->dma_dir); + sgl = data->sg; + sg_len = data->sg_len; + } else { + /* pio */ + sgl = (struct scatterlist *) host->ssp_pio_words; + sg_len = SSP_PIO_NUM; + } + + desc = host->dmach->device->device_prep_slave_sg(host->dmach, + sgl, sg_len, host->dma_dir, append); + if (desc) { + desc->callback = mxs_mmc_dma_irq_callback; + desc->callback_param = host; + } else { + if (data) + dma_unmap_sg(mmc_dev(host->mmc), data->sg, + data->sg_len, host->dma_dir); + } + + return desc; +} + +static void mxs_mmc_bc(struct mxs_mmc_host *host) +{ + struct mmc_command *cmd = host->cmd; + struct dma_async_tx_descriptor *desc; + u32 ctrl0, cmd0, cmd1; + + ctrl0 = BM_SSP_CTRL0_ENABLE | BM_SSP_CTRL0_IGNORE_CRC; + cmd0 = BF_SSP(cmd->opcode, CMD0_CMD) | BM_SSP_CMD0_APPEND_8CYC; + cmd1 = cmd->arg; + + if (host->sdio_irq_en) { + ctrl0 |= BM_SSP_CTRL0_SDIO_IRQ_CHECK; + cmd0 |= BM_SSP_CMD0_CONT_CLKING_EN | BM_SSP_CMD0_SLOW_CLKING_EN; + } + + host->ssp_pio_words[0] = ctrl0; + host->ssp_pio_words[1] = cmd0; + host->ssp_pio_words[2] = cmd1; + host->dma_dir = DMA_NONE; + desc = mxs_mmc_prep_dma(host, 0); + if (!desc) + goto out; + + dmaengine_submit(desc); + return; + +out: + dev_warn(mmc_dev(host->mmc), + "%s: failed to prep dma\n", __func__); +} + +static void mxs_mmc_ac(struct mxs_mmc_host *host) +{ + struct mmc_command *cmd = host->cmd; + struct dma_async_tx_descriptor *desc; + u32 ignore_crc, get_resp, long_resp; + u32 ctrl0, cmd0, cmd1; + + ignore_crc = (mmc_resp_type(cmd) & MMC_RSP_CRC) ? + 0 : BM_SSP_CTRL0_IGNORE_CRC; + get_resp = (mmc_resp_type(cmd) & MMC_RSP_PRESENT) ? + BM_SSP_CTRL0_GET_RESP : 0; + long_resp = (mmc_resp_type(cmd) & MMC_RSP_136) ? + BM_SSP_CTRL0_LONG_RESP : 0; + + ctrl0 = BM_SSP_CTRL0_ENABLE | ignore_crc | get_resp | long_resp; + cmd0 = BF_SSP(cmd->opcode, CMD0_CMD); + cmd1 = cmd->arg; + + if (host->sdio_irq_en) { + ctrl0 |= BM_SSP_CTRL0_SDIO_IRQ_CHECK; + cmd0 |= BM_SSP_CMD0_CONT_CLKING_EN | BM_SSP_CMD0_SLOW_CLKING_EN; + } + + host->ssp_pio_words[0] = ctrl0; + host->ssp_pio_words[1] = cmd0; + host->ssp_pio_words[2] = cmd1; + host->dma_dir = DMA_NONE; + desc = mxs_mmc_prep_dma(host, 0); + if (!desc) + goto out; + + dmaengine_submit(desc); + return; + +out: + dev_warn(mmc_dev(host->mmc), + "%s: failed to prep dma\n", __func__); +} + +static unsigned short mxs_ns_to_ssp_ticks(unsigned clock_rate, unsigned ns) +{ + const unsigned int ssp_timeout_mul = 4096; + /* + * Calculate ticks in ms since ns are large numbers + * and might overflow + */ + const unsigned int clock_per_ms = clock_rate / 1000; + const unsigned int ms = ns / 1000; + const unsigned int ticks = ms * clock_per_ms; + const unsigned int ssp_ticks = ticks / ssp_timeout_mul; + + WARN_ON(ssp_ticks == 0); + return ssp_ticks; +} + +static void mxs_mmc_adtc(struct mxs_mmc_host *host) +{ + struct mmc_command *cmd = host->cmd; + struct mmc_data *data = cmd->data; + struct dma_async_tx_descriptor *desc; + struct scatterlist *sgl = data->sg, *sg; + unsigned int sg_len = data->sg_len; + int i; + + unsigned short dma_data_dir, timeout; + unsigned int data_size = 0, log2_blksz; + unsigned int blocks = data->blocks; + + u32 ignore_crc, get_resp, long_resp, read; + u32 ctrl0, cmd0, cmd1, val; + + ignore_crc = (mmc_resp_type(cmd) & MMC_RSP_CRC) ? + 0 : BM_SSP_CTRL0_IGNORE_CRC; + get_resp = (mmc_resp_type(cmd) & MMC_RSP_PRESENT) ? + BM_SSP_CTRL0_GET_RESP : 0; + long_resp = (mmc_resp_type(cmd) & MMC_RSP_136) ? + BM_SSP_CTRL0_LONG_RESP : 0; + + if (data->flags & MMC_DATA_WRITE) { + dma_data_dir = DMA_TO_DEVICE; + read = 0; + } else { + dma_data_dir = DMA_FROM_DEVICE; + read = BM_SSP_CTRL0_READ; + } + + ctrl0 = BF_SSP(host->bus_width, CTRL0_BUS_WIDTH) | + ignore_crc | get_resp | long_resp | + BM_SSP_CTRL0_DATA_XFER | read | + BM_SSP_CTRL0_WAIT_FOR_IRQ | + BM_SSP_CTRL0_ENABLE; + + cmd0 = BF_SSP(cmd->opcode, CMD0_CMD); + + /* get logarithm to base 2 of block size for setting register */ + log2_blksz = ilog2(data->blksz); + + /* + * take special care of the case that data size from data->sg + * is not equal to blocks x blksz + */ + for_each_sg(sgl, sg, sg_len, i) + data_size += sg->length; + + if (data_size != data->blocks * data->blksz) + blocks = 1; + + /* xfer count, block size and count need to be set differently */ + if (ssp_is_old()) { + ctrl0 |= BF_SSP(data_size, CTRL0_XFER_COUNT); + cmd0 |= BF_SSP(log2_blksz, CMD0_BLOCK_SIZE) | + BF_SSP(blocks - 1, CMD0_BLOCK_COUNT); + } else { + writel(data_size, host->base + HW_SSP_XFER_SIZE); + writel(BF_SSP(log2_blksz, BLOCK_SIZE_BLOCK_SIZE) | + BF_SSP(blocks - 1, BLOCK_SIZE_BLOCK_COUNT), + host->base + HW_SSP_BLOCK_SIZE); + } + + if ((cmd->opcode == MMC_STOP_TRANSMISSION) || + (cmd->opcode == SD_IO_RW_EXTENDED)) + cmd0 |= BM_SSP_CMD0_APPEND_8CYC; + + cmd1 = cmd->arg; + + if (host->sdio_irq_en) { + ctrl0 |= BM_SSP_CTRL0_SDIO_IRQ_CHECK; + cmd0 |= BM_SSP_CMD0_CONT_CLKING_EN | BM_SSP_CMD0_SLOW_CLKING_EN; + } + + /* set the timeout count */ + timeout = mxs_ns_to_ssp_ticks(host->clk_rate, data->timeout_ns); + val = readl(host->base + HW_SSP_TIMING); + val &= ~(BM_SSP_TIMING_TIMEOUT); + val |= BF_SSP(timeout, TIMING_TIMEOUT); + writel(val, host->base + HW_SSP_TIMING); + + /* pio */ + host->ssp_pio_words[0] = ctrl0; + host->ssp_pio_words[1] = cmd0; + host->ssp_pio_words[2] = cmd1; + host->dma_dir = DMA_NONE; + desc = mxs_mmc_prep_dma(host, 0); + if (!desc) + goto out; + + /* append data sg */ + WARN_ON(host->data != NULL); + host->data = data; + host->dma_dir = dma_data_dir; + desc = mxs_mmc_prep_dma(host, 1); + if (!desc) + goto out; + + dmaengine_submit(desc); + return; +out: + dev_warn(mmc_dev(host->mmc), + "%s: failed to prep dma\n", __func__); +} + +static void mxs_mmc_start_cmd(struct mxs_mmc_host *host, + struct mmc_command *cmd) +{ + host->cmd = cmd; + + switch (mmc_cmd_type(cmd)) { + case MMC_CMD_BC: + mxs_mmc_bc(host); + break; + case MMC_CMD_BCR: + mxs_mmc_ac(host); + break; + case MMC_CMD_AC: + mxs_mmc_ac(host); + break; + case MMC_CMD_ADTC: + mxs_mmc_adtc(host); + break; + default: + dev_warn(mmc_dev(host->mmc), + "%s: unknown MMC command\n", __func__); + break; + } +} + +static void mxs_mmc_request(struct mmc_host *mmc, struct mmc_request *mrq) +{ + struct mxs_mmc_host *host = mmc_priv(mmc); + + WARN_ON(host->mrq != NULL); + host->mrq = mrq; + mxs_mmc_start_cmd(host, mrq->cmd); +} + +static void mxs_mmc_set_clk_rate(struct mxs_mmc_host *host, unsigned int rate) +{ + unsigned int ssp_rate, bit_rate; + u32 div1, div2; + u32 val; + + ssp_rate = clk_get_rate(host->clk); + + for (div1 = 2; div1 < 254; div1 += 2) { + div2 = ssp_rate / rate / div1; + if (div2 < 0x100) + break; + } + + if (div1 >= 254) { + dev_err(mmc_dev(host->mmc), + "%s: cannot set clock to %d\n", __func__, rate); + return; + } + + if (div2 == 0) + bit_rate = ssp_rate / div1; + else + bit_rate = ssp_rate / div1 / div2; + + val = readl(host->base + HW_SSP_TIMING); + val &= ~(BM_SSP_TIMING_CLOCK_DIVIDE | BM_SSP_TIMING_CLOCK_RATE); + val |= BF_SSP(div1, TIMING_CLOCK_DIVIDE); + val |= BF_SSP(div2 - 1, TIMING_CLOCK_RATE); + writel(val, host->base + HW_SSP_TIMING); + + host->clk_rate = bit_rate; + + dev_dbg(mmc_dev(host->mmc), + "%s: div1 %d, div2 %d, ssp %d, bit %d, rate %d\n", + __func__, div1, div2, ssp_rate, bit_rate, rate); +} + +static void mxs_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) +{ + struct mxs_mmc_host *host = mmc_priv(mmc); + + if (ios->bus_width == MMC_BUS_WIDTH_8) + host->bus_width = 2; + else if (ios->bus_width == MMC_BUS_WIDTH_4) + host->bus_width = 1; + else + host->bus_width = 0; + + if (ios->clock) + mxs_mmc_set_clk_rate(host, ios->clock); +} + +static void mxs_mmc_enable_sdio_irq(struct mmc_host *mmc, int enable) +{ + struct mxs_mmc_host *host = mmc_priv(mmc); + unsigned long flags; + + spin_lock_irqsave(&host->lock, flags); + + host->sdio_irq_en = enable; + + if (enable) { + writel(BM_SSP_CTRL0_SDIO_IRQ_CHECK, + host->base + HW_SSP_CTRL0 + MXS_SET_ADDR); + writel(BM_SSP_CTRL1_SDIO_IRQ_EN, + host->base + HW_SSP_CTRL1 + MXS_SET_ADDR); + + if (readl(host->base + HW_SSP_STATUS) & BM_SSP_STATUS_SDIO_IRQ) + mmc_signal_sdio_irq(host->mmc); + + } else { + writel(BM_SSP_CTRL0_SDIO_IRQ_CHECK, + host->base + HW_SSP_CTRL0 + MXS_CLR_ADDR); + writel(BM_SSP_CTRL1_SDIO_IRQ_EN, + host->base + HW_SSP_CTRL1 + MXS_CLR_ADDR); + } + + spin_unlock_irqrestore(&host->lock, flags); +} + +static const struct mmc_host_ops mxs_mmc_ops = { + .request = mxs_mmc_request, + .get_ro = mxs_mmc_get_ro, + .get_cd = mxs_mmc_get_cd, + .set_ios = mxs_mmc_set_ios, + .enable_sdio_irq = mxs_mmc_enable_sdio_irq, +}; + +static bool mxs_mmc_dma_filter(struct dma_chan *chan, void *param) +{ + struct mxs_mmc_host *host = param; + + if (!mxs_dma_is_apbh(chan)) + return false; + + if (chan->chan_id != host->dma_res->start) + return false; + + chan->private = &host->dma_data; + + return true; +} + +static int mxs_mmc_probe(struct platform_device *pdev) +{ + struct mxs_mmc_host *host; + struct mmc_host *mmc; + struct resource *iores, *dmares, *r; + struct mxs_mmc_platform_data *pdata; + int ret = 0, irq_err, irq_dma; + dma_cap_mask_t mask; + + iores = platform_get_resource(pdev, IORESOURCE_MEM, 0); + dmares = platform_get_resource(pdev, IORESOURCE_DMA, 0); + irq_err = platform_get_irq(pdev, 0); + irq_dma = platform_get_irq(pdev, 1); + if (!iores || !dmares || irq_err < 0 || irq_dma < 0) + return -EINVAL; + + r = request_mem_region(iores->start, resource_size(iores), pdev->name); + if (!r) + return -EBUSY; + + mmc = mmc_alloc_host(sizeof(struct mxs_mmc_host), &pdev->dev); + if (!mmc) { + ret = -ENOMEM; + goto out_release_mem; + } + + host = mmc_priv(mmc); + host->base = ioremap(r->start, resource_size(r)); + if (!host->base) { + ret = -ENOMEM; + goto out_mmc_free; + } + + /* only major verion does matter */ + host->version = readl(host->base + HW_SSP_VERSION) >> + BP_SSP_VERSION_MAJOR; + + host->mmc = mmc; + host->res = r; + host->dma_res = dmares; + host->irq = irq_err; + host->sdio_irq_en = 0; + + host->clk = clk_get(&pdev->dev, NULL); + if (IS_ERR(host->clk)) { + ret = PTR_ERR(host->clk); + goto out_iounmap; + } + clk_enable(host->clk); + + mxs_mmc_reset(host); + + dma_cap_zero(mask); + dma_cap_set(DMA_SLAVE, mask); + host->dma_data.chan_irq = irq_dma; + host->dmach = dma_request_channel(mask, mxs_mmc_dma_filter, host); + if (!host->dmach) { + dev_err(mmc_dev(host->mmc), + "%s: failed to request dma\n", __func__); + goto out_clk_put; + } + + /* set mmc core parameters */ + mmc->ops = &mxs_mmc_ops; + mmc->caps = MMC_CAP_SD_HIGHSPEED | MMC_CAP_MMC_HIGHSPEED | + MMC_CAP_SDIO_IRQ | MMC_CAP_NEEDS_POLL; + + pdata = mmc_dev(host->mmc)->platform_data; + if (pdata) { + if (pdata->flags & SLOTF_8_BIT_CAPABLE) + mmc->caps |= MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA; + if (pdata->flags & SLOTF_4_BIT_CAPABLE) + mmc->caps |= MMC_CAP_4_BIT_DATA; + } + + mmc->f_min = 400000; + mmc->f_max = 288000000; + mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34; + + mmc->max_segs = 52; + mmc->max_blk_size = 1 << 0xf; + mmc->max_blk_count = (ssp_is_old()) ? 0xff : 0xffffff; + mmc->max_req_size = (ssp_is_old()) ? 0xffff : 0xffffffff; + mmc->max_seg_size = dma_get_max_seg_size(host->dmach->device->dev); + + platform_set_drvdata(pdev, mmc); + + ret = request_irq(host->irq, mxs_mmc_irq_handler, 0, DRIVER_NAME, host); + if (ret) + goto out_free_dma; + + spin_lock_init(&host->lock); + + ret = mmc_add_host(mmc); + if (ret) + goto out_free_irq; + + dev_info(mmc_dev(host->mmc), "initialized\n"); + + return 0; + +out_free_irq: + free_irq(host->irq, host); +out_free_dma: + if (host->dmach) + dma_release_channel(host->dmach); +out_clk_put: + clk_disable(host->clk); + clk_put(host->clk); +out_iounmap: + iounmap(host->base); +out_mmc_free: + mmc_free_host(mmc); +out_release_mem: + release_mem_region(iores->start, resource_size(iores)); + return ret; +} + +static int mxs_mmc_remove(struct platform_device *pdev) +{ + struct mmc_host *mmc = platform_get_drvdata(pdev); + struct mxs_mmc_host *host = mmc_priv(mmc); + struct resource *res = host->res; + + mmc_remove_host(mmc); + + free_irq(host->irq, host); + + platform_set_drvdata(pdev, NULL); + + if (host->dmach) + dma_release_channel(host->dmach); + + clk_disable(host->clk); + clk_put(host->clk); + + iounmap(host->base); + + mmc_free_host(mmc); + + release_mem_region(res->start, resource_size(res)); + + return 0; +} + +#ifdef CONFIG_PM +static int mxs_mmc_suspend(struct device *dev) +{ + struct mmc_host *mmc = dev_get_drvdata(dev); + struct mxs_mmc_host *host = mmc_priv(mmc); + int ret = 0; + + ret = mmc_suspend_host(mmc); + + clk_disable(host->clk); + + return ret; +} + +static int mxs_mmc_resume(struct device *dev) +{ + struct mmc_host *mmc = dev_get_drvdata(dev); + struct mxs_mmc_host *host = mmc_priv(mmc); + int ret = 0; + + clk_enable(host->clk); + + ret = mmc_resume_host(mmc); + + return ret; +} + +static const struct dev_pm_ops mxs_mmc_pm_ops = { + .suspend = mxs_mmc_suspend, + .resume = mxs_mmc_resume, +}; +#endif + +static struct platform_driver mxs_mmc_driver = { + .probe = mxs_mmc_probe, + .remove = mxs_mmc_remove, + .driver = { + .name = DRIVER_NAME, + .owner = THIS_MODULE, +#ifdef CONFIG_PM + .pm = &mxs_mmc_pm_ops, +#endif + }, +}; + +static int __init mxs_mmc_init(void) +{ + return platform_driver_register(&mxs_mmc_driver); +} + +static void __exit mxs_mmc_exit(void) +{ + platform_driver_unregister(&mxs_mmc_driver); +} + +module_init(mxs_mmc_init); +module_exit(mxs_mmc_exit); + +MODULE_DESCRIPTION("FREESCALE MXS MMC peripheral"); +MODULE_AUTHOR("Freescale Semiconductor"); +MODULE_LICENSE("GPL"); -- GitLab From 24c300199b2f9125169c09ca3e950b17c16e2eab Mon Sep 17 00:00:00 2001 From: Chris Ball Date: Wed, 23 Feb 2011 17:29:11 -0500 Subject: [PATCH 0710/2822] mmc: sdhci-pci: Remove set-but-unused variable. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit drivers/mmc/host/sdhci-pci.c: In function ‘sdhci_pci_probe_slot’: drivers/mmc/host/sdhci-pci.c:913:18: warning: variable ‘addr’ set but not used [-Wunused-but-set-variable] Signed-off-by: Chris Ball Acked-by: Wolfram Sang --- drivers/mmc/host/sdhci-pci.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/mmc/host/sdhci-pci.c b/drivers/mmc/host/sdhci-pci.c index f7e622c539baa..2f8d46854acd0 100644 --- a/drivers/mmc/host/sdhci-pci.c +++ b/drivers/mmc/host/sdhci-pci.c @@ -908,9 +908,6 @@ static struct sdhci_pci_slot * __devinit sdhci_pci_probe_slot( { struct sdhci_pci_slot *slot; struct sdhci_host *host; - - resource_size_t addr; - int ret; if (!(pci_resource_flags(pdev, bar) & IORESOURCE_MEM)) { @@ -957,7 +954,6 @@ static struct sdhci_pci_slot * __devinit sdhci_pci_probe_slot( goto free; } - addr = pci_resource_start(pdev, bar); host->ioaddr = pci_ioremap_bar(pdev, bar); if (!host->ioaddr) { dev_err(&pdev->dev, "failed to remap registers\n"); -- GitLab From b3bd1b5b0054f716e58a65d4e2e449ea0252e9dd Mon Sep 17 00:00:00 2001 From: Chris Ball Date: Wed, 23 Feb 2011 23:17:43 +0000 Subject: [PATCH 0711/2822] mmc: cb710: Return err value in cb710_wait_while_busy() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes: drivers/mmc/host/cb710-mmc.c: In function ‘cb710_wait_while_busy’: drivers/mmc/host/cb710-mmc.c:182:6: warning: variable ‘err’ set but not used [-Wunused-but-set-variable] Signed-off-by: Chris Ball Acked-by: Michał Mirosław Acked-by: Wolfram Sang --- drivers/mmc/host/cb710-mmc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mmc/host/cb710-mmc.c b/drivers/mmc/host/cb710-mmc.c index 66b4ce587f4bd..ce2a47b71dd6a 100644 --- a/drivers/mmc/host/cb710-mmc.c +++ b/drivers/mmc/host/cb710-mmc.c @@ -205,7 +205,7 @@ static int cb710_wait_while_busy(struct cb710_slot *slot, uint8_t mask) "WAIT12: waited %d loops, mask %02X, entry val %08X, exit val %08X\n", limit, mask, e, x); #endif - return 0; + return err; } static void cb710_mmc_set_transfer_size(struct cb710_slot *slot, -- GitLab From e7054ba1f73c0a0e2489251499bdbc21b88b4190 Mon Sep 17 00:00:00 2001 From: Chris Ball Date: Wed, 23 Feb 2011 17:29:13 -0500 Subject: [PATCH 0712/2822] mmc: via-sdmmc: Remove set-but-unused variable. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit drivers/mmc/host/via-sdmmc.c: In function ‘via_reset_pcictrl’: drivers/mmc/host/via-sdmmc.c:805:8: warning: variable ‘addrbase’ set but not used [-Wunused-but-set-variable] Signed-off-by: Chris Ball Cc: Harald Welte Acked-by: Wolfram Sang --- drivers/mmc/host/via-sdmmc.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/mmc/host/via-sdmmc.c b/drivers/mmc/host/via-sdmmc.c index 9ed84ddb47806..8c5b4881ccd60 100644 --- a/drivers/mmc/host/via-sdmmc.c +++ b/drivers/mmc/host/via-sdmmc.c @@ -802,12 +802,9 @@ static const struct mmc_host_ops via_sdc_ops = { static void via_reset_pcictrl(struct via_crdr_mmc_host *host) { - void __iomem *addrbase; unsigned long flags; u8 gatt; - addrbase = host->pcictrl_mmiobase; - spin_lock_irqsave(&host->lock, flags); via_save_pcictrlreg(host); -- GitLab From 41babf753cc82ab6208903625a084bf305c32d06 Mon Sep 17 00:00:00 2001 From: Jaehoon Chung Date: Thu, 24 Feb 2011 13:46:11 +0900 Subject: [PATCH 0713/2822] mmc: dw_mmc: support DDR mode This patch adds DDR mode support to dw_mmc. If we set any bit in UHS_REG bit[16:31], the card of that slot is supported for DDR mode. For example, if UHS_REG[16] is set, card number 0 is DDR mode. Signed-off-by: Jaehoon Chung Signed-off-by: Kyungmin Park Acked-by: Will Newton Signed-off-by: Chris Ball --- drivers/mmc/host/dw_mmc.c | 8 ++++++++ drivers/mmc/host/dw_mmc.h | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c index 62c8440ff04b9..58476c1bb0562 100644 --- a/drivers/mmc/host/dw_mmc.c +++ b/drivers/mmc/host/dw_mmc.c @@ -662,6 +662,7 @@ static void dw_mci_request(struct mmc_host *mmc, struct mmc_request *mrq) static void dw_mci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) { struct dw_mci_slot *slot = mmc_priv(mmc); + u32 regs; /* set default 1 bit mode */ slot->ctype = SDMMC_CTYPE_1BIT; @@ -678,6 +679,13 @@ static void dw_mci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) break; } + /* DDR mode set */ + if (ios->ddr) { + regs = mci_readl(slot->host, UHS_REG); + regs |= (0x1 << slot->id) << 16; + mci_writel(slot->host, UHS_REG, regs); + } + if (ios->clock) { /* * Use mirror of ios->clock to prevent race with mmc diff --git a/drivers/mmc/host/dw_mmc.h b/drivers/mmc/host/dw_mmc.h index 5dd55a75233d9..23c662af5616f 100644 --- a/drivers/mmc/host/dw_mmc.h +++ b/drivers/mmc/host/dw_mmc.h @@ -43,6 +43,7 @@ #define SDMMC_USRID 0x068 #define SDMMC_VERID 0x06c #define SDMMC_HCON 0x070 +#define SDMMC_UHS_REG 0x074 #define SDMMC_BMOD 0x080 #define SDMMC_PLDMND 0x084 #define SDMMC_DBADDR 0x088 @@ -51,7 +52,6 @@ #define SDMMC_DSCADDR 0x094 #define SDMMC_BUFADDR 0x098 #define SDMMC_DATA 0x100 -#define SDMMC_DATA_ADR 0x100 /* shift bit field */ #define _SBF(f, v) ((v) << (f)) -- GitLab From ce005cf450b2c1c93e48c45a4cc717e9d104c054 Mon Sep 17 00:00:00 2001 From: Mike Rapoport Date: Wed, 9 Mar 2011 16:31:17 +0200 Subject: [PATCH 0714/2822] ARM: tegra: harmony: update PCI-e initialization sequence On Harmony board PCI-e subsystem can be enabled only after certain voltage regulators are on. One of the regulators is an internal regulator on the PMIC and another one is controlled by a PMIC GPIO. Addition of the voltage control to the Harmony PCI-e initialization allows booting of kernel with CONFIG_TEGRA_PCI even if the PMIC driver is not loaded. In this case the PCI-e initialization will fail gracefully intead of hanging the system. Signed-off-by: Mike Rapoport Signed-off-by: Olof Johansson --- arch/arm/mach-tegra/board-harmony-pcie.c | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/arch/arm/mach-tegra/board-harmony-pcie.c b/arch/arm/mach-tegra/board-harmony-pcie.c index f7e7d4514b6ad..9c27b95b8d869 100644 --- a/arch/arm/mach-tegra/board-harmony-pcie.c +++ b/arch/arm/mach-tegra/board-harmony-pcie.c @@ -27,13 +27,29 @@ #ifdef CONFIG_TEGRA_PCI +/* GPIO 3 of the PMIC */ +#define EN_VDD_1V05_GPIO (TEGRA_NR_GPIOS + 2) + static int __init harmony_pcie_init(void) { + struct regulator *regulator = NULL; int err; if (!machine_is_harmony()) return 0; + err = gpio_request(EN_VDD_1V05_GPIO, "EN_VDD_1V05"); + if (err) + return err; + + gpio_direction_output(EN_VDD_1V05_GPIO, 1); + + regulator = regulator_get(NULL, "pex_clk"); + if (IS_ERR_OR_NULL(regulator)) + goto err_reg; + + regulator_enable(regulator); + tegra_pinmux_set_tristate(TEGRA_PINGROUP_GPV, TEGRA_TRI_NORMAL); tegra_pinmux_set_tristate(TEGRA_PINGROUP_SLXA, TEGRA_TRI_NORMAL); tegra_pinmux_set_tristate(TEGRA_PINGROUP_SLXK, TEGRA_TRI_NORMAL); @@ -49,9 +65,15 @@ err_pcie: tegra_pinmux_set_tristate(TEGRA_PINGROUP_SLXA, TEGRA_TRI_TRISTATE); tegra_pinmux_set_tristate(TEGRA_PINGROUP_SLXK, TEGRA_TRI_TRISTATE); + regulator_disable(regulator); + regulator_put(regulator); +err_reg: + gpio_free(EN_VDD_1V05_GPIO); + return err; } -subsys_initcall(harmony_pcie_init); +/* PCI should be initialized after I2C, mfd and regulators */ +subsys_initcall_sync(harmony_pcie_init); #endif -- GitLab From 944d46b5347c20be3a3f4c36a6d830e126d9735a Mon Sep 17 00:00:00 2001 From: Mike Rapoport Date: Wed, 9 Mar 2011 16:31:19 +0200 Subject: [PATCH 0715/2822] ARM: tegra: update defconfig * Enable TPS6586x PMIC driver * Enable RealTek 8169 used on TrimSlice * Allow booting with root on NFS Signed-off-by: Mike Rapoport Signed-off-by: Olof Johansson --- arch/arm/configs/tegra_defconfig | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/arch/arm/configs/tegra_defconfig b/arch/arm/configs/tegra_defconfig index eb8c31ee4e531..8845f1c9925d9 100644 --- a/arch/arm/configs/tegra_defconfig +++ b/arch/arm/configs/tegra_defconfig @@ -44,6 +44,10 @@ CONFIG_PACKET=y CONFIG_UNIX=y CONFIG_NET_KEY=y CONFIG_INET=y +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +CONFIG_IP_PNP_BOOTP=y +CONFIG_IP_PNP_RARP=y CONFIG_INET_ESP=y # CONFIG_INET_XFRM_MODE_TUNNEL is not set # CONFIG_INET_XFRM_MODE_BEET is not set @@ -70,7 +74,7 @@ CONFIG_APDS9802ALS=y CONFIG_ISL29003=y CONFIG_NETDEVICES=y CONFIG_DUMMY=y -# CONFIG_NETDEV_1000 is not set +CONFIG_R8169=y # CONFIG_NETDEV_10000 is not set # CONFIG_WLAN is not set # CONFIG_INPUT is not set @@ -86,7 +90,9 @@ CONFIG_I2C=y # CONFIG_I2C_HELPER_AUTO is not set CONFIG_I2C_TEGRA=y CONFIG_SENSORS_LM90=y -# CONFIG_MFD_SUPPORT is not set +CONFIG_MFD_TPS6586X=y +CONFIG_REGULATOR=y +CONFIG_REGULATOR_TPS6586X=y # CONFIG_USB_SUPPORT is not set CONFIG_MMC=y CONFIG_MMC_SDHCI=y @@ -108,6 +114,8 @@ CONFIG_EXT3_FS_SECURITY=y # CONFIG_DNOTIFY is not set CONFIG_VFAT_FS=y CONFIG_TMPFS=y +CONFIG_NFS_FS=y +CONFIG_ROOT_NFS=y CONFIG_PARTITION_ADVANCED=y CONFIG_EFI_PARTITION=y CONFIG_NLS_CODEPAGE_437=y -- GitLab From 6f168f2fa60f87e85e0df25e87e2372f22f5eb7c Mon Sep 17 00:00:00 2001 From: Mike Rapoport Date: Wed, 9 Mar 2011 16:31:18 +0200 Subject: [PATCH 0716/2822] ARM: tegra: harmony: initialize the TPS65862 PMIC Initialize the PMIC voltage regulators and provide the supply map for PCI-e clock supply. The rest of the supplies should be added together with the drivers that use them. Signed-off-by: Mike Rapoport CC: Mark Brown Signed-off-by: Olof Johansson --- arch/arm/mach-tegra/Makefile | 1 + arch/arm/mach-tegra/board-harmony-power.c | 117 ++++++++++++++++++++++ arch/arm/mach-tegra/board-harmony.c | 1 + arch/arm/mach-tegra/board-harmony.h | 1 + 4 files changed, 120 insertions(+) create mode 100644 arch/arm/mach-tegra/board-harmony-power.c diff --git a/arch/arm/mach-tegra/Makefile b/arch/arm/mach-tegra/Makefile index 673651f0efb82..bbe1dbe939bb2 100644 --- a/arch/arm/mach-tegra/Makefile +++ b/arch/arm/mach-tegra/Makefile @@ -21,6 +21,7 @@ obj-$(CONFIG_TEGRA_PCI) += pcie.o obj-${CONFIG_MACH_HARMONY} += board-harmony.o obj-${CONFIG_MACH_HARMONY} += board-harmony-pinmux.o obj-${CONFIG_MACH_HARMONY} += board-harmony-pcie.o +obj-${CONFIG_MACH_HARMONY} += board-harmony-power.o obj-${CONFIG_MACH_PAZ00} += board-paz00.o obj-${CONFIG_MACH_PAZ00} += board-paz00-pinmux.o diff --git a/arch/arm/mach-tegra/board-harmony-power.c b/arch/arm/mach-tegra/board-harmony-power.c new file mode 100644 index 0000000000000..c84442cabe077 --- /dev/null +++ b/arch/arm/mach-tegra/board-harmony-power.c @@ -0,0 +1,117 @@ +/* + * Copyright (C) 2010 NVIDIA, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + * 02111-1307, USA + */ +#include +#include +#include + +#include +#include + +#include + +#define PMC_CTRL 0x0 +#define PMC_CTRL_INTR_LOW (1 << 17) + +static struct regulator_consumer_supply tps658621_ldo0_supply[] = { + REGULATOR_SUPPLY("pex_clk", NULL), +}; + +static struct regulator_init_data ldo0_data = { + .constraints = { + .min_uV = 1250 * 1000, + .max_uV = 3300 * 1000, + .valid_modes_mask = (REGULATOR_MODE_NORMAL | + REGULATOR_MODE_STANDBY), + .valid_ops_mask = (REGULATOR_CHANGE_MODE | + REGULATOR_CHANGE_STATUS | + REGULATOR_CHANGE_VOLTAGE), + }, + .num_consumer_supplies = ARRAY_SIZE(tps658621_ldo0_supply), + .consumer_supplies = tps658621_ldo0_supply, +}; + +#define HARMONY_REGULATOR_INIT(_id, _minmv, _maxmv) \ + static struct regulator_init_data _id##_data = { \ + .constraints = { \ + .min_uV = (_minmv)*1000, \ + .max_uV = (_maxmv)*1000, \ + .valid_modes_mask = (REGULATOR_MODE_NORMAL | \ + REGULATOR_MODE_STANDBY), \ + .valid_ops_mask = (REGULATOR_CHANGE_MODE | \ + REGULATOR_CHANGE_STATUS | \ + REGULATOR_CHANGE_VOLTAGE), \ + }, \ + } + +HARMONY_REGULATOR_INIT(sm0, 725, 1500); +HARMONY_REGULATOR_INIT(sm1, 725, 1500); +HARMONY_REGULATOR_INIT(sm2, 3000, 4550); +HARMONY_REGULATOR_INIT(ldo1, 725, 1500); +HARMONY_REGULATOR_INIT(ldo2, 725, 1500); +HARMONY_REGULATOR_INIT(ldo3, 1250, 3300); +HARMONY_REGULATOR_INIT(ldo4, 1700, 2475); +HARMONY_REGULATOR_INIT(ldo5, 1250, 3300); +HARMONY_REGULATOR_INIT(ldo6, 1250, 3300); +HARMONY_REGULATOR_INIT(ldo7, 1250, 3300); +HARMONY_REGULATOR_INIT(ldo8, 1250, 3300); +HARMONY_REGULATOR_INIT(ldo9, 1250, 3300); + +#define TPS_REG(_id, _data) \ + { \ + .id = TPS6586X_ID_##_id, \ + .name = "tps6586x-regulator", \ + .platform_data = _data, \ + } + +static struct tps6586x_subdev_info tps_devs[] = { + TPS_REG(SM_0, &sm0_data), + TPS_REG(SM_1, &sm1_data), + TPS_REG(SM_2, &sm2_data), + TPS_REG(LDO_0, &ldo0_data), + TPS_REG(LDO_1, &ldo1_data), + TPS_REG(LDO_2, &ldo2_data), + TPS_REG(LDO_3, &ldo3_data), + TPS_REG(LDO_4, &ldo4_data), + TPS_REG(LDO_5, &ldo5_data), + TPS_REG(LDO_6, &ldo6_data), + TPS_REG(LDO_7, &ldo7_data), + TPS_REG(LDO_8, &ldo8_data), + TPS_REG(LDO_9, &ldo9_data), +}; + +static struct tps6586x_platform_data tps_platform = { + .irq_base = TEGRA_NR_IRQS, + .num_subdevs = ARRAY_SIZE(tps_devs), + .subdevs = tps_devs, + .gpio_base = TEGRA_NR_GPIOS, +}; + +static struct i2c_board_info __initdata harmony_regulators[] = { + { + I2C_BOARD_INFO("tps6586x", 0x34), + .irq = INT_EXTERNAL_PMU, + .platform_data = &tps_platform, + }, +}; + +int __init harmony_regulator_init(void) +{ + i2c_register_board_info(3, harmony_regulators, 1); + + return 0; +} diff --git a/arch/arm/mach-tegra/board-harmony.c b/arch/arm/mach-tegra/board-harmony.c index e7c2fead1e2fb..75c918a86a31d 100644 --- a/arch/arm/mach-tegra/board-harmony.c +++ b/arch/arm/mach-tegra/board-harmony.c @@ -196,6 +196,7 @@ static void __init tegra_harmony_init(void) platform_add_devices(harmony_devices, ARRAY_SIZE(harmony_devices)); harmony_i2c_init(); + harmony_regulator_init(); } MACHINE_START(HARMONY, "harmony") diff --git a/arch/arm/mach-tegra/board-harmony.h b/arch/arm/mach-tegra/board-harmony.h index 9243521a1d190..1e57b071f52de 100644 --- a/arch/arm/mach-tegra/board-harmony.h +++ b/arch/arm/mach-tegra/board-harmony.h @@ -32,5 +32,6 @@ #define TEGRA_GPIO_EXT_MIC_EN TEGRA_GPIO_PX1 void harmony_pinmux_init(void); +int harmony_regulator_init(void); #endif -- GitLab From 8c4037b501acd2ec3abc7925e66af8af40a2da9d Mon Sep 17 00:00:00 2001 From: David Dillow Date: Fri, 14 Jan 2011 17:02:23 -0500 Subject: [PATCH 0717/2822] IB/srp: always avoid non-zero offsets into an FMR It is unclear exactly how this code works around Mellanox SRP targets, or if the problem is on the target side or in the HCA itself. In an abundance of caution, we should always enable the workaround. Signed-off-by: David Dillow --- drivers/infiniband/ulp/srp/ib_srp.c | 17 +---------------- 1 file changed, 1 insertion(+), 16 deletions(-) diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c index 83664ed2804f9..197e26cc2b0bd 100644 --- a/drivers/infiniband/ulp/srp/ib_srp.c +++ b/drivers/infiniband/ulp/srp/ib_srp.c @@ -72,12 +72,6 @@ module_param(topspin_workarounds, int, 0444); MODULE_PARM_DESC(topspin_workarounds, "Enable workarounds for Topspin/Cisco SRP target bugs if != 0"); -static int mellanox_workarounds = 1; - -module_param(mellanox_workarounds, int, 0444); -MODULE_PARM_DESC(mellanox_workarounds, - "Enable workarounds for Mellanox SRP target bugs if != 0"); - static void srp_add_one(struct ib_device *device); static void srp_remove_one(struct ib_device *device); static void srp_recv_completion(struct ib_cq *cq, void *target_ptr); @@ -114,14 +108,6 @@ static int srp_target_is_topspin(struct srp_target_port *target) !memcmp(&target->ioc_guid, cisco_oui, sizeof cisco_oui)); } -static int srp_target_is_mellanox(struct srp_target_port *target) -{ - static const u8 mellanox_oui[3] = { 0x00, 0x02, 0xc9 }; - - return mellanox_workarounds && - !memcmp(&target->ioc_guid, mellanox_oui, sizeof mellanox_oui); -} - static struct srp_iu *srp_alloc_iu(struct srp_host *host, size_t size, gfp_t gfp_mask, enum dma_data_direction direction) @@ -662,8 +648,7 @@ static int srp_map_fmr(struct srp_target_port *target, struct scatterlist *scat, if (!dev->fmr_pool) return -ENODEV; - if (srp_target_is_mellanox(target) && - (ib_sg_dma_address(ibdev, &scat[0]) & ~dev->fmr_page_mask)) + if (ib_sg_dma_address(ibdev, &scat[0]) & ~dev->fmr_page_mask) return -EINVAL; len = page_cnt = 0; -- GitLab From 961e0be89a5120a1409ebc525cca6f603615a8a8 Mon Sep 17 00:00:00 2001 From: David Dillow Date: Fri, 14 Jan 2011 17:32:07 -0500 Subject: [PATCH 0718/2822] IB/srp: move IB CM setup completion into its own function This is to clean up prior to further changes. Signed-off-by: David Dillow --- drivers/infiniband/ulp/srp/ib_srp.c | 144 ++++++++++++++-------------- 1 file changed, 73 insertions(+), 71 deletions(-) diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c index 197e26cc2b0bd..060e6a84f18fb 100644 --- a/drivers/infiniband/ulp/srp/ib_srp.c +++ b/drivers/infiniband/ulp/srp/ib_srp.c @@ -1213,6 +1213,78 @@ err: return -ENOMEM; } +static void srp_cm_rep_handler(struct ib_cm_id *cm_id, + struct srp_login_rsp *lrsp, + struct srp_target_port *target) +{ + struct ib_qp_attr *qp_attr = NULL; + int attr_mask = 0; + int ret; + int i; + + if (lrsp->opcode == SRP_LOGIN_RSP) { + target->max_ti_iu_len = be32_to_cpu(lrsp->max_ti_iu_len); + target->req_lim = be32_to_cpu(lrsp->req_lim_delta); + + /* + * Reserve credits for task management so we don't + * bounce requests back to the SCSI mid-layer. + */ + target->scsi_host->can_queue + = min(target->req_lim - SRP_TSK_MGMT_SQ_SIZE, + target->scsi_host->can_queue); + } else { + shost_printk(KERN_WARNING, target->scsi_host, + PFX "Unhandled RSP opcode %#x\n", lrsp->opcode); + ret = -ECONNRESET; + goto error; + } + + if (!target->rx_ring[0]) { + ret = srp_alloc_iu_bufs(target); + if (ret) + goto error; + } + + ret = -ENOMEM; + qp_attr = kmalloc(sizeof *qp_attr, GFP_KERNEL); + if (!qp_attr) + goto error; + + qp_attr->qp_state = IB_QPS_RTR; + ret = ib_cm_init_qp_attr(cm_id, qp_attr, &attr_mask); + if (ret) + goto error_free; + + ret = ib_modify_qp(target->qp, qp_attr, attr_mask); + if (ret) + goto error_free; + + for (i = 0; i < SRP_RQ_SIZE; i++) { + struct srp_iu *iu = target->rx_ring[i]; + ret = srp_post_recv(target, iu); + if (ret) + goto error_free; + } + + qp_attr->qp_state = IB_QPS_RTS; + ret = ib_cm_init_qp_attr(cm_id, qp_attr, &attr_mask); + if (ret) + goto error_free; + + ret = ib_modify_qp(target->qp, qp_attr, attr_mask); + if (ret) + goto error_free; + + ret = ib_send_cm_rtu(cm_id, NULL, 0); + +error_free: + kfree(qp_attr); + +error: + target->status = ret; +} + static void srp_cm_rej_handler(struct ib_cm_id *cm_id, struct ib_cm_event *event, struct srp_target_port *target) @@ -1296,11 +1368,7 @@ static void srp_cm_rej_handler(struct ib_cm_id *cm_id, static int srp_cm_handler(struct ib_cm_id *cm_id, struct ib_cm_event *event) { struct srp_target_port *target = cm_id->context; - struct ib_qp_attr *qp_attr = NULL; - int attr_mask = 0; int comp = 0; - int opcode = 0; - int i; switch (event->event) { case IB_CM_REQ_ERROR: @@ -1312,71 +1380,7 @@ static int srp_cm_handler(struct ib_cm_id *cm_id, struct ib_cm_event *event) case IB_CM_REP_RECEIVED: comp = 1; - opcode = *(u8 *) event->private_data; - - if (opcode == SRP_LOGIN_RSP) { - struct srp_login_rsp *rsp = event->private_data; - - target->max_ti_iu_len = be32_to_cpu(rsp->max_ti_iu_len); - target->req_lim = be32_to_cpu(rsp->req_lim_delta); - - /* - * Reserve credits for task management so we don't - * bounce requests back to the SCSI mid-layer. - */ - target->scsi_host->can_queue - = min(target->req_lim - SRP_TSK_MGMT_SQ_SIZE, - target->scsi_host->can_queue); - } else { - shost_printk(KERN_WARNING, target->scsi_host, - PFX "Unhandled RSP opcode %#x\n", opcode); - target->status = -ECONNRESET; - break; - } - - if (!target->rx_ring[0]) { - target->status = srp_alloc_iu_bufs(target); - if (target->status) - break; - } - - qp_attr = kmalloc(sizeof *qp_attr, GFP_KERNEL); - if (!qp_attr) { - target->status = -ENOMEM; - break; - } - - qp_attr->qp_state = IB_QPS_RTR; - target->status = ib_cm_init_qp_attr(cm_id, qp_attr, &attr_mask); - if (target->status) - break; - - target->status = ib_modify_qp(target->qp, qp_attr, attr_mask); - if (target->status) - break; - - for (i = 0; i < SRP_RQ_SIZE; i++) { - struct srp_iu *iu = target->rx_ring[i]; - target->status = srp_post_recv(target, iu); - if (target->status) - break; - } - if (target->status) - break; - - qp_attr->qp_state = IB_QPS_RTS; - target->status = ib_cm_init_qp_attr(cm_id, qp_attr, &attr_mask); - if (target->status) - break; - - target->status = ib_modify_qp(target->qp, qp_attr, attr_mask); - if (target->status) - break; - - target->status = ib_send_cm_rtu(cm_id, NULL, 0); - if (target->status) - break; - + srp_cm_rep_handler(cm_id, event->private_data, target); break; case IB_CM_REJ_RECEIVED: @@ -1416,8 +1420,6 @@ static int srp_cm_handler(struct ib_cm_id *cm_id, struct ib_cm_event *event) if (comp) complete(&target->done); - kfree(qp_attr); - return 0; } -- GitLab From 4924864404d0ce2c32a6d20b27b5b6fcb31e481d Mon Sep 17 00:00:00 2001 From: David Dillow Date: Fri, 14 Jan 2011 18:23:24 -0500 Subject: [PATCH 0719/2822] IB/srp: allow sg_tablesize to be set for each target Different configurations of target software allow differing max sizes of the command IU. Allowing this to be changed per-target allows all targets on an initiator to get an optimal setting. We deprecate srp_sg_tablesize and replace it with cmd_sg_entries in preparation for allowing more indirect descriptors than can fit in the IU. Signed-off-by: David Dillow --- drivers/infiniband/ulp/srp/ib_srp.c | 81 ++++++++++++++++++++--------- drivers/infiniband/ulp/srp/ib_srp.h | 2 + 2 files changed, 59 insertions(+), 24 deletions(-) diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c index 060e6a84f18fb..6f8ee0c7ef5f3 100644 --- a/drivers/infiniband/ulp/srp/ib_srp.c +++ b/drivers/infiniband/ulp/srp/ib_srp.c @@ -59,14 +59,16 @@ MODULE_DESCRIPTION("InfiniBand SCSI RDMA Protocol initiator " "v" DRV_VERSION " (" DRV_RELDATE ")"); MODULE_LICENSE("Dual BSD/GPL"); -static int srp_sg_tablesize = SRP_DEF_SG_TABLESIZE; -static int srp_max_iu_len; +static unsigned int srp_sg_tablesize; +static unsigned int cmd_sg_entries; +static int topspin_workarounds = 1; -module_param(srp_sg_tablesize, int, 0444); -MODULE_PARM_DESC(srp_sg_tablesize, - "Max number of gather/scatter entries per I/O (default is 12, max 255)"); +module_param(srp_sg_tablesize, uint, 0444); +MODULE_PARM_DESC(srp_sg_tablesize, "Deprecated name for cmd_sg_entries"); -static int topspin_workarounds = 1; +module_param(cmd_sg_entries, uint, 0444); +MODULE_PARM_DESC(cmd_sg_entries, + "Default number of gather/scatter entries in the SRP command (default is 12, max 255)"); module_param(topspin_workarounds, int, 0444); MODULE_PARM_DESC(topspin_workarounds, @@ -364,7 +366,7 @@ static int srp_send_req(struct srp_target_port *target) req->priv.opcode = SRP_LOGIN_REQ; req->priv.tag = 0; - req->priv.req_it_iu_len = cpu_to_be32(srp_max_iu_len); + req->priv.req_it_iu_len = cpu_to_be32(target->max_iu_len); req->priv.req_buf_fmt = cpu_to_be16(SRP_BUF_FORMAT_DIRECT | SRP_BUF_FORMAT_INDIRECT); /* @@ -1125,7 +1127,7 @@ static int srp_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *scmnd) spin_unlock_irqrestore(&target->lock, flags); dev = target->srp_host->srp_dev->dev; - ib_dma_sync_single_for_cpu(dev, iu->dma, srp_max_iu_len, + ib_dma_sync_single_for_cpu(dev, iu->dma, target->max_iu_len, DMA_TO_DEVICE); scmnd->result = 0; @@ -1149,7 +1151,7 @@ static int srp_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *scmnd) goto err_iu; } - ib_dma_sync_single_for_device(dev, iu->dma, srp_max_iu_len, + ib_dma_sync_single_for_device(dev, iu->dma, target->max_iu_len, DMA_TO_DEVICE); if (srp_post_send(target, iu, len)) { @@ -1189,7 +1191,7 @@ static int srp_alloc_iu_bufs(struct srp_target_port *target) for (i = 0; i < SRP_SQ_SIZE; ++i) { target->tx_ring[i] = srp_alloc_iu(target->srp_host, - srp_max_iu_len, + target->max_iu_len, GFP_KERNEL, DMA_TO_DEVICE); if (!target->tx_ring[i]) goto err; @@ -1645,6 +1647,14 @@ static ssize_t show_local_ib_device(struct device *dev, return sprintf(buf, "%s\n", target->srp_host->srp_dev->dev->name); } +static ssize_t show_cmd_sg_entries(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct srp_target_port *target = host_to_target(class_to_shost(dev)); + + return sprintf(buf, "%u\n", target->cmd_sg_cnt); +} + static DEVICE_ATTR(id_ext, S_IRUGO, show_id_ext, NULL); static DEVICE_ATTR(ioc_guid, S_IRUGO, show_ioc_guid, NULL); static DEVICE_ATTR(service_id, S_IRUGO, show_service_id, NULL); @@ -1655,6 +1665,7 @@ static DEVICE_ATTR(req_lim, S_IRUGO, show_req_lim, NULL); static DEVICE_ATTR(zero_req_lim, S_IRUGO, show_zero_req_lim, NULL); static DEVICE_ATTR(local_ib_port, S_IRUGO, show_local_ib_port, NULL); static DEVICE_ATTR(local_ib_device, S_IRUGO, show_local_ib_device, NULL); +static DEVICE_ATTR(cmd_sg_entries, S_IRUGO, show_cmd_sg_entries, NULL); static struct device_attribute *srp_host_attrs[] = { &dev_attr_id_ext, @@ -1667,6 +1678,7 @@ static struct device_attribute *srp_host_attrs[] = { &dev_attr_zero_req_lim, &dev_attr_local_ib_port, &dev_attr_local_ib_device, + &dev_attr_cmd_sg_entries, NULL }; @@ -1679,6 +1691,7 @@ static struct scsi_host_template srp_template = { .eh_abort_handler = srp_abort, .eh_device_reset_handler = srp_reset_device, .eh_host_reset_handler = srp_reset_host, + .sg_tablesize = SRP_DEF_SG_TABLESIZE, .can_queue = SRP_CMD_SQ_SIZE, .this_id = -1, .cmd_per_lun = SRP_CMD_SQ_SIZE, @@ -1750,6 +1763,7 @@ enum { SRP_OPT_MAX_CMD_PER_LUN = 1 << 6, SRP_OPT_IO_CLASS = 1 << 7, SRP_OPT_INITIATOR_EXT = 1 << 8, + SRP_OPT_CMD_SG_ENTRIES = 1 << 9, SRP_OPT_ALL = (SRP_OPT_ID_EXT | SRP_OPT_IOC_GUID | SRP_OPT_DGID | @@ -1767,6 +1781,7 @@ static const match_table_t srp_opt_tokens = { { SRP_OPT_MAX_CMD_PER_LUN, "max_cmd_per_lun=%d" }, { SRP_OPT_IO_CLASS, "io_class=%x" }, { SRP_OPT_INITIATOR_EXT, "initiator_ext=%s" }, + { SRP_OPT_CMD_SG_ENTRIES, "cmd_sg_entries=%u" }, { SRP_OPT_ERR, NULL } }; @@ -1894,6 +1909,14 @@ static int srp_parse_options(const char *buf, struct srp_target_port *target) kfree(p); break; + case SRP_OPT_CMD_SG_ENTRIES: + if (match_int(args, &token) || token < 1 || token > 255) { + printk(KERN_WARNING PFX "bad max cmd_sg_entries parameter '%s'\n", p); + goto out; + } + target->cmd_sg_cnt = token; + break; + default: printk(KERN_WARNING PFX "unknown parameter or missing value " "'%s' in target creation request\n", p); @@ -1932,17 +1955,18 @@ static ssize_t srp_create_target(struct device *dev, if (!target_host) return -ENOMEM; - target_host->transportt = ib_srp_transport_template; + target_host->transportt = ib_srp_transport_template; target_host->max_lun = SRP_MAX_LUN; target_host->max_cmd_len = sizeof ((struct srp_cmd *) (void *) 0L)->cdb; target = host_to_target(target_host); - target->io_class = SRP_REV16A_IB_IO_CLASS; - target->scsi_host = target_host; - target->srp_host = host; - target->lkey = host->srp_dev->mr->lkey; - target->rkey = host->srp_dev->mr->rkey; + target->io_class = SRP_REV16A_IB_IO_CLASS; + target->scsi_host = target_host; + target->srp_host = host; + target->lkey = host->srp_dev->mr->lkey; + target->rkey = host->srp_dev->mr->rkey; + target->cmd_sg_cnt = cmd_sg_entries; spin_lock_init(&target->lock); INIT_LIST_HEAD(&target->free_tx); @@ -1956,6 +1980,11 @@ static ssize_t srp_create_target(struct device *dev, if (ret) goto err; + target_host->sg_tablesize = target->cmd_sg_cnt; + target->max_iu_len = sizeof (struct srp_cmd) + + sizeof (struct srp_indirect_buf) + + target->cmd_sg_cnt * sizeof (struct srp_direct_buf); + ib_query_gid(host->srp_dev->dev, host->port, 0, &target->path.sgid); shost_printk(KERN_DEBUG, target->scsi_host, PFX @@ -2217,9 +2246,18 @@ static int __init srp_init_module(void) BUILD_BUG_ON(FIELD_SIZEOF(struct ib_wc, wr_id) < sizeof(void *)); - if (srp_sg_tablesize > 255) { - printk(KERN_WARNING PFX "Clamping srp_sg_tablesize to 255\n"); - srp_sg_tablesize = 255; + if (srp_sg_tablesize) { + printk(KERN_WARNING PFX "srp_sg_tablesize is deprecated, please use cmd_sg_entries\n"); + if (!cmd_sg_entries) + cmd_sg_entries = srp_sg_tablesize; + } + + if (!cmd_sg_entries) + cmd_sg_entries = SRP_DEF_SG_TABLESIZE; + + if (cmd_sg_entries > 255) { + printk(KERN_WARNING PFX "Clamping cmd_sg_entries to 255\n"); + cmd_sg_entries = 255; } ib_srp_transport_template = @@ -2227,11 +2265,6 @@ static int __init srp_init_module(void) if (!ib_srp_transport_template) return -ENOMEM; - srp_template.sg_tablesize = srp_sg_tablesize; - srp_max_iu_len = (sizeof (struct srp_cmd) + - sizeof (struct srp_indirect_buf) + - srp_sg_tablesize * 16); - ret = class_register(&srp_class); if (ret) { printk(KERN_ERR PFX "couldn't register class infiniband_srp\n"); diff --git a/drivers/infiniband/ulp/srp/ib_srp.h b/drivers/infiniband/ulp/srp/ib_srp.h index 9dc6fc3fd894f..db39dbf762160 100644 --- a/drivers/infiniband/ulp/srp/ib_srp.h +++ b/drivers/infiniband/ulp/srp/ib_srp.h @@ -130,6 +130,8 @@ struct srp_target_port { u32 lkey; u32 rkey; enum srp_target_state state; + unsigned int max_iu_len; + unsigned int cmd_sg_cnt; /* Everything above this point is used in the hot path of * command processing. Try to keep them packed into cachelines. -- GitLab From 8f26c9ff9cd0317ad867bce972f69e0c6c2cbe3c Mon Sep 17 00:00:00 2001 From: David Dillow Date: Fri, 14 Jan 2011 19:45:50 -0500 Subject: [PATCH 0720/2822] IB/srp: rework mapping engine to use multiple FMR entries Instead of forcing all of the S/G entries to fit in one FMR, and falling back to indirect descriptors if that fails, allow the use of as many FMRs as needed to map the request. This lays the groundwork for allowing indirect descriptor tables that are larger than can fit in the command IU, but should marginally improve performance now by reducing the number of indirect descriptors needed. We increase the minimum page size for the FMR pool to 4K, as larger pages help increase the coverage of each FMR, and it is rare that the kernel would send down a request with scattered 512 byte fragments. This patch also move some of the target initialization code afte the parsing of options, to keep it together with the new code that needs to allocate memory based on the options given. Signed-off-by: David Dillow --- drivers/infiniband/ulp/srp/ib_srp.c | 367 ++++++++++++++++++---------- drivers/infiniband/ulp/srp/ib_srp.h | 28 ++- 2 files changed, 266 insertions(+), 129 deletions(-) diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c index 6f8ee0c7ef5f3..9ce129ab3beb3 100644 --- a/drivers/infiniband/ulp/srp/ib_srp.c +++ b/drivers/infiniband/ulp/srp/ib_srp.c @@ -444,6 +444,17 @@ static bool srp_change_state(struct srp_target_port *target, return changed; } +static void srp_free_req_data(struct srp_target_port *target) +{ + struct srp_request *req; + int i; + + for (i = 0, req = target->req_ring; i < SRP_CMD_SQ_SIZE; ++i, ++req) { + kfree(req->fmr_list); + kfree(req->map_page); + } +} + static void srp_remove_work(struct work_struct *work) { struct srp_target_port *target = @@ -460,6 +471,7 @@ static void srp_remove_work(struct work_struct *work) scsi_remove_host(target->scsi_host); ib_destroy_cm_id(target->cm_id); srp_free_target_ib(target); + srp_free_req_data(target); scsi_host_put(target->scsi_host); } @@ -523,18 +535,20 @@ static void srp_unmap_data(struct scsi_cmnd *scmnd, struct srp_target_port *target, struct srp_request *req) { + struct ib_device *ibdev = target->srp_host->srp_dev->dev; + struct ib_pool_fmr **pfmr; + if (!scsi_sglist(scmnd) || (scmnd->sc_data_direction != DMA_TO_DEVICE && scmnd->sc_data_direction != DMA_FROM_DEVICE)) return; - if (req->fmr) { - ib_fmr_pool_unmap(req->fmr); - req->fmr = NULL; - } + pfmr = req->fmr_list; + while (req->nfmr--) + ib_fmr_pool_unmap(*pfmr++); - ib_dma_unmap_sg(target->srp_host->srp_dev->dev, scsi_sglist(scmnd), - scsi_sg_count(scmnd), scmnd->sc_data_direction); + ib_dma_unmap_sg(ibdev, scsi_sglist(scmnd), scsi_sg_count(scmnd), + scmnd->sc_data_direction); } static void srp_remove_req(struct srp_target_port *target, @@ -633,95 +647,152 @@ err: return ret; } -static int srp_map_fmr(struct srp_target_port *target, struct scatterlist *scat, - int sg_cnt, struct srp_request *req, - struct srp_direct_buf *buf) +static void srp_map_desc(struct srp_map_state *state, dma_addr_t dma_addr, + unsigned int dma_len, u32 rkey) { - u64 io_addr = 0; - u64 *dma_pages; - u32 len; - int page_cnt; - int i, j; - int ret; - struct srp_device *dev = target->srp_host->srp_dev; - struct ib_device *ibdev = dev->dev; - struct scatterlist *sg; + struct srp_direct_buf *desc = state->desc; - if (!dev->fmr_pool) - return -ENODEV; + desc->va = cpu_to_be64(dma_addr); + desc->key = cpu_to_be32(rkey); + desc->len = cpu_to_be32(dma_len); - if (ib_sg_dma_address(ibdev, &scat[0]) & ~dev->fmr_page_mask) - return -EINVAL; + state->total_len += dma_len; + state->desc++; + state->ndesc++; +} - len = page_cnt = 0; - scsi_for_each_sg(req->scmnd, sg, sg_cnt, i) { - unsigned int dma_len = ib_sg_dma_len(ibdev, sg); +static int srp_map_finish_fmr(struct srp_map_state *state, + struct srp_target_port *target) +{ + struct srp_device *dev = target->srp_host->srp_dev; + struct ib_pool_fmr *fmr; + u64 io_addr = 0; - if (ib_sg_dma_address(ibdev, sg) & ~dev->fmr_page_mask) { - if (i > 0) - return -EINVAL; - else - ++page_cnt; - } - if ((ib_sg_dma_address(ibdev, sg) + dma_len) & - ~dev->fmr_page_mask) { - if (i < sg_cnt - 1) - return -EINVAL; - else - ++page_cnt; - } + if (!state->npages) + return 0; - len += dma_len; + if (state->npages == 1) { + srp_map_desc(state, state->base_dma_addr, state->fmr_len, + target->rkey); + state->npages = state->fmr_len = 0; + return 0; } - page_cnt += len >> dev->fmr_page_shift; - if (page_cnt > SRP_FMR_SIZE) - return -ENOMEM; + fmr = ib_fmr_pool_map_phys(dev->fmr_pool, state->pages, + state->npages, io_addr); + if (IS_ERR(fmr)) + return PTR_ERR(fmr); - dma_pages = kmalloc(sizeof (u64) * page_cnt, GFP_ATOMIC); - if (!dma_pages) - return -ENOMEM; + *state->next_fmr++ = fmr; + state->nfmr++; - page_cnt = 0; - scsi_for_each_sg(req->scmnd, sg, sg_cnt, i) { - unsigned int dma_len = ib_sg_dma_len(ibdev, sg); + srp_map_desc(state, 0, state->fmr_len, fmr->fmr->rkey); + state->npages = state->fmr_len = 0; + return 0; +} + +static void srp_map_update_start(struct srp_map_state *state, + struct scatterlist *sg, int sg_index, + dma_addr_t dma_addr) +{ + state->unmapped_sg = sg; + state->unmapped_index = sg_index; + state->unmapped_addr = dma_addr; +} - for (j = 0; j < dma_len; j += dev->fmr_page_size) - dma_pages[page_cnt++] = - (ib_sg_dma_address(ibdev, sg) & - dev->fmr_page_mask) + j; +static int srp_map_sg_entry(struct srp_map_state *state, + struct srp_target_port *target, + struct scatterlist *sg, int sg_index, + int use_fmr) +{ + struct srp_device *dev = target->srp_host->srp_dev; + struct ib_device *ibdev = dev->dev; + dma_addr_t dma_addr = ib_sg_dma_address(ibdev, sg); + unsigned int dma_len = ib_sg_dma_len(ibdev, sg); + unsigned int len; + int ret; + + if (!dma_len) + return 0; + + if (use_fmr == SRP_MAP_NO_FMR) { + /* Once we're in direct map mode for a request, we don't + * go back to FMR mode, so no need to update anything + * other than the descriptor. + */ + srp_map_desc(state, dma_addr, dma_len, target->rkey); + return 0; } - req->fmr = ib_fmr_pool_map_phys(dev->fmr_pool, - dma_pages, page_cnt, io_addr); - if (IS_ERR(req->fmr)) { - ret = PTR_ERR(req->fmr); - req->fmr = NULL; - goto out; + /* If we start at an offset into the FMR page, don't merge into + * the current FMR. Finish it out, and use the kernel's MR for this + * sg entry. This is to avoid potential bugs on some SRP targets + * that were never quite defined, but went away when the initiator + * avoided using FMR on such page fragments. + */ + if (dma_addr & ~dev->fmr_page_mask || dma_len > dev->fmr_max_size) { + ret = srp_map_finish_fmr(state, target); + if (ret) + return ret; + + srp_map_desc(state, dma_addr, dma_len, target->rkey); + srp_map_update_start(state, NULL, 0, 0); + return 0; } - buf->va = cpu_to_be64(ib_sg_dma_address(ibdev, &scat[0]) & - ~dev->fmr_page_mask); - buf->key = cpu_to_be32(req->fmr->fmr->rkey); - buf->len = cpu_to_be32(len); + /* If this is the first sg to go into the FMR, save our position. + * We need to know the first unmapped entry, its index, and the + * first unmapped address within that entry to be able to restart + * mapping after an error. + */ + if (!state->unmapped_sg) + srp_map_update_start(state, sg, sg_index, dma_addr); - ret = 0; + while (dma_len) { + if (state->npages == SRP_FMR_SIZE) { + ret = srp_map_finish_fmr(state, target); + if (ret) + return ret; -out: - kfree(dma_pages); + srp_map_update_start(state, sg, sg_index, dma_addr); + } + + len = min_t(unsigned int, dma_len, dev->fmr_page_size); + if (!state->npages) + state->base_dma_addr = dma_addr; + state->pages[state->npages++] = dma_addr; + state->fmr_len += len; + dma_addr += len; + dma_len -= len; + } + + /* If the last entry of the FMR wasn't a full page, then we need to + * close it out and start a new one -- we can only merge at page + * boundries. + */ + ret = 0; + if (len != dev->fmr_page_size) { + ret = srp_map_finish_fmr(state, target); + if (!ret) + srp_map_update_start(state, NULL, 0, 0); + } return ret; } static int srp_map_data(struct scsi_cmnd *scmnd, struct srp_target_port *target, struct srp_request *req) { - struct scatterlist *scat; + struct scatterlist *scat, *sg; struct srp_cmd *cmd = req->cmd->buf; - int len, nents, count; - u8 fmt = SRP_DATA_DESC_DIRECT; + int i, len, nents, count, use_fmr; struct srp_device *dev; struct ib_device *ibdev; + struct srp_map_state state; + struct srp_indirect_buf *indirect_hdr; + dma_addr_t indirect_addr; + u32 table_len; + u8 fmt; if (!scsi_sglist(scmnd) || scmnd->sc_data_direction == DMA_NONE) return sizeof (struct srp_cmd); @@ -741,6 +812,8 @@ static int srp_map_data(struct scsi_cmnd *scmnd, struct srp_target_port *target, ibdev = dev->dev; count = ib_dma_map_sg(ibdev, scat, nents, scmnd->sc_data_direction); + if (unlikely(count == 0)) + return -EIO; fmt = SRP_DATA_DESC_DIRECT; len = sizeof (struct srp_cmd) + sizeof (struct srp_direct_buf); @@ -757,49 +830,80 @@ static int srp_map_data(struct scsi_cmnd *scmnd, struct srp_target_port *target, buf->va = cpu_to_be64(ib_sg_dma_address(ibdev, scat)); buf->key = cpu_to_be32(target->rkey); buf->len = cpu_to_be32(ib_sg_dma_len(ibdev, scat)); - } else if (srp_map_fmr(target, scat, count, req, - (void *) cmd->add_data)) { - /* - * FMR mapping failed, and the scatterlist has more - * than one entry. Generate an indirect memory - * descriptor. - */ - struct srp_indirect_buf *buf = (void *) cmd->add_data; - struct scatterlist *sg; - u32 datalen = 0; - int i; - - fmt = SRP_DATA_DESC_INDIRECT; - len = sizeof (struct srp_cmd) + - sizeof (struct srp_indirect_buf) + - count * sizeof (struct srp_direct_buf); - - scsi_for_each_sg(scmnd, sg, count, i) { - unsigned int dma_len = ib_sg_dma_len(ibdev, sg); - - buf->desc_list[i].va = - cpu_to_be64(ib_sg_dma_address(ibdev, sg)); - buf->desc_list[i].key = - cpu_to_be32(target->rkey); - buf->desc_list[i].len = cpu_to_be32(dma_len); - datalen += dma_len; + + req->nfmr = 0; + goto map_complete; + } + + /* We have more than one scatter/gather entry, so build our indirect + * descriptor table, trying to merge as many entries with FMR as we + * can. + */ + indirect_hdr = (void *) cmd->add_data; + + memset(&state, 0, sizeof(state)); + state.desc = indirect_hdr->desc_list; + state.pages = req->map_page; + state.next_fmr = req->fmr_list; + + use_fmr = dev->fmr_pool ? SRP_MAP_ALLOW_FMR : SRP_MAP_NO_FMR; + + for_each_sg(scat, sg, count, i) { + if (srp_map_sg_entry(&state, target, sg, i, use_fmr)) { + /* FMR mapping failed, so backtrack to the first + * unmapped entry and continue on without using FMR. + */ + dma_addr_t dma_addr; + unsigned int dma_len; + +backtrack: + sg = state.unmapped_sg; + i = state.unmapped_index; + + dma_addr = ib_sg_dma_address(ibdev, sg); + dma_len = ib_sg_dma_len(ibdev, sg); + dma_len -= (state.unmapped_addr - dma_addr); + dma_addr = state.unmapped_addr; + use_fmr = SRP_MAP_NO_FMR; + srp_map_desc(&state, dma_addr, dma_len, target->rkey); } + } - if (scmnd->sc_data_direction == DMA_TO_DEVICE) - cmd->data_out_desc_cnt = count; - else - cmd->data_in_desc_cnt = count; + if (use_fmr == SRP_MAP_ALLOW_FMR && srp_map_finish_fmr(&state, target)) + goto backtrack; - buf->table_desc.va = - cpu_to_be64(req->cmd->dma + sizeof *cmd + sizeof *buf); - buf->table_desc.key = - cpu_to_be32(target->rkey); - buf->table_desc.len = - cpu_to_be32(count * sizeof (struct srp_direct_buf)); + /* We've mapped the request, fill in the command buffer. + */ + req->nfmr = state.nfmr; + if (state.ndesc == 1) { + /* FMR mapping was able to collapse this to one entry, + * so use a direct descriptor. + */ + struct srp_direct_buf *buf = (void *) cmd->add_data; - buf->len = cpu_to_be32(datalen); + *buf = indirect_hdr->desc_list[0]; + goto map_complete; } + table_len = state.ndesc * sizeof (struct srp_direct_buf); + + fmt = SRP_DATA_DESC_INDIRECT; + len = sizeof(struct srp_cmd) + sizeof (struct srp_indirect_buf); + len += table_len; + + indirect_addr = req->cmd->dma + sizeof *cmd + sizeof *indirect_hdr; + + indirect_hdr->table_desc.va = cpu_to_be64(indirect_addr); + indirect_hdr->table_desc.key = cpu_to_be32(target->rkey); + indirect_hdr->table_desc.len = cpu_to_be32(table_len); + indirect_hdr->len = cpu_to_be32(state.total_len); + + if (scmnd->sc_data_direction == DMA_TO_DEVICE) + cmd->data_out_desc_cnt = state.ndesc; + else + cmd->data_in_desc_cnt = state.ndesc; + +map_complete: if (scmnd->sc_data_direction == DMA_TO_DEVICE) cmd->buf_fmt = fmt << 4; else @@ -1947,8 +2051,7 @@ static ssize_t srp_create_target(struct device *dev, container_of(dev, struct srp_host, dev); struct Scsi_Host *target_host; struct srp_target_port *target; - int ret; - int i; + int i, ret; target_host = scsi_host_alloc(&srp_template, sizeof (struct srp_target_port)); @@ -1968,14 +2071,6 @@ static ssize_t srp_create_target(struct device *dev, target->rkey = host->srp_dev->mr->rkey; target->cmd_sg_cnt = cmd_sg_entries; - spin_lock_init(&target->lock); - INIT_LIST_HEAD(&target->free_tx); - INIT_LIST_HEAD(&target->free_reqs); - for (i = 0; i < SRP_CMD_SQ_SIZE; ++i) { - target->req_ring[i].index = i; - list_add_tail(&target->req_ring[i].list, &target->free_reqs); - } - ret = srp_parse_options(buf, target); if (ret) goto err; @@ -1985,6 +2080,23 @@ static ssize_t srp_create_target(struct device *dev, sizeof (struct srp_indirect_buf) + target->cmd_sg_cnt * sizeof (struct srp_direct_buf); + spin_lock_init(&target->lock); + INIT_LIST_HEAD(&target->free_tx); + INIT_LIST_HEAD(&target->free_reqs); + for (i = 0; i < SRP_CMD_SQ_SIZE; ++i) { + struct srp_request *req = &target->req_ring[i]; + + req->fmr_list = kmalloc(target->cmd_sg_cnt * sizeof (void *), + GFP_KERNEL); + req->map_page = kmalloc(SRP_FMR_SIZE * sizeof (void *), + GFP_KERNEL); + if (!req->fmr_list || !req->map_page) + goto err_free_mem; + + req->index = i; + list_add_tail(&req->list, &target->free_reqs); + } + ib_query_gid(host->srp_dev->dev, host->port, 0, &target->path.sgid); shost_printk(KERN_DEBUG, target->scsi_host, PFX @@ -1998,11 +2110,11 @@ static ssize_t srp_create_target(struct device *dev, ret = srp_create_target_ib(target); if (ret) - goto err; + goto err_free_mem; ret = srp_new_cm_id(target); if (ret) - goto err_free; + goto err_free_ib; target->qp_in_error = 0; ret = srp_connect_target(target); @@ -2024,9 +2136,12 @@ err_disconnect: err_cm_id: ib_destroy_cm_id(target->cm_id); -err_free: +err_free_ib: srp_free_target_ib(target); +err_free_mem: + srp_free_req_data(target); + err: scsi_host_put(target_host); @@ -2099,7 +2214,7 @@ static void srp_add_one(struct ib_device *device) struct ib_device_attr *dev_attr; struct ib_fmr_pool_param fmr_param; struct srp_host *host; - int s, e, p; + int fmr_page_shift, s, e, p; dev_attr = kmalloc(sizeof *dev_attr, GFP_KERNEL); if (!dev_attr) @@ -2117,12 +2232,13 @@ static void srp_add_one(struct ib_device *device) /* * Use the smallest page size supported by the HCA, down to a - * minimum of 512 bytes (which is the smallest sector that a - * SCSI command will ever carry). + * minimum of 4096 bytes. We're unlikely to build large sglists + * out of smaller entries. */ - srp_dev->fmr_page_shift = max(9, ffs(dev_attr->page_size_cap) - 1); - srp_dev->fmr_page_size = 1 << srp_dev->fmr_page_shift; - srp_dev->fmr_page_mask = ~((u64) srp_dev->fmr_page_size - 1); + fmr_page_shift = max(12, ffs(dev_attr->page_size_cap) - 1); + srp_dev->fmr_page_size = 1 << fmr_page_shift; + srp_dev->fmr_page_mask = ~((u64) srp_dev->fmr_page_size - 1); + srp_dev->fmr_max_size = srp_dev->fmr_page_size * SRP_FMR_SIZE; INIT_LIST_HEAD(&srp_dev->dev_list); @@ -2143,7 +2259,7 @@ static void srp_add_one(struct ib_device *device) fmr_param.dirty_watermark = SRP_FMR_DIRTY_SIZE; fmr_param.cache = 1; fmr_param.max_pages_per_fmr = SRP_FMR_SIZE; - fmr_param.page_shift = srp_dev->fmr_page_shift; + fmr_param.page_shift = fmr_page_shift; fmr_param.access = (IB_ACCESS_LOCAL_WRITE | IB_ACCESS_REMOTE_WRITE | IB_ACCESS_REMOTE_READ); @@ -2223,6 +2339,7 @@ static void srp_remove_one(struct ib_device *device) srp_disconnect_target(target); ib_destroy_cm_id(target->cm_id); srp_free_target_ib(target); + srp_free_req_data(target); scsi_host_put(target->scsi_host); } diff --git a/drivers/infiniband/ulp/srp/ib_srp.h b/drivers/infiniband/ulp/srp/ib_srp.h index db39dbf762160..b43b5e7acbde4 100644 --- a/drivers/infiniband/ulp/srp/ib_srp.h +++ b/drivers/infiniband/ulp/srp/ib_srp.h @@ -71,7 +71,10 @@ enum { SRP_FMR_SIZE = 256, SRP_FMR_POOL_SIZE = 1024, - SRP_FMR_DIRTY_SIZE = SRP_FMR_POOL_SIZE / 4 + SRP_FMR_DIRTY_SIZE = SRP_FMR_POOL_SIZE / 4, + + SRP_MAP_ALLOW_FMR = 0, + SRP_MAP_NO_FMR = 1, }; enum srp_target_state { @@ -93,9 +96,9 @@ struct srp_device { struct ib_pd *pd; struct ib_mr *mr; struct ib_fmr_pool *fmr_pool; - int fmr_page_shift; - int fmr_page_size; u64 fmr_page_mask; + int fmr_page_size; + int fmr_max_size; }; struct srp_host { @@ -112,7 +115,9 @@ struct srp_request { struct list_head list; struct scsi_cmnd *scmnd; struct srp_iu *cmd; - struct ib_pool_fmr *fmr; + struct ib_pool_fmr **fmr_list; + u64 *map_page; + short nfmr; short index; }; @@ -181,4 +186,19 @@ struct srp_iu { enum dma_data_direction direction; }; +struct srp_map_state { + struct ib_pool_fmr **next_fmr; + struct srp_direct_buf *desc; + u64 *pages; + dma_addr_t base_dma_addr; + u32 fmr_len; + u32 total_len; + unsigned int npages; + unsigned int nfmr; + unsigned int ndesc; + struct scatterlist *unmapped_sg; + int unmapped_index; + dma_addr_t unmapped_addr; +}; + #endif /* IB_SRP_H */ -- GitLab From c07d424d6118d528ef71b22b7424bfc359c307a5 Mon Sep 17 00:00:00 2001 From: David Dillow Date: Sun, 16 Jan 2011 13:57:10 -0500 Subject: [PATCH 0721/2822] IB/srp: add support for indirect tables that don't fit in SRP_CMD This allows us to guarantee the ability to submit up to 8 MB requests based on the current value of SCSI_MAX_SG_CHAIN_SEGMENTS. While FMR will usually condense the requests into 8 SG entries, it is imperative that the target support external tables in case the FMR mapping fails or is not supported. We add a safety valve to allow targets without the needed support to reap the benefits of the large tables, but fail in a manner that lets the user know that the data didn't make it to the device. The user must add "allow_ext_sg=1" to the target parameters to indicate that the target has the needed support. If indirect_sg_entries is not specified in the modules options, then the sg_tablesize for the target will default to cmd_sg_entries unless overridden by the target options. Signed-off-by: David Dillow --- drivers/infiniband/ulp/srp/ib_srp.c | 117 +++++++++++++++++++++++++--- drivers/infiniband/ulp/srp/ib_srp.h | 5 ++ 2 files changed, 110 insertions(+), 12 deletions(-) diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c index 9ce129ab3beb3..4ec7dddbbf490 100644 --- a/drivers/infiniband/ulp/srp/ib_srp.c +++ b/drivers/infiniband/ulp/srp/ib_srp.c @@ -61,6 +61,8 @@ MODULE_LICENSE("Dual BSD/GPL"); static unsigned int srp_sg_tablesize; static unsigned int cmd_sg_entries; +static unsigned int indirect_sg_entries; +static bool allow_ext_sg; static int topspin_workarounds = 1; module_param(srp_sg_tablesize, uint, 0444); @@ -70,6 +72,14 @@ module_param(cmd_sg_entries, uint, 0444); MODULE_PARM_DESC(cmd_sg_entries, "Default number of gather/scatter entries in the SRP command (default is 12, max 255)"); +module_param(indirect_sg_entries, uint, 0444); +MODULE_PARM_DESC(indirect_sg_entries, + "Default max number of gather/scatter entries (default is 12, max is " __stringify(SCSI_MAX_SG_CHAIN_SEGMENTS) ")"); + +module_param(allow_ext_sg, bool, 0444); +MODULE_PARM_DESC(allow_ext_sg, + "Default behavior when there are more than cmd_sg_entries S/G entries after mapping; fails the request when false (default false)"); + module_param(topspin_workarounds, int, 0444); MODULE_PARM_DESC(topspin_workarounds, "Enable workarounds for Topspin/Cisco SRP target bugs if != 0"); @@ -446,12 +456,19 @@ static bool srp_change_state(struct srp_target_port *target, static void srp_free_req_data(struct srp_target_port *target) { + struct ib_device *ibdev = target->srp_host->srp_dev->dev; struct srp_request *req; int i; for (i = 0, req = target->req_ring; i < SRP_CMD_SQ_SIZE; ++i, ++req) { kfree(req->fmr_list); kfree(req->map_page); + if (req->indirect_dma_addr) { + ib_dma_unmap_single(ibdev, req->indirect_dma_addr, + target->indirect_size, + DMA_TO_DEVICE); + } + kfree(req->indirect_desc); } } @@ -790,7 +807,6 @@ static int srp_map_data(struct scsi_cmnd *scmnd, struct srp_target_port *target, struct ib_device *ibdev; struct srp_map_state state; struct srp_indirect_buf *indirect_hdr; - dma_addr_t indirect_addr; u32 table_len; u8 fmt; @@ -841,8 +857,11 @@ static int srp_map_data(struct scsi_cmnd *scmnd, struct srp_target_port *target, */ indirect_hdr = (void *) cmd->add_data; + ib_dma_sync_single_for_cpu(ibdev, req->indirect_dma_addr, + target->indirect_size, DMA_TO_DEVICE); + memset(&state, 0, sizeof(state)); - state.desc = indirect_hdr->desc_list; + state.desc = req->indirect_desc; state.pages = req->map_page; state.next_fmr = req->fmr_list; @@ -872,7 +891,11 @@ backtrack: if (use_fmr == SRP_MAP_ALLOW_FMR && srp_map_finish_fmr(&state, target)) goto backtrack; - /* We've mapped the request, fill in the command buffer. + /* We've mapped the request, now pull as much of the indirect + * descriptor table as we can into the command buffer. If this + * target is not using an external indirect table, we are + * guaranteed to fit into the command, as the SCSI layer won't + * give us more S/G entries than we allow. */ req->nfmr = state.nfmr; if (state.ndesc == 1) { @@ -881,27 +904,39 @@ backtrack: */ struct srp_direct_buf *buf = (void *) cmd->add_data; - *buf = indirect_hdr->desc_list[0]; + *buf = req->indirect_desc[0]; goto map_complete; } + if (unlikely(target->cmd_sg_cnt < state.ndesc && + !target->allow_ext_sg)) { + shost_printk(KERN_ERR, target->scsi_host, + "Could not fit S/G list into SRP_CMD\n"); + return -EIO; + } + + count = min(state.ndesc, target->cmd_sg_cnt); table_len = state.ndesc * sizeof (struct srp_direct_buf); fmt = SRP_DATA_DESC_INDIRECT; len = sizeof(struct srp_cmd) + sizeof (struct srp_indirect_buf); - len += table_len; + len += count * sizeof (struct srp_direct_buf); - indirect_addr = req->cmd->dma + sizeof *cmd + sizeof *indirect_hdr; + memcpy(indirect_hdr->desc_list, req->indirect_desc, + count * sizeof (struct srp_direct_buf)); - indirect_hdr->table_desc.va = cpu_to_be64(indirect_addr); + indirect_hdr->table_desc.va = cpu_to_be64(req->indirect_dma_addr); indirect_hdr->table_desc.key = cpu_to_be32(target->rkey); indirect_hdr->table_desc.len = cpu_to_be32(table_len); indirect_hdr->len = cpu_to_be32(state.total_len); if (scmnd->sc_data_direction == DMA_TO_DEVICE) - cmd->data_out_desc_cnt = state.ndesc; + cmd->data_out_desc_cnt = count; else - cmd->data_in_desc_cnt = state.ndesc; + cmd->data_in_desc_cnt = count; + + ib_dma_sync_single_for_device(ibdev, req->indirect_dma_addr, table_len, + DMA_TO_DEVICE); map_complete: if (scmnd->sc_data_direction == DMA_TO_DEVICE) @@ -1759,6 +1794,14 @@ static ssize_t show_cmd_sg_entries(struct device *dev, return sprintf(buf, "%u\n", target->cmd_sg_cnt); } +static ssize_t show_allow_ext_sg(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct srp_target_port *target = host_to_target(class_to_shost(dev)); + + return sprintf(buf, "%s\n", target->allow_ext_sg ? "true" : "false"); +} + static DEVICE_ATTR(id_ext, S_IRUGO, show_id_ext, NULL); static DEVICE_ATTR(ioc_guid, S_IRUGO, show_ioc_guid, NULL); static DEVICE_ATTR(service_id, S_IRUGO, show_service_id, NULL); @@ -1770,6 +1813,7 @@ static DEVICE_ATTR(zero_req_lim, S_IRUGO, show_zero_req_lim, NULL); static DEVICE_ATTR(local_ib_port, S_IRUGO, show_local_ib_port, NULL); static DEVICE_ATTR(local_ib_device, S_IRUGO, show_local_ib_device, NULL); static DEVICE_ATTR(cmd_sg_entries, S_IRUGO, show_cmd_sg_entries, NULL); +static DEVICE_ATTR(allow_ext_sg, S_IRUGO, show_allow_ext_sg, NULL); static struct device_attribute *srp_host_attrs[] = { &dev_attr_id_ext, @@ -1783,6 +1827,7 @@ static struct device_attribute *srp_host_attrs[] = { &dev_attr_local_ib_port, &dev_attr_local_ib_device, &dev_attr_cmd_sg_entries, + &dev_attr_allow_ext_sg, NULL }; @@ -1868,6 +1913,8 @@ enum { SRP_OPT_IO_CLASS = 1 << 7, SRP_OPT_INITIATOR_EXT = 1 << 8, SRP_OPT_CMD_SG_ENTRIES = 1 << 9, + SRP_OPT_ALLOW_EXT_SG = 1 << 10, + SRP_OPT_SG_TABLESIZE = 1 << 11, SRP_OPT_ALL = (SRP_OPT_ID_EXT | SRP_OPT_IOC_GUID | SRP_OPT_DGID | @@ -1886,6 +1933,8 @@ static const match_table_t srp_opt_tokens = { { SRP_OPT_IO_CLASS, "io_class=%x" }, { SRP_OPT_INITIATOR_EXT, "initiator_ext=%s" }, { SRP_OPT_CMD_SG_ENTRIES, "cmd_sg_entries=%u" }, + { SRP_OPT_ALLOW_EXT_SG, "allow_ext_sg=%u" }, + { SRP_OPT_SG_TABLESIZE, "sg_tablesize=%u" }, { SRP_OPT_ERR, NULL } }; @@ -2021,6 +2070,23 @@ static int srp_parse_options(const char *buf, struct srp_target_port *target) target->cmd_sg_cnt = token; break; + case SRP_OPT_ALLOW_EXT_SG: + if (match_int(args, &token)) { + printk(KERN_WARNING PFX "bad allow_ext_sg parameter '%s'\n", p); + goto out; + } + target->allow_ext_sg = !!token; + break; + + case SRP_OPT_SG_TABLESIZE: + if (match_int(args, &token) || token < 1 || + token > SCSI_MAX_SG_CHAIN_SEGMENTS) { + printk(KERN_WARNING PFX "bad max sg_tablesize parameter '%s'\n", p); + goto out; + } + target->sg_tablesize = token; + break; + default: printk(KERN_WARNING PFX "unknown parameter or missing value " "'%s' in target creation request\n", p); @@ -2051,6 +2117,8 @@ static ssize_t srp_create_target(struct device *dev, container_of(dev, struct srp_host, dev); struct Scsi_Host *target_host; struct srp_target_port *target; + struct ib_device *ibdev = host->srp_dev->dev; + dma_addr_t dma_addr; int i, ret; target_host = scsi_host_alloc(&srp_template, @@ -2070,12 +2138,22 @@ static ssize_t srp_create_target(struct device *dev, target->lkey = host->srp_dev->mr->lkey; target->rkey = host->srp_dev->mr->rkey; target->cmd_sg_cnt = cmd_sg_entries; + target->sg_tablesize = indirect_sg_entries ? : cmd_sg_entries; + target->allow_ext_sg = allow_ext_sg; ret = srp_parse_options(buf, target); if (ret) goto err; - target_host->sg_tablesize = target->cmd_sg_cnt; + if (!host->srp_dev->fmr_pool && !target->allow_ext_sg && + target->cmd_sg_cnt < target->sg_tablesize) { + printk(KERN_WARNING PFX "No FMR pool and no external indirect descriptors, limiting sg_tablesize to cmd_sg_cnt\n"); + target->sg_tablesize = target->cmd_sg_cnt; + } + + target_host->sg_tablesize = target->sg_tablesize; + target->indirect_size = target->sg_tablesize * + sizeof (struct srp_direct_buf); target->max_iu_len = sizeof (struct srp_cmd) + sizeof (struct srp_indirect_buf) + target->cmd_sg_cnt * sizeof (struct srp_direct_buf); @@ -2090,14 +2168,22 @@ static ssize_t srp_create_target(struct device *dev, GFP_KERNEL); req->map_page = kmalloc(SRP_FMR_SIZE * sizeof (void *), GFP_KERNEL); - if (!req->fmr_list || !req->map_page) + req->indirect_desc = kmalloc(target->indirect_size, GFP_KERNEL); + if (!req->fmr_list || !req->map_page || !req->indirect_desc) goto err_free_mem; + dma_addr = ib_dma_map_single(ibdev, req->indirect_desc, + target->indirect_size, + DMA_TO_DEVICE); + if (ib_dma_mapping_error(ibdev, dma_addr)) + goto err_free_mem; + + req->indirect_dma_addr = dma_addr; req->index = i; list_add_tail(&req->list, &target->free_reqs); } - ib_query_gid(host->srp_dev->dev, host->port, 0, &target->path.sgid); + ib_query_gid(ibdev, host->port, 0, &target->path.sgid); shost_printk(KERN_DEBUG, target->scsi_host, PFX "new target: id_ext %016llx ioc_guid %016llx pkey %04x " @@ -2377,6 +2463,13 @@ static int __init srp_init_module(void) cmd_sg_entries = 255; } + if (!indirect_sg_entries) + indirect_sg_entries = cmd_sg_entries; + else if (indirect_sg_entries < cmd_sg_entries) { + printk(KERN_WARNING PFX "Bumping up indirect_sg_entries to match cmd_sg_entries (%u)\n", cmd_sg_entries); + indirect_sg_entries = cmd_sg_entries; + } + ib_srp_transport_template = srp_attach_transport(&ib_srp_transport_functions); if (!ib_srp_transport_template) diff --git a/drivers/infiniband/ulp/srp/ib_srp.h b/drivers/infiniband/ulp/srp/ib_srp.h index b43b5e7acbde4..cf696218eeebb 100644 --- a/drivers/infiniband/ulp/srp/ib_srp.h +++ b/drivers/infiniband/ulp/srp/ib_srp.h @@ -117,6 +117,8 @@ struct srp_request { struct srp_iu *cmd; struct ib_pool_fmr **fmr_list; u64 *map_page; + struct srp_direct_buf *indirect_desc; + dma_addr_t indirect_dma_addr; short nfmr; short index; }; @@ -137,6 +139,8 @@ struct srp_target_port { enum srp_target_state state; unsigned int max_iu_len; unsigned int cmd_sg_cnt; + unsigned int indirect_size; + bool allow_ext_sg; /* Everything above this point is used in the hot path of * command processing. Try to keep them packed into cachelines. @@ -151,6 +155,7 @@ struct srp_target_port { struct Scsi_Host *scsi_host; char target_name[32]; unsigned int scsi_id; + unsigned int sg_tablesize; struct ib_sa_path_rec path; __be16 orig_dgid[8]; -- GitLab From be8b981453a4904399cb090c1660618e250092d8 Mon Sep 17 00:00:00 2001 From: David Dillow Date: Tue, 18 Jan 2011 21:58:09 -0500 Subject: [PATCH 0722/2822] IB/srp: try to use larger FMR sizes to cover our mappings Now that we can get larger SG lists, we can take advantage of HCAs that allow us to use larger FMR sizes. In many cases, we can use up to 512 entries, so start there and work our way down. Signed-off-by: David Dillow --- drivers/infiniband/ulp/srp/ib_srp.c | 31 ++++++++++++++++++----------- drivers/infiniband/ulp/srp/ib_srp.h | 3 ++- 2 files changed, 21 insertions(+), 13 deletions(-) diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c index 4ec7dddbbf490..376d640487d2c 100644 --- a/drivers/infiniband/ulp/srp/ib_srp.c +++ b/drivers/infiniband/ulp/srp/ib_srp.c @@ -2300,7 +2300,7 @@ static void srp_add_one(struct ib_device *device) struct ib_device_attr *dev_attr; struct ib_fmr_pool_param fmr_param; struct srp_host *host; - int fmr_page_shift, s, e, p; + int max_pages_per_fmr, fmr_page_shift, s, e, p; dev_attr = kmalloc(sizeof *dev_attr, GFP_KERNEL); if (!dev_attr) @@ -2340,17 +2340,24 @@ static void srp_add_one(struct ib_device *device) if (IS_ERR(srp_dev->mr)) goto err_pd; - memset(&fmr_param, 0, sizeof fmr_param); - fmr_param.pool_size = SRP_FMR_POOL_SIZE; - fmr_param.dirty_watermark = SRP_FMR_DIRTY_SIZE; - fmr_param.cache = 1; - fmr_param.max_pages_per_fmr = SRP_FMR_SIZE; - fmr_param.page_shift = fmr_page_shift; - fmr_param.access = (IB_ACCESS_LOCAL_WRITE | - IB_ACCESS_REMOTE_WRITE | - IB_ACCESS_REMOTE_READ); - - srp_dev->fmr_pool = ib_create_fmr_pool(srp_dev->pd, &fmr_param); + for (max_pages_per_fmr = SRP_FMR_SIZE; + max_pages_per_fmr >= SRP_FMR_MIN_SIZE; + max_pages_per_fmr /= 2, srp_dev->fmr_max_size /= 2) { + memset(&fmr_param, 0, sizeof fmr_param); + fmr_param.pool_size = SRP_FMR_POOL_SIZE; + fmr_param.dirty_watermark = SRP_FMR_DIRTY_SIZE; + fmr_param.cache = 1; + fmr_param.max_pages_per_fmr = max_pages_per_fmr; + fmr_param.page_shift = fmr_page_shift; + fmr_param.access = (IB_ACCESS_LOCAL_WRITE | + IB_ACCESS_REMOTE_WRITE | + IB_ACCESS_REMOTE_READ); + + srp_dev->fmr_pool = ib_create_fmr_pool(srp_dev->pd, &fmr_param); + if (!IS_ERR(srp_dev->fmr_pool)) + break; + } + if (IS_ERR(srp_dev->fmr_pool)) srp_dev->fmr_pool = NULL; diff --git a/drivers/infiniband/ulp/srp/ib_srp.h b/drivers/infiniband/ulp/srp/ib_srp.h index cf696218eeebb..020caf0c3789e 100644 --- a/drivers/infiniband/ulp/srp/ib_srp.h +++ b/drivers/infiniband/ulp/srp/ib_srp.h @@ -69,7 +69,8 @@ enum { SRP_TAG_NO_REQ = ~0U, SRP_TAG_TSK_MGMT = 1U << 31, - SRP_FMR_SIZE = 256, + SRP_FMR_SIZE = 512, + SRP_FMR_MIN_SIZE = 128, SRP_FMR_POOL_SIZE = 1024, SRP_FMR_DIRTY_SIZE = SRP_FMR_POOL_SIZE / 4, -- GitLab From 44cff8a9ee8a974f9e931df910688e7fc1f0b0f9 Mon Sep 17 00:00:00 2001 From: Phillip Lougher Date: Tue, 15 Mar 2011 22:09:55 +0000 Subject: [PATCH 0723/2822] Squashfs: handle corruption of directory structure Handle the rare case where a directory metadata block is uncompressed and corrupted, leading to a kernel oops in directory scanning (memcpy). Normally corruption is detected at the decompression stage and dealt with then, however, this will not happen if: - metadata isn't compressed (users can optionally request no metadata compression), or - the compressed metadata block was larger than the original, in which case the uncompressed version was used, or - the data was corrupt after decompression This patch fixes this by adding some sanity checks against known maximum values. Signed-off-by: Phillip Lougher --- fs/squashfs/dir.c | 9 +++++++++ fs/squashfs/namei.c | 12 ++++++++++++ 2 files changed, 21 insertions(+) diff --git a/fs/squashfs/dir.c b/fs/squashfs/dir.c index 0dc340aa2be97..3f79cd1d0c197 100644 --- a/fs/squashfs/dir.c +++ b/fs/squashfs/dir.c @@ -172,6 +172,11 @@ static int squashfs_readdir(struct file *file, void *dirent, filldir_t filldir) length += sizeof(dirh); dir_count = le32_to_cpu(dirh.count) + 1; + + /* dir_count should never be larger than 256 */ + if (dir_count > 256) + goto failed_read; + while (dir_count--) { /* * Read directory entry. @@ -183,6 +188,10 @@ static int squashfs_readdir(struct file *file, void *dirent, filldir_t filldir) size = le16_to_cpu(dire->size) + 1; + /* size should never be larger than SQUASHFS_NAME_LEN */ + if (size > SQUASHFS_NAME_LEN) + goto failed_read; + err = squashfs_read_metadata(inode->i_sb, dire->name, &block, &offset, size); if (err < 0) diff --git a/fs/squashfs/namei.c b/fs/squashfs/namei.c index 7a9464d08cf63..5d922a6701ab7 100644 --- a/fs/squashfs/namei.c +++ b/fs/squashfs/namei.c @@ -176,6 +176,11 @@ static struct dentry *squashfs_lookup(struct inode *dir, struct dentry *dentry, length += sizeof(dirh); dir_count = le32_to_cpu(dirh.count) + 1; + + /* dir_count should never be larger than 256 */ + if (dir_count > 256) + goto data_error; + while (dir_count--) { /* * Read directory entry. @@ -187,6 +192,10 @@ static struct dentry *squashfs_lookup(struct inode *dir, struct dentry *dentry, size = le16_to_cpu(dire->size) + 1; + /* size should never be larger than SQUASHFS_NAME_LEN */ + if (size > SQUASHFS_NAME_LEN) + goto data_error; + err = squashfs_read_metadata(dir->i_sb, dire->name, &block, &offset, size); if (err < 0) @@ -228,6 +237,9 @@ exit_lookup: d_add(dentry, inode); return ERR_PTR(0); +data_error: + err = -EIO; + read_failure: ERROR("Unable to read directory block [%llx:%x]\n", squashfs_i(dir)->start + msblk->directory_table, -- GitLab From b119601d4e226e42a067ff33116774d79dd9afbc Mon Sep 17 00:00:00 2001 From: Mythri P K Date: Tue, 8 Mar 2011 17:15:54 +0530 Subject: [PATCH 0724/2822] OMAP4: DSS2: Add display type HDMI to DSS2 Adding display type HDMI in dss_features, overlay and the manager so that HDMI type of display will be recognized. Signed-off-by: Mythri P K Signed-off-by: Tomi Valkeinen --- arch/arm/plat-omap/include/plat/display.h | 1 + drivers/video/omap2/dss/display.c | 2 ++ drivers/video/omap2/dss/dss_features.c | 2 +- drivers/video/omap2/dss/manager.c | 9 +++++++-- drivers/video/omap2/dss/overlay.c | 6 ++++-- 5 files changed, 15 insertions(+), 5 deletions(-) diff --git a/arch/arm/plat-omap/include/plat/display.h b/arch/arm/plat-omap/include/plat/display.h index e81ca66dfbb46..5e04ddc18fa8c 100644 --- a/arch/arm/plat-omap/include/plat/display.h +++ b/arch/arm/plat-omap/include/plat/display.h @@ -58,6 +58,7 @@ enum omap_display_type { OMAP_DISPLAY_TYPE_SDI = 1 << 2, OMAP_DISPLAY_TYPE_DSI = 1 << 3, OMAP_DISPLAY_TYPE_VENC = 1 << 4, + OMAP_DISPLAY_TYPE_HDMI = 1 << 5, }; enum omap_plane { diff --git a/drivers/video/omap2/dss/display.c b/drivers/video/omap2/dss/display.c index 7d96b724c9926..c40bcbd2e1403 100644 --- a/drivers/video/omap2/dss/display.c +++ b/drivers/video/omap2/dss/display.c @@ -342,6 +342,7 @@ int omapdss_default_get_recommended_bpp(struct omap_dss_device *dssdev) return 16; case OMAP_DISPLAY_TYPE_VENC: case OMAP_DISPLAY_TYPE_SDI: + case OMAP_DISPLAY_TYPE_HDMI: return 24; default: BUG(); @@ -368,6 +369,7 @@ bool dss_use_replication(struct omap_dss_device *dssdev, case OMAP_DISPLAY_TYPE_DPI: bpp = dssdev->phy.dpi.data_lines; break; + case OMAP_DISPLAY_TYPE_HDMI: case OMAP_DISPLAY_TYPE_VENC: case OMAP_DISPLAY_TYPE_SDI: bpp = 24; diff --git a/drivers/video/omap2/dss/dss_features.c b/drivers/video/omap2/dss/dss_features.c index 06b18f73449b0..aa1622241d0d7 100644 --- a/drivers/video/omap2/dss/dss_features.c +++ b/drivers/video/omap2/dss/dss_features.c @@ -130,7 +130,7 @@ static const enum omap_display_type omap4_dss_supported_displays[] = { OMAP_DISPLAY_TYPE_DBI | OMAP_DISPLAY_TYPE_DSI, /* OMAP_DSS_CHANNEL_DIGIT */ - OMAP_DISPLAY_TYPE_VENC, + OMAP_DISPLAY_TYPE_VENC | OMAP_DISPLAY_TYPE_HDMI, /* OMAP_DSS_CHANNEL_LCD2 */ OMAP_DISPLAY_TYPE_DPI | OMAP_DISPLAY_TYPE_DBI | diff --git a/drivers/video/omap2/dss/manager.c b/drivers/video/omap2/dss/manager.c index 1f53bf20b6cb2..bcd37ec86952f 100644 --- a/drivers/video/omap2/dss/manager.c +++ b/drivers/video/omap2/dss/manager.c @@ -515,6 +515,8 @@ static int dss_mgr_wait_for_vsync(struct omap_overlay_manager *mgr) if (mgr->device->type == OMAP_DISPLAY_TYPE_VENC) { irq = DISPC_IRQ_EVSYNC_ODD; + } else if (mgr->device->type == OMAP_DISPLAY_TYPE_HDMI) { + irq = DISPC_IRQ_EVSYNC_EVEN; } else { if (mgr->id == OMAP_DSS_CHANNEL_LCD) irq = DISPC_IRQ_VSYNC; @@ -536,7 +538,8 @@ static int dss_mgr_wait_for_go(struct omap_overlay_manager *mgr) if (!dssdev || dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) return 0; - if (dssdev->type == OMAP_DISPLAY_TYPE_VENC) { + if (dssdev->type == OMAP_DISPLAY_TYPE_VENC + || dssdev->type == OMAP_DISPLAY_TYPE_HDMI) { irq = DISPC_IRQ_EVSYNC_ODD | DISPC_IRQ_EVSYNC_EVEN; } else { if (dssdev->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE) { @@ -613,7 +616,8 @@ int dss_mgr_wait_for_go_ovl(struct omap_overlay *ovl) if (!dssdev || dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) return 0; - if (dssdev->type == OMAP_DISPLAY_TYPE_VENC) { + if (dssdev->type == OMAP_DISPLAY_TYPE_VENC + || dssdev->type == OMAP_DISPLAY_TYPE_HDMI) { irq = DISPC_IRQ_EVSYNC_ODD | DISPC_IRQ_EVSYNC_EVEN; } else { if (dssdev->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE) { @@ -1377,6 +1381,7 @@ static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr) case OMAP_DISPLAY_TYPE_DBI: case OMAP_DISPLAY_TYPE_SDI: case OMAP_DISPLAY_TYPE_VENC: + case OMAP_DISPLAY_TYPE_HDMI: default_get_overlay_fifo_thresholds(ovl->id, size, &oc->burst_size, &oc->fifo_low, &oc->fifo_high); diff --git a/drivers/video/omap2/dss/overlay.c b/drivers/video/omap2/dss/overlay.c index 996e9a4f6771e..f1aca6d040111 100644 --- a/drivers/video/omap2/dss/overlay.c +++ b/drivers/video/omap2/dss/overlay.c @@ -679,7 +679,8 @@ void dss_recheck_connections(struct omap_dss_device *dssdev, bool force) lcd2_mgr->set_device(lcd2_mgr, dssdev); mgr = lcd2_mgr; } - } else if (dssdev->type != OMAP_DISPLAY_TYPE_VENC) { + } else if (dssdev->type != OMAP_DISPLAY_TYPE_VENC + && dssdev->type != OMAP_DISPLAY_TYPE_HDMI) { if (!lcd_mgr->device || force) { if (lcd_mgr->device) lcd_mgr->unset_device(lcd_mgr); @@ -688,7 +689,8 @@ void dss_recheck_connections(struct omap_dss_device *dssdev, bool force) } } - if (dssdev->type == OMAP_DISPLAY_TYPE_VENC) { + if (dssdev->type == OMAP_DISPLAY_TYPE_VENC + || dssdev->type == OMAP_DISPLAY_TYPE_HDMI) { if (!tv_mgr->device || force) { if (tv_mgr->device) tv_mgr->unset_device(tv_mgr); -- GitLab From 7ed024aa280cb38c8aa5c188d2d2c98f5daede10 Mon Sep 17 00:00:00 2001 From: Mythri P K Date: Wed, 9 Mar 2011 16:31:38 +0530 Subject: [PATCH 0725/2822] OMAP4: DSS2: HDMI: Select between HDMI VENC clock source. Adding function to select between HDMI or VENC clock source. Signed-off-by: Mythri P K Signed-off-by: Tomi Valkeinen --- drivers/video/omap2/dss/dss.c | 5 +++++ drivers/video/omap2/dss/dss.h | 6 ++++++ 2 files changed, 11 insertions(+) diff --git a/drivers/video/omap2/dss/dss.c b/drivers/video/omap2/dss/dss.c index 562d8d28d4f2d..f1628bd850d1a 100644 --- a/drivers/video/omap2/dss/dss.c +++ b/drivers/video/omap2/dss/dss.c @@ -605,6 +605,11 @@ void dss_set_dac_pwrdn_bgz(bool enable) REG_FLD_MOD(DSS_CONTROL, enable, 5, 5); /* DAC Power-Down Control */ } +void dss_select_hdmi_venc_clk_source(enum dss_hdmi_venc_clk_source_select hdmi) +{ + REG_FLD_MOD(DSS_CONTROL, hdmi, 15, 15); /* VENC_HDMI_SWITCH */ +} + static int dss_init(void) { int r; diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h index 26a43c93e4893..eb05d39ef17cb 100644 --- a/drivers/video/omap2/dss/dss.h +++ b/drivers/video/omap2/dss/dss.h @@ -126,6 +126,11 @@ enum dss_clk_source { * OMAP4: DSS_FCLK */ }; +enum dss_hdmi_venc_clk_source_select { + DSS_VENC_TV_CLK = 0, + DSS_HDMI_M_PCLK = 1, +}; + struct dss_clock_info { /* rates that we get with dividers below */ unsigned long fck; @@ -214,6 +219,7 @@ void dss_recheck_connections(struct omap_dss_device *dssdev, bool force); int dss_init_platform_driver(void); void dss_uninit_platform_driver(void); +void dss_select_hdmi_venc_clk_source(enum dss_hdmi_venc_clk_source_select); void dss_save_context(void); void dss_restore_context(void); void dss_clk_enable(enum dss_clock clks); -- GitLab From d3862610c95564a586951d5be291b9b0200d39fe Mon Sep 17 00:00:00 2001 From: Mythri P K Date: Fri, 11 Mar 2011 18:02:49 +0530 Subject: [PATCH 0726/2822] OMAP4: DSS2: HDMI: Dispc gamma enable set/reset function for TV. Adding function to reset/set gamma table bit for TV interface, currently only support for disabled is added. Signed-off-by: Mythri P K Signed-off-by: Tomi Valkeinen --- drivers/video/omap2/dss/dispc.c | 14 ++++++++++++++ drivers/video/omap2/dss/dss.h | 1 + 2 files changed, 15 insertions(+) diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c index b8c576a0bc02c..7804779c9da15 100644 --- a/drivers/video/omap2/dss/dispc.c +++ b/drivers/video/omap2/dss/dispc.c @@ -1008,6 +1008,20 @@ void dispc_set_burst_size(enum omap_plane plane, enable_clocks(0); } +void dispc_enable_gamma_table(bool enable) +{ + /* + * This is partially implemented to support only disabling of + * the gamma table. + */ + if (enable) { + DSSWARN("Gamma table enabling for TV not yet supported"); + return; + } + + REG_FLD_MOD(DISPC_CONFIG, enable, 9, 9); +} + static void _dispc_set_vid_color_conv(enum omap_plane plane, bool enable) { u32 val; diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h index eb05d39ef17cb..ab20270d761ab 100644 --- a/drivers/video/omap2/dss/dss.h +++ b/drivers/video/omap2/dss/dss.h @@ -370,6 +370,7 @@ void dispc_set_plane_size(enum omap_plane plane, u16 width, u16 height); void dispc_set_channel_out(enum omap_plane plane, enum omap_channel channel_out); +void dispc_enable_gamma_table(bool enable); int dispc_setup_plane(enum omap_plane plane, u32 paddr, u16 screen_width, u16 pos_x, u16 pos_y, -- GitLab From 26adeece88ffe172db7e26f856b576cccfb0ec85 Mon Sep 17 00:00:00 2001 From: Mythri P K Date: Tue, 8 Mar 2011 17:27:56 +0530 Subject: [PATCH 0727/2822] OMAP4: DSS2: HDMI: HDMI driver header file addition Adding the hdmi interface driver header file (hdmi.h) to the dss driver. Register and structure declaration done here. Signed-off-by: Mythri P K Signed-off-by: Tomi Valkeinen --- drivers/video/omap2/dss/hdmi.h | 415 +++++++++++++++++++++++++++++++++ 1 file changed, 415 insertions(+) create mode 100644 drivers/video/omap2/dss/hdmi.h diff --git a/drivers/video/omap2/dss/hdmi.h b/drivers/video/omap2/dss/hdmi.h new file mode 100644 index 0000000000000..9887ab96da3c5 --- /dev/null +++ b/drivers/video/omap2/dss/hdmi.h @@ -0,0 +1,415 @@ +/* + * hdmi.h + * + * HDMI driver definition for TI OMAP4 processors. + * + * Copyright (C) 2010-2011 Texas Instruments Incorporated - http://www.ti.com/ + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published by + * the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see . + */ + +#ifndef _OMAP4_DSS_HDMI_H_ +#define _OMAP4_DSS_HDMI_H_ + +#include +#include + +#define HDMI_WP 0x0 +#define HDMI_CORE_SYS 0x400 +#define HDMI_CORE_AV 0x900 +#define HDMI_PLLCTRL 0x200 +#define HDMI_PHY 0x300 + +struct hdmi_reg { u16 idx; }; + +#define HDMI_REG(idx) ((const struct hdmi_reg) { idx }) + +/* HDMI Wrapper */ +#define HDMI_WP_REG(idx) HDMI_REG(HDMI_WP + idx) + +#define HDMI_WP_REVISION HDMI_WP_REG(0x0) +#define HDMI_WP_SYSCONFIG HDMI_WP_REG(0x10) +#define HDMI_WP_IRQSTATUS_RAW HDMI_WP_REG(0x24) +#define HDMI_WP_IRQSTATUS HDMI_WP_REG(0x28) +#define HDMI_WP_PWR_CTRL HDMI_WP_REG(0x40) +#define HDMI_WP_IRQENABLE_SET HDMI_WP_REG(0x2C) +#define HDMI_WP_VIDEO_CFG HDMI_WP_REG(0x50) +#define HDMI_WP_VIDEO_SIZE HDMI_WP_REG(0x60) +#define HDMI_WP_VIDEO_TIMING_H HDMI_WP_REG(0x68) +#define HDMI_WP_VIDEO_TIMING_V HDMI_WP_REG(0x6C) +#define HDMI_WP_WP_CLK HDMI_WP_REG(0x70) + +/* HDMI IP Core System */ +#define HDMI_CORE_SYS_REG(idx) HDMI_REG(HDMI_CORE_SYS + idx) + +#define HDMI_CORE_SYS_VND_IDL HDMI_CORE_SYS_REG(0x0) +#define HDMI_CORE_SYS_DEV_IDL HDMI_CORE_SYS_REG(0x8) +#define HDMI_CORE_SYS_DEV_IDH HDMI_CORE_SYS_REG(0xC) +#define HDMI_CORE_SYS_DEV_REV HDMI_CORE_SYS_REG(0x10) +#define HDMI_CORE_SYS_SRST HDMI_CORE_SYS_REG(0x14) +#define HDMI_CORE_CTRL1 HDMI_CORE_SYS_REG(0x20) +#define HDMI_CORE_SYS_SYS_STAT HDMI_CORE_SYS_REG(0x24) +#define HDMI_CORE_SYS_VID_ACEN HDMI_CORE_SYS_REG(0x124) +#define HDMI_CORE_SYS_VID_MODE HDMI_CORE_SYS_REG(0x128) +#define HDMI_CORE_SYS_INTR_STATE HDMI_CORE_SYS_REG(0x1C0) +#define HDMI_CORE_SYS_INTR1 HDMI_CORE_SYS_REG(0x1C4) +#define HDMI_CORE_SYS_INTR2 HDMI_CORE_SYS_REG(0x1C8) +#define HDMI_CORE_SYS_INTR3 HDMI_CORE_SYS_REG(0x1CC) +#define HDMI_CORE_SYS_INTR4 HDMI_CORE_SYS_REG(0x1D0) +#define HDMI_CORE_SYS_UMASK1 HDMI_CORE_SYS_REG(0x1D4) +#define HDMI_CORE_SYS_TMDS_CTRL HDMI_CORE_SYS_REG(0x208) +#define HDMI_CORE_SYS_DE_DLY HDMI_CORE_SYS_REG(0xC8) +#define HDMI_CORE_SYS_DE_CTRL HDMI_CORE_SYS_REG(0xCC) +#define HDMI_CORE_SYS_DE_TOP HDMI_CORE_SYS_REG(0xD0) +#define HDMI_CORE_SYS_DE_CNTL HDMI_CORE_SYS_REG(0xD8) +#define HDMI_CORE_SYS_DE_CNTH HDMI_CORE_SYS_REG(0xDC) +#define HDMI_CORE_SYS_DE_LINL HDMI_CORE_SYS_REG(0xE0) +#define HDMI_CORE_SYS_DE_LINH_1 HDMI_CORE_SYS_REG(0xE4) +#define HDMI_CORE_CTRL1_VEN_FOLLOWVSYNC 0x1 +#define HDMI_CORE_CTRL1_HEN_FOLLOWHSYNC 0x1 +#define HDMI_CORE_CTRL1_BSEL_24BITBUS 0x1 +#define HDMI_CORE_CTRL1_EDGE_RISINGEDGE 0x1 + +/* HDMI DDC E-DID */ +#define HDMI_CORE_DDC_CMD HDMI_CORE_SYS_REG(0x3CC) +#define HDMI_CORE_DDC_STATUS HDMI_CORE_SYS_REG(0x3C8) +#define HDMI_CORE_DDC_ADDR HDMI_CORE_SYS_REG(0x3B4) +#define HDMI_CORE_DDC_OFFSET HDMI_CORE_SYS_REG(0x3BC) +#define HDMI_CORE_DDC_COUNT1 HDMI_CORE_SYS_REG(0x3C0) +#define HDMI_CORE_DDC_COUNT2 HDMI_CORE_SYS_REG(0x3C4) +#define HDMI_CORE_DDC_DATA HDMI_CORE_SYS_REG(0x3D0) +#define HDMI_CORE_DDC_SEGM HDMI_CORE_SYS_REG(0x3B8) + +/* HDMI IP Core Audio Video */ +#define HDMI_CORE_AV_REG(idx) HDMI_REG(HDMI_CORE_AV + idx) + +#define HDMI_CORE_AV_HDMI_CTRL HDMI_CORE_AV_REG(0xBC) +#define HDMI_CORE_AV_DPD HDMI_CORE_AV_REG(0xF4) +#define HDMI_CORE_AV_PB_CTRL1 HDMI_CORE_AV_REG(0xF8) +#define HDMI_CORE_AV_PB_CTRL2 HDMI_CORE_AV_REG(0xFC) +#define HDMI_CORE_AV_AVI_TYPE HDMI_CORE_AV_REG(0x100) +#define HDMI_CORE_AV_AVI_VERS HDMI_CORE_AV_REG(0x104) +#define HDMI_CORE_AV_AVI_LEN HDMI_CORE_AV_REG(0x108) +#define HDMI_CORE_AV_AVI_CHSUM HDMI_CORE_AV_REG(0x10C) +#define HDMI_CORE_AV_AVI_DBYTE(n) HDMI_CORE_AV_REG(n * 4 + 0x110) +#define HDMI_CORE_AV_AVI_DBYTE_NELEMS HDMI_CORE_AV_REG(15) +#define HDMI_CORE_AV_SPD_DBYTE HDMI_CORE_AV_REG(0x190) +#define HDMI_CORE_AV_SPD_DBYTE_NELEMS HDMI_CORE_AV_REG(27) +#define HDMI_CORE_AV_MPEG_DBYTE HDMI_CORE_AV_REG(0x290) +#define HDMI_CORE_AV_MPEG_DBYTE_NELEMS HDMI_CORE_AV_REG(27) +#define HDMI_CORE_AV_GEN_DBYTE HDMI_CORE_AV_REG(0x300) +#define HDMI_CORE_AV_GEN_DBYTE_NELEMS HDMI_CORE_AV_REG(31) +#define HDMI_CORE_AV_GEN2_DBYTE HDMI_CORE_AV_REG(0x380) +#define HDMI_CORE_AV_GEN2_DBYTE_NELEMS HDMI_CORE_AV_REG(31) +#define HDMI_CORE_AV_ACR_CTRL HDMI_CORE_AV_REG(0x4) +#define HDMI_CORE_AV_FREQ_SVAL HDMI_CORE_AV_REG(0x8) +#define HDMI_CORE_AV_N_SVAL1 HDMI_CORE_AV_REG(0xC) +#define HDMI_CORE_AV_N_SVAL2 HDMI_CORE_AV_REG(0x10) +#define HDMI_CORE_AV_N_SVAL3 HDMI_CORE_AV_REG(0x14) +#define HDMI_CORE_AV_CTS_SVAL1 HDMI_CORE_AV_REG(0x18) +#define HDMI_CORE_AV_CTS_SVAL2 HDMI_CORE_AV_REG(0x1C) +#define HDMI_CORE_AV_CTS_SVAL3 HDMI_CORE_AV_REG(0x20) +#define HDMI_CORE_AV_CTS_HVAL1 HDMI_CORE_AV_REG(0x24) +#define HDMI_CORE_AV_CTS_HVAL2 HDMI_CORE_AV_REG(0x28) +#define HDMI_CORE_AV_CTS_HVAL3 HDMI_CORE_AV_REG(0x2C) +#define HDMI_CORE_AV_AUD_MODE HDMI_CORE_AV_REG(0x50) +#define HDMI_CORE_AV_SPDIF_CTRL HDMI_CORE_AV_REG(0x54) +#define HDMI_CORE_AV_HW_SPDIF_FS HDMI_CORE_AV_REG(0x60) +#define HDMI_CORE_AV_SWAP_I2S HDMI_CORE_AV_REG(0x64) +#define HDMI_CORE_AV_SPDIF_ERTH HDMI_CORE_AV_REG(0x6C) +#define HDMI_CORE_AV_I2S_IN_MAP HDMI_CORE_AV_REG(0x70) +#define HDMI_CORE_AV_I2S_IN_CTRL HDMI_CORE_AV_REG(0x74) +#define HDMI_CORE_AV_I2S_CHST0 HDMI_CORE_AV_REG(0x78) +#define HDMI_CORE_AV_I2S_CHST1 HDMI_CORE_AV_REG(0x7C) +#define HDMI_CORE_AV_I2S_CHST2 HDMI_CORE_AV_REG(0x80) +#define HDMI_CORE_AV_I2S_CHST4 HDMI_CORE_AV_REG(0x84) +#define HDMI_CORE_AV_I2S_CHST5 HDMI_CORE_AV_REG(0x88) +#define HDMI_CORE_AV_ASRC HDMI_CORE_AV_REG(0x8C) +#define HDMI_CORE_AV_I2S_IN_LEN HDMI_CORE_AV_REG(0x90) +#define HDMI_CORE_AV_HDMI_CTRL HDMI_CORE_AV_REG(0xBC) +#define HDMI_CORE_AV_AUDO_TXSTAT HDMI_CORE_AV_REG(0xC0) +#define HDMI_CORE_AV_AUD_PAR_BUSCLK_1 HDMI_CORE_AV_REG(0xCC) +#define HDMI_CORE_AV_AUD_PAR_BUSCLK_2 HDMI_CORE_AV_REG(0xD0) +#define HDMI_CORE_AV_AUD_PAR_BUSCLK_3 HDMI_CORE_AV_REG(0xD4) +#define HDMI_CORE_AV_TEST_TXCTRL HDMI_CORE_AV_REG(0xF0) +#define HDMI_CORE_AV_DPD HDMI_CORE_AV_REG(0xF4) +#define HDMI_CORE_AV_PB_CTRL1 HDMI_CORE_AV_REG(0xF8) +#define HDMI_CORE_AV_PB_CTRL2 HDMI_CORE_AV_REG(0xFC) +#define HDMI_CORE_AV_AVI_TYPE HDMI_CORE_AV_REG(0x100) +#define HDMI_CORE_AV_AVI_VERS HDMI_CORE_AV_REG(0x104) +#define HDMI_CORE_AV_AVI_LEN HDMI_CORE_AV_REG(0x108) +#define HDMI_CORE_AV_AVI_CHSUM HDMI_CORE_AV_REG(0x10C) +#define HDMI_CORE_AV_SPD_TYPE HDMI_CORE_AV_REG(0x180) +#define HDMI_CORE_AV_SPD_VERS HDMI_CORE_AV_REG(0x184) +#define HDMI_CORE_AV_SPD_LEN HDMI_CORE_AV_REG(0x188) +#define HDMI_CORE_AV_SPD_CHSUM HDMI_CORE_AV_REG(0x18C) +#define HDMI_CORE_AV_MPEG_TYPE HDMI_CORE_AV_REG(0x280) +#define HDMI_CORE_AV_MPEG_VERS HDMI_CORE_AV_REG(0x284) +#define HDMI_CORE_AV_MPEG_LEN HDMI_CORE_AV_REG(0x288) +#define HDMI_CORE_AV_MPEG_CHSUM HDMI_CORE_AV_REG(0x28C) +#define HDMI_CORE_AV_CP_BYTE1 HDMI_CORE_AV_REG(0x37C) +#define HDMI_CORE_AV_CEC_ADDR_ID HDMI_CORE_AV_REG(0x3FC) +#define HDMI_CORE_AV_SPD_DBYTE_ELSIZE 0x4 +#define HDMI_CORE_AV_GEN2_DBYTE_ELSIZE 0x4 +#define HDMI_CORE_AV_MPEG_DBYTE_ELSIZE 0x4 +#define HDMI_CORE_AV_GEN_DBYTE_ELSIZE 0x4 + +/* PLL */ +#define HDMI_PLL_REG(idx) HDMI_REG(HDMI_PLLCTRL + idx) + +#define PLLCTRL_PLL_CONTROL HDMI_PLL_REG(0x0) +#define PLLCTRL_PLL_STATUS HDMI_PLL_REG(0x4) +#define PLLCTRL_PLL_GO HDMI_PLL_REG(0x8) +#define PLLCTRL_CFG1 HDMI_PLL_REG(0xC) +#define PLLCTRL_CFG2 HDMI_PLL_REG(0x10) +#define PLLCTRL_CFG3 HDMI_PLL_REG(0x14) +#define PLLCTRL_CFG4 HDMI_PLL_REG(0x20) + +/* HDMI PHY */ +#define HDMI_PHY_REG(idx) HDMI_REG(HDMI_PHY + idx) + +#define HDMI_TXPHY_TX_CTRL HDMI_PHY_REG(0x0) +#define HDMI_TXPHY_DIGITAL_CTRL HDMI_PHY_REG(0x4) +#define HDMI_TXPHY_POWER_CTRL HDMI_PHY_REG(0x8) +#define HDMI_TXPHY_PAD_CFG_CTRL HDMI_PHY_REG(0xC) + +/* HDMI EDID Length */ +#define HDMI_EDID_MAX_LENGTH 256 +#define EDID_TIMING_DESCRIPTOR_SIZE 0x12 +#define EDID_DESCRIPTOR_BLOCK0_ADDRESS 0x36 +#define EDID_DESCRIPTOR_BLOCK1_ADDRESS 0x80 +#define EDID_SIZE_BLOCK0_TIMING_DESCRIPTOR 4 +#define EDID_SIZE_BLOCK1_TIMING_DESCRIPTOR 4 + +#define OMAP_HDMI_TIMINGS_NB 34 + +#define REG_FLD_MOD(idx, val, start, end) \ + hdmi_write_reg(idx, FLD_MOD(hdmi_read_reg(idx), val, start, end)) +#define REG_GET(idx, start, end) \ + FLD_GET(hdmi_read_reg(idx), start, end) + +/* HDMI timing structure */ +struct hdmi_timings { + struct omap_video_timings timings; + int vsync_pol; + int hsync_pol; +}; + +enum hdmi_phy_pwr { + HDMI_PHYPWRCMD_OFF = 0, + HDMI_PHYPWRCMD_LDOON = 1, + HDMI_PHYPWRCMD_TXON = 2 +}; + +enum hdmi_pll_pwr { + HDMI_PLLPWRCMD_ALLOFF = 0, + HDMI_PLLPWRCMD_PLLONLY = 1, + HDMI_PLLPWRCMD_BOTHON_ALLCLKS = 2, + HDMI_PLLPWRCMD_BOTHON_NOPHYCLK = 3 +}; + +enum hdmi_clk_refsel { + HDMI_REFSEL_PCLK = 0, + HDMI_REFSEL_REF1 = 1, + HDMI_REFSEL_REF2 = 2, + HDMI_REFSEL_SYSCLK = 3 +}; + +enum hdmi_core_inputbus_width { + HDMI_INPUT_8BIT = 0, + HDMI_INPUT_10BIT = 1, + HDMI_INPUT_12BIT = 2 +}; + +enum hdmi_core_dither_trunc { + HDMI_OUTPUTTRUNCATION_8BIT = 0, + HDMI_OUTPUTTRUNCATION_10BIT = 1, + HDMI_OUTPUTTRUNCATION_12BIT = 2, + HDMI_OUTPUTDITHER_8BIT = 3, + HDMI_OUTPUTDITHER_10BIT = 4, + HDMI_OUTPUTDITHER_12BIT = 5 +}; + +enum hdmi_core_deepcolor_ed { + HDMI_DEEPCOLORPACKECTDISABLE = 0, + HDMI_DEEPCOLORPACKECTENABLE = 1 +}; + +enum hdmi_core_packet_mode { + HDMI_PACKETMODERESERVEDVALUE = 0, + HDMI_PACKETMODE24BITPERPIXEL = 4, + HDMI_PACKETMODE30BITPERPIXEL = 5, + HDMI_PACKETMODE36BITPERPIXEL = 6, + HDMI_PACKETMODE48BITPERPIXEL = 7 +}; + +enum hdmi_core_hdmi_dvi { + HDMI_DVI = 0, + HDMI_HDMI = 1 +}; + +enum hdmi_core_tclkselclkmult { + HDMI_FPLL05IDCK = 0, + HDMI_FPLL10IDCK = 1, + HDMI_FPLL20IDCK = 2, + HDMI_FPLL40IDCK = 3 +}; + +enum hdmi_core_packet_ctrl { + HDMI_PACKETENABLE = 1, + HDMI_PACKETDISABLE = 0, + HDMI_PACKETREPEATON = 1, + HDMI_PACKETREPEATOFF = 0 +}; + +/* INFOFRAME_AVI_ definitions */ +enum hdmi_core_infoframe { + HDMI_INFOFRAME_AVI_DB1Y_RGB = 0, + HDMI_INFOFRAME_AVI_DB1Y_YUV422 = 1, + HDMI_INFOFRAME_AVI_DB1Y_YUV444 = 2, + HDMI_INFOFRAME_AVI_DB1A_ACTIVE_FORMAT_OFF = 0, + HDMI_INFOFRAME_AVI_DB1A_ACTIVE_FORMAT_ON = 1, + HDMI_INFOFRAME_AVI_DB1B_NO = 0, + HDMI_INFOFRAME_AVI_DB1B_VERT = 1, + HDMI_INFOFRAME_AVI_DB1B_HORI = 2, + HDMI_INFOFRAME_AVI_DB1B_VERTHORI = 3, + HDMI_INFOFRAME_AVI_DB1S_0 = 0, + HDMI_INFOFRAME_AVI_DB1S_1 = 1, + HDMI_INFOFRAME_AVI_DB1S_2 = 2, + HDMI_INFOFRAME_AVI_DB2C_NO = 0, + HDMI_INFOFRAME_AVI_DB2C_ITU601 = 1, + HDMI_INFOFRAME_AVI_DB2C_ITU709 = 2, + HDMI_INFOFRAME_AVI_DB2C_EC_EXTENDED = 3, + HDMI_INFOFRAME_AVI_DB2M_NO = 0, + HDMI_INFOFRAME_AVI_DB2M_43 = 1, + HDMI_INFOFRAME_AVI_DB2M_169 = 2, + HDMI_INFOFRAME_AVI_DB2R_SAME = 8, + HDMI_INFOFRAME_AVI_DB2R_43 = 9, + HDMI_INFOFRAME_AVI_DB2R_169 = 10, + HDMI_INFOFRAME_AVI_DB2R_149 = 11, + HDMI_INFOFRAME_AVI_DB3ITC_NO = 0, + HDMI_INFOFRAME_AVI_DB3ITC_YES = 1, + HDMI_INFOFRAME_AVI_DB3EC_XVYUV601 = 0, + HDMI_INFOFRAME_AVI_DB3EC_XVYUV709 = 1, + HDMI_INFOFRAME_AVI_DB3Q_DEFAULT = 0, + HDMI_INFOFRAME_AVI_DB3Q_LR = 1, + HDMI_INFOFRAME_AVI_DB3Q_FR = 2, + HDMI_INFOFRAME_AVI_DB3SC_NO = 0, + HDMI_INFOFRAME_AVI_DB3SC_HORI = 1, + HDMI_INFOFRAME_AVI_DB3SC_VERT = 2, + HDMI_INFOFRAME_AVI_DB3SC_HORIVERT = 3, + HDMI_INFOFRAME_AVI_DB5PR_NO = 0, + HDMI_INFOFRAME_AVI_DB5PR_2 = 1, + HDMI_INFOFRAME_AVI_DB5PR_3 = 2, + HDMI_INFOFRAME_AVI_DB5PR_4 = 3, + HDMI_INFOFRAME_AVI_DB5PR_5 = 4, + HDMI_INFOFRAME_AVI_DB5PR_6 = 5, + HDMI_INFOFRAME_AVI_DB5PR_7 = 6, + HDMI_INFOFRAME_AVI_DB5PR_8 = 7, + HDMI_INFOFRAME_AVI_DB5PR_9 = 8, + HDMI_INFOFRAME_AVI_DB5PR_10 = 9 +}; + +enum hdmi_packing_mode { + HDMI_PACK_10b_RGB_YUV444 = 0, + HDMI_PACK_24b_RGB_YUV444_YUV422 = 1, + HDMI_PACK_20b_YUV422 = 2, + HDMI_PACK_ALREADYPACKED = 7 +}; + +struct hdmi_core_video_config { + enum hdmi_core_inputbus_width ip_bus_width; + enum hdmi_core_dither_trunc op_dither_truc; + enum hdmi_core_deepcolor_ed deep_color_pkt; + enum hdmi_core_packet_mode pkt_mode; + enum hdmi_core_hdmi_dvi hdmi_dvi; + enum hdmi_core_tclkselclkmult tclk_sel_clkmult; +}; + +/* + * Refer to section 8.2 in HDMI 1.3 specification for + * details about infoframe databytes + */ +struct hdmi_core_infoframe_avi { + u8 db1_format; + /* Y0, Y1 rgb,yCbCr */ + u8 db1_active_info; + /* A0 Active information Present */ + u8 db1_bar_info_dv; + /* B0, B1 Bar info data valid */ + u8 db1_scan_info; + /* S0, S1 scan information */ + u8 db2_colorimetry; + /* C0, C1 colorimetry */ + u8 db2_aspect_ratio; + /* M0, M1 Aspect ratio (4:3, 16:9) */ + u8 db2_active_fmt_ar; + /* R0...R3 Active format aspect ratio */ + u8 db3_itc; + /* ITC IT content. */ + u8 db3_ec; + /* EC0, EC1, EC2 Extended colorimetry */ + u8 db3_q_range; + /* Q1, Q0 Quantization range */ + u8 db3_nup_scaling; + /* SC1, SC0 Non-uniform picture scaling */ + u8 db4_videocode; + /* VIC0..6 Video format identification */ + u8 db5_pixel_repeat; + /* PR0..PR3 Pixel repetition factor */ + u16 db6_7_line_eoftop; + /* Line number end of top bar */ + u16 db8_9_line_sofbottom; + /* Line number start of bottom bar */ + u16 db10_11_pixel_eofleft; + /* Pixel number end of left bar */ + u16 db12_13_pixel_sofright; + /* Pixel number start of right bar */ +}; + +struct hdmi_core_packet_enable_repeat { + u32 audio_pkt; + u32 audio_pkt_repeat; + u32 avi_infoframe; + u32 avi_infoframe_repeat; + u32 gen_cntrl_pkt; + u32 gen_cntrl_pkt_repeat; + u32 generic_pkt; + u32 generic_pkt_repeat; +}; + +struct hdmi_video_format { + enum hdmi_packing_mode packing_mode; + u32 y_res; /* Line per panel */ + u32 x_res; /* pixel per line */ +}; + +struct hdmi_video_interface { + int vsp; /* Vsync polarity */ + int hsp; /* Hsync polarity */ + int interlacing; + int tm; /* Timing mode */ +}; + +struct hdmi_cm { + int code; + int mode; +}; + +struct hdmi_config { + struct hdmi_timings timings; + u16 interlace; + struct hdmi_cm cm; +}; + +#endif -- GitLab From c3198a5e83121d6e3d01816f15164f158f4301d8 Mon Sep 17 00:00:00 2001 From: Mythri P K Date: Sat, 12 Mar 2011 12:04:27 +0530 Subject: [PATCH 0728/2822] OMAP4: DSS2: HDMI: HDMI driver addition in the DSS Adding the hdmi interface driver(hdmi.c) to the dss driver. It configures the audio and video portion of HDMI based on functionality called by the panel driver. Signed-off-by: Mythri P K Signed-off-by: Yong Zhi Signed-off-by: Tomi Valkeinen --- drivers/video/omap2/dss/display.c | 3 + drivers/video/omap2/dss/dss.h | 34 + drivers/video/omap2/dss/hdmi.c | 1332 +++++++++++++++++++++++++++++ 3 files changed, 1369 insertions(+) create mode 100644 drivers/video/omap2/dss/hdmi.c diff --git a/drivers/video/omap2/dss/display.c b/drivers/video/omap2/dss/display.c index c40bcbd2e1403..a85a6f38b40c1 100644 --- a/drivers/video/omap2/dss/display.c +++ b/drivers/video/omap2/dss/display.c @@ -418,6 +418,9 @@ void dss_init_device(struct platform_device *pdev, r = dsi_init_display(dssdev); break; #endif + case OMAP_DISPLAY_TYPE_HDMI: + r = hdmi_init_display(dssdev); + break; default: DSSERR("Support for display '%s' not compiled in.\n", dssdev->name); diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h index ab20270d761ab..91ed3fa8e60d6 100644 --- a/drivers/video/omap2/dss/dss.h +++ b/drivers/video/omap2/dss/dss.h @@ -173,6 +173,16 @@ struct dsi_clock_info { bool use_sys_clk; }; +/* HDMI PLL structure */ +struct hdmi_pll_info { + u16 regn; + u16 regm; + u32 regmf; + u16 regm2; + u16 regsd; + u16 dcofreq; +}; + struct seq_file; struct platform_device; @@ -444,6 +454,30 @@ static inline void venc_uninit_platform_driver(void) } #endif +/* HDMI */ +#ifdef CONFIG_OMAP4_DSS_HDMI +int hdmi_init_platform_driver(void); +void hdmi_uninit_platform_driver(void); +int hdmi_init_display(struct omap_dss_device *dssdev); +#else +static inline int hdmi_init_display(struct omap_dss_device *dssdev) +{ + return 0; +} +static inline int hdmi_init_platform_driver(void) +{ + return 0; +} +static inline void hdmi_uninit_platform_driver(void) +{ +} +#endif +int omapdss_hdmi_display_enable(struct omap_dss_device *dssdev); +void omapdss_hdmi_display_disable(struct omap_dss_device *dssdev); +void omapdss_hdmi_display_set_timing(struct omap_dss_device *dssdev); +int omapdss_hdmi_display_check_timing(struct omap_dss_device *dssdev, + struct omap_video_timings *timings); + /* RFBI */ #ifdef CONFIG_OMAP2_DSS_RFBI int rfbi_init_platform_driver(void); diff --git a/drivers/video/omap2/dss/hdmi.c b/drivers/video/omap2/dss/hdmi.c new file mode 100644 index 0000000000000..0d44f070ef364 --- /dev/null +++ b/drivers/video/omap2/dss/hdmi.c @@ -0,0 +1,1332 @@ +/* + * hdmi.c + * + * HDMI interface DSS driver setting for TI's OMAP4 family of processor. + * Copyright (C) 2010-2011 Texas Instruments Incorporated - http://www.ti.com/ + * Authors: Yong Zhi + * Mythri pk + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published by + * the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see . + */ + +#define DSS_SUBSYS_NAME "HDMI" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "dss.h" +#include "hdmi.h" + +static struct { + struct mutex lock; + struct omap_display_platform_data *pdata; + struct platform_device *pdev; + void __iomem *base_wp; /* HDMI wrapper */ + int code; + int mode; + u8 edid[HDMI_EDID_MAX_LENGTH]; + u8 edid_set; + bool custom_set; + struct hdmi_config cfg; +} hdmi; + +/* + * Logic for the below structure : + * user enters the CEA or VESA timings by specifying the HDMI/DVI code. + * There is a correspondence between CEA/VESA timing and code, please + * refer to section 6.3 in HDMI 1.3 specification for timing code. + * + * In the below structure, cea_vesa_timings corresponds to all OMAP4 + * supported CEA and VESA timing values.code_cea corresponds to the CEA + * code, It is used to get the timing from cea_vesa_timing array.Similarly + * with code_vesa. Code_index is used for back mapping, that is once EDID + * is read from the TV, EDID is parsed to find the timing values and then + * map it to corresponding CEA or VESA index. + */ + +static const struct hdmi_timings cea_vesa_timings[OMAP_HDMI_TIMINGS_NB] = { + { {640, 480, 25200, 96, 16, 48, 2, 10, 33} , 0 , 0}, + { {1280, 720, 74250, 40, 440, 220, 5, 5, 20}, 1, 1}, + { {1280, 720, 74250, 40, 110, 220, 5, 5, 20}, 1, 1}, + { {720, 480, 27027, 62, 16, 60, 6, 9, 30}, 0, 0}, + { {2880, 576, 108000, 256, 48, 272, 5, 5, 39}, 0, 0}, + { {1440, 240, 27027, 124, 38, 114, 3, 4, 15}, 0, 0}, + { {1440, 288, 27000, 126, 24, 138, 3, 2, 19}, 0, 0}, + { {1920, 540, 74250, 44, 528, 148, 5, 2, 15}, 1, 1}, + { {1920, 540, 74250, 44, 88, 148, 5, 2, 15}, 1, 1}, + { {1920, 1080, 148500, 44, 88, 148, 5, 4, 36}, 1, 1}, + { {720, 576, 27000, 64, 12, 68, 5, 5, 39}, 0, 0}, + { {1440, 576, 54000, 128, 24, 136, 5, 5, 39}, 0, 0}, + { {1920, 1080, 148500, 44, 528, 148, 5, 4, 36}, 1, 1}, + { {2880, 480, 108108, 248, 64, 240, 6, 9, 30}, 0, 0}, + { {1920, 1080, 74250, 44, 638, 148, 5, 4, 36}, 1, 1}, + /* VESA From Here */ + { {640, 480, 25175, 96, 16, 48, 2 , 11, 31}, 0, 0}, + { {800, 600, 40000, 128, 40, 88, 4 , 1, 23}, 1, 1}, + { {848, 480, 33750, 112, 16, 112, 8 , 6, 23}, 1, 1}, + { {1280, 768, 79500, 128, 64, 192, 7 , 3, 20}, 1, 0}, + { {1280, 800, 83500, 128, 72, 200, 6 , 3, 22}, 1, 0}, + { {1360, 768, 85500, 112, 64, 256, 6 , 3, 18}, 1, 1}, + { {1280, 960, 108000, 112, 96, 312, 3 , 1, 36}, 1, 1}, + { {1280, 1024, 108000, 112, 48, 248, 3 , 1, 38}, 1, 1}, + { {1024, 768, 65000, 136, 24, 160, 6, 3, 29}, 0, 0}, + { {1400, 1050, 121750, 144, 88, 232, 4, 3, 32}, 1, 0}, + { {1440, 900, 106500, 152, 80, 232, 6, 3, 25}, 1, 0}, + { {1680, 1050, 146250, 176 , 104, 280, 6, 3, 30}, 1, 0}, + { {1366, 768, 85500, 143, 70, 213, 3, 3, 24}, 1, 1}, + { {1920, 1080, 148500, 44, 148, 80, 5, 4, 36}, 1, 1}, + { {1280, 768, 68250, 32, 48, 80, 7, 3, 12}, 0, 1}, + { {1400, 1050, 101000, 32, 48, 80, 4, 3, 23}, 0, 1}, + { {1680, 1050, 119000, 32, 48, 80, 6, 3, 21}, 0, 1}, + { {1280, 800, 79500, 32, 48, 80, 6, 3, 14}, 0, 1}, + { {1280, 720, 74250, 40, 110, 220, 5, 5, 20}, 1, 1} +}; + +/* + * This is a static mapping array which maps the timing values + * with corresponding CEA / VESA code + */ +static const int code_index[OMAP_HDMI_TIMINGS_NB] = { + 1, 19, 4, 2, 37, 6, 21, 20, 5, 16, 17, 29, 31, 35, 32, + /* <--15 CEA 17--> vesa*/ + 4, 9, 0xE, 0x17, 0x1C, 0x27, 0x20, 0x23, 0x10, 0x2A, + 0X2F, 0x3A, 0X51, 0X52, 0x16, 0x29, 0x39, 0x1B +}; + +/* + * This is reverse static mapping which maps the CEA / VESA code + * to the corresponding timing values + */ +static const int code_cea[39] = { + -1, 0, 3, 3, 2, 8, 5, 5, -1, -1, + -1, -1, -1, -1, -1, -1, 9, 10, 10, 1, + 7, 6, 6, -1, -1, -1, -1, -1, -1, 11, + 11, 12, 14, -1, -1, 13, 13, 4, 4 +}; + +static const int code_vesa[85] = { + -1, -1, -1, -1, 15, -1, -1, -1, -1, 16, + -1, -1, -1, -1, 17, -1, 23, -1, -1, -1, + -1, -1, 29, 18, -1, -1, -1, 32, 19, -1, + -1, -1, 21, -1, -1, 22, -1, -1, -1, 20, + -1, 30, 24, -1, -1, -1, -1, 25, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 31, 26, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 27, 28, -1, 33}; + +static const u8 edid_header[8] = {0x0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0}; + +static inline void hdmi_write_reg(const struct hdmi_reg idx, u32 val) +{ + __raw_writel(val, hdmi.base_wp + idx.idx); +} + +static inline u32 hdmi_read_reg(const struct hdmi_reg idx) +{ + return __raw_readl(hdmi.base_wp + idx.idx); +} + +static inline int hdmi_wait_for_bit_change(const struct hdmi_reg idx, + int b2, int b1, u32 val) +{ + u32 t = 0; + while (val != REG_GET(idx, b2, b1)) { + udelay(1); + if (t++ > 10000) + return !val; + } + return val; +} + +int hdmi_init_display(struct omap_dss_device *dssdev) +{ + DSSDBG("init_display\n"); + + return 0; +} + +static int hdmi_pll_init(enum hdmi_clk_refsel refsel, int dcofreq, + struct hdmi_pll_info *fmt, u16 sd) +{ + u32 r; + + /* PLL start always use manual mode */ + REG_FLD_MOD(PLLCTRL_PLL_CONTROL, 0x0, 0, 0); + + r = hdmi_read_reg(PLLCTRL_CFG1); + r = FLD_MOD(r, fmt->regm, 20, 9); /* CFG1_PLL_REGM */ + r = FLD_MOD(r, fmt->regn, 8, 1); /* CFG1_PLL_REGN */ + + hdmi_write_reg(PLLCTRL_CFG1, r); + + r = hdmi_read_reg(PLLCTRL_CFG2); + + r = FLD_MOD(r, 0x0, 12, 12); /* PLL_HIGHFREQ divide by 2 */ + r = FLD_MOD(r, 0x1, 13, 13); /* PLL_REFEN */ + r = FLD_MOD(r, 0x0, 14, 14); /* PHY_CLKINEN de-assert during locking */ + + if (dcofreq) { + /* divider programming for frequency beyond 1000Mhz */ + REG_FLD_MOD(PLLCTRL_CFG3, sd, 17, 10); + r = FLD_MOD(r, 0x4, 3, 1); /* 1000MHz and 2000MHz */ + } else { + r = FLD_MOD(r, 0x2, 3, 1); /* 500MHz and 1000MHz */ + } + + hdmi_write_reg(PLLCTRL_CFG2, r); + + r = hdmi_read_reg(PLLCTRL_CFG4); + r = FLD_MOD(r, fmt->regm2, 24, 18); + r = FLD_MOD(r, fmt->regmf, 17, 0); + + hdmi_write_reg(PLLCTRL_CFG4, r); + + /* go now */ + REG_FLD_MOD(PLLCTRL_PLL_GO, 0x1, 0, 0); + + /* wait for bit change */ + if (hdmi_wait_for_bit_change(PLLCTRL_PLL_GO, 0, 0, 1) != 1) { + DSSERR("PLL GO bit not set\n"); + return -ETIMEDOUT; + } + + /* Wait till the lock bit is set in PLL status */ + if (hdmi_wait_for_bit_change(PLLCTRL_PLL_STATUS, 1, 1, 1) != 1) { + DSSWARN("cannot lock PLL\n"); + DSSWARN("CFG1 0x%x\n", + hdmi_read_reg(PLLCTRL_CFG1)); + DSSWARN("CFG2 0x%x\n", + hdmi_read_reg(PLLCTRL_CFG2)); + DSSWARN("CFG4 0x%x\n", + hdmi_read_reg(PLLCTRL_CFG4)); + return -ETIMEDOUT; + } + + DSSDBG("PLL locked!\n"); + + return 0; +} + +/* PHY_PWR_CMD */ +static int hdmi_set_phy_pwr(enum hdmi_phy_pwr val) +{ + /* Command for power control of HDMI PHY */ + REG_FLD_MOD(HDMI_WP_PWR_CTRL, val, 7, 6); + + /* Status of the power control of HDMI PHY */ + if (hdmi_wait_for_bit_change(HDMI_WP_PWR_CTRL, 5, 4, val) != val) { + DSSERR("Failed to set PHY power mode to %d\n", val); + return -ETIMEDOUT; + } + + return 0; +} + +/* PLL_PWR_CMD */ +static int hdmi_set_pll_pwr(enum hdmi_pll_pwr val) +{ + /* Command for power control of HDMI PLL */ + REG_FLD_MOD(HDMI_WP_PWR_CTRL, val, 3, 2); + + /* wait till PHY_PWR_STATUS is set */ + if (hdmi_wait_for_bit_change(HDMI_WP_PWR_CTRL, 1, 0, val) != val) { + DSSERR("Failed to set PHY_PWR_STATUS\n"); + return -ETIMEDOUT; + } + + return 0; +} + +static int hdmi_pll_reset(void) +{ + /* SYSRESET controlled by power FSM */ + REG_FLD_MOD(PLLCTRL_PLL_CONTROL, 0x0, 3, 3); + + /* READ 0x0 reset is in progress */ + if (hdmi_wait_for_bit_change(PLLCTRL_PLL_STATUS, 0, 0, 1) != 1) { + DSSERR("Failed to sysreset PLL\n"); + return -ETIMEDOUT; + } + + return 0; +} + +static int hdmi_phy_init(void) +{ + u16 r = 0; + + r = hdmi_set_phy_pwr(HDMI_PHYPWRCMD_LDOON); + if (r) + return r; + + r = hdmi_set_phy_pwr(HDMI_PHYPWRCMD_TXON); + if (r) + return r; + + /* + * Read address 0 in order to get the SCP reset done completed + * Dummy access performed to make sure reset is done + */ + hdmi_read_reg(HDMI_TXPHY_TX_CTRL); + + /* + * Write to phy address 0 to configure the clock + * use HFBITCLK write HDMI_TXPHY_TX_CONTROL_FREQOUT field + */ + REG_FLD_MOD(HDMI_TXPHY_TX_CTRL, 0x1, 31, 30); + + /* Write to phy address 1 to start HDMI line (TXVALID and TMDSCLKEN) */ + hdmi_write_reg(HDMI_TXPHY_DIGITAL_CTRL, 0xF0000000); + + /* Setup max LDO voltage */ + REG_FLD_MOD(HDMI_TXPHY_POWER_CTRL, 0xB, 3, 0); + + /* Write to phy address 3 to change the polarity control */ + REG_FLD_MOD(HDMI_TXPHY_PAD_CFG_CTRL, 0x1, 27, 27); + + return 0; +} + +static int hdmi_wait_softreset(void) +{ + /* reset W1 */ + REG_FLD_MOD(HDMI_WP_SYSCONFIG, 0x1, 0, 0); + + /* wait till SOFTRESET == 0 */ + if (hdmi_wait_for_bit_change(HDMI_WP_SYSCONFIG, 0, 0, 0) != 0) { + DSSERR("sysconfig reset failed\n"); + return -ETIMEDOUT; + } + + return 0; +} + +static int hdmi_pll_program(struct hdmi_pll_info *fmt) +{ + u16 r = 0; + enum hdmi_clk_refsel refsel; + + /* wait for wrapper reset */ + r = hdmi_wait_softreset(); + if (r) + return r; + + r = hdmi_set_pll_pwr(HDMI_PLLPWRCMD_ALLOFF); + if (r) + return r; + + r = hdmi_set_pll_pwr(HDMI_PLLPWRCMD_BOTHON_ALLCLKS); + if (r) + return r; + + r = hdmi_pll_reset(); + if (r) + return r; + + refsel = HDMI_REFSEL_SYSCLK; + + r = hdmi_pll_init(refsel, fmt->dcofreq, fmt, fmt->regsd); + if (r) + return r; + + return 0; +} + +static void hdmi_phy_off(void) +{ + hdmi_set_phy_pwr(HDMI_PHYPWRCMD_OFF); +} + +static int hdmi_core_ddc_edid(u8 *pedid, int ext) +{ + u32 i, j; + char checksum = 0; + u32 offset = 0; + + /* Turn on CLK for DDC */ + REG_FLD_MOD(HDMI_CORE_AV_DPD, 0x7, 2, 0); + + /* + * SW HACK : Without the Delay DDC(i2c bus) reads 0 values / + * right shifted values( The behavior is not consistent and seen only + * with some TV's) + */ + usleep_range(800, 1000); + + if (!ext) { + /* Clk SCL Devices */ + REG_FLD_MOD(HDMI_CORE_DDC_CMD, 0xA, 3, 0); + + /* HDMI_CORE_DDC_STATUS_IN_PROG */ + if (hdmi_wait_for_bit_change(HDMI_CORE_DDC_STATUS, + 4, 4, 0) != 0) { + DSSERR("Failed to program DDC\n"); + return -ETIMEDOUT; + } + + /* Clear FIFO */ + REG_FLD_MOD(HDMI_CORE_DDC_CMD, 0x9, 3, 0); + + /* HDMI_CORE_DDC_STATUS_IN_PROG */ + if (hdmi_wait_for_bit_change(HDMI_CORE_DDC_STATUS, + 4, 4, 0) != 0) { + DSSERR("Failed to program DDC\n"); + return -ETIMEDOUT; + } + + } else { + if (ext % 2 != 0) + offset = 0x80; + } + + /* Load Segment Address Register */ + REG_FLD_MOD(HDMI_CORE_DDC_SEGM, ext/2, 7, 0); + + /* Load Slave Address Register */ + REG_FLD_MOD(HDMI_CORE_DDC_ADDR, 0xA0 >> 1, 7, 1); + + /* Load Offset Address Register */ + REG_FLD_MOD(HDMI_CORE_DDC_OFFSET, offset, 7, 0); + + /* Load Byte Count */ + REG_FLD_MOD(HDMI_CORE_DDC_COUNT1, 0x80, 7, 0); + REG_FLD_MOD(HDMI_CORE_DDC_COUNT2, 0x0, 1, 0); + + /* Set DDC_CMD */ + if (ext) + REG_FLD_MOD(HDMI_CORE_DDC_CMD, 0x4, 3, 0); + else + REG_FLD_MOD(HDMI_CORE_DDC_CMD, 0x2, 3, 0); + + /* HDMI_CORE_DDC_STATUS_BUS_LOW */ + if (REG_GET(HDMI_CORE_DDC_STATUS, 6, 6) == 1) { + DSSWARN("I2C Bus Low?\n"); + return -EIO; + } + /* HDMI_CORE_DDC_STATUS_NO_ACK */ + if (REG_GET(HDMI_CORE_DDC_STATUS, 5, 5) == 1) { + DSSWARN("I2C No Ack\n"); + return -EIO; + } + + i = ext * 128; + j = 0; + while (((REG_GET(HDMI_CORE_DDC_STATUS, 4, 4) == 1) || + (REG_GET(HDMI_CORE_DDC_STATUS, 2, 2) == 0)) && + j < 128) { + + if (REG_GET(HDMI_CORE_DDC_STATUS, 2, 2) == 0) { + /* FIFO not empty */ + pedid[i++] = REG_GET(HDMI_CORE_DDC_DATA, 7, 0); + j++; + } + } + + for (j = 0; j < 128; j++) + checksum += pedid[j]; + + if (checksum != 0) { + DSSERR("E-EDID checksum failed!!\n"); + return -EIO; + } + + return 0; +} + +static int read_edid(u8 *pedid, u16 max_length) +{ + int r = 0, n = 0, i = 0; + int max_ext_blocks = (max_length / 128) - 1; + + r = hdmi_core_ddc_edid(pedid, 0); + if (r) { + return r; + } else { + n = pedid[0x7e]; + + /* + * README: need to comply with max_length set by the caller. + * Better implementation should be to allocate necessary + * memory to store EDID according to nb_block field found + * in first block + */ + if (n > max_ext_blocks) + n = max_ext_blocks; + + for (i = 1; i <= n; i++) { + r = hdmi_core_ddc_edid(pedid, i); + if (r) + return r; + } + } + return 0; +} + +static int get_timings_index(void) +{ + int code; + + if (hdmi.mode == 0) + code = code_vesa[hdmi.code]; + else + code = code_cea[hdmi.code]; + + if (code == -1) { + /* HDMI code 4 corresponds to 640 * 480 VGA */ + hdmi.code = 4; + /* DVI mode 1 corresponds to HDMI 0 to DVI */ + hdmi.mode = HDMI_DVI; + + code = code_vesa[hdmi.code]; + } + return code; +} + +static struct hdmi_cm hdmi_get_code(struct omap_video_timings *timing) +{ + int i = 0, code = -1, temp_vsync = 0, temp_hsync = 0; + int timing_vsync = 0, timing_hsync = 0; + struct omap_video_timings temp; + struct hdmi_cm cm = {-1}; + DSSDBG("hdmi_get_code\n"); + + for (i = 0; i < OMAP_HDMI_TIMINGS_NB; i++) { + temp = cea_vesa_timings[i].timings; + if ((temp.pixel_clock == timing->pixel_clock) && + (temp.x_res == timing->x_res) && + (temp.y_res == timing->y_res)) { + + temp_hsync = temp.hfp + temp.hsw + temp.hbp; + timing_hsync = timing->hfp + timing->hsw + timing->hbp; + temp_vsync = temp.vfp + temp.vsw + temp.vbp; + timing_vsync = timing->vfp + timing->vsw + timing->vbp; + + DSSDBG("temp_hsync = %d , temp_vsync = %d" + "timing_hsync = %d, timing_vsync = %d\n", + temp_hsync, temp_hsync, + timing_hsync, timing_vsync); + + if ((temp_hsync == timing_hsync) && + (temp_vsync == timing_vsync)) { + code = i; + cm.code = code_index[i]; + if (code < 14) + cm.mode = HDMI_HDMI; + else + cm.mode = HDMI_DVI; + DSSDBG("Hdmi_code = %d mode = %d\n", + cm.code, cm.mode); + break; + } + } + } + + return cm; +} + +static void get_horz_vert_timing_info(int current_descriptor_addrs, u8 *edid , + struct omap_video_timings *timings) +{ + /* X and Y resolution */ + timings->x_res = (((edid[current_descriptor_addrs + 4] & 0xF0) << 4) | + edid[current_descriptor_addrs + 2]); + timings->y_res = (((edid[current_descriptor_addrs + 7] & 0xF0) << 4) | + edid[current_descriptor_addrs + 5]); + + timings->pixel_clock = ((edid[current_descriptor_addrs + 1] << 8) | + edid[current_descriptor_addrs]); + + timings->pixel_clock = 10 * timings->pixel_clock; + + /* HORIZONTAL FRONT PORCH */ + timings->hfp = edid[current_descriptor_addrs + 8] | + ((edid[current_descriptor_addrs + 11] & 0xc0) << 2); + /* HORIZONTAL SYNC WIDTH */ + timings->hsw = edid[current_descriptor_addrs + 9] | + ((edid[current_descriptor_addrs + 11] & 0x30) << 4); + /* HORIZONTAL BACK PORCH */ + timings->hbp = (((edid[current_descriptor_addrs + 4] & 0x0F) << 8) | + edid[current_descriptor_addrs + 3]) - + (timings->hfp + timings->hsw); + /* VERTICAL FRONT PORCH */ + timings->vfp = ((edid[current_descriptor_addrs + 10] & 0xF0) >> 4) | + ((edid[current_descriptor_addrs + 11] & 0x0f) << 2); + /* VERTICAL SYNC WIDTH */ + timings->vsw = (edid[current_descriptor_addrs + 10] & 0x0F) | + ((edid[current_descriptor_addrs + 11] & 0x03) << 4); + /* VERTICAL BACK PORCH */ + timings->vbp = (((edid[current_descriptor_addrs + 7] & 0x0F) << 8) | + edid[current_descriptor_addrs + 6]) - + (timings->vfp + timings->vsw); + +} + +/* Description : This function gets the resolution information from EDID */ +static void get_edid_timing_data(u8 *edid) +{ + u8 count; + u16 current_descriptor_addrs; + struct hdmi_cm cm; + struct omap_video_timings edid_timings; + + /* seach block 0, there are 4 DTDs arranged in priority order */ + for (count = 0; count < EDID_SIZE_BLOCK0_TIMING_DESCRIPTOR; count++) { + current_descriptor_addrs = + EDID_DESCRIPTOR_BLOCK0_ADDRESS + + count * EDID_TIMING_DESCRIPTOR_SIZE; + get_horz_vert_timing_info(current_descriptor_addrs, + edid, &edid_timings); + cm = hdmi_get_code(&edid_timings); + DSSDBG("Block0[%d] value matches code = %d , mode = %d\n", + count, cm.code, cm.mode); + if (cm.code == -1) { + continue; + } else { + hdmi.code = cm.code; + hdmi.mode = cm.mode; + DSSDBG("code = %d , mode = %d\n", + hdmi.code, hdmi.mode); + return; + } + } + if (edid[0x7e] != 0x00) { + for (count = 0; count < EDID_SIZE_BLOCK1_TIMING_DESCRIPTOR; + count++) { + current_descriptor_addrs = + EDID_DESCRIPTOR_BLOCK1_ADDRESS + + count * EDID_TIMING_DESCRIPTOR_SIZE; + get_horz_vert_timing_info(current_descriptor_addrs, + edid, &edid_timings); + cm = hdmi_get_code(&edid_timings); + DSSDBG("Block1[%d] value matches code = %d, mode = %d", + count, cm.code, cm.mode); + if (cm.code == -1) { + continue; + } else { + hdmi.code = cm.code; + hdmi.mode = cm.mode; + DSSDBG("code = %d , mode = %d\n", + hdmi.code, hdmi.mode); + return; + } + } + } + + DSSINFO("no valid timing found , falling back to VGA\n"); + hdmi.code = 4; /* setting default value of 640 480 VGA */ + hdmi.mode = HDMI_DVI; +} + +static void hdmi_read_edid(struct omap_video_timings *dp) +{ + int ret = 0, code; + + memset(hdmi.edid, 0, HDMI_EDID_MAX_LENGTH); + + if (!hdmi.edid_set) + ret = read_edid(hdmi.edid, HDMI_EDID_MAX_LENGTH); + + if (!ret) { + if (!memcmp(hdmi.edid, edid_header, sizeof(edid_header))) { + /* search for timings of default resolution */ + get_edid_timing_data(hdmi.edid); + hdmi.edid_set = true; + } + } else { + DSSWARN("failed to read E-EDID\n"); + } + + if (!hdmi.edid_set) { + DSSINFO("fallback to VGA\n"); + hdmi.code = 4; /* setting default value of 640 480 VGA */ + hdmi.mode = HDMI_DVI; + } + + code = get_timings_index(); + + *dp = cea_vesa_timings[code].timings; +} + +static void hdmi_core_init(struct hdmi_core_video_config *video_cfg, + struct hdmi_core_infoframe_avi *avi_cfg, + struct hdmi_core_packet_enable_repeat *repeat_cfg) +{ + DSSDBG("Enter hdmi_core_init\n"); + + /* video core */ + video_cfg->ip_bus_width = HDMI_INPUT_8BIT; + video_cfg->op_dither_truc = HDMI_OUTPUTTRUNCATION_8BIT; + video_cfg->deep_color_pkt = HDMI_DEEPCOLORPACKECTDISABLE; + video_cfg->pkt_mode = HDMI_PACKETMODERESERVEDVALUE; + video_cfg->hdmi_dvi = HDMI_DVI; + video_cfg->tclk_sel_clkmult = HDMI_FPLL10IDCK; + + /* info frame */ + avi_cfg->db1_format = 0; + avi_cfg->db1_active_info = 0; + avi_cfg->db1_bar_info_dv = 0; + avi_cfg->db1_scan_info = 0; + avi_cfg->db2_colorimetry = 0; + avi_cfg->db2_aspect_ratio = 0; + avi_cfg->db2_active_fmt_ar = 0; + avi_cfg->db3_itc = 0; + avi_cfg->db3_ec = 0; + avi_cfg->db3_q_range = 0; + avi_cfg->db3_nup_scaling = 0; + avi_cfg->db4_videocode = 0; + avi_cfg->db5_pixel_repeat = 0; + avi_cfg->db6_7_line_eoftop = 0 ; + avi_cfg->db8_9_line_sofbottom = 0; + avi_cfg->db10_11_pixel_eofleft = 0; + avi_cfg->db12_13_pixel_sofright = 0; + + /* packet enable and repeat */ + repeat_cfg->audio_pkt = 0; + repeat_cfg->audio_pkt_repeat = 0; + repeat_cfg->avi_infoframe = 0; + repeat_cfg->avi_infoframe_repeat = 0; + repeat_cfg->gen_cntrl_pkt = 0; + repeat_cfg->gen_cntrl_pkt_repeat = 0; + repeat_cfg->generic_pkt = 0; + repeat_cfg->generic_pkt_repeat = 0; +} + +static void hdmi_core_powerdown_disable(void) +{ + DSSDBG("Enter hdmi_core_powerdown_disable\n"); + REG_FLD_MOD(HDMI_CORE_CTRL1, 0x0, 0, 0); +} + +static void hdmi_core_swreset_release(void) +{ + DSSDBG("Enter hdmi_core_swreset_release\n"); + REG_FLD_MOD(HDMI_CORE_SYS_SRST, 0x0, 0, 0); +} + +static void hdmi_core_swreset_assert(void) +{ + DSSDBG("Enter hdmi_core_swreset_assert\n"); + REG_FLD_MOD(HDMI_CORE_SYS_SRST, 0x1, 0, 0); +} + +/* DSS_HDMI_CORE_VIDEO_CONFIG */ +static void hdmi_core_video_config(struct hdmi_core_video_config *cfg) +{ + u32 r = 0; + + /* sys_ctrl1 default configuration not tunable */ + r = hdmi_read_reg(HDMI_CORE_CTRL1); + r = FLD_MOD(r, HDMI_CORE_CTRL1_VEN_FOLLOWVSYNC, 5, 5); + r = FLD_MOD(r, HDMI_CORE_CTRL1_HEN_FOLLOWHSYNC, 4, 4); + r = FLD_MOD(r, HDMI_CORE_CTRL1_BSEL_24BITBUS, 2, 2); + r = FLD_MOD(r, HDMI_CORE_CTRL1_EDGE_RISINGEDGE, 1, 1); + hdmi_write_reg(HDMI_CORE_CTRL1, r); + + REG_FLD_MOD(HDMI_CORE_SYS_VID_ACEN, cfg->ip_bus_width, 7, 6); + + /* Vid_Mode */ + r = hdmi_read_reg(HDMI_CORE_SYS_VID_MODE); + + /* dither truncation configuration */ + if (cfg->op_dither_truc > HDMI_OUTPUTTRUNCATION_12BIT) { + r = FLD_MOD(r, cfg->op_dither_truc - 3, 7, 6); + r = FLD_MOD(r, 1, 5, 5); + } else { + r = FLD_MOD(r, cfg->op_dither_truc, 7, 6); + r = FLD_MOD(r, 0, 5, 5); + } + hdmi_write_reg(HDMI_CORE_SYS_VID_MODE, r); + + /* HDMI_Ctrl */ + r = hdmi_read_reg(HDMI_CORE_AV_HDMI_CTRL); + r = FLD_MOD(r, cfg->deep_color_pkt, 6, 6); + r = FLD_MOD(r, cfg->pkt_mode, 5, 3); + r = FLD_MOD(r, cfg->hdmi_dvi, 0, 0); + hdmi_write_reg(HDMI_CORE_AV_HDMI_CTRL, r); + + /* TMDS_CTRL */ + REG_FLD_MOD(HDMI_CORE_SYS_TMDS_CTRL, + cfg->tclk_sel_clkmult, 6, 5); +} + +static void hdmi_core_aux_infoframe_avi_config( + struct hdmi_core_infoframe_avi info_avi) +{ + u32 val; + char sum = 0, checksum = 0; + + sum += 0x82 + 0x002 + 0x00D; + hdmi_write_reg(HDMI_CORE_AV_AVI_TYPE, 0x082); + hdmi_write_reg(HDMI_CORE_AV_AVI_VERS, 0x002); + hdmi_write_reg(HDMI_CORE_AV_AVI_LEN, 0x00D); + + val = (info_avi.db1_format << 5) | + (info_avi.db1_active_info << 4) | + (info_avi.db1_bar_info_dv << 2) | + (info_avi.db1_scan_info); + hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(0), val); + sum += val; + + val = (info_avi.db2_colorimetry << 6) | + (info_avi.db2_aspect_ratio << 4) | + (info_avi.db2_active_fmt_ar); + hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(1), val); + sum += val; + + val = (info_avi.db3_itc << 7) | + (info_avi.db3_ec << 4) | + (info_avi.db3_q_range << 2) | + (info_avi.db3_nup_scaling); + hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(2), val); + sum += val; + + hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(3), info_avi.db4_videocode); + sum += info_avi.db4_videocode; + + val = info_avi.db5_pixel_repeat; + hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(4), val); + sum += val; + + val = info_avi.db6_7_line_eoftop & 0x00FF; + hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(5), val); + sum += val; + + val = ((info_avi.db6_7_line_eoftop >> 8) & 0x00FF); + hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(6), val); + sum += val; + + val = info_avi.db8_9_line_sofbottom & 0x00FF; + hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(7), val); + sum += val; + + val = ((info_avi.db8_9_line_sofbottom >> 8) & 0x00FF); + hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(8), val); + sum += val; + + val = info_avi.db10_11_pixel_eofleft & 0x00FF; + hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(9), val); + sum += val; + + val = ((info_avi.db10_11_pixel_eofleft >> 8) & 0x00FF); + hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(10), val); + sum += val; + + val = info_avi.db12_13_pixel_sofright & 0x00FF; + hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(11), val); + sum += val; + + val = ((info_avi.db12_13_pixel_sofright >> 8) & 0x00FF); + hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(12), val); + sum += val; + + checksum = 0x100 - sum; + hdmi_write_reg(HDMI_CORE_AV_AVI_CHSUM, checksum); +} + +static void hdmi_core_av_packet_config( + struct hdmi_core_packet_enable_repeat repeat_cfg) +{ + /* enable/repeat the infoframe */ + hdmi_write_reg(HDMI_CORE_AV_PB_CTRL1, + (repeat_cfg.audio_pkt << 5) | + (repeat_cfg.audio_pkt_repeat << 4) | + (repeat_cfg.avi_infoframe << 1) | + (repeat_cfg.avi_infoframe_repeat)); + + /* enable/repeat the packet */ + hdmi_write_reg(HDMI_CORE_AV_PB_CTRL2, + (repeat_cfg.gen_cntrl_pkt << 3) | + (repeat_cfg.gen_cntrl_pkt_repeat << 2) | + (repeat_cfg.generic_pkt << 1) | + (repeat_cfg.generic_pkt_repeat)); +} + +static void hdmi_wp_init(struct omap_video_timings *timings, + struct hdmi_video_format *video_fmt, + struct hdmi_video_interface *video_int) +{ + DSSDBG("Enter hdmi_wp_init\n"); + + timings->hbp = 0; + timings->hfp = 0; + timings->hsw = 0; + timings->vbp = 0; + timings->vfp = 0; + timings->vsw = 0; + + video_fmt->packing_mode = HDMI_PACK_10b_RGB_YUV444; + video_fmt->y_res = 0; + video_fmt->x_res = 0; + + video_int->vsp = 0; + video_int->hsp = 0; + + video_int->interlacing = 0; + video_int->tm = 0; /* HDMI_TIMING_SLAVE */ + +} + +static void hdmi_wp_video_start(bool start) +{ + REG_FLD_MOD(HDMI_WP_VIDEO_CFG, start, 31, 31); +} + +static void hdmi_wp_video_init_format(struct hdmi_video_format *video_fmt, + struct omap_video_timings *timings, struct hdmi_config *param) +{ + DSSDBG("Enter hdmi_wp_video_init_format\n"); + + video_fmt->y_res = param->timings.timings.y_res; + video_fmt->x_res = param->timings.timings.x_res; + + timings->hbp = param->timings.timings.hbp; + timings->hfp = param->timings.timings.hfp; + timings->hsw = param->timings.timings.hsw; + timings->vbp = param->timings.timings.vbp; + timings->vfp = param->timings.timings.vfp; + timings->vsw = param->timings.timings.vsw; +} + +static void hdmi_wp_video_config_format( + struct hdmi_video_format *video_fmt) +{ + u32 l = 0; + + REG_FLD_MOD(HDMI_WP_VIDEO_CFG, video_fmt->packing_mode, 10, 8); + + l |= FLD_VAL(video_fmt->y_res, 31, 16); + l |= FLD_VAL(video_fmt->x_res, 15, 0); + hdmi_write_reg(HDMI_WP_VIDEO_SIZE, l); +} + +static void hdmi_wp_video_config_interface( + struct hdmi_video_interface *video_int) +{ + u32 r; + DSSDBG("Enter hdmi_wp_video_config_interface\n"); + + r = hdmi_read_reg(HDMI_WP_VIDEO_CFG); + r = FLD_MOD(r, video_int->vsp, 7, 7); + r = FLD_MOD(r, video_int->hsp, 6, 6); + r = FLD_MOD(r, video_int->interlacing, 3, 3); + r = FLD_MOD(r, video_int->tm, 1, 0); + hdmi_write_reg(HDMI_WP_VIDEO_CFG, r); +} + +static void hdmi_wp_video_config_timing( + struct omap_video_timings *timings) +{ + u32 timing_h = 0; + u32 timing_v = 0; + + DSSDBG("Enter hdmi_wp_video_config_timing\n"); + + timing_h |= FLD_VAL(timings->hbp, 31, 20); + timing_h |= FLD_VAL(timings->hfp, 19, 8); + timing_h |= FLD_VAL(timings->hsw, 7, 0); + hdmi_write_reg(HDMI_WP_VIDEO_TIMING_H, timing_h); + + timing_v |= FLD_VAL(timings->vbp, 31, 20); + timing_v |= FLD_VAL(timings->vfp, 19, 8); + timing_v |= FLD_VAL(timings->vsw, 7, 0); + hdmi_write_reg(HDMI_WP_VIDEO_TIMING_V, timing_v); +} + +static void hdmi_basic_configure(struct hdmi_config *cfg) +{ + /* HDMI */ + struct omap_video_timings video_timing; + struct hdmi_video_format video_format; + struct hdmi_video_interface video_interface; + /* HDMI core */ + struct hdmi_core_infoframe_avi avi_cfg; + struct hdmi_core_video_config v_core_cfg; + struct hdmi_core_packet_enable_repeat repeat_cfg; + + hdmi_wp_init(&video_timing, &video_format, + &video_interface); + + hdmi_core_init(&v_core_cfg, + &avi_cfg, + &repeat_cfg); + + hdmi_wp_video_init_format(&video_format, + &video_timing, cfg); + + hdmi_wp_video_config_timing(&video_timing); + + /* video config */ + video_format.packing_mode = HDMI_PACK_24b_RGB_YUV444_YUV422; + + hdmi_wp_video_config_format(&video_format); + + video_interface.vsp = cfg->timings.vsync_pol; + video_interface.hsp = cfg->timings.hsync_pol; + video_interface.interlacing = cfg->interlace; + video_interface.tm = 1 ; /* HDMI_TIMING_MASTER_24BIT */ + + hdmi_wp_video_config_interface(&video_interface); + + /* + * configure core video part + * set software reset in the core + */ + hdmi_core_swreset_assert(); + + /* power down off */ + hdmi_core_powerdown_disable(); + + v_core_cfg.pkt_mode = HDMI_PACKETMODE24BITPERPIXEL; + v_core_cfg.hdmi_dvi = cfg->cm.mode; + + hdmi_core_video_config(&v_core_cfg); + + /* release software reset in the core */ + hdmi_core_swreset_release(); + + /* + * configure packet + * info frame video see doc CEA861-D page 65 + */ + avi_cfg.db1_format = HDMI_INFOFRAME_AVI_DB1Y_RGB; + avi_cfg.db1_active_info = + HDMI_INFOFRAME_AVI_DB1A_ACTIVE_FORMAT_OFF; + avi_cfg.db1_bar_info_dv = HDMI_INFOFRAME_AVI_DB1B_NO; + avi_cfg.db1_scan_info = HDMI_INFOFRAME_AVI_DB1S_0; + avi_cfg.db2_colorimetry = HDMI_INFOFRAME_AVI_DB2C_NO; + avi_cfg.db2_aspect_ratio = HDMI_INFOFRAME_AVI_DB2M_NO; + avi_cfg.db2_active_fmt_ar = HDMI_INFOFRAME_AVI_DB2R_SAME; + avi_cfg.db3_itc = HDMI_INFOFRAME_AVI_DB3ITC_NO; + avi_cfg.db3_ec = HDMI_INFOFRAME_AVI_DB3EC_XVYUV601; + avi_cfg.db3_q_range = HDMI_INFOFRAME_AVI_DB3Q_DEFAULT; + avi_cfg.db3_nup_scaling = HDMI_INFOFRAME_AVI_DB3SC_NO; + avi_cfg.db4_videocode = cfg->cm.code; + avi_cfg.db5_pixel_repeat = HDMI_INFOFRAME_AVI_DB5PR_NO; + avi_cfg.db6_7_line_eoftop = 0; + avi_cfg.db8_9_line_sofbottom = 0; + avi_cfg.db10_11_pixel_eofleft = 0; + avi_cfg.db12_13_pixel_sofright = 0; + + hdmi_core_aux_infoframe_avi_config(avi_cfg); + + /* enable/repeat the infoframe */ + repeat_cfg.avi_infoframe = HDMI_PACKETENABLE; + repeat_cfg.avi_infoframe_repeat = HDMI_PACKETREPEATON; + /* wakeup */ + repeat_cfg.audio_pkt = HDMI_PACKETENABLE; + repeat_cfg.audio_pkt_repeat = HDMI_PACKETREPEATON; + hdmi_core_av_packet_config(repeat_cfg); +} + +static void update_hdmi_timings(struct hdmi_config *cfg, + struct omap_video_timings *timings, int code) +{ + cfg->timings.timings.x_res = timings->x_res; + cfg->timings.timings.y_res = timings->y_res; + cfg->timings.timings.hbp = timings->hbp; + cfg->timings.timings.hfp = timings->hfp; + cfg->timings.timings.hsw = timings->hsw; + cfg->timings.timings.vbp = timings->vbp; + cfg->timings.timings.vfp = timings->vfp; + cfg->timings.timings.vsw = timings->vsw; + cfg->timings.timings.pixel_clock = timings->pixel_clock; + cfg->timings.vsync_pol = cea_vesa_timings[code].vsync_pol; + cfg->timings.hsync_pol = cea_vesa_timings[code].hsync_pol; +} + +static void hdmi_compute_pll(unsigned long clkin, int phy, + int n, struct hdmi_pll_info *pi) +{ + unsigned long refclk; + u32 mf; + + /* + * Input clock is predivided by N + 1 + * out put of which is reference clk + */ + refclk = clkin / (n + 1); + pi->regn = n; + + /* + * multiplier is pixel_clk/ref_clk + * Multiplying by 100 to avoid fractional part removal + */ + pi->regm = (phy * 100/(refclk))/100; + pi->regm2 = 1; + + /* + * fractional multiplier is remainder of the difference between + * multiplier and actual phy(required pixel clock thus should be + * multiplied by 2^18(262144) divided by the reference clock + */ + mf = (phy - pi->regm * refclk) * 262144; + pi->regmf = mf/(refclk); + + /* + * Dcofreq should be set to 1 if required pixel clock + * is greater than 1000MHz + */ + pi->dcofreq = phy > 1000 * 100; + pi->regsd = ((pi->regm * clkin / 10) / ((n + 1) * 250) + 5) / 10; + + DSSDBG("M = %d Mf = %d\n", pi->regm, pi->regmf); + DSSDBG("range = %d sd = %d\n", pi->dcofreq, pi->regsd); +} + +static void hdmi_enable_clocks(int enable) +{ + if (enable) + dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK | + DSS_CLK_SYSCK | DSS_CLK_VIDFCK); + else + dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK | + DSS_CLK_SYSCK | DSS_CLK_VIDFCK); +} + +static int hdmi_power_on(struct omap_dss_device *dssdev) +{ + int r, code = 0; + struct hdmi_pll_info pll_data; + struct omap_video_timings *p; + int clkin, n, phy; + + hdmi_enable_clocks(1); + + dispc_enable_channel(OMAP_DSS_CHANNEL_DIGIT, 0); + + p = &dssdev->panel.timings; + + DSSDBG("hdmi_power_on x_res= %d y_res = %d\n", + dssdev->panel.timings.x_res, + dssdev->panel.timings.y_res); + + if (!hdmi.custom_set) { + DSSDBG("Read EDID as no EDID is not set on poweron\n"); + hdmi_read_edid(p); + } + code = get_timings_index(); + dssdev->panel.timings = cea_vesa_timings[code].timings; + update_hdmi_timings(&hdmi.cfg, p, code); + + clkin = 3840; /* 38.4 MHz */ + n = 15; /* this is a constant for our math */ + phy = p->pixel_clock; + + hdmi_compute_pll(clkin, phy, n, &pll_data); + + hdmi_wp_video_start(0); + + /* config the PLL and PHY first */ + r = hdmi_pll_program(&pll_data); + if (r) { + DSSDBG("Failed to lock PLL\n"); + goto err; + } + + r = hdmi_phy_init(); + if (r) { + DSSDBG("Failed to start PHY\n"); + goto err; + } + + hdmi.cfg.cm.mode = hdmi.mode; + hdmi.cfg.cm.code = hdmi.code; + hdmi_basic_configure(&hdmi.cfg); + + /* Make selection of HDMI in DSS */ + dss_select_hdmi_venc_clk_source(DSS_HDMI_M_PCLK); + + /* Select the dispc clock source as PRCM clock, to ensure that it is not + * DSI PLL source as the clock selected by DSI PLL might not be + * sufficient for the resolution selected / that can be changed + * dynamically by user. This can be moved to single location , say + * Boardfile. + */ + dss_select_dispc_clk_source(DSS_CLK_SRC_FCK); + + /* bypass TV gamma table */ + dispc_enable_gamma_table(0); + + /* tv size */ + dispc_set_digit_size(dssdev->panel.timings.x_res, + dssdev->panel.timings.y_res); + + dispc_enable_channel(OMAP_DSS_CHANNEL_DIGIT, 1); + + hdmi_wp_video_start(1); + + return 0; +err: + hdmi_enable_clocks(0); + return -EIO; +} + +static void hdmi_power_off(struct omap_dss_device *dssdev) +{ + dispc_enable_channel(OMAP_DSS_CHANNEL_DIGIT, 0); + + hdmi_wp_video_start(0); + hdmi_phy_off(); + hdmi_set_pll_pwr(HDMI_PLLPWRCMD_ALLOFF); + hdmi_enable_clocks(0); + + hdmi.edid_set = 0; +} + +int omapdss_hdmi_display_check_timing(struct omap_dss_device *dssdev, + struct omap_video_timings *timings) +{ + struct hdmi_cm cm; + + cm = hdmi_get_code(timings); + if (cm.code == -1) { + DSSERR("Invalid timing entered\n"); + return -EINVAL; + } + + return 0; + +} + +void omapdss_hdmi_display_set_timing(struct omap_dss_device *dssdev) +{ + struct hdmi_cm cm; + + hdmi.custom_set = 1; + cm = hdmi_get_code(&dssdev->panel.timings); + hdmi.code = cm.code; + hdmi.mode = cm.mode; + omapdss_hdmi_display_enable(dssdev); + hdmi.custom_set = 0; +} + +int omapdss_hdmi_display_enable(struct omap_dss_device *dssdev) +{ + int r = 0; + + DSSDBG("ENTER hdmi_display_enable\n"); + + mutex_lock(&hdmi.lock); + + r = omap_dss_start_device(dssdev); + if (r) { + DSSERR("failed to start device\n"); + goto err0; + } + + if (dssdev->platform_enable) { + r = dssdev->platform_enable(dssdev); + if (r) { + DSSERR("failed to enable GPIO's\n"); + goto err1; + } + } + + r = hdmi_power_on(dssdev); + if (r) { + DSSERR("failed to power on device\n"); + goto err2; + } + + mutex_unlock(&hdmi.lock); + return 0; + +err2: + if (dssdev->platform_disable) + dssdev->platform_disable(dssdev); +err1: + omap_dss_stop_device(dssdev); +err0: + mutex_unlock(&hdmi.lock); + return r; +} + +void omapdss_hdmi_display_disable(struct omap_dss_device *dssdev) +{ + DSSDBG("Enter hdmi_display_disable\n"); + + mutex_lock(&hdmi.lock); + + hdmi_power_off(dssdev); + + if (dssdev->platform_disable) + dssdev->platform_disable(dssdev); + + omap_dss_stop_device(dssdev); + + mutex_unlock(&hdmi.lock); +} + +/* HDMI HW IP initialisation */ +static int omapdss_hdmihw_probe(struct platform_device *pdev) +{ + struct resource *hdmi_mem; + + hdmi.pdata = pdev->dev.platform_data; + hdmi.pdev = pdev; + + mutex_init(&hdmi.lock); + + hdmi_mem = platform_get_resource(hdmi.pdev, IORESOURCE_MEM, 0); + if (!hdmi_mem) { + DSSERR("can't get IORESOURCE_MEM HDMI\n"); + return -EINVAL; + } + + /* Base address taken from platform */ + hdmi.base_wp = ioremap(hdmi_mem->start, resource_size(hdmi_mem)); + if (!hdmi.base_wp) { + DSSERR("can't ioremap WP\n"); + return -ENOMEM; + } + + hdmi_panel_init(); + + return 0; +} + +static int omapdss_hdmihw_remove(struct platform_device *pdev) +{ + hdmi_panel_exit(); + + iounmap(hdmi.base_wp); + + return 0; +} + +static struct platform_driver omapdss_hdmihw_driver = { + .probe = omapdss_hdmihw_probe, + .remove = omapdss_hdmihw_remove, + .driver = { + .name = "omapdss_hdmi", + .owner = THIS_MODULE, + }, +}; + +int hdmi_init_platform_driver(void) +{ + return platform_driver_register(&omapdss_hdmihw_driver); +} + +void hdmi_uninit_platform_driver(void) +{ + return platform_driver_unregister(&omapdss_hdmihw_driver); +} -- GitLab From 70be83235ea2815f6c2a5fd45753de406be6c6aa Mon Sep 17 00:00:00 2001 From: Mythri P K Date: Thu, 10 Mar 2011 15:48:48 +0530 Subject: [PATCH 0729/2822] OMAP4: DSS2: HDMI: HDMI panel driver addition in the DSS The panel driver(hdmi_omap4_panel.c) in omap2/dss acts as a controller to manage the enable and disable requests and synchronize audio and video. Signed-off-by: Mythri P K Signed-off-by: Tomi Valkeinen --- drivers/video/omap2/dss/dss.h | 2 + drivers/video/omap2/dss/hdmi_omap4_panel.c | 222 +++++++++++++++++++++ 2 files changed, 224 insertions(+) create mode 100644 drivers/video/omap2/dss/hdmi_omap4_panel.c diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h index 91ed3fa8e60d6..c2f582bb19c05 100644 --- a/drivers/video/omap2/dss/dss.h +++ b/drivers/video/omap2/dss/dss.h @@ -477,6 +477,8 @@ void omapdss_hdmi_display_disable(struct omap_dss_device *dssdev); void omapdss_hdmi_display_set_timing(struct omap_dss_device *dssdev); int omapdss_hdmi_display_check_timing(struct omap_dss_device *dssdev, struct omap_video_timings *timings); +int hdmi_panel_init(void); +void hdmi_panel_exit(void); /* RFBI */ #ifdef CONFIG_OMAP2_DSS_RFBI diff --git a/drivers/video/omap2/dss/hdmi_omap4_panel.c b/drivers/video/omap2/dss/hdmi_omap4_panel.c new file mode 100644 index 0000000000000..ffb5de94131fa --- /dev/null +++ b/drivers/video/omap2/dss/hdmi_omap4_panel.c @@ -0,0 +1,222 @@ +/* + * hdmi_omap4_panel.c + * + * HDMI library support functions for TI OMAP4 processors. + * + * Copyright (C) 2010-2011 Texas Instruments Incorporated - http://www.ti.com/ + * Authors: Mythri P k + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published by + * the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see . + */ + +#include +#include +#include +#include +#include +#include + +#include "dss.h" + +static struct { + struct mutex hdmi_lock; +} hdmi; + + +static int hdmi_panel_probe(struct omap_dss_device *dssdev) +{ + DSSDBG("ENTER hdmi_panel_probe\n"); + + dssdev->panel.config = OMAP_DSS_LCD_TFT | + OMAP_DSS_LCD_IVS | OMAP_DSS_LCD_IHS; + + /* + * Initialize the timings to 640 * 480 + * This is only for framebuffer update not for TV timing setting + * Setting TV timing will be done only on enable + */ + dssdev->panel.timings.x_res = 640; + dssdev->panel.timings.y_res = 480; + + DSSDBG("hdmi_panel_probe x_res= %d y_res = %d\n", + dssdev->panel.timings.x_res, + dssdev->panel.timings.y_res); + return 0; +} + +static void hdmi_panel_remove(struct omap_dss_device *dssdev) +{ + +} + +static int hdmi_panel_enable(struct omap_dss_device *dssdev) +{ + int r = 0; + DSSDBG("ENTER hdmi_panel_enable\n"); + + mutex_lock(&hdmi.hdmi_lock); + + if (dssdev->state != OMAP_DSS_DISPLAY_DISABLED) { + r = -EINVAL; + goto err; + } + + r = omapdss_hdmi_display_enable(dssdev); + if (r) { + DSSERR("failed to power on\n"); + goto err; + } + + dssdev->state = OMAP_DSS_DISPLAY_ACTIVE; + +err: + mutex_unlock(&hdmi.hdmi_lock); + + return r; +} + +static void hdmi_panel_disable(struct omap_dss_device *dssdev) +{ + mutex_lock(&hdmi.hdmi_lock); + + if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) + omapdss_hdmi_display_disable(dssdev); + + dssdev->state = OMAP_DSS_DISPLAY_DISABLED; + + mutex_unlock(&hdmi.hdmi_lock); +} + +static int hdmi_panel_suspend(struct omap_dss_device *dssdev) +{ + int r = 0; + + mutex_lock(&hdmi.hdmi_lock); + + if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) { + r = -EINVAL; + goto err; + } + + dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED; + + omapdss_hdmi_display_disable(dssdev); + +err: + mutex_unlock(&hdmi.hdmi_lock); + + return r; +} + +static int hdmi_panel_resume(struct omap_dss_device *dssdev) +{ + int r = 0; + + mutex_lock(&hdmi.hdmi_lock); + + if (dssdev->state != OMAP_DSS_DISPLAY_SUSPENDED) { + r = -EINVAL; + goto err; + } + + r = omapdss_hdmi_display_enable(dssdev); + if (r) { + DSSERR("failed to power on\n"); + goto err; + } + + dssdev->state = OMAP_DSS_DISPLAY_ACTIVE; + +err: + mutex_unlock(&hdmi.hdmi_lock); + + return r; +} + +static void hdmi_get_timings(struct omap_dss_device *dssdev, + struct omap_video_timings *timings) +{ + mutex_lock(&hdmi.hdmi_lock); + + *timings = dssdev->panel.timings; + + mutex_unlock(&hdmi.hdmi_lock); +} + +static void hdmi_set_timings(struct omap_dss_device *dssdev, + struct omap_video_timings *timings) +{ + DSSDBG("hdmi_set_timings\n"); + + mutex_lock(&hdmi.hdmi_lock); + + dssdev->panel.timings = *timings; + + if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) { + /* turn the hdmi off and on to get new timings to use */ + omapdss_hdmi_display_disable(dssdev); + omapdss_hdmi_display_set_timing(dssdev); + } + + mutex_unlock(&hdmi.hdmi_lock); +} + +static int hdmi_check_timings(struct omap_dss_device *dssdev, + struct omap_video_timings *timings) +{ + int r = 0; + + DSSDBG("hdmi_check_timings\n"); + + mutex_lock(&hdmi.hdmi_lock); + + r = omapdss_hdmi_display_check_timing(dssdev, timings); + if (r) { + DSSERR("Timing cannot be applied\n"); + goto err; + } +err: + mutex_unlock(&hdmi.hdmi_lock); + return r; +} + +static struct omap_dss_driver hdmi_driver = { + .probe = hdmi_panel_probe, + .remove = hdmi_panel_remove, + .enable = hdmi_panel_enable, + .disable = hdmi_panel_disable, + .suspend = hdmi_panel_suspend, + .resume = hdmi_panel_resume, + .get_timings = hdmi_get_timings, + .set_timings = hdmi_set_timings, + .check_timings = hdmi_check_timings, + .driver = { + .name = "hdmi_panel", + .owner = THIS_MODULE, + }, +}; + +int hdmi_panel_init(void) +{ + mutex_init(&hdmi.hdmi_lock); + + omap_dss_register_driver(&hdmi_driver); + + return 0; +} + +void hdmi_panel_exit(void) +{ + omap_dss_unregister_driver(&hdmi_driver); + +} -- GitLab From 642e21bff200610b1d4c0e706d0a6b16ae4e25db Mon Sep 17 00:00:00 2001 From: Mythri P K Date: Thu, 10 Mar 2011 15:12:48 +0530 Subject: [PATCH 0730/2822] OMAP4: DSS2: HDMI: Add makefile and kconfig changes to enable HDMI in OMAP4 Adding kconfig and makefile changes to add support for HDMI in OMAP4. Signed-off-by: Mythri P K Signed-off-by: Tomi Valkeinen --- drivers/video/omap2/dss/Kconfig | 8 ++++++++ drivers/video/omap2/dss/Makefile | 2 ++ 2 files changed, 10 insertions(+) diff --git a/drivers/video/omap2/dss/Kconfig b/drivers/video/omap2/dss/Kconfig index db01473c3307f..bfc5da0e9700b 100644 --- a/drivers/video/omap2/dss/Kconfig +++ b/drivers/video/omap2/dss/Kconfig @@ -60,6 +60,14 @@ config OMAP2_DSS_VENC help OMAP Video Encoder support for S-Video and composite TV-out. +config OMAP4_DSS_HDMI + bool "HDMI support" + depends on ARCH_OMAP4 + default y + help + HDMI Interface. This adds the High Definition Multimedia Interface. + See http://www.hdmi.org/ for HDMI specification. + config OMAP2_DSS_SDI bool "SDI support" depends on ARCH_OMAP3 diff --git a/drivers/video/omap2/dss/Makefile b/drivers/video/omap2/dss/Makefile index 7db17b5e570c4..10d9d3bb3e24c 100644 --- a/drivers/video/omap2/dss/Makefile +++ b/drivers/video/omap2/dss/Makefile @@ -5,3 +5,5 @@ omapdss-$(CONFIG_OMAP2_DSS_RFBI) += rfbi.o omapdss-$(CONFIG_OMAP2_DSS_VENC) += venc.o omapdss-$(CONFIG_OMAP2_DSS_SDI) += sdi.o omapdss-$(CONFIG_OMAP2_DSS_DSI) += dsi.o +omapdss-$(CONFIG_OMAP4_DSS_HDMI) += hdmi.o \ + hdmi_omap4_panel.o -- GitLab From adbc2feee11aef2b3b0f4eff427d2ea5c211e798 Mon Sep 17 00:00:00 2001 From: Mythri P K Date: Wed, 9 Mar 2011 15:40:02 +0530 Subject: [PATCH 0731/2822] OMAP4: DSS: HDMI: Call to HDMI module init to register driver. calling the platform registration of HDMI driver from core during initialization. Signed-off-by: Mythri P K Signed-off-by: Tomi Valkeinen --- drivers/video/omap2/dss/core.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/video/omap2/dss/core.c b/drivers/video/omap2/dss/core.c index c2f930bf2844a..1aa2ed1e786e1 100644 --- a/drivers/video/omap2/dss/core.c +++ b/drivers/video/omap2/dss/core.c @@ -209,6 +209,12 @@ static int omap_dss_probe(struct platform_device *pdev) goto err_dsi; } + r = hdmi_init_platform_driver(); + if (r) { + DSSERR("Failed to initialize hdmi\n"); + goto err_hdmi; + } + r = dss_initialize_debugfs(); if (r) goto err_debugfs; @@ -238,6 +244,8 @@ static int omap_dss_probe(struct platform_device *pdev) err_register: dss_uninitialize_debugfs(); err_debugfs: + hdmi_uninit_platform_driver(); +err_hdmi: dsi_uninit_platform_driver(); err_dsi: venc_uninit_platform_driver(); @@ -263,6 +271,7 @@ static int omap_dss_remove(struct platform_device *pdev) dispc_uninit_platform_driver(); rfbi_uninit_platform_driver(); dsi_uninit_platform_driver(); + hdmi_uninit_platform_driver(); dss_uninit_platform_driver(); dss_uninit_overlays(pdev); -- GitLab From 0425b48b3f24b0b2b1f9b4f24fd491b70a8f911c Mon Sep 17 00:00:00 2001 From: Mythri P K Date: Tue, 8 Mar 2011 18:50:09 +0530 Subject: [PATCH 0732/2822] OMAP4: HDMI: Add HDMI structure in the board file for OMAP4 SDP Adding board file structure for display which adds the display structure with HDMI as the default driver when the display init is called. HDMI GPIO configurations are also done in this file. Signed-off-by: Mythri P K Signed-off-by: Tomi Valkeinen --- arch/arm/mach-omap2/board-4430sdp.c | 75 +++++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) diff --git a/arch/arm/mach-omap2/board-4430sdp.c b/arch/arm/mach-omap2/board-4430sdp.c index 85805d432e38b..f5fcc5f2258da 100644 --- a/arch/arm/mach-omap2/board-4430sdp.c +++ b/arch/arm/mach-omap2/board-4430sdp.c @@ -36,6 +36,7 @@ #include #include #include +#include #include "mux.h" #include "hsmmc.h" @@ -47,6 +48,8 @@ #define ETH_KS8851_QUART 138 #define OMAP4_SFH7741_SENSOR_OUTPUT_GPIO 184 #define OMAP4_SFH7741_ENABLE_GPIO 188 +#define HDMI_GPIO_HPD 60 /* Hot plug pin for HDMI */ +#define HDMI_GPIO_LS_OE 41 /* Level shifter for HDMI */ static const int sdp4430_keymap[] = { KEY(0, 0, KEY_E), @@ -620,6 +623,76 @@ static void __init omap_sfh7741prox_init(void) } } +static void sdp4430_hdmi_mux_init(void) +{ + /* PAD0_HDMI_HPD_PAD1_HDMI_CEC */ + omap_mux_init_signal("hdmi_hpd", + OMAP_PIN_INPUT_PULLUP); + omap_mux_init_signal("hdmi_cec", + OMAP_PIN_INPUT_PULLUP); + /* PAD0_HDMI_DDC_SCL_PAD1_HDMI_DDC_SDA */ + omap_mux_init_signal("hdmi_ddc_scl", + OMAP_PIN_INPUT_PULLUP); + omap_mux_init_signal("hdmi_ddc_sda", + OMAP_PIN_INPUT_PULLUP); +} + +static int sdp4430_panel_enable_hdmi(struct omap_dss_device *dssdev) +{ + int status; + + status = gpio_request_one(HDMI_GPIO_HPD, GPIOF_OUT_INIT_HIGH, + "hdmi_gpio_hpd"); + if (status) { + pr_err("Cannot request GPIO %d\n", HDMI_GPIO_HPD); + return status; + } + status = gpio_request_one(HDMI_GPIO_LS_OE, GPIOF_OUT_INIT_HIGH, + "hdmi_gpio_ls_oe"); + if (status) { + pr_err("Cannot request GPIO %d\n", HDMI_GPIO_LS_OE); + goto error1; + } + + return 0; + +error1: + gpio_free(HDMI_GPIO_HPD); + + return status; +} + +static void sdp4430_panel_disable_hdmi(struct omap_dss_device *dssdev) +{ + gpio_free(HDMI_GPIO_LS_OE); + gpio_free(HDMI_GPIO_HPD); +} + +static struct omap_dss_device sdp4430_hdmi_device = { + .name = "hdmi", + .driver_name = "hdmi_panel", + .type = OMAP_DISPLAY_TYPE_HDMI, + .platform_enable = sdp4430_panel_enable_hdmi, + .platform_disable = sdp4430_panel_disable_hdmi, + .channel = OMAP_DSS_CHANNEL_DIGIT, +}; + +static struct omap_dss_device *sdp4430_dss_devices[] = { + &sdp4430_hdmi_device, +}; + +static struct omap_dss_board_info sdp4430_dss_data = { + .num_devices = ARRAY_SIZE(sdp4430_dss_devices), + .devices = sdp4430_dss_devices, + .default_device = &sdp4430_hdmi_device, +}; + +void omap_4430sdp_display_init(void) +{ + sdp4430_hdmi_mux_init(); + omap_display_init(&sdp4430_dss_data); +} + #ifdef CONFIG_OMAP_MUX static struct omap_board_mux board_mux[] __initdata = { OMAP4_MUX(USBB2_ULPITLL_CLK, OMAP_MUX_MODE4 | OMAP_PIN_OUTPUT), @@ -661,6 +734,8 @@ static void __init omap_4430sdp_init(void) status = omap4_keyboard_init(&sdp4430_keypad_data); if (status) pr_err("Keypad initialization failed: %d\n", status); + + omap_4430sdp_display_init(); } static void __init omap_4430sdp_map_io(void) -- GitLab From 17c84ef1e1265fad787d4082bd40a63eb6f3eeb1 Mon Sep 17 00:00:00 2001 From: "K, Mythri P" Date: Mon, 14 Mar 2011 23:57:42 -0500 Subject: [PATCH 0733/2822] OMAP4: HDMI: Add HDMI structure in the board file for OMAP4 PANDA Adding board file structure for display which adds the display structure with HDMI as the default driver when the display init is called. HDMI GPIO configurations are also done in this file. Signed-off-by: Mythri P K Signed-off-by: Tomi Valkeinen --- arch/arm/mach-omap2/board-omap4panda.c | 74 ++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) diff --git a/arch/arm/mach-omap2/board-omap4panda.c b/arch/arm/mach-omap2/board-omap4panda.c index a94ce07be72ff..795ffc4615221 100644 --- a/arch/arm/mach-omap2/board-omap4panda.c +++ b/arch/arm/mach-omap2/board-omap4panda.c @@ -34,6 +34,7 @@ #include #include #include +#include #include #include @@ -49,6 +50,8 @@ #define GPIO_HUB_NRESET 62 #define GPIO_WIFI_PMENA 43 #define GPIO_WIFI_IRQ 53 +#define HDMI_GPIO_HPD 60 /* Hot plug pin for HDMI */ +#define HDMI_GPIO_LS_OE 41 /* Level shifter for HDMI */ /* wl127x BT, FM, GPS connectivity chip */ static int wl1271_gpios[] = {46, -1, -1}; @@ -467,6 +470,76 @@ static struct omap_board_mux board_mux[] __initdata = { #define board_mux NULL #endif +static void omap4_panda_hdmi_mux_init(void) +{ + /* PAD0_HDMI_HPD_PAD1_HDMI_CEC */ + omap_mux_init_signal("hdmi_hpd", + OMAP_PIN_INPUT_PULLUP); + omap_mux_init_signal("hdmi_cec", + OMAP_PIN_INPUT_PULLUP); + /* PAD0_HDMI_DDC_SCL_PAD1_HDMI_DDC_SDA */ + omap_mux_init_signal("hdmi_ddc_scl", + OMAP_PIN_INPUT_PULLUP); + omap_mux_init_signal("hdmi_ddc_sda", + OMAP_PIN_INPUT_PULLUP); +} + +static int omap4_panda_panel_enable_hdmi(struct omap_dss_device *dssdev) +{ + int status; + + status = gpio_request_one(HDMI_GPIO_HPD, GPIOF_OUT_INIT_HIGH, + "hdmi_gpio_hpd"); + if (status) { + pr_err("Cannot request GPIO %d\n", HDMI_GPIO_HPD); + return status; + } + status = gpio_request_one(HDMI_GPIO_LS_OE, GPIOF_OUT_INIT_HIGH, + "hdmi_gpio_ls_oe"); + if (status) { + pr_err("Cannot request GPIO %d\n", HDMI_GPIO_LS_OE); + goto error1; + } + + return 0; + +error1: + gpio_free(HDMI_GPIO_HPD); + + return status; +} + +static void omap4_panda_panel_disable_hdmi(struct omap_dss_device *dssdev) +{ + gpio_free(HDMI_GPIO_LS_OE); + gpio_free(HDMI_GPIO_HPD); +} + +static struct omap_dss_device omap4_panda_hdmi_device = { + .name = "hdmi", + .driver_name = "hdmi_panel", + .type = OMAP_DISPLAY_TYPE_HDMI, + .platform_enable = omap4_panda_panel_enable_hdmi, + .platform_disable = omap4_panda_panel_disable_hdmi, + .channel = OMAP_DSS_CHANNEL_DIGIT, +}; + +static struct omap_dss_device *omap4_panda_dss_devices[] = { + &omap4_panda_hdmi_device, +}; + +static struct omap_dss_board_info omap4_panda_dss_data = { + .num_devices = ARRAY_SIZE(omap4_panda_dss_devices), + .devices = omap4_panda_dss_devices, + .default_device = &omap4_panda_hdmi_device, +}; + +void omap4_panda_display_init(void) +{ + omap4_panda_hdmi_mux_init(); + omap_display_init(&omap4_panda_dss_data); +} + static void __init omap4_panda_init(void) { int package = OMAP_PACKAGE_CBS; @@ -485,6 +558,7 @@ static void __init omap4_panda_init(void) omap4_twl6030_hsmmc_init(mmc); omap4_ehci_init(); usb_musb_init(&musb_board_data); + omap4_panda_display_init(); } static void __init omap4_panda_map_io(void) -- GitLab From 64dcddd888998f7db9929e19fc063e75e3ea21f5 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Tue, 15 Mar 2011 22:32:39 -0700 Subject: [PATCH 0734/2822] Input: tca6416-keypad - suspend/resume wakeup support Extend the tca6416 driver to use enable_irq_wake() and disable_irq_wake() in the suspend/resume hooks. This makes it possible to wake up from suspend-to-ram using a tca6416 key on the sh7372 mackerel board. Signed-off-by: Magnus Damm Signed-off-by: Dmitry Torokhov --- drivers/input/keyboard/tca6416-keypad.c | 28 +++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/drivers/input/keyboard/tca6416-keypad.c b/drivers/input/keyboard/tca6416-keypad.c index 800fbccf1f0fb..3afea3f897182 100644 --- a/drivers/input/keyboard/tca6416-keypad.c +++ b/drivers/input/keyboard/tca6416-keypad.c @@ -297,6 +297,7 @@ static int __devinit tca6416_keypad_probe(struct i2c_client *client, } i2c_set_clientdata(client, chip); + device_init_wakeup(&client->dev, 1); return 0; @@ -326,10 +327,37 @@ static int __devexit tca6416_keypad_remove(struct i2c_client *client) return 0; } +#ifdef CONFIG_PM_SLEEP +static int tca6416_keypad_suspend(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct tca6416_keypad_chip *chip = i2c_get_clientdata(client); + + if (device_may_wakeup(dev)) + enable_irq_wake(chip->irqnum); + + return 0; +} + +static int tca6416_keypad_resume(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct tca6416_keypad_chip *chip = i2c_get_clientdata(client); + + if (device_may_wakeup(dev)) + disable_irq_wake(chip->irqnum); + + return 0; +} +#endif + +static SIMPLE_DEV_PM_OPS(tca6416_keypad_dev_pm_ops, + tca6416_keypad_suspend, tca6416_keypad_resume); static struct i2c_driver tca6416_keypad_driver = { .driver = { .name = "tca6416-keypad", + .pm = &tca6416_keypad_dev_pm_ops, }, .probe = tca6416_keypad_probe, .remove = __devexit_p(tca6416_keypad_remove), -- GitLab From 53a2b81c4e659d894aadc56715c8d8a9afa60d67 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Tue, 15 Mar 2011 23:18:00 -0700 Subject: [PATCH 0735/2822] Input: tc3589x-keypad - fix 'double const' warning Also rearrange driver structure initializer a bit. Signed-off-by: Dmitry Torokhov --- drivers/input/keyboard/tc3589x-keypad.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/drivers/input/keyboard/tc3589x-keypad.c b/drivers/input/keyboard/tc3589x-keypad.c index dbbe761778d28..99122f59e9882 100644 --- a/drivers/input/keyboard/tc3589x-keypad.c +++ b/drivers/input/keyboard/tc3589x-keypad.c @@ -402,7 +402,7 @@ static int __devexit tc3589x_keypad_remove(struct platform_device *pdev) return 0; } -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP static int tc3589x_keypad_suspend(struct device *dev) { struct platform_device *pdev = to_platform_device(dev); @@ -439,19 +439,19 @@ static int tc3589x_keypad_resume(struct device *dev) return 0; } - -static const SIMPLE_DEV_PM_OPS(tc3589x_keypad_dev_pm_ops, - tc3589x_keypad_suspend, tc3589x_keypad_resume); #endif +static SIMPLE_DEV_PM_OPS(tc3589x_keypad_dev_pm_ops, + tc3589x_keypad_suspend, tc3589x_keypad_resume); + static struct platform_driver tc3589x_keypad_driver = { - .driver.name = "tc3589x-keypad", - .driver.owner = THIS_MODULE, -#ifdef CONFIG_PM - .driver.pm = &tc3589x_keypad_dev_pm_ops, -#endif - .probe = tc3589x_keypad_probe, - .remove = __devexit_p(tc3589x_keypad_remove), + .driver = { + .name = "tc3589x-keypad", + .owner = THIS_MODULE, + .pm = &tc3589x_keypad_dev_pm_ops, + }, + .probe = tc3589x_keypad_probe, + .remove = __devexit_p(tc3589x_keypad_remove), }; static int __init tc3589x_keypad_init(void) -- GitLab From f8d878ddbb3c08bc2f876975df674484208536ac Mon Sep 17 00:00:00 2001 From: Heiko Stuebner Date: Mon, 14 Mar 2011 21:12:39 +0100 Subject: [PATCH 0736/2822] s3c_adc_battery: Fix method names when PM not set s3c_adc_battery declares wrong method names when CONFIG_PM is not set. Signed-off-by: Heiko Stuebner Acked-by: Vasily Khoruzhick Signed-off-by: Anton Vorontsov --- drivers/power/s3c_adc_battery.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/power/s3c_adc_battery.c b/drivers/power/s3c_adc_battery.c index 4255f2358b138..d36c289aaef52 100644 --- a/drivers/power/s3c_adc_battery.c +++ b/drivers/power/s3c_adc_battery.c @@ -406,8 +406,8 @@ static int s3c_adc_bat_resume(struct platform_device *pdev) return 0; } #else -#define s3c_adc_battery_suspend NULL -#define s3c_adc_battery_resume NULL +#define s3c_adc_bat_suspend NULL +#define s3c_adc_bat_resume NULL #endif static struct platform_driver s3c_adc_bat_driver = { -- GitLab From a223246f7280422f77c15b71455fe3362d3604b4 Mon Sep 17 00:00:00 2001 From: Vasily Khoruzhick Date: Fri, 11 Mar 2011 15:09:32 +0200 Subject: [PATCH 0737/2822] z2_battery: Fix count of properties PROP_STATUS property was not counted, as result VOLTAGE_MIN property is missing in sysfs. Fix it. Signed-off-by: Vasily Khoruzhick Acked-by: Marek Vasut Signed-off-by: Anton Vorontsov --- drivers/power/z2_battery.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/power/z2_battery.c b/drivers/power/z2_battery.c index 81304c0bb9d3b..2a9ab89f83b8a 100644 --- a/drivers/power/z2_battery.c +++ b/drivers/power/z2_battery.c @@ -134,6 +134,8 @@ static int z2_batt_ps_init(struct z2_charger *charger, int props) enum power_supply_property *prop; struct z2_battery_info *info = charger->info; + if (info->charge_gpio >= 0) + props++; /* POWER_SUPPLY_PROP_STATUS */ if (info->batt_tech >= 0) props++; /* POWER_SUPPLY_PROP_TECHNOLOGY */ if (info->batt_I2C_reg >= 0) -- GitLab From a7d9ace4eb3a6a3c3fcb12fb05510c1893808263 Mon Sep 17 00:00:00 2001 From: Rhyland Klein Date: Wed, 9 Mar 2011 16:18:02 -0800 Subject: [PATCH 0738/2822] bq20z75: Fix issues with present and suspend There are a few issues found around the battery not being present. If the battery isn't present, then a few undesirable things happen. The first was excessive reporting of failed properties. This was fixed by instead returning ENODATA for all properties other than PRESENT if the battery isn't present. That way the callers can identify the difference between a failure and the battery not being there. The next issue was in the suspend logic. It was found that if the battery wasn't present, then it would return a failure, preventing the system from going into suspend. If there is no battery present, the io is expected to fail, so in that case, we shouldn't return the failure and just acknowledge that it was expected. I also found that when a gpio was used, i didn't maintain the internal is_present state properly. I added a set of that to fix that. Lastly, the code to see io's fail and figure out that the battery isn't present when not using a gpio had a problem. In that code, it looked for the read to fail and if it did, then handled it. The problem is that in function to get the property, it first writes a value and that write can fail, causing the code to never reach the logic after the read. Fix is to move the logic till after the write. Signed-off-by: Rhyland Klein Signed-off-by: Anton Vorontsov --- drivers/power/bq20z75.c | 32 +++++++++++++++++++++----------- 1 file changed, 21 insertions(+), 11 deletions(-) diff --git a/drivers/power/bq20z75.c b/drivers/power/bq20z75.c index 8018e8cc7a743..5615c92bef667 100644 --- a/drivers/power/bq20z75.c +++ b/drivers/power/bq20z75.c @@ -171,7 +171,7 @@ static int bq20z75_read_word_data(struct i2c_client *client, u8 address) } if (ret < 0) { - dev_warn(&client->dev, + dev_dbg(&client->dev, "%s: i2c read at address 0x%x failed\n", __func__, address); return ret; @@ -199,7 +199,7 @@ static int bq20z75_write_word_data(struct i2c_client *client, u8 address, } if (ret < 0) { - dev_warn(&client->dev, + dev_dbg(&client->dev, "%s: i2c write to address 0x%x failed\n", __func__, address); return ret; @@ -223,6 +223,7 @@ static int bq20z75_get_battery_presence_and_health( val->intval = 1; else val->intval = 0; + bq20z75_device->is_present = val->intval; return ret; } @@ -232,18 +233,17 @@ static int bq20z75_get_battery_presence_and_health( ret = bq20z75_write_word_data(client, bq20z75_data[REG_MANUFACTURER_DATA].addr, MANUFACTURER_ACCESS_STATUS); - if (ret < 0) - return ret; - - - ret = bq20z75_read_word_data(client, - bq20z75_data[REG_MANUFACTURER_DATA].addr); if (ret < 0) { if (psp == POWER_SUPPLY_PROP_PRESENT) val->intval = 0; /* battery removed */ return ret; } + ret = bq20z75_read_word_data(client, + bq20z75_data[REG_MANUFACTURER_DATA].addr); + if (ret < 0) + return ret; + if (ret < bq20z75_data[REG_MANUFACTURER_DATA].min_value || ret > bq20z75_data[REG_MANUFACTURER_DATA].max_value) { val->intval = 0; @@ -455,6 +455,8 @@ static int bq20z75_get_property(struct power_supply *psy, case POWER_SUPPLY_PROP_PRESENT: case POWER_SUPPLY_PROP_HEALTH: ret = bq20z75_get_battery_presence_and_health(client, psp, val); + if (psp == POWER_SUPPLY_PROP_PRESENT) + return 0; break; case POWER_SUPPLY_PROP_TECHNOLOGY: @@ -516,9 +518,16 @@ done: } dev_dbg(&client->dev, - "%s: property = %d, value = %d\n", __func__, psp, val->intval); + "%s: property = %d, value = %x\n", __func__, psp, val->intval); + + if (ret && bq20z75_device->is_present) + return ret; + + /* battery not present, so return NODATA for properties */ + if (ret) + return -ENODATA; - return ret; + return 0; } static irqreturn_t bq20z75_irq(int irq, void *devid) @@ -643,13 +652,14 @@ static int __devexit bq20z75_remove(struct i2c_client *client) static int bq20z75_suspend(struct i2c_client *client, pm_message_t state) { + struct bq20z75_info *bq20z75_device = i2c_get_clientdata(client); s32 ret; /* write to manufacturer access with sleep command */ ret = bq20z75_write_word_data(client, bq20z75_data[REG_MANUFACTURER_DATA].addr, MANUFACTURER_ACCESS_SLEEP); - if (ret < 0) + if (bq20z75_device->is_present && ret < 0) return ret; return 0; -- GitLab From 909a78b320b31ca9709d7ea5f602ec1bd2015192 Mon Sep 17 00:00:00 2001 From: Benson Leung Date: Sun, 27 Feb 2011 17:41:48 -0800 Subject: [PATCH 0739/2822] bq20z75: Fix time and temp units MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Corrected temperature and time to empty/full conversions. Temperature is in 0.1°C, time is in seconds. Corrected units in comment. "Convert to µWh." Signed-off-by: Benson Leung Acked-by: Rhyland Klein Signed-off-by: Anton Vorontsov --- drivers/power/bq20z75.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/drivers/power/bq20z75.c b/drivers/power/bq20z75.c index 5615c92bef667..506585e31a5be 100644 --- a/drivers/power/bq20z75.c +++ b/drivers/power/bq20z75.c @@ -318,12 +318,15 @@ static void bq20z75_unit_adjustment(struct i2c_client *client, { #define BASE_UNIT_CONVERSION 1000 #define BATTERY_MODE_CAP_MULT_WATT (10 * BASE_UNIT_CONVERSION) -#define TIME_UNIT_CONVERSION 600 -#define TEMP_KELVIN_TO_CELCIUS 2731 +#define TIME_UNIT_CONVERSION 60 +#define TEMP_KELVIN_TO_CELSIUS 2731 switch (psp) { case POWER_SUPPLY_PROP_ENERGY_NOW: case POWER_SUPPLY_PROP_ENERGY_FULL: case POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN: + /* bq20z75 provides energy in units of 10mWh. + * Convert to µWh + */ val->intval *= BATTERY_MODE_CAP_MULT_WATT; break; @@ -337,14 +340,17 @@ static void bq20z75_unit_adjustment(struct i2c_client *client, break; case POWER_SUPPLY_PROP_TEMP: - /* bq20z75 provides battery tempreture in 0.1°K - * so convert it to 0.1°C */ - val->intval -= TEMP_KELVIN_TO_CELCIUS; - val->intval *= 10; + /* bq20z75 provides battery temperature in 0.1K + * so convert it to 0.1°C + */ + val->intval -= TEMP_KELVIN_TO_CELSIUS; break; case POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG: case POWER_SUPPLY_PROP_TIME_TO_FULL_AVG: + /* bq20z75 provides time to empty and time to full in minutes. + * Convert to seconds + */ val->intval *= TIME_UNIT_CONVERSION; break; -- GitLab From d2b217439fd1d8f7857175f063113f4d1d66306c Mon Sep 17 00:00:00 2001 From: Mi Jinlong Date: Thu, 10 Mar 2011 17:43:37 +0800 Subject: [PATCH 0740/2822] nfs41: make sure nfs server return right ca_maxresponsesize_cached According to rfc5661, ca_maxresponsesize_cached: Like ca_maxresponsesize, but the maximum size of a reply that will be stored in the reply cache (Section 2.10.6.1). For each channel, the server MAY decrease this value, but MUST NOT increase it. the latest kernel(2.6.38-rc8) may increase the value for ignoring request's ca_maxresponsesize_cached value. We should not ignore it. Signed-off-by: Mi Jinlong Signed-off-by: J. Bruce Fields --- fs/nfsd/nfs4state.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index c26dc31fb943c..a20827804c50d 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c @@ -608,7 +608,8 @@ static void init_forechannel_attrs(struct nfsd4_channel_attrs *new, struct nfsd4 u32 maxrpc = nfsd_serv->sv_max_mesg; new->maxreqs = numslots; - new->maxresp_cached = slotsize + NFSD_MIN_HDR_SEQ_SZ; + new->maxresp_cached = min_t(u32, req->maxresp_cached, + slotsize + NFSD_MIN_HDR_SEQ_SZ); new->maxreq_sz = min_t(u32, req->maxreq_sz, maxrpc); new->maxresp_sz = min_t(u32, req->maxresp_sz, maxrpc); new->maxops = min_t(u32, req->maxops, NFSD_MAX_OPS_PER_COMPOUND); -- GitLab From 2f94e55ae5ddad83e661002985d2ea11b6d51d3d Mon Sep 17 00:00:00 2001 From: Philip Rakity Date: Sun, 13 Feb 2011 23:12:28 -0800 Subject: [PATCH 0741/2822] mmc: core: comment on why sdio_reset is done at init time sdio_reset sends a CMD52 to reset the sdio card. This is highly recommended for sdio cards being reinitialized. Since we do not know if the card is being reinitialized we just send the command. SD/eMMC cards are supposed to ignore the CMD before the CMD0. Document why we are doing this. Signed-off-by: Philip Rakity Signed-off-by: Chris Ball --- drivers/mmc/core/core.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index 2af2ee1a2265a..c47e13b79eeec 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c @@ -1494,6 +1494,12 @@ static int mmc_rescan_try_freq(struct mmc_host *host, unsigned freq) mmc_hostname(host), __func__, host->f_init); #endif mmc_power_up(host); + + /* + * sdio_reset sends CMD52 to reset card. Since we do not know + * if the card is being re-initialized, just send it. CMD52 + * should be ignored by SD/eMMC cards. + */ sdio_reset(host); mmc_go_idle(host); -- GitLab From b676f0391a5f6816c047cbd1e2ad2a897f3c161a Mon Sep 17 00:00:00 2001 From: Philip Rakity Date: Sun, 13 Feb 2011 23:13:09 -0800 Subject: [PATCH 0742/2822] mmc: check if mmc cards < 2GB do sector addressing Some TOSHIBA MMC cards only support sector addressing even though the size is < 2GB. According to JEDEC Spec JESD84-A441-1 the ocr register (bits 30, 29) determine byte/sector mode. Use them. Signed-off-by: Philip Rakity Signed-off-by: Chris Ball --- drivers/mmc/core/mmc.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c index 6396c5d98e853..14e95f39a7bf3 100644 --- a/drivers/mmc/core/mmc.c +++ b/drivers/mmc/core/mmc.c @@ -421,6 +421,7 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr, int err, ddr = 0; u32 cid[4]; unsigned int max_dtr; + u32 rocr; BUG_ON(!host); WARN_ON(!host->claimed); @@ -434,7 +435,7 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr, mmc_go_idle(host); /* The extra bit indicates that we support high capacity */ - err = mmc_send_op_cond(host, ocr | (1 << 30), NULL); + err = mmc_send_op_cond(host, ocr | (1 << 30), &rocr); if (err) goto err; @@ -522,6 +523,15 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr, err = mmc_read_ext_csd(card); if (err) goto free_card; + + /* If doing byte addressing, check if required to do sector + * addressing. Handle the case of <2GB cards needing sector + * addressing. See section 8.1 JEDEC Standard JED84-A441; + * ocr register has bit 30 set for sector addressing. + */ + if (!(mmc_card_blockaddr(card)) && (rocr & (1<<30))) + mmc_card_set_blockaddr(card); + /* Erase size depends on CSD and Extended CSD */ mmc_set_erase_size(card); } -- GitLab From f5e0cec4495398b259b3ede7cbc3ce4bd0e1cef0 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Fri, 25 Feb 2011 16:58:38 +0100 Subject: [PATCH 0743/2822] mmc: sh_mmcif: support aggressive clock gating To support MMC aggressive clock gating the driver has to stop the interface clock when the .set_ios() method is called with .clock == 0. Signed-off-by: Guennadi Liakhovetski Signed-off-by: Chris Ball --- drivers/mmc/host/sh_mmcif.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/mmc/host/sh_mmcif.c b/drivers/mmc/host/sh_mmcif.c index aea86262ed66c..af97015a2fc7f 100644 --- a/drivers/mmc/host/sh_mmcif.c +++ b/drivers/mmc/host/sh_mmcif.c @@ -844,15 +844,15 @@ static void sh_mmcif_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) struct sh_mmcif_host *host = mmc_priv(mmc); struct sh_mmcif_plat_data *p = host->pd->dev.platform_data; - if (ios->power_mode == MMC_POWER_OFF) { + if (ios->power_mode == MMC_POWER_UP) { + if (p->set_pwr) + p->set_pwr(host->pd, ios->power_mode); + } else if (ios->power_mode == MMC_POWER_OFF || !ios->clock) { /* clock stop */ sh_mmcif_clock_control(host, 0); - if (p->down_pwr) + if (ios->power_mode == MMC_POWER_OFF && p->down_pwr) p->down_pwr(host->pd); return; - } else if (ios->power_mode == MMC_POWER_UP) { - if (p->set_pwr) - p->set_pwr(host->pd, ios->power_mode); } if (ios->clock) -- GitLab From 688f869ce3bdc892daa993534dc6df18c95df931 Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Wed, 16 Mar 2011 17:16:31 -0400 Subject: [PATCH 0744/2822] ext4: Initialize fsync transaction ids in ext4_new_inode() When allocating a new inode, we need to make sure i_sync_tid and i_datasync_tid are initialized. Otherwise, one or both of these two values could be left initialized to zero, which could potentially result in BUG_ON in jbd2_journal_commit_transaction. (This could happen by having journal->commit_request getting set to zero, which could wake up the kjournald process even though there is no running transaction, which then causes a BUG_ON via the J_ASSERT(j_ruinning_transaction != NULL) statement. Signed-off-by: "Theodore Ts'o" --- fs/ext4/ialloc.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c index 2fd3b0e41787a..a679a482c986e 100644 --- a/fs/ext4/ialloc.c +++ b/fs/ext4/ialloc.c @@ -1054,6 +1054,11 @@ got: } } + if (ext4_handle_valid(handle)) { + ei->i_sync_tid = handle->h_transaction->t_tid; + ei->i_datasync_tid = handle->h_transaction->t_tid; + } + err = ext4_mark_inode_dirty(handle, inode); if (err) { ext4_std_error(sb, err); -- GitLab From 8c3c283e6bf463ab498d6e7823aff6c4762314b6 Mon Sep 17 00:00:00 2001 From: Olaf Hering Date: Wed, 16 Mar 2011 22:11:46 -0700 Subject: [PATCH 0745/2822] Input: xen-kbdfront - advertise either absolute or relative coordinates A virtualized display device is usually viewed with the vncviewer application, either by 'xm vnc domU' or with vncviewer localhost:port. vncviewer and the RFB protocol provides absolute coordinates to the virtual display. These coordinates are either passed through to a PV guest or converted to relative coordinates for a HVM guest. A PV guest receives these coordinates and passes them to the kernels evdev driver. There it can be picked up by applications such as the xorg-input drivers. Using absolute coordinates avoids issues such as guest mouse pointer not tracking host mouse pointer due to wrong mouse acceleration settings in the guests X display. Advertise either absolute or relative coordinates to the input system and the evdev driver, depending on what dom0 provides. The xorg-input driver prefers relative coordinates even if a devices provides both. Signed-off-by: Olaf Hering Signed-off-by: Stefano Stabellini Signed-off-by: Dmitry Torokhov --- drivers/input/xen-kbdfront.c | 44 ++++++++++++++++++++---------------- 1 file changed, 24 insertions(+), 20 deletions(-) diff --git a/drivers/input/xen-kbdfront.c b/drivers/input/xen-kbdfront.c index 7f85a862ad116..53e62732ee96f 100644 --- a/drivers/input/xen-kbdfront.c +++ b/drivers/input/xen-kbdfront.c @@ -110,7 +110,7 @@ static irqreturn_t input_handler(int rq, void *dev_id) static int __devinit xenkbd_probe(struct xenbus_device *dev, const struct xenbus_device_id *id) { - int ret, i; + int ret, i, abs; struct xenkbd_info *info; struct input_dev *kbd, *ptr; @@ -128,6 +128,11 @@ static int __devinit xenkbd_probe(struct xenbus_device *dev, if (!info->page) goto error_nomem; + if (xenbus_scanf(XBT_NIL, dev->otherend, "feature-abs-pointer", "%d", &abs) < 0) + abs = 0; + if (abs) + xenbus_printf(XBT_NIL, dev->nodename, "request-abs-pointer", "1"); + /* keyboard */ kbd = input_allocate_device(); if (!kbd) @@ -137,11 +142,12 @@ static int __devinit xenkbd_probe(struct xenbus_device *dev, kbd->id.bustype = BUS_PCI; kbd->id.vendor = 0x5853; kbd->id.product = 0xffff; - kbd->evbit[0] = BIT(EV_KEY); + + __set_bit(EV_KEY, kbd->evbit); for (i = KEY_ESC; i < KEY_UNKNOWN; i++) - set_bit(i, kbd->keybit); + __set_bit(i, kbd->keybit); for (i = KEY_OK; i < KEY_MAX; i++) - set_bit(i, kbd->keybit); + __set_bit(i, kbd->keybit); ret = input_register_device(kbd); if (ret) { @@ -160,12 +166,20 @@ static int __devinit xenkbd_probe(struct xenbus_device *dev, ptr->id.bustype = BUS_PCI; ptr->id.vendor = 0x5853; ptr->id.product = 0xfffe; - ptr->evbit[0] = BIT(EV_KEY) | BIT(EV_REL) | BIT(EV_ABS); + + if (abs) { + __set_bit(EV_ABS, ptr->evbit); + input_set_abs_params(ptr, ABS_X, 0, XENFB_WIDTH, 0, 0); + input_set_abs_params(ptr, ABS_Y, 0, XENFB_HEIGHT, 0, 0); + } else { + input_set_capability(ptr, EV_REL, REL_X); + input_set_capability(ptr, EV_REL, REL_Y); + } + input_set_capability(ptr, EV_REL, REL_WHEEL); + + __set_bit(EV_KEY, ptr->evbit); for (i = BTN_LEFT; i <= BTN_TASK; i++) - set_bit(i, ptr->keybit); - ptr->relbit[0] = BIT(REL_X) | BIT(REL_Y) | BIT(REL_WHEEL); - input_set_abs_params(ptr, ABS_X, 0, XENFB_WIDTH, 0, 0); - input_set_abs_params(ptr, ABS_Y, 0, XENFB_HEIGHT, 0, 0); + __set_bit(i, ptr->keybit); ret = input_register_device(ptr); if (ret) { @@ -272,7 +286,7 @@ static void xenkbd_backend_changed(struct xenbus_device *dev, enum xenbus_state backend_state) { struct xenkbd_info *info = dev_get_drvdata(&dev->dev); - int ret, val; + int val; switch (backend_state) { case XenbusStateInitialising: @@ -285,16 +299,6 @@ static void xenkbd_backend_changed(struct xenbus_device *dev, case XenbusStateInitWait: InitWait: - ret = xenbus_scanf(XBT_NIL, info->xbdev->otherend, - "feature-abs-pointer", "%d", &val); - if (ret < 0) - val = 0; - if (val) { - ret = xenbus_printf(XBT_NIL, info->xbdev->nodename, - "request-abs-pointer", "1"); - if (ret) - pr_warning("can't request abs-pointer\n"); - } xenbus_switch_state(dev, XenbusStateConnected); break; -- GitLab From 0a4dfa5ddb5fc0aff331e255da282b01a74a6cd3 Mon Sep 17 00:00:00 2001 From: Daniel De Graaf Date: Wed, 16 Mar 2011 22:52:42 -0700 Subject: [PATCH 0746/2822] Input: xen-kbdfront - add grant reference for shared page Without a grant reference, full access to the domain's memory is required to use the shared page. Add an additional parameter in xenstore to allow grant mapping to be used. Signed-off-by: Daniel De Graaf Signed-off-by: Konrad Rzeszutek Wilk Acked-by: Ian Campbell Signed-off-by: Dmitry Torokhov --- drivers/input/xen-kbdfront.c | 39 ++++++++++++++++++++++++++---------- 1 file changed, 28 insertions(+), 11 deletions(-) diff --git a/drivers/input/xen-kbdfront.c b/drivers/input/xen-kbdfront.c index 53e62732ee96f..7077f9bf5ead8 100644 --- a/drivers/input/xen-kbdfront.c +++ b/drivers/input/xen-kbdfront.c @@ -11,12 +11,6 @@ * more details. */ -/* - * TODO: - * - * Switch to grant tables together with xen-fbfront.c. - */ - #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #include @@ -30,6 +24,8 @@ #include #include #include +#include +#include #include #include #include @@ -38,6 +34,7 @@ struct xenkbd_info { struct input_dev *kbd; struct input_dev *ptr; struct xenkbd_page *page; + int gref; int irq; struct xenbus_device *xbdev; char phys[32]; @@ -122,6 +119,7 @@ static int __devinit xenkbd_probe(struct xenbus_device *dev, dev_set_drvdata(&dev->dev, info); info->xbdev = dev; info->irq = -1; + info->gref = -1; snprintf(info->phys, sizeof(info->phys), "xenbus/%s", dev->nodename); info->page = (void *)__get_free_page(GFP_KERNEL | __GFP_ZERO); @@ -232,15 +230,20 @@ static int xenkbd_connect_backend(struct xenbus_device *dev, int ret, evtchn; struct xenbus_transaction xbt; + ret = gnttab_grant_foreign_access(dev->otherend_id, + virt_to_mfn(info->page), 0); + if (ret < 0) + return ret; + info->gref = ret; + ret = xenbus_alloc_evtchn(dev, &evtchn); if (ret) - return ret; + goto error_grant; ret = bind_evtchn_to_irqhandler(evtchn, input_handler, 0, dev->devicetype, info); if (ret < 0) { - xenbus_free_evtchn(dev, evtchn); xenbus_dev_fatal(dev, ret, "bind_evtchn_to_irqhandler"); - return ret; + goto error_evtchan; } info->irq = ret; @@ -248,10 +251,13 @@ static int xenkbd_connect_backend(struct xenbus_device *dev, ret = xenbus_transaction_start(&xbt); if (ret) { xenbus_dev_fatal(dev, ret, "starting transaction"); - return ret; + goto error_irqh; } ret = xenbus_printf(xbt, dev->nodename, "page-ref", "%lu", virt_to_mfn(info->page)); + if (ret) + goto error_xenbus; + ret = xenbus_printf(xbt, dev->nodename, "page-gref", "%u", info->gref); if (ret) goto error_xenbus; ret = xenbus_printf(xbt, dev->nodename, "event-channel", "%u", @@ -263,7 +269,7 @@ static int xenkbd_connect_backend(struct xenbus_device *dev, if (ret == -EAGAIN) goto again; xenbus_dev_fatal(dev, ret, "completing transaction"); - return ret; + goto error_irqh; } xenbus_switch_state(dev, XenbusStateInitialised); @@ -272,6 +278,14 @@ static int xenkbd_connect_backend(struct xenbus_device *dev, error_xenbus: xenbus_transaction_end(xbt, 1); xenbus_dev_fatal(dev, ret, "writing xenstore"); + error_irqh: + unbind_from_irqhandler(info->irq, info); + info->irq = -1; + error_evtchan: + xenbus_free_evtchn(dev, evtchn); + error_grant: + gnttab_end_foreign_access_ref(info->gref, 0); + info->gref = -1; return ret; } @@ -280,6 +294,9 @@ static void xenkbd_disconnect_backend(struct xenkbd_info *info) if (info->irq >= 0) unbind_from_irqhandler(info->irq, info); info->irq = -1; + if (info->gref >= 0) + gnttab_end_foreign_access_ref(info->gref, 0); + info->gref = -1; } static void xenkbd_backend_changed(struct xenbus_device *dev, -- GitLab From 49851ca04c7f941ef6f5ca04751b0e0fefe9d50d Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Wed, 16 Mar 2011 22:56:03 -0700 Subject: [PATCH 0747/2822] Input: xen-kbdfront - move to drivers/input/misc drivers/input is reserved for input core code and input handlers with drivers belonging to one of the sub-directories. Signed-off-by: Dmitry Torokhov --- drivers/input/Kconfig | 10 ---------- drivers/input/Makefile | 2 -- drivers/input/misc/Kconfig | 13 +++++++++++++ drivers/input/misc/Makefile | 1 + drivers/input/{ => misc}/xen-kbdfront.c | 0 5 files changed, 14 insertions(+), 12 deletions(-) rename drivers/input/{ => misc}/xen-kbdfront.c (100%) diff --git a/drivers/input/Kconfig b/drivers/input/Kconfig index 1903c0f5b9257..23e82e46656db 100644 --- a/drivers/input/Kconfig +++ b/drivers/input/Kconfig @@ -161,16 +161,6 @@ config INPUT_APMPOWER To compile this driver as a module, choose M here: the module will be called apm-power. -config XEN_KBDDEV_FRONTEND - tristate "Xen virtual keyboard and mouse support" - depends on XEN_FBDEV_FRONTEND - default y - select XEN_XENBUS_FRONTEND - help - This driver implements the front-end of the Xen virtual - keyboard and mouse device driver. It communicates with a back-end - in another domain. - comment "Input Device Drivers" source "drivers/input/keyboard/Kconfig" diff --git a/drivers/input/Makefile b/drivers/input/Makefile index 09614ce74961b..0c789490e0b35 100644 --- a/drivers/input/Makefile +++ b/drivers/input/Makefile @@ -24,5 +24,3 @@ obj-$(CONFIG_INPUT_TOUCHSCREEN) += touchscreen/ obj-$(CONFIG_INPUT_MISC) += misc/ obj-$(CONFIG_INPUT_APMPOWER) += apm-power.o - -obj-$(CONFIG_XEN_KBDDEV_FRONTEND) += xen-kbdfront.o diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig index b0c6772851a99..f9cf0881b0e3c 100644 --- a/drivers/input/misc/Kconfig +++ b/drivers/input/misc/Kconfig @@ -454,4 +454,17 @@ config INPUT_CMA3000_I2C To compile this driver as a module, choose M here: the module will be called cma3000_d0x_i2c. +config INPUT_XEN_KBDDEV_FRONTEND + tristate "Xen virtual keyboard and mouse support" + depends on XEN_FBDEV_FRONTEND + default y + select XEN_XENBUS_FRONTEND + help + This driver implements the front-end of the Xen virtual + keyboard and mouse device driver. It communicates with a back-end + in another domain. + + To compile this driver as a module, choose M here: the + module will be called xen-kbdfront. + endif diff --git a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile index 9b4797112c9ac..e3f7984e62742 100644 --- a/drivers/input/misc/Makefile +++ b/drivers/input/misc/Makefile @@ -42,5 +42,6 @@ obj-$(CONFIG_INPUT_TWL4030_VIBRA) += twl4030-vibra.o obj-$(CONFIG_INPUT_UINPUT) += uinput.o obj-$(CONFIG_INPUT_WISTRON_BTNS) += wistron_btns.o obj-$(CONFIG_INPUT_WM831X_ON) += wm831x-on.o +obj-$(CONFIG_INPUT_XEN_KBDDEV_FRONTEND) += xen-kbdfront.o obj-$(CONFIG_INPUT_YEALINK) += yealink.o diff --git a/drivers/input/xen-kbdfront.c b/drivers/input/misc/xen-kbdfront.c similarity index 100% rename from drivers/input/xen-kbdfront.c rename to drivers/input/misc/xen-kbdfront.c -- GitLab From 37bd44694c7215e3e46e6ee4a930d197325a7168 Mon Sep 17 00:00:00 2001 From: Lauri Leukkunen Date: Wed, 16 Mar 2011 22:07:36 -0700 Subject: [PATCH 0748/2822] Input: introduce tsc2005 driver Discussions: http://www.mail-archive.com/linux-omap@vger.kernel.org/msg26748.html Introduce a driver for the Texas Instruments TSC2005 touchscreen controller (http://focus.ti.com/docs/prod/folders/print/tsc2005.html). The patch is based on a driver by Lauri Leukkunen, with modifications by David Brownell, Phil Carmody, Imre Deak, Hiroshi DOYU, Ari Kauppi, Tony Lindgren, Jarkko Nikula, Eero Nurkkala and Roman Tereshonkov. Signed-off-by: Lauri Leukkunen [aaro.koskinen@nokia.com: patch description, rebasing & cleanup] Signed-off-by: Aaro Koskinen [ext-srikar.1.bhavanarayana@nokia.com: various fixes] Signed-off-by: Srikar Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/Kconfig | 11 + drivers/input/touchscreen/Makefile | 1 + drivers/input/touchscreen/tsc2005.c | 713 ++++++++++++++++++++++++++++ include/linux/spi/tsc2005.h | 41 ++ 4 files changed, 766 insertions(+) create mode 100644 drivers/input/touchscreen/tsc2005.c create mode 100644 include/linux/spi/tsc2005.h diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig index 06ea8da95c62b..30703ad363f3c 100644 --- a/drivers/input/touchscreen/Kconfig +++ b/drivers/input/touchscreen/Kconfig @@ -629,6 +629,17 @@ config TOUCHSCREEN_TOUCHIT213 To compile this driver as a module, choose M here: the module will be called touchit213. +config TOUCHSCREEN_TSC2005 + tristate "TSC2005 based touchscreens" + depends on SPI_MASTER + help + Say Y here if you have a TSC2005 based touchscreen. + + If unsure, say N. + + To compile this driver as a module, choose M here: the + module will be called tsc2005. + config TOUCHSCREEN_TSC2007 tristate "TSC2007 based touchscreens" depends on I2C diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile index 7cc1b4f4b677d..34b26ad65ceee 100644 --- a/drivers/input/touchscreen/Makefile +++ b/drivers/input/touchscreen/Makefile @@ -44,6 +44,7 @@ obj-$(CONFIG_TOUCHSCREEN_TNETV107X) += tnetv107x-ts.o obj-$(CONFIG_TOUCHSCREEN_TOUCHIT213) += touchit213.o obj-$(CONFIG_TOUCHSCREEN_TOUCHRIGHT) += touchright.o obj-$(CONFIG_TOUCHSCREEN_TOUCHWIN) += touchwin.o +obj-$(CONFIG_TOUCHSCREEN_TSC2005) += tsc2005.o obj-$(CONFIG_TOUCHSCREEN_TSC2007) += tsc2007.o obj-$(CONFIG_TOUCHSCREEN_UCB1400) += ucb1400_ts.o obj-$(CONFIG_TOUCHSCREEN_WACOM_W8001) += wacom_w8001.o diff --git a/drivers/input/touchscreen/tsc2005.c b/drivers/input/touchscreen/tsc2005.c new file mode 100644 index 0000000000000..f95f968f18e1c --- /dev/null +++ b/drivers/input/touchscreen/tsc2005.c @@ -0,0 +1,713 @@ +/* + * TSC2005 touchscreen driver + * + * Copyright (C) 2006-2010 Nokia Corporation + * + * Author: Lauri Leukkunen + * based on TSC2301 driver by Klaus K. Pedersen + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include +#include +#include +#include +#include +#include +#include + +/* + * The touchscreen interface operates as follows: + * + * 1) Pen is pressed against the touchscreen. + * 2) TSC2005 performs AD conversion. + * 3) After the conversion is done TSC2005 drives DAV line down. + * 4) GPIO IRQ is received and tsc2005_irq_thread() is scheduled. + * 5) tsc2005_irq_thread() queues up an spi transfer to fetch the x, y, z1, z2 + * values. + * 6) tsc2005_irq_thread() reports coordinates to input layer and sets up + * tsc2005_penup_timer() to be called after TSC2005_PENUP_TIME_MS (40ms). + * 7) When the penup timer expires, there have not been touch or DAV interrupts + * during the last 40ms which means the pen has been lifted. + * + * ESD recovery via a hardware reset is done if the TSC2005 doesn't respond + * after a configurable period (in ms) of activity. If esd_timeout is 0, the + * watchdog is disabled. + */ + +/* control byte 1 */ +#define TSC2005_CMD 0x80 +#define TSC2005_CMD_NORMAL 0x00 +#define TSC2005_CMD_STOP 0x01 +#define TSC2005_CMD_12BIT 0x04 + +/* control byte 0 */ +#define TSC2005_REG_READ 0x0001 +#define TSC2005_REG_PND0 0x0002 +#define TSC2005_REG_X 0x0000 +#define TSC2005_REG_Y 0x0008 +#define TSC2005_REG_Z1 0x0010 +#define TSC2005_REG_Z2 0x0018 +#define TSC2005_REG_TEMP_HIGH 0x0050 +#define TSC2005_REG_CFR0 0x0060 +#define TSC2005_REG_CFR1 0x0068 +#define TSC2005_REG_CFR2 0x0070 + +/* configuration register 0 */ +#define TSC2005_CFR0_PRECHARGE_276US 0x0040 +#define TSC2005_CFR0_STABTIME_1MS 0x0300 +#define TSC2005_CFR0_CLOCK_1MHZ 0x1000 +#define TSC2005_CFR0_RESOLUTION12 0x2000 +#define TSC2005_CFR0_PENMODE 0x8000 +#define TSC2005_CFR0_INITVALUE (TSC2005_CFR0_STABTIME_1MS | \ + TSC2005_CFR0_CLOCK_1MHZ | \ + TSC2005_CFR0_RESOLUTION12 | \ + TSC2005_CFR0_PRECHARGE_276US | \ + TSC2005_CFR0_PENMODE) + +/* bits common to both read and write of configuration register 0 */ +#define TSC2005_CFR0_RW_MASK 0x3fff + +/* configuration register 1 */ +#define TSC2005_CFR1_BATCHDELAY_4MS 0x0003 +#define TSC2005_CFR1_INITVALUE TSC2005_CFR1_BATCHDELAY_4MS + +/* configuration register 2 */ +#define TSC2005_CFR2_MAVE_Z 0x0004 +#define TSC2005_CFR2_MAVE_Y 0x0008 +#define TSC2005_CFR2_MAVE_X 0x0010 +#define TSC2005_CFR2_AVG_7 0x0800 +#define TSC2005_CFR2_MEDIUM_15 0x3000 +#define TSC2005_CFR2_INITVALUE (TSC2005_CFR2_MAVE_X | \ + TSC2005_CFR2_MAVE_Y | \ + TSC2005_CFR2_MAVE_Z | \ + TSC2005_CFR2_MEDIUM_15 | \ + TSC2005_CFR2_AVG_7) + +#define MAX_12BIT 0xfff +#define TSC2005_SPI_MAX_SPEED_HZ 10000000 +#define TSC2005_PENUP_TIME_MS 40 + +struct tsc2005_spi_rd { + struct spi_transfer spi_xfer; + u32 spi_tx; + u32 spi_rx; +}; + +struct tsc2005 { + struct spi_device *spi; + + struct spi_message spi_read_msg; + struct tsc2005_spi_rd spi_x; + struct tsc2005_spi_rd spi_y; + struct tsc2005_spi_rd spi_z1; + struct tsc2005_spi_rd spi_z2; + + struct input_dev *idev; + char phys[32]; + + struct mutex mutex; + + /* raw copy of previous x,y,z */ + int in_x; + int in_y; + int in_z1; + int in_z2; + + struct timer_list penup_timer; + struct work_struct penup_work; + + unsigned int esd_timeout; + struct timer_list esd_timer; + struct work_struct esd_work; + + unsigned int x_plate_ohm; + + bool disabled; + unsigned int disable_depth; + unsigned int pen_down; + + void (*set_reset)(bool enable); +}; + +static void tsc2005_cmd(struct tsc2005 *ts, u8 cmd) +{ + u8 tx; + struct spi_message msg; + struct spi_transfer xfer = { 0 }; + + tx = TSC2005_CMD | TSC2005_CMD_12BIT | cmd; + + xfer.tx_buf = &tx; + xfer.rx_buf = NULL; + xfer.len = 1; + xfer.bits_per_word = 8; + + spi_message_init(&msg); + spi_message_add_tail(&xfer, &msg); + spi_sync(ts->spi, &msg); +} + +static void tsc2005_write(struct tsc2005 *ts, u8 reg, u16 value) +{ + u32 tx; + struct spi_message msg; + struct spi_transfer xfer = { 0 }; + + tx = (reg | TSC2005_REG_PND0) << 16; + tx |= value; + + xfer.tx_buf = &tx; + xfer.rx_buf = NULL; + xfer.len = 4; + xfer.bits_per_word = 24; + + spi_message_init(&msg); + spi_message_add_tail(&xfer, &msg); + spi_sync(ts->spi, &msg); +} + +static void tsc2005_setup_read(struct tsc2005_spi_rd *rd, u8 reg, bool last) +{ + rd->spi_tx = (reg | TSC2005_REG_READ) << 16; + rd->spi_xfer.tx_buf = &rd->spi_tx; + rd->spi_xfer.rx_buf = &rd->spi_rx; + rd->spi_xfer.len = 4; + rd->spi_xfer.bits_per_word = 24; + rd->spi_xfer.cs_change = !last; +} + +static void tsc2005_read(struct tsc2005 *ts, u8 reg, u16 *value) +{ + struct spi_message msg; + struct tsc2005_spi_rd spi_rd = { { 0 }, 0, 0 }; + + tsc2005_setup_read(&spi_rd, reg, 1); + + spi_message_init(&msg); + spi_message_add_tail(&spi_rd.spi_xfer, &msg); + spi_sync(ts->spi, &msg); + *value = spi_rd.spi_rx; +} + +static void tsc2005_update_pen_state(struct tsc2005 *ts, + int x, int y, int pressure) +{ + if (pressure) { + input_report_abs(ts->idev, ABS_X, x); + input_report_abs(ts->idev, ABS_Y, y); + input_report_abs(ts->idev, ABS_PRESSURE, pressure); + if (!ts->pen_down) { + input_report_key(ts->idev, BTN_TOUCH, !!pressure); + ts->pen_down = 1; + } + } else { + input_report_abs(ts->idev, ABS_PRESSURE, 0); + if (ts->pen_down) { + input_report_key(ts->idev, BTN_TOUCH, 0); + ts->pen_down = 0; + } + } + input_sync(ts->idev); + dev_dbg(&ts->spi->dev, "point(%4d,%4d), pressure (%4d)\n", x, y, + pressure); +} + +static irqreturn_t tsc2005_irq_handler(int irq, void *dev_id) +{ + struct tsc2005 *ts = dev_id; + + /* update the penup timer only if it's pending */ + mod_timer_pending(&ts->penup_timer, + jiffies + msecs_to_jiffies(TSC2005_PENUP_TIME_MS)); + + return IRQ_WAKE_THREAD; +} + +static irqreturn_t tsc2005_irq_thread(int irq, void *_ts) +{ + struct tsc2005 *ts = _ts; + unsigned int pressure; + u32 x; + u32 y; + u32 z1; + u32 z2; + + mutex_lock(&ts->mutex); + + if (unlikely(ts->disable_depth)) + goto out; + + /* read the coordinates */ + spi_sync(ts->spi, &ts->spi_read_msg); + x = ts->spi_x.spi_rx; + y = ts->spi_y.spi_rx; + z1 = ts->spi_z1.spi_rx; + z2 = ts->spi_z2.spi_rx; + + /* validate position */ + if (unlikely(x > MAX_12BIT || y > MAX_12BIT)) + goto out; + + /* skip coords if the pressure components are out of range */ + if (unlikely(z1 == 0 || z2 > MAX_12BIT || z1 >= z2)) + goto out; + + /* skip point if this is a pen down with the exact same values as + * the value before pen-up - that implies SPI fed us stale data + */ + if (!ts->pen_down && + ts->in_x == x && + ts->in_y == y && + ts->in_z1 == z1 && + ts->in_z2 == z2) + goto out; + + /* At this point we are happy we have a valid and useful reading. + * Remember it for later comparisons. We may now begin downsampling + */ + ts->in_x = x; + ts->in_y = y; + ts->in_z1 = z1; + ts->in_z2 = z2; + + /* compute touch pressure resistance using equation #1 */ + pressure = x * (z2 - z1) / z1; + pressure = pressure * ts->x_plate_ohm / 4096; + if (unlikely(pressure > MAX_12BIT)) + goto out; + + tsc2005_update_pen_state(ts, x, y, pressure); + + /* set the penup timer */ + mod_timer(&ts->penup_timer, + jiffies + msecs_to_jiffies(TSC2005_PENUP_TIME_MS)); + + if (!ts->esd_timeout) + goto out; + + /* update the watchdog timer */ + mod_timer(&ts->esd_timer, + round_jiffies(jiffies + msecs_to_jiffies(ts->esd_timeout))); + +out: + mutex_unlock(&ts->mutex); + return IRQ_HANDLED; +} + +static void tsc2005_penup_timer(unsigned long data) +{ + struct tsc2005 *ts = (struct tsc2005 *)data; + + schedule_work(&ts->penup_work); +} + +static void tsc2005_penup_work(struct work_struct *work) +{ + struct tsc2005 *ts = container_of(work, struct tsc2005, penup_work); + + mutex_lock(&ts->mutex); + tsc2005_update_pen_state(ts, 0, 0, 0); + mutex_unlock(&ts->mutex); +} + +static void tsc2005_start_scan(struct tsc2005 *ts) +{ + tsc2005_write(ts, TSC2005_REG_CFR0, TSC2005_CFR0_INITVALUE); + tsc2005_write(ts, TSC2005_REG_CFR1, TSC2005_CFR1_INITVALUE); + tsc2005_write(ts, TSC2005_REG_CFR2, TSC2005_CFR2_INITVALUE); + tsc2005_cmd(ts, TSC2005_CMD_NORMAL); +} + +static void tsc2005_stop_scan(struct tsc2005 *ts) +{ + tsc2005_cmd(ts, TSC2005_CMD_STOP); +} + +/* must be called with mutex held */ +static void tsc2005_disable(struct tsc2005 *ts) +{ + if (ts->disable_depth++ != 0) + return; + disable_irq(ts->spi->irq); + if (ts->esd_timeout) + del_timer_sync(&ts->esd_timer); + del_timer_sync(&ts->penup_timer); + tsc2005_stop_scan(ts); +} + +/* must be called with mutex held */ +static void tsc2005_enable(struct tsc2005 *ts) +{ + if (--ts->disable_depth != 0) + return; + tsc2005_start_scan(ts); + enable_irq(ts->spi->irq); + if (!ts->esd_timeout) + return; + mod_timer(&ts->esd_timer, + round_jiffies(jiffies + msecs_to_jiffies(ts->esd_timeout))); +} + +static ssize_t tsc2005_disable_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct tsc2005 *ts = dev_get_drvdata(dev); + + return sprintf(buf, "%u\n", ts->disabled); +} + +static ssize_t tsc2005_disable_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct tsc2005 *ts = dev_get_drvdata(dev); + unsigned long res; + int i; + + if (strict_strtoul(buf, 10, &res) < 0) + return -EINVAL; + i = res ? 1 : 0; + + mutex_lock(&ts->mutex); + if (i == ts->disabled) + goto out; + ts->disabled = i; + if (i) + tsc2005_disable(ts); + else + tsc2005_enable(ts); +out: + mutex_unlock(&ts->mutex); + return count; +} +static DEVICE_ATTR(disable, 0664, tsc2005_disable_show, tsc2005_disable_store); + +static ssize_t tsc2005_selftest_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct tsc2005 *ts = dev_get_drvdata(dev); + u16 temp_high; + u16 temp_high_orig; + u16 temp_high_test; + unsigned int result; + + if (!ts->set_reset) { + dev_warn(&ts->spi->dev, + "unable to selftest: no reset function\n"); + result = 0; + goto out; + } + + mutex_lock(&ts->mutex); + + /* + * Test TSC2005 communications via temp high register. + */ + tsc2005_disable(ts); + result = 1; + tsc2005_read(ts, TSC2005_REG_TEMP_HIGH, &temp_high_orig); + temp_high_test = (temp_high_orig - 1) & MAX_12BIT; + tsc2005_write(ts, TSC2005_REG_TEMP_HIGH, temp_high_test); + tsc2005_read(ts, TSC2005_REG_TEMP_HIGH, &temp_high); + if (temp_high != temp_high_test) { + dev_warn(dev, "selftest failed: %d != %d\n", + temp_high, temp_high_test); + result = 0; + } + + /* hardware reset */ + ts->set_reset(0); + usleep_range(100, 500); /* only 10us required */ + ts->set_reset(1); + tsc2005_enable(ts); + + /* test that the reset really happened */ + tsc2005_read(ts, TSC2005_REG_TEMP_HIGH, &temp_high); + if (temp_high != temp_high_orig) { + dev_warn(dev, "selftest failed after reset: %d != %d\n", + temp_high, temp_high_orig); + result = 0; + } + + mutex_unlock(&ts->mutex); + +out: + return sprintf(buf, "%u\n", result); +} +static DEVICE_ATTR(selftest, S_IRUGO, tsc2005_selftest_show, NULL); + +static void tsc2005_esd_timer(unsigned long data) +{ + struct tsc2005 *ts = (struct tsc2005 *)data; + + schedule_work(&ts->esd_work); +} + +static void tsc2005_esd_work(struct work_struct *work) +{ + struct tsc2005 *ts = container_of(work, struct tsc2005, esd_work); + u16 r; + + mutex_lock(&ts->mutex); + + if (ts->disable_depth) + goto out; + + /* + * If we cannot read our known value from configuration register 0 then + * reset the controller as if from power-up and start scanning again. + */ + tsc2005_read(ts, TSC2005_REG_CFR0, &r); + if ((r ^ TSC2005_CFR0_INITVALUE) & TSC2005_CFR0_RW_MASK) { + dev_info(&ts->spi->dev, "TSC2005 not responding - resetting\n"); + ts->set_reset(0); + tsc2005_update_pen_state(ts, 0, 0, 0); + usleep_range(100, 500); /* only 10us required */ + ts->set_reset(1); + tsc2005_start_scan(ts); + } + + /* re-arm the watchdog */ + mod_timer(&ts->esd_timer, + round_jiffies(jiffies + msecs_to_jiffies(ts->esd_timeout))); + +out: + mutex_unlock(&ts->mutex); +} + +static void __devinit tsc2005_setup_spi_xfer(struct tsc2005 *ts) +{ + tsc2005_setup_read(&ts->spi_x, TSC2005_REG_X, 0); + tsc2005_setup_read(&ts->spi_y, TSC2005_REG_Y, 0); + tsc2005_setup_read(&ts->spi_z1, TSC2005_REG_Z1, 0); + tsc2005_setup_read(&ts->spi_z2, TSC2005_REG_Z2, 1); + + spi_message_init(&ts->spi_read_msg); + spi_message_add_tail(&ts->spi_x.spi_xfer, &ts->spi_read_msg); + spi_message_add_tail(&ts->spi_y.spi_xfer, &ts->spi_read_msg); + spi_message_add_tail(&ts->spi_z1.spi_xfer, &ts->spi_read_msg); + spi_message_add_tail(&ts->spi_z2.spi_xfer, &ts->spi_read_msg); +} + +static struct attribute *tsc2005_attrs[] = { + &dev_attr_disable.attr, + &dev_attr_selftest.attr, + NULL +}; + +static struct attribute_group tsc2005_attr_group = { + .attrs = tsc2005_attrs, +}; + +static int __devinit tsc2005_setup(struct tsc2005 *ts, + struct tsc2005_platform_data *pdata) +{ + int r; + int fudge_x; + int fudge_y; + int fudge_p; + int p_max; + int x_max; + int y_max; + + mutex_init(&ts->mutex); + + tsc2005_setup_spi_xfer(ts); + + init_timer(&ts->penup_timer); + setup_timer(&ts->penup_timer, tsc2005_penup_timer, (unsigned long)ts); + INIT_WORK(&ts->penup_work, tsc2005_penup_work); + + fudge_x = pdata->ts_x_fudge ? : 4; + fudge_y = pdata->ts_y_fudge ? : 8; + fudge_p = pdata->ts_pressure_fudge ? : 2; + x_max = pdata->ts_x_max ? : MAX_12BIT; + y_max = pdata->ts_y_max ? : MAX_12BIT; + p_max = pdata->ts_pressure_max ? : MAX_12BIT; + ts->x_plate_ohm = pdata->ts_x_plate_ohm ? : 280; + ts->esd_timeout = pdata->esd_timeout_ms; + ts->set_reset = pdata->set_reset; + + ts->idev = input_allocate_device(); + if (ts->idev == NULL) + return -ENOMEM; + ts->idev->name = "TSC2005 touchscreen"; + snprintf(ts->phys, sizeof(ts->phys), "%s/input-ts", + dev_name(&ts->spi->dev)); + ts->idev->phys = ts->phys; + ts->idev->evbit[0] = BIT(EV_ABS) | BIT(EV_KEY); + ts->idev->absbit[0] = BIT(ABS_X) | BIT(ABS_Y) | BIT(ABS_PRESSURE); + ts->idev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH); + + input_set_abs_params(ts->idev, ABS_X, 0, x_max, fudge_x, 0); + input_set_abs_params(ts->idev, ABS_Y, 0, y_max, fudge_y, 0); + input_set_abs_params(ts->idev, ABS_PRESSURE, 0, p_max, fudge_p, 0); + + r = request_threaded_irq(ts->spi->irq, tsc2005_irq_handler, + tsc2005_irq_thread, IRQF_TRIGGER_RISING, + "tsc2005", ts); + if (r) { + dev_err(&ts->spi->dev, "request_threaded_irq(): %d\n", r); + goto err1; + } + set_irq_wake(ts->spi->irq, 1); + + r = input_register_device(ts->idev); + if (r) { + dev_err(&ts->spi->dev, "input_register_device(): %d\n", r); + goto err2; + } + + r = sysfs_create_group(&ts->spi->dev.kobj, &tsc2005_attr_group); + if (r) + dev_warn(&ts->spi->dev, "sysfs entry creation failed: %d\n", r); + + tsc2005_start_scan(ts); + + if (!ts->esd_timeout || !ts->set_reset) + goto done; + + /* start the optional ESD watchdog */ + setup_timer(&ts->esd_timer, tsc2005_esd_timer, (unsigned long)ts); + INIT_WORK(&ts->esd_work, tsc2005_esd_work); + mod_timer(&ts->esd_timer, + round_jiffies(jiffies + msecs_to_jiffies(ts->esd_timeout))); + +done: + return 0; + +err2: + free_irq(ts->spi->irq, ts); + +err1: + input_free_device(ts->idev); + return r; +} + +static int __devinit tsc2005_probe(struct spi_device *spi) +{ + struct tsc2005_platform_data *pdata = spi->dev.platform_data; + struct tsc2005 *ts; + int r; + + if (spi->irq < 0) { + dev_dbg(&spi->dev, "no irq\n"); + return -ENODEV; + } + + if (!pdata) { + dev_dbg(&spi->dev, "no platform data\n"); + return -ENODEV; + } + + ts = kzalloc(sizeof(*ts), GFP_KERNEL); + if (ts == NULL) + return -ENOMEM; + + dev_set_drvdata(&spi->dev, ts); + ts->spi = spi; + spi->dev.power.power_state = PMSG_ON; + spi->mode = SPI_MODE_0; + spi->bits_per_word = 8; + if (!spi->max_speed_hz) + spi->max_speed_hz = TSC2005_SPI_MAX_SPEED_HZ; + spi_setup(spi); + + r = tsc2005_setup(ts, pdata); + if (r) + kfree(ts); + return r; +} + +static int __devexit tsc2005_remove(struct spi_device *spi) +{ + struct tsc2005 *ts = dev_get_drvdata(&spi->dev); + + mutex_lock(&ts->mutex); + tsc2005_disable(ts); + mutex_unlock(&ts->mutex); + + if (ts->esd_timeout) + del_timer_sync(&ts->esd_timer); + del_timer_sync(&ts->penup_timer); + + flush_work(&ts->esd_work); + flush_work(&ts->penup_work); + + sysfs_remove_group(&ts->spi->dev.kobj, &tsc2005_attr_group); + free_irq(ts->spi->irq, ts); + input_unregister_device(ts->idev); + kfree(ts); + + return 0; +} + +#ifdef CONFIG_PM +static int tsc2005_suspend(struct spi_device *spi, pm_message_t mesg) +{ + struct tsc2005 *ts = dev_get_drvdata(&spi->dev); + + mutex_lock(&ts->mutex); + tsc2005_disable(ts); + mutex_unlock(&ts->mutex); + + return 0; +} + +static int tsc2005_resume(struct spi_device *spi) +{ + struct tsc2005 *ts = dev_get_drvdata(&spi->dev); + + mutex_lock(&ts->mutex); + tsc2005_enable(ts); + mutex_unlock(&ts->mutex); + + return 0; +} +#endif + +static struct spi_driver tsc2005_driver = { + .driver = { + .name = "tsc2005", + .owner = THIS_MODULE, + }, +#ifdef CONFIG_PM + .suspend = tsc2005_suspend, + .resume = tsc2005_resume, +#endif + .probe = tsc2005_probe, + .remove = __devexit_p(tsc2005_remove), +}; + +static int __init tsc2005_init(void) +{ + printk(KERN_INFO "TSC2005 driver initializing\n"); + return spi_register_driver(&tsc2005_driver); +} +module_init(tsc2005_init); + +static void __exit tsc2005_exit(void) +{ + spi_unregister_driver(&tsc2005_driver); +} +module_exit(tsc2005_exit); + +MODULE_AUTHOR("Lauri Leukkunen "); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:tsc2005"); diff --git a/include/linux/spi/tsc2005.h b/include/linux/spi/tsc2005.h new file mode 100644 index 0000000000000..d9b0c84220c73 --- /dev/null +++ b/include/linux/spi/tsc2005.h @@ -0,0 +1,41 @@ +/* + * This file is part of TSC2005 touchscreen driver + * + * Copyright (C) 2009-2010 Nokia Corporation + * + * Contact: Aaro Koskinen + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#ifndef _LINUX_SPI_TSC2005_H +#define _LINUX_SPI_TSC2005_H + +#include + +struct tsc2005_platform_data { + int ts_pressure_max; + int ts_pressure_fudge; + int ts_x_max; + int ts_x_fudge; + int ts_y_max; + int ts_y_fudge; + int ts_x_plate_ohm; + unsigned int esd_timeout_ms; + void (*set_reset)(bool enable); +}; + +#endif -- GitLab From 6b007d62fabb279b51c784c7c8abc6848b66a917 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Wed, 16 Mar 2011 22:08:08 -0700 Subject: [PATCH 0749/2822] Input: tsc2005 - use spi_get/set_drvdata() Instead of peeking into underlying device and using dev_get/set_drvdata(), let's use SPI layer's implementation to access driver-private data (which may be different from driver-core private data). Tested-by: Aaro Koskinen Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/tsc2005.c | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/drivers/input/touchscreen/tsc2005.c b/drivers/input/touchscreen/tsc2005.c index f95f968f18e1c..5dad30a4b1536 100644 --- a/drivers/input/touchscreen/tsc2005.c +++ b/drivers/input/touchscreen/tsc2005.c @@ -366,7 +366,8 @@ static void tsc2005_enable(struct tsc2005 *ts) static ssize_t tsc2005_disable_show(struct device *dev, struct device_attribute *attr, char *buf) { - struct tsc2005 *ts = dev_get_drvdata(dev); + struct spi_device *spi = to_spi_device(dev); + struct tsc2005 *ts = spi_get_drvdata(spi); return sprintf(buf, "%u\n", ts->disabled); } @@ -375,7 +376,8 @@ static ssize_t tsc2005_disable_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - struct tsc2005 *ts = dev_get_drvdata(dev); + struct spi_device *spi = to_spi_device(dev); + struct tsc2005 *ts = spi_get_drvdata(spi); unsigned long res; int i; @@ -401,7 +403,8 @@ static ssize_t tsc2005_selftest_show(struct device *dev, struct device_attribute *attr, char *buf) { - struct tsc2005 *ts = dev_get_drvdata(dev); + struct spi_device *spi = to_spi_device(dev); + struct tsc2005 *ts = spi_get_drvdata(spi); u16 temp_high; u16 temp_high_orig; u16 temp_high_test; @@ -620,7 +623,7 @@ static int __devinit tsc2005_probe(struct spi_device *spi) if (ts == NULL) return -ENOMEM; - dev_set_drvdata(&spi->dev, ts); + spi_set_drvdata(spi, ts); ts->spi = spi; spi->dev.power.power_state = PMSG_ON; spi->mode = SPI_MODE_0; @@ -637,7 +640,7 @@ static int __devinit tsc2005_probe(struct spi_device *spi) static int __devexit tsc2005_remove(struct spi_device *spi) { - struct tsc2005 *ts = dev_get_drvdata(&spi->dev); + struct tsc2005 *ts = spi_get_drvdata(spi); mutex_lock(&ts->mutex); tsc2005_disable(ts); @@ -661,7 +664,8 @@ static int __devexit tsc2005_remove(struct spi_device *spi) #ifdef CONFIG_PM static int tsc2005_suspend(struct spi_device *spi, pm_message_t mesg) { - struct tsc2005 *ts = dev_get_drvdata(&spi->dev); + struct spi_device *spi = to_spi_device(dev); + struct tsc2005 *ts = spi_get_drvdata(spi); mutex_lock(&ts->mutex); tsc2005_disable(ts); @@ -672,7 +676,8 @@ static int tsc2005_suspend(struct spi_device *spi, pm_message_t mesg) static int tsc2005_resume(struct spi_device *spi) { - struct tsc2005 *ts = dev_get_drvdata(&spi->dev); + struct spi_device *spi = to_spi_device(dev); + struct tsc2005 *ts = spi_get_drvdata(spi); mutex_lock(&ts->mutex); tsc2005_enable(ts); -- GitLab From 3ff8ff53aae7b7e46dec6a50c29b8a022ec299ba Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Wed, 16 Mar 2011 22:08:26 -0700 Subject: [PATCH 0750/2822] Input: tsc2005 - convert to using dev_pm_ops Newer code should not be using legacy suspend/resume methods but rather supply dev_pm_ops structure as it allows better control over power management. Tested-by: Aaro Koskinen Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/tsc2005.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/drivers/input/touchscreen/tsc2005.c b/drivers/input/touchscreen/tsc2005.c index 5dad30a4b1536..109efbffe5ad1 100644 --- a/drivers/input/touchscreen/tsc2005.c +++ b/drivers/input/touchscreen/tsc2005.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include @@ -661,8 +662,8 @@ static int __devexit tsc2005_remove(struct spi_device *spi) return 0; } -#ifdef CONFIG_PM -static int tsc2005_suspend(struct spi_device *spi, pm_message_t mesg) +#ifdef CONFIG_PM_SLEEP +static int tsc2005_suspend(struct device *dev) { struct spi_device *spi = to_spi_device(dev); struct tsc2005 *ts = spi_get_drvdata(spi); @@ -674,7 +675,7 @@ static int tsc2005_suspend(struct spi_device *spi, pm_message_t mesg) return 0; } -static int tsc2005_resume(struct spi_device *spi) +static int tsc2005_resume(struct device *dev) { struct spi_device *spi = to_spi_device(dev); struct tsc2005 *ts = spi_get_drvdata(spi); @@ -687,17 +688,16 @@ static int tsc2005_resume(struct spi_device *spi) } #endif +static SIMPLE_DEV_PM_OPS(tsc2005_pm_ops, tsc2005_suspend, tsc2005_resume); + static struct spi_driver tsc2005_driver = { - .driver = { - .name = "tsc2005", - .owner = THIS_MODULE, + .driver = { + .name = "tsc2005", + .owner = THIS_MODULE, + .pm = &tsc2005_pm_ops, }, -#ifdef CONFIG_PM - .suspend = tsc2005_suspend, - .resume = tsc2005_resume, -#endif - .probe = tsc2005_probe, - .remove = __devexit_p(tsc2005_remove), + .probe = tsc2005_probe, + .remove = __devexit_p(tsc2005_remove), }; static int __init tsc2005_init(void) -- GitLab From ef5a672f8d67c45fe2739c3a98a4e41d96b5cabc Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Wed, 16 Mar 2011 22:08:39 -0700 Subject: [PATCH 0751/2822] Input: tsc2005 - remove incorrect module alias TSC2005 is not a platform driver so it should not define "platform:tsc2005" module alias. Tested-by: Aaro Koskinen Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/tsc2005.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/input/touchscreen/tsc2005.c b/drivers/input/touchscreen/tsc2005.c index 109efbffe5ad1..8c2e02402f329 100644 --- a/drivers/input/touchscreen/tsc2005.c +++ b/drivers/input/touchscreen/tsc2005.c @@ -715,4 +715,3 @@ module_exit(tsc2005_exit); MODULE_AUTHOR("Lauri Leukkunen "); MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:tsc2005"); -- GitLab From bcd11879fb5c84b3ca9167022b4c2b66d0935c52 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Wed, 16 Mar 2011 22:08:53 -0700 Subject: [PATCH 0752/2822] Input: tsc2005 - remove driver banner message The boot process is noisy as it is and input core already announces all new device so let's get rid of the banner message in the driver. Tested-by: Aaro Koskinen Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/tsc2005.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/input/touchscreen/tsc2005.c b/drivers/input/touchscreen/tsc2005.c index 8c2e02402f329..2435235db6277 100644 --- a/drivers/input/touchscreen/tsc2005.c +++ b/drivers/input/touchscreen/tsc2005.c @@ -702,7 +702,6 @@ static struct spi_driver tsc2005_driver = { static int __init tsc2005_init(void) { - printk(KERN_INFO "TSC2005 driver initializing\n"); return spi_register_driver(&tsc2005_driver); } module_init(tsc2005_init); -- GitLab From b88aa494c27552e6fa94e4abaa5ea4f9b2f170a8 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Wed, 16 Mar 2011 22:09:03 -0700 Subject: [PATCH 0753/2822] Input: tsc2005 - add module description Add proper module description so that it would show in 'modinfo' output. Tested-by: Aaro Koskinen Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/tsc2005.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/input/touchscreen/tsc2005.c b/drivers/input/touchscreen/tsc2005.c index 2435235db6277..596fd1f01b22b 100644 --- a/drivers/input/touchscreen/tsc2005.c +++ b/drivers/input/touchscreen/tsc2005.c @@ -713,4 +713,5 @@ static void __exit tsc2005_exit(void) module_exit(tsc2005_exit); MODULE_AUTHOR("Lauri Leukkunen "); +MODULE_DESCRIPTION("TSC2005 Touchscreen Driver"); MODULE_LICENSE("GPL"); -- GitLab From 2721a89ac41f2e7705484c1582c293c4eee5344d Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Wed, 16 Mar 2011 22:09:09 -0700 Subject: [PATCH 0754/2822] Input: tsc2005 - clear driver data after unbinding We should not leave garbage pointers in driver structure after we unbind it from the device or if bind fails. Tested-by: Aaro Koskinen Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/tsc2005.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/input/touchscreen/tsc2005.c b/drivers/input/touchscreen/tsc2005.c index 596fd1f01b22b..732c81e9a3e63 100644 --- a/drivers/input/touchscreen/tsc2005.c +++ b/drivers/input/touchscreen/tsc2005.c @@ -634,8 +634,10 @@ static int __devinit tsc2005_probe(struct spi_device *spi) spi_setup(spi); r = tsc2005_setup(ts, pdata); - if (r) + if (r) { kfree(ts); + spi_set_drvdata(spi, NULL); + } return r; } @@ -659,6 +661,7 @@ static int __devexit tsc2005_remove(struct spi_device *spi) input_unregister_device(ts->idev); kfree(ts); + spi_set_drvdata(spi, NULL); return 0; } -- GitLab From b4b480a8d643cbdef6f925e55759c18a674fa454 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Wed, 16 Mar 2011 22:09:25 -0700 Subject: [PATCH 0755/2822] Input: tsc2005 - set up parent device Set up SPI device as parent of the input device so it gets placed into proper place in sysfs tree. Tested-by: Aaro Koskinen Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/tsc2005.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/input/touchscreen/tsc2005.c b/drivers/input/touchscreen/tsc2005.c index 732c81e9a3e63..e294648a97c95 100644 --- a/drivers/input/touchscreen/tsc2005.c +++ b/drivers/input/touchscreen/tsc2005.c @@ -555,6 +555,7 @@ static int __devinit tsc2005_setup(struct tsc2005 *ts, snprintf(ts->phys, sizeof(ts->phys), "%s/input-ts", dev_name(&ts->spi->dev)); ts->idev->phys = ts->phys; + ts->idev->dev.parent = &ts->spi->dev; ts->idev->evbit[0] = BIT(EV_ABS) | BIT(EV_KEY); ts->idev->absbit[0] = BIT(ABS_X) | BIT(ABS_Y) | BIT(ABS_PRESSURE); ts->idev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH); -- GitLab From f8a67139c68eb8a58907906622c9aa02cd6a1dd1 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Wed, 16 Mar 2011 22:09:32 -0700 Subject: [PATCH 0756/2822] Input: tsc2005 - set up bus type in input device We know what bus we are residing on (SPI) so let's make this data available to the users. Tested-by: Aaro Koskinen Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/tsc2005.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/input/touchscreen/tsc2005.c b/drivers/input/touchscreen/tsc2005.c index e294648a97c95..09cbcb0b19fea 100644 --- a/drivers/input/touchscreen/tsc2005.c +++ b/drivers/input/touchscreen/tsc2005.c @@ -555,6 +555,7 @@ static int __devinit tsc2005_setup(struct tsc2005 *ts, snprintf(ts->phys, sizeof(ts->phys), "%s/input-ts", dev_name(&ts->spi->dev)); ts->idev->phys = ts->phys; + ts->idev->id.bustype = BUS_SPI; ts->idev->dev.parent = &ts->spi->dev; ts->idev->evbit[0] = BIT(EV_ABS) | BIT(EV_KEY); ts->idev->absbit[0] = BIT(ABS_X) | BIT(ABS_Y) | BIT(ABS_PRESSURE); -- GitLab From 99bb892d8a3f4f384d61e5d20499247a7cdd3d74 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Wed, 16 Mar 2011 22:09:38 -0700 Subject: [PATCH 0757/2822] Input: tsc2005 - rework driver initialization code We need to make sure we have time/work initialized before requesting and enabling interrupts, otherwise we might start using them way too early. Tested-by: Aaro Koskinen Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/tsc2005.c | 215 ++++++++++++++-------------- 1 file changed, 105 insertions(+), 110 deletions(-) diff --git a/drivers/input/touchscreen/tsc2005.c b/drivers/input/touchscreen/tsc2005.c index 09cbcb0b19fea..de170e9dc54ac 100644 --- a/drivers/input/touchscreen/tsc2005.c +++ b/drivers/input/touchscreen/tsc2005.c @@ -495,6 +495,16 @@ out: mutex_unlock(&ts->mutex); } +static struct attribute *tsc2005_attrs[] = { + &dev_attr_disable.attr, + &dev_attr_selftest.attr, + NULL +}; + +static struct attribute_group tsc2005_attr_group = { + .attrs = tsc2005_attrs, +}; + static void __devinit tsc2005_setup_spi_xfer(struct tsc2005 *ts) { tsc2005_setup_read(&ts->spi_x, TSC2005_REG_X, 0); @@ -509,144 +519,130 @@ static void __devinit tsc2005_setup_spi_xfer(struct tsc2005 *ts) spi_message_add_tail(&ts->spi_z2.spi_xfer, &ts->spi_read_msg); } -static struct attribute *tsc2005_attrs[] = { - &dev_attr_disable.attr, - &dev_attr_selftest.attr, - NULL -}; - -static struct attribute_group tsc2005_attr_group = { - .attrs = tsc2005_attrs, -}; - -static int __devinit tsc2005_setup(struct tsc2005 *ts, - struct tsc2005_platform_data *pdata) +static int __devinit tsc2005_probe(struct spi_device *spi) { - int r; - int fudge_x; - int fudge_y; - int fudge_p; - int p_max; - int x_max; - int y_max; + const struct tsc2005_platform_data *pdata = spi->dev.platform_data; + struct tsc2005 *ts; + struct input_dev *input_dev; + unsigned int max_x, max_y, max_p; + unsigned int fudge_x, fudge_y, fudge_p; + int error; - mutex_init(&ts->mutex); + if (!pdata) { + dev_dbg(&spi->dev, "no platform data\n"); + return -ENODEV; + } - tsc2005_setup_spi_xfer(ts); + fudge_x = pdata->ts_x_fudge ? : 4; + fudge_y = pdata->ts_y_fudge ? : 8; + fudge_p = pdata->ts_pressure_fudge ? : 2; + max_x = pdata->ts_x_max ? : MAX_12BIT; + max_y = pdata->ts_y_max ? : MAX_12BIT; + max_p = pdata->ts_pressure_max ? : MAX_12BIT; - init_timer(&ts->penup_timer); - setup_timer(&ts->penup_timer, tsc2005_penup_timer, (unsigned long)ts); - INIT_WORK(&ts->penup_work, tsc2005_penup_work); + if (spi->irq <= 0) { + dev_dbg(&spi->dev, "no irq\n"); + return -ENODEV; + } - fudge_x = pdata->ts_x_fudge ? : 4; - fudge_y = pdata->ts_y_fudge ? : 8; - fudge_p = pdata->ts_pressure_fudge ? : 2; - x_max = pdata->ts_x_max ? : MAX_12BIT; - y_max = pdata->ts_y_max ? : MAX_12BIT; - p_max = pdata->ts_pressure_max ? : MAX_12BIT; - ts->x_plate_ohm = pdata->ts_x_plate_ohm ? : 280; - ts->esd_timeout = pdata->esd_timeout_ms; - ts->set_reset = pdata->set_reset; + spi->mode = SPI_MODE_0; + spi->bits_per_word = 8; + if (!spi->max_speed_hz) + spi->max_speed_hz = TSC2005_SPI_MAX_SPEED_HZ; - ts->idev = input_allocate_device(); - if (ts->idev == NULL) - return -ENOMEM; - ts->idev->name = "TSC2005 touchscreen"; - snprintf(ts->phys, sizeof(ts->phys), "%s/input-ts", - dev_name(&ts->spi->dev)); - ts->idev->phys = ts->phys; - ts->idev->id.bustype = BUS_SPI; - ts->idev->dev.parent = &ts->spi->dev; - ts->idev->evbit[0] = BIT(EV_ABS) | BIT(EV_KEY); - ts->idev->absbit[0] = BIT(ABS_X) | BIT(ABS_Y) | BIT(ABS_PRESSURE); - ts->idev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH); - - input_set_abs_params(ts->idev, ABS_X, 0, x_max, fudge_x, 0); - input_set_abs_params(ts->idev, ABS_Y, 0, y_max, fudge_y, 0); - input_set_abs_params(ts->idev, ABS_PRESSURE, 0, p_max, fudge_p, 0); - - r = request_threaded_irq(ts->spi->irq, tsc2005_irq_handler, - tsc2005_irq_thread, IRQF_TRIGGER_RISING, - "tsc2005", ts); - if (r) { - dev_err(&ts->spi->dev, "request_threaded_irq(): %d\n", r); - goto err1; - } - set_irq_wake(ts->spi->irq, 1); + error = spi_setup(spi); + if (error) + return error; - r = input_register_device(ts->idev); - if (r) { - dev_err(&ts->spi->dev, "input_register_device(): %d\n", r); - goto err2; + ts = kzalloc(sizeof(*ts), GFP_KERNEL); + input_dev = input_allocate_device(); + if (!ts || !input_dev) { + error = -ENOMEM; + goto err_free_mem; } - r = sysfs_create_group(&ts->spi->dev.kobj, &tsc2005_attr_group); - if (r) - dev_warn(&ts->spi->dev, "sysfs entry creation failed: %d\n", r); + ts->spi = spi; + ts->idev = input_dev; + + ts->x_plate_ohm = pdata->ts_x_plate_ohm ? : 280; + ts->esd_timeout = pdata->esd_timeout_ms; + ts->set_reset = pdata->set_reset; - tsc2005_start_scan(ts); + mutex_init(&ts->mutex); - if (!ts->esd_timeout || !ts->set_reset) - goto done; + setup_timer(&ts->penup_timer, tsc2005_penup_timer, (unsigned long)ts); + INIT_WORK(&ts->penup_work, tsc2005_penup_work); - /* start the optional ESD watchdog */ setup_timer(&ts->esd_timer, tsc2005_esd_timer, (unsigned long)ts); INIT_WORK(&ts->esd_work, tsc2005_esd_work); - mod_timer(&ts->esd_timer, - round_jiffies(jiffies + msecs_to_jiffies(ts->esd_timeout))); - -done: - return 0; -err2: - free_irq(ts->spi->irq, ts); - -err1: - input_free_device(ts->idev); - return r; -} - -static int __devinit tsc2005_probe(struct spi_device *spi) -{ - struct tsc2005_platform_data *pdata = spi->dev.platform_data; - struct tsc2005 *ts; - int r; + tsc2005_setup_spi_xfer(ts); - if (spi->irq < 0) { - dev_dbg(&spi->dev, "no irq\n"); - return -ENODEV; + snprintf(ts->phys, sizeof(ts->phys), + "%s/input-ts", dev_name(&spi->dev)); + + input_dev->name = "TSC2005 touchscreen"; + input_dev->phys = ts->phys; + input_dev->id.bustype = BUS_SPI; + input_dev->dev.parent = &spi->dev; + input_dev->evbit[0] = BIT(EV_ABS) | BIT(EV_KEY); + input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH); + + input_set_abs_params(input_dev, ABS_X, 0, max_x, fudge_x, 0); + input_set_abs_params(input_dev, ABS_Y, 0, max_y, fudge_y, 0); + input_set_abs_params(input_dev, ABS_PRESSURE, 0, max_p, fudge_p, 0); + + error = request_threaded_irq(spi->irq, + tsc2005_irq_handler, tsc2005_irq_thread, + IRQF_TRIGGER_RISING, "tsc2005", ts); + if (error) { + dev_err(&spi->dev, "Failed to request irq, err: %d\n", error); + goto err_free_mem; } - if (!pdata) { - dev_dbg(&spi->dev, "no platform data\n"); - return -ENODEV; + spi_set_drvdata(spi, ts); + error = sysfs_create_group(&spi->dev.kobj, &tsc2005_attr_group); + if (error) { + dev_err(&spi->dev, + "Failed to create sysfs attributes, err: %d\n", error); + goto err_clear_drvdata; } - ts = kzalloc(sizeof(*ts), GFP_KERNEL); - if (ts == NULL) - return -ENOMEM; + error = input_register_device(ts->idev); + if (error) { + dev_err(&spi->dev, + "Failed to register input device, err: %d\n", error); + goto err_remove_sysfs; + } - spi_set_drvdata(spi, ts); - ts->spi = spi; - spi->dev.power.power_state = PMSG_ON; - spi->mode = SPI_MODE_0; - spi->bits_per_word = 8; - if (!spi->max_speed_hz) - spi->max_speed_hz = TSC2005_SPI_MAX_SPEED_HZ; - spi_setup(spi); + tsc2005_start_scan(ts); - r = tsc2005_setup(ts, pdata); - if (r) { - kfree(ts); - spi_set_drvdata(spi, NULL); + if (ts->esd_timeout && ts->set_reset) { + /* start the optional ESD watchdog */ + mod_timer(&ts->esd_timer, round_jiffies(jiffies + + msecs_to_jiffies(ts->esd_timeout))); } - return r; + + set_irq_wake(spi->irq, 1); + return 0; + +err_remove_sysfs: + sysfs_remove_group(&spi->dev.kobj, &tsc2005_attr_group); +err_clear_drvdata: + spi_set_drvdata(spi, NULL); + free_irq(spi->irq, ts); +err_free_mem: + input_free_device(input_dev); + kfree(ts); + return error; } static int __devexit tsc2005_remove(struct spi_device *spi) { struct tsc2005 *ts = spi_get_drvdata(spi); + sysfs_remove_group(&ts->spi->dev.kobj, &tsc2005_attr_group); + mutex_lock(&ts->mutex); tsc2005_disable(ts); mutex_unlock(&ts->mutex); @@ -658,7 +654,6 @@ static int __devexit tsc2005_remove(struct spi_device *spi) flush_work(&ts->esd_work); flush_work(&ts->penup_work); - sysfs_remove_group(&ts->spi->dev.kobj, &tsc2005_attr_group); free_irq(ts->spi->irq, ts); input_unregister_device(ts->idev); kfree(ts); -- GitLab From 8dbcc432c2b4adf4ff7183afc5f2b42276b2a987 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Wed, 16 Mar 2011 22:10:37 -0700 Subject: [PATCH 0758/2822] Input: tsc2005 - hide selftest attribute if we can't reset If implementation to perform self-test/reset has not been provided by the platform code hide 'selftest' sysfs attribute instead of returning error when someone tries to use it. Tested-by: Aaro Koskinen Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/tsc2005.c | 46 ++++++++++++++++++----------- 1 file changed, 28 insertions(+), 18 deletions(-) diff --git a/drivers/input/touchscreen/tsc2005.c b/drivers/input/touchscreen/tsc2005.c index de170e9dc54ac..bc7e2f974b7ee 100644 --- a/drivers/input/touchscreen/tsc2005.c +++ b/drivers/input/touchscreen/tsc2005.c @@ -411,13 +411,6 @@ static ssize_t tsc2005_selftest_show(struct device *dev, u16 temp_high_test; unsigned int result; - if (!ts->set_reset) { - dev_warn(&ts->spi->dev, - "unable to selftest: no reset function\n"); - result = 0; - goto out; - } - mutex_lock(&ts->mutex); /* @@ -451,11 +444,38 @@ static ssize_t tsc2005_selftest_show(struct device *dev, mutex_unlock(&ts->mutex); -out: return sprintf(buf, "%u\n", result); } + static DEVICE_ATTR(selftest, S_IRUGO, tsc2005_selftest_show, NULL); +static struct attribute *tsc2005_attrs[] = { + &dev_attr_disable.attr, + &dev_attr_selftest.attr, + NULL +}; + +static mode_t tsc2005_attr_is_visible(struct kobject *kobj, + struct attribute *attr, int n) +{ + struct device *dev = container_of(kobj, struct device, kobj); + struct spi_device *spi = to_spi_device(dev); + struct tsc2005 *ts = spi_get_drvdata(spi); + mode_t mode = attr->mode; + + if (attr == &dev_attr_selftest.attr) { + if (!ts->set_reset) + mode = 0; + } + + return mode; +} + +static const struct attribute_group tsc2005_attr_group = { + .is_visible = tsc2005_attr_is_visible, + .attrs = tsc2005_attrs, +}; + static void tsc2005_esd_timer(unsigned long data) { struct tsc2005 *ts = (struct tsc2005 *)data; @@ -495,16 +515,6 @@ out: mutex_unlock(&ts->mutex); } -static struct attribute *tsc2005_attrs[] = { - &dev_attr_disable.attr, - &dev_attr_selftest.attr, - NULL -}; - -static struct attribute_group tsc2005_attr_group = { - .attrs = tsc2005_attrs, -}; - static void __devinit tsc2005_setup_spi_xfer(struct tsc2005 *ts) { tsc2005_setup_read(&ts->spi_x, TSC2005_REG_X, 0); -- GitLab From c8b6846a7559e64d7ac4ba1ccdba05f3ee2e34e8 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Wed, 16 Mar 2011 22:10:46 -0700 Subject: [PATCH 0759/2822] Input: tsc2005 - use true/false for boolean variables Tested-by: Aaro Koskinen Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/tsc2005.c | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/drivers/input/touchscreen/tsc2005.c b/drivers/input/touchscreen/tsc2005.c index bc7e2f974b7ee..f457cb95b95b2 100644 --- a/drivers/input/touchscreen/tsc2005.c +++ b/drivers/input/touchscreen/tsc2005.c @@ -140,7 +140,8 @@ struct tsc2005 { bool disabled; unsigned int disable_depth; - unsigned int pen_down; + + bool pen_down; void (*set_reset)(bool enable); }; @@ -197,7 +198,7 @@ static void tsc2005_read(struct tsc2005 *ts, u8 reg, u16 *value) struct spi_message msg; struct tsc2005_spi_rd spi_rd = { { 0 }, 0, 0 }; - tsc2005_setup_read(&spi_rd, reg, 1); + tsc2005_setup_read(&spi_rd, reg, true); spi_message_init(&msg); spi_message_add_tail(&spi_rd.spi_xfer, &msg); @@ -214,13 +215,13 @@ static void tsc2005_update_pen_state(struct tsc2005 *ts, input_report_abs(ts->idev, ABS_PRESSURE, pressure); if (!ts->pen_down) { input_report_key(ts->idev, BTN_TOUCH, !!pressure); - ts->pen_down = 1; + ts->pen_down = true; } } else { input_report_abs(ts->idev, ABS_PRESSURE, 0); if (ts->pen_down) { input_report_key(ts->idev, BTN_TOUCH, 0); - ts->pen_down = 0; + ts->pen_down = false; } } input_sync(ts->idev); @@ -429,9 +430,9 @@ static ssize_t tsc2005_selftest_show(struct device *dev, } /* hardware reset */ - ts->set_reset(0); + ts->set_reset(false); usleep_range(100, 500); /* only 10us required */ - ts->set_reset(1); + ts->set_reset(true); tsc2005_enable(ts); /* test that the reset really happened */ @@ -500,10 +501,10 @@ static void tsc2005_esd_work(struct work_struct *work) tsc2005_read(ts, TSC2005_REG_CFR0, &r); if ((r ^ TSC2005_CFR0_INITVALUE) & TSC2005_CFR0_RW_MASK) { dev_info(&ts->spi->dev, "TSC2005 not responding - resetting\n"); - ts->set_reset(0); + ts->set_reset(false); tsc2005_update_pen_state(ts, 0, 0, 0); usleep_range(100, 500); /* only 10us required */ - ts->set_reset(1); + ts->set_reset(true); tsc2005_start_scan(ts); } @@ -517,10 +518,10 @@ out: static void __devinit tsc2005_setup_spi_xfer(struct tsc2005 *ts) { - tsc2005_setup_read(&ts->spi_x, TSC2005_REG_X, 0); - tsc2005_setup_read(&ts->spi_y, TSC2005_REG_Y, 0); - tsc2005_setup_read(&ts->spi_z1, TSC2005_REG_Z1, 0); - tsc2005_setup_read(&ts->spi_z2, TSC2005_REG_Z2, 1); + tsc2005_setup_read(&ts->spi_x, TSC2005_REG_X, false); + tsc2005_setup_read(&ts->spi_y, TSC2005_REG_Y, false); + tsc2005_setup_read(&ts->spi_z1, TSC2005_REG_Z1, false); + tsc2005_setup_read(&ts->spi_z2, TSC2005_REG_Z2, true); spi_message_init(&ts->spi_read_msg); spi_message_add_tail(&ts->spi_x.spi_xfer, &ts->spi_read_msg); -- GitLab From 9a6e180af78247e3a7680460240bb450c39d3a5b Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Wed, 16 Mar 2011 22:10:52 -0700 Subject: [PATCH 0760/2822] Input: tsc2005 - do not use 0 in place of NULL Sparse in unhappy when people use 0 instead of NULL for pointers so let's rework the way we initialize spi_transfer structure in tsc2005_cmd() and tsc2005_write(). Tested-by: Aaro Koskinen Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/tsc2005.c | 36 +++++++++++++---------------- 1 file changed, 16 insertions(+), 20 deletions(-) diff --git a/drivers/input/touchscreen/tsc2005.c b/drivers/input/touchscreen/tsc2005.c index f457cb95b95b2..289057e1b9a29 100644 --- a/drivers/input/touchscreen/tsc2005.c +++ b/drivers/input/touchscreen/tsc2005.c @@ -148,16 +148,13 @@ struct tsc2005 { static void tsc2005_cmd(struct tsc2005 *ts, u8 cmd) { - u8 tx; + u8 tx = TSC2005_CMD | TSC2005_CMD_12BIT | cmd; + struct spi_transfer xfer = { + .tx_buf = &tx, + .len = 1, + .bits_per_word = 8, + }; struct spi_message msg; - struct spi_transfer xfer = { 0 }; - - tx = TSC2005_CMD | TSC2005_CMD_12BIT | cmd; - - xfer.tx_buf = &tx; - xfer.rx_buf = NULL; - xfer.len = 1; - xfer.bits_per_word = 8; spi_message_init(&msg); spi_message_add_tail(&xfer, &msg); @@ -166,17 +163,13 @@ static void tsc2005_cmd(struct tsc2005 *ts, u8 cmd) static void tsc2005_write(struct tsc2005 *ts, u8 reg, u16 value) { - u32 tx; + u32 tx = ((reg | TSC2005_REG_PND0) << 16) | value; + struct spi_transfer xfer = { + .tx_buf = &tx, + .len = 4, + .bits_per_word = 24, + }; struct spi_message msg; - struct spi_transfer xfer = { 0 }; - - tx = (reg | TSC2005_REG_PND0) << 16; - tx |= value; - - xfer.tx_buf = &tx; - xfer.rx_buf = NULL; - xfer.len = 4; - xfer.bits_per_word = 24; spi_message_init(&msg); spi_message_add_tail(&xfer, &msg); @@ -185,6 +178,8 @@ static void tsc2005_write(struct tsc2005 *ts, u8 reg, u16 value) static void tsc2005_setup_read(struct tsc2005_spi_rd *rd, u8 reg, bool last) { + memset(rd, 0, sizeof(*rd)); + rd->spi_tx = (reg | TSC2005_REG_READ) << 16; rd->spi_xfer.tx_buf = &rd->spi_tx; rd->spi_xfer.rx_buf = &rd->spi_rx; @@ -195,14 +190,15 @@ static void tsc2005_setup_read(struct tsc2005_spi_rd *rd, u8 reg, bool last) static void tsc2005_read(struct tsc2005 *ts, u8 reg, u16 *value) { + struct tsc2005_spi_rd spi_rd; struct spi_message msg; - struct tsc2005_spi_rd spi_rd = { { 0 }, 0, 0 }; tsc2005_setup_read(&spi_rd, reg, true); spi_message_init(&msg); spi_message_add_tail(&spi_rd.spi_xfer, &msg); spi_sync(ts->spi, &msg); + *value = spi_rd.spi_rx; } -- GitLab From 80cc2f0c928ddf58051f2809e1c2e7d0172d0291 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Wed, 16 Mar 2011 22:11:08 -0700 Subject: [PATCH 0761/2822] Input: tsc2005 - don't use work for 'pen up' handling We do not need process context to send input events so let's switch to a regular timer. I am going to get rid of taking ts->mutex in tsc2005_irq_thread() later. Tested-by: Aaro Koskinen Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/tsc2005.c | 58 ++++++++++++++--------------- 1 file changed, 27 insertions(+), 31 deletions(-) diff --git a/drivers/input/touchscreen/tsc2005.c b/drivers/input/touchscreen/tsc2005.c index 289057e1b9a29..dc309da59fca3 100644 --- a/drivers/input/touchscreen/tsc2005.c +++ b/drivers/input/touchscreen/tsc2005.c @@ -129,8 +129,8 @@ struct tsc2005 { int in_z1; int in_z2; + spinlock_t lock; struct timer_list penup_timer; - struct work_struct penup_work; unsigned int esd_timeout; struct timer_list esd_timer; @@ -239,11 +239,10 @@ static irqreturn_t tsc2005_irq_handler(int irq, void *dev_id) static irqreturn_t tsc2005_irq_thread(int irq, void *_ts) { struct tsc2005 *ts = _ts; + unsigned long flags; unsigned int pressure; - u32 x; - u32 y; - u32 z1; - u32 z2; + u32 x, y; + u32 z1, z2; mutex_lock(&ts->mutex); @@ -261,46 +260,50 @@ static irqreturn_t tsc2005_irq_thread(int irq, void *_ts) if (unlikely(x > MAX_12BIT || y > MAX_12BIT)) goto out; - /* skip coords if the pressure components are out of range */ + /* Skip reading if the pressure components are out of range */ if (unlikely(z1 == 0 || z2 > MAX_12BIT || z1 >= z2)) goto out; - /* skip point if this is a pen down with the exact same values as + /* + * Skip point if this is a pen down with the exact same values as * the value before pen-up - that implies SPI fed us stale data */ if (!ts->pen_down && - ts->in_x == x && - ts->in_y == y && - ts->in_z1 == z1 && - ts->in_z2 == z2) + ts->in_x == x && ts->in_y == y && + ts->in_z1 == z1 && ts->in_z2 == z2) { goto out; + } - /* At this point we are happy we have a valid and useful reading. - * Remember it for later comparisons. We may now begin downsampling - */ + /* + * At this point we are happy we have a valid and useful reading. + * Remember it for later comparisons. We may now begin downsampling. + */ ts->in_x = x; ts->in_y = y; ts->in_z1 = z1; ts->in_z2 = z2; - /* compute touch pressure resistance using equation #1 */ + /* Compute touch pressure resistance using equation #1 */ pressure = x * (z2 - z1) / z1; pressure = pressure * ts->x_plate_ohm / 4096; if (unlikely(pressure > MAX_12BIT)) goto out; + spin_lock_irqsave(&ts->lock, flags); + tsc2005_update_pen_state(ts, x, y, pressure); /* set the penup timer */ mod_timer(&ts->penup_timer, jiffies + msecs_to_jiffies(TSC2005_PENUP_TIME_MS)); - if (!ts->esd_timeout) - goto out; + if (ts->esd_timeout && ts->set_reset) { + /* update the watchdog timer */ + mod_timer(&ts->esd_timer, round_jiffies(jiffies + + msecs_to_jiffies(ts->esd_timeout))); + } - /* update the watchdog timer */ - mod_timer(&ts->esd_timer, - round_jiffies(jiffies + msecs_to_jiffies(ts->esd_timeout))); + spin_unlock_irqrestore(&ts->lock, flags); out: mutex_unlock(&ts->mutex); @@ -310,17 +313,11 @@ out: static void tsc2005_penup_timer(unsigned long data) { struct tsc2005 *ts = (struct tsc2005 *)data; + unsigned long flags; - schedule_work(&ts->penup_work); -} - -static void tsc2005_penup_work(struct work_struct *work) -{ - struct tsc2005 *ts = container_of(work, struct tsc2005, penup_work); - - mutex_lock(&ts->mutex); + spin_lock_irqsave(&ts->lock, flags); tsc2005_update_pen_state(ts, 0, 0, 0); - mutex_unlock(&ts->mutex); + spin_unlock_irqrestore(&ts->lock, flags); } static void tsc2005_start_scan(struct tsc2005 *ts) @@ -577,8 +574,8 @@ static int __devinit tsc2005_probe(struct spi_device *spi) mutex_init(&ts->mutex); + spin_lock_init(&ts->lock); setup_timer(&ts->penup_timer, tsc2005_penup_timer, (unsigned long)ts); - INIT_WORK(&ts->penup_work, tsc2005_penup_work); setup_timer(&ts->esd_timer, tsc2005_esd_timer, (unsigned long)ts); INIT_WORK(&ts->esd_work, tsc2005_esd_work); @@ -659,7 +656,6 @@ static int __devexit tsc2005_remove(struct spi_device *spi) del_timer_sync(&ts->penup_timer); flush_work(&ts->esd_work); - flush_work(&ts->penup_work); free_irq(ts->spi->irq, ts); input_unregister_device(ts->idev); -- GitLab From dacb650f125c7dc7ead9735d081bc078325b6d23 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Wed, 16 Mar 2011 22:11:14 -0700 Subject: [PATCH 0762/2822] Input: tsc2005 - do not rearm timer in hardirq handler We will most likely rearm it yet again the IRQ thread so doing it here is pointless. Tested-by: Aaro Koskinen Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/tsc2005.c | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/drivers/input/touchscreen/tsc2005.c b/drivers/input/touchscreen/tsc2005.c index dc309da59fca3..7a76533901870 100644 --- a/drivers/input/touchscreen/tsc2005.c +++ b/drivers/input/touchscreen/tsc2005.c @@ -225,17 +225,6 @@ static void tsc2005_update_pen_state(struct tsc2005 *ts, pressure); } -static irqreturn_t tsc2005_irq_handler(int irq, void *dev_id) -{ - struct tsc2005 *ts = dev_id; - - /* update the penup timer only if it's pending */ - mod_timer_pending(&ts->penup_timer, - jiffies + msecs_to_jiffies(TSC2005_PENUP_TIME_MS)); - - return IRQ_WAKE_THREAD; -} - static irqreturn_t tsc2005_irq_thread(int irq, void *_ts) { struct tsc2005 *ts = _ts; @@ -596,8 +585,7 @@ static int __devinit tsc2005_probe(struct spi_device *spi) input_set_abs_params(input_dev, ABS_Y, 0, max_y, fudge_y, 0); input_set_abs_params(input_dev, ABS_PRESSURE, 0, max_p, fudge_p, 0); - error = request_threaded_irq(spi->irq, - tsc2005_irq_handler, tsc2005_irq_thread, + error = request_threaded_irq(spi->irq, NULL, tsc2005_irq_thread, IRQF_TRIGGER_RISING, "tsc2005", ts); if (error) { dev_err(&spi->dev, "Failed to request irq, err: %d\n", error); -- GitLab From 71f80045d48f259ea423bae3c14c2361e010a9ce Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Wed, 16 Mar 2011 22:11:25 -0700 Subject: [PATCH 0763/2822] Input: tsc2005 - handle read errors from SPI layer Tested-by: Aaro Koskinen Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/tsc2005.c | 100 ++++++++++++++++++++++------ 1 file changed, 81 insertions(+), 19 deletions(-) diff --git a/drivers/input/touchscreen/tsc2005.c b/drivers/input/touchscreen/tsc2005.c index 7a76533901870..5a15919ec4c75 100644 --- a/drivers/input/touchscreen/tsc2005.c +++ b/drivers/input/touchscreen/tsc2005.c @@ -146,7 +146,7 @@ struct tsc2005 { void (*set_reset)(bool enable); }; -static void tsc2005_cmd(struct tsc2005 *ts, u8 cmd) +static int tsc2005_cmd(struct tsc2005 *ts, u8 cmd) { u8 tx = TSC2005_CMD | TSC2005_CMD_12BIT | cmd; struct spi_transfer xfer = { @@ -155,13 +155,22 @@ static void tsc2005_cmd(struct tsc2005 *ts, u8 cmd) .bits_per_word = 8, }; struct spi_message msg; + int error; spi_message_init(&msg); spi_message_add_tail(&xfer, &msg); - spi_sync(ts->spi, &msg); + + error = spi_sync(ts->spi, &msg); + if (error) { + dev_err(&ts->spi->dev, "%s: failed, command: %x, error: %d\n", + __func__, cmd, error); + return error; + } + + return 0; } -static void tsc2005_write(struct tsc2005 *ts, u8 reg, u16 value) +static int tsc2005_write(struct tsc2005 *ts, u8 reg, u16 value) { u32 tx = ((reg | TSC2005_REG_PND0) << 16) | value; struct spi_transfer xfer = { @@ -170,10 +179,20 @@ static void tsc2005_write(struct tsc2005 *ts, u8 reg, u16 value) .bits_per_word = 24, }; struct spi_message msg; + int error; spi_message_init(&msg); spi_message_add_tail(&xfer, &msg); - spi_sync(ts->spi, &msg); + + error = spi_sync(ts->spi, &msg); + if (error) { + dev_err(&ts->spi->dev, + "%s: failed, register: %x, value: %x, error: %d\n", + __func__, reg, value, error); + return error; + } + + return 0; } static void tsc2005_setup_read(struct tsc2005_spi_rd *rd, u8 reg, bool last) @@ -188,18 +207,23 @@ static void tsc2005_setup_read(struct tsc2005_spi_rd *rd, u8 reg, bool last) rd->spi_xfer.cs_change = !last; } -static void tsc2005_read(struct tsc2005 *ts, u8 reg, u16 *value) +static int tsc2005_read(struct tsc2005 *ts, u8 reg, u16 *value) { struct tsc2005_spi_rd spi_rd; struct spi_message msg; + int error; tsc2005_setup_read(&spi_rd, reg, true); spi_message_init(&msg); spi_message_add_tail(&spi_rd.spi_xfer, &msg); - spi_sync(ts->spi, &msg); + + error = spi_sync(ts->spi, &msg); + if (error) + return error; *value = spi_rd.spi_rx; + return 0; } static void tsc2005_update_pen_state(struct tsc2005 *ts, @@ -232,6 +256,7 @@ static irqreturn_t tsc2005_irq_thread(int irq, void *_ts) unsigned int pressure; u32 x, y; u32 z1, z2; + int error; mutex_lock(&ts->mutex); @@ -239,7 +264,10 @@ static irqreturn_t tsc2005_irq_thread(int irq, void *_ts) goto out; /* read the coordinates */ - spi_sync(ts->spi, &ts->spi_read_msg); + error = spi_sync(ts->spi, &ts->spi_read_msg); + if (unlikely(error)) + goto out; + x = ts->spi_x.spi_rx; y = ts->spi_y.spi_rx; z1 = ts->spi_z1.spi_rx; @@ -392,7 +420,8 @@ static ssize_t tsc2005_selftest_show(struct device *dev, u16 temp_high; u16 temp_high_orig; u16 temp_high_test; - unsigned int result; + bool success = true; + int error; mutex_lock(&ts->mutex); @@ -400,34 +429,65 @@ static ssize_t tsc2005_selftest_show(struct device *dev, * Test TSC2005 communications via temp high register. */ tsc2005_disable(ts); - result = 1; - tsc2005_read(ts, TSC2005_REG_TEMP_HIGH, &temp_high_orig); + + error = tsc2005_read(ts, TSC2005_REG_TEMP_HIGH, &temp_high_orig); + if (error) { + dev_warn(dev, "selftest failed: read error %d\n", error); + success = false; + goto out; + } + temp_high_test = (temp_high_orig - 1) & MAX_12BIT; - tsc2005_write(ts, TSC2005_REG_TEMP_HIGH, temp_high_test); - tsc2005_read(ts, TSC2005_REG_TEMP_HIGH, &temp_high); + + error = tsc2005_write(ts, TSC2005_REG_TEMP_HIGH, temp_high_test); + if (error) { + dev_warn(dev, "selftest failed: write error %d\n", error); + success = false; + goto out; + } + + error = tsc2005_read(ts, TSC2005_REG_TEMP_HIGH, &temp_high); + if (error) { + dev_warn(dev, "selftest failed: read error %d after write\n", + error); + success = false; + goto out; + } + if (temp_high != temp_high_test) { dev_warn(dev, "selftest failed: %d != %d\n", temp_high, temp_high_test); - result = 0; + success = false; } /* hardware reset */ ts->set_reset(false); usleep_range(100, 500); /* only 10us required */ ts->set_reset(true); - tsc2005_enable(ts); + + if (!success) + goto out; /* test that the reset really happened */ - tsc2005_read(ts, TSC2005_REG_TEMP_HIGH, &temp_high); + error = tsc2005_read(ts, TSC2005_REG_TEMP_HIGH, &temp_high); + if (error) { + dev_warn(dev, "selftest failed: read error %d after reset\n", + error); + success = false; + goto out; + } + if (temp_high != temp_high_orig) { dev_warn(dev, "selftest failed after reset: %d != %d\n", temp_high, temp_high_orig); - result = 0; + success = false; } +out: + tsc2005_enable(ts); mutex_unlock(&ts->mutex); - return sprintf(buf, "%u\n", result); + return sprintf(buf, "%d\n", success); } static DEVICE_ATTR(selftest, S_IRUGO, tsc2005_selftest_show, NULL); @@ -469,6 +529,7 @@ static void tsc2005_esd_timer(unsigned long data) static void tsc2005_esd_work(struct work_struct *work) { struct tsc2005 *ts = container_of(work, struct tsc2005, esd_work); + int error; u16 r; mutex_lock(&ts->mutex); @@ -480,8 +541,9 @@ static void tsc2005_esd_work(struct work_struct *work) * If we cannot read our known value from configuration register 0 then * reset the controller as if from power-up and start scanning again. */ - tsc2005_read(ts, TSC2005_REG_CFR0, &r); - if ((r ^ TSC2005_CFR0_INITVALUE) & TSC2005_CFR0_RW_MASK) { + error = tsc2005_read(ts, TSC2005_REG_CFR0, &r); + if (error || + ((r ^ TSC2005_CFR0_INITVALUE) & TSC2005_CFR0_RW_MASK)) { dev_info(&ts->spi->dev, "TSC2005 not responding - resetting\n"); ts->set_reset(false); tsc2005_update_pen_state(ts, 0, 0, 0); -- GitLab From 0b950d3d7ce4c1e870b8efc4ae0faaf0ef53532c Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Wed, 16 Mar 2011 22:11:34 -0700 Subject: [PATCH 0764/2822] Input: tsc2005 - add open/close Introduce open and close methods for the input device to keep the device powered down when it is not in use. Also rework interaction between interrupt thread and starting/shutting off/resetting the device: instead of taking a mutex in the intterrupt thread and elsewhere disable interrupts before transitioning the device in a new state. The ESD handling is also separated from the IRQ thread; we poll regularly at a given interval and simply skip reads if we see that valid interrupt happened not so long ago. This allows us not cancel and reschedule ESD work from interrupt context all the time. Tested-by: Aaro Koskinen Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/tsc2005.c | 218 ++++++++++++++++------------ 1 file changed, 124 insertions(+), 94 deletions(-) diff --git a/drivers/input/touchscreen/tsc2005.c b/drivers/input/touchscreen/tsc2005.c index 5a15919ec4c75..3e1c9c297f330 100644 --- a/drivers/input/touchscreen/tsc2005.c +++ b/drivers/input/touchscreen/tsc2005.c @@ -133,13 +133,14 @@ struct tsc2005 { struct timer_list penup_timer; unsigned int esd_timeout; - struct timer_list esd_timer; - struct work_struct esd_work; + struct delayed_work esd_work; + unsigned long last_valid_interrupt; unsigned int x_plate_ohm; bool disabled; - unsigned int disable_depth; + bool opened; + bool suspended; bool pen_down; @@ -258,11 +259,6 @@ static irqreturn_t tsc2005_irq_thread(int irq, void *_ts) u32 z1, z2; int error; - mutex_lock(&ts->mutex); - - if (unlikely(ts->disable_depth)) - goto out; - /* read the coordinates */ error = spi_sync(ts->spi, &ts->spi_read_msg); if (unlikely(error)) @@ -309,21 +305,13 @@ static irqreturn_t tsc2005_irq_thread(int irq, void *_ts) spin_lock_irqsave(&ts->lock, flags); tsc2005_update_pen_state(ts, x, y, pressure); - - /* set the penup timer */ mod_timer(&ts->penup_timer, jiffies + msecs_to_jiffies(TSC2005_PENUP_TIME_MS)); - if (ts->esd_timeout && ts->set_reset) { - /* update the watchdog timer */ - mod_timer(&ts->esd_timer, round_jiffies(jiffies + - msecs_to_jiffies(ts->esd_timeout))); - } - spin_unlock_irqrestore(&ts->lock, flags); + ts->last_valid_interrupt = jiffies; out: - mutex_unlock(&ts->mutex); return IRQ_HANDLED; } @@ -350,29 +338,31 @@ static void tsc2005_stop_scan(struct tsc2005 *ts) tsc2005_cmd(ts, TSC2005_CMD_STOP); } -/* must be called with mutex held */ -static void tsc2005_disable(struct tsc2005 *ts) +/* must be called with ts->mutex held */ +static void __tsc2005_disable(struct tsc2005 *ts) { - if (ts->disable_depth++ != 0) - return; + tsc2005_stop_scan(ts); + disable_irq(ts->spi->irq); - if (ts->esd_timeout) - del_timer_sync(&ts->esd_timer); del_timer_sync(&ts->penup_timer); - tsc2005_stop_scan(ts); + + cancel_delayed_work_sync(&ts->esd_work); + + enable_irq(ts->spi->irq); } -/* must be called with mutex held */ -static void tsc2005_enable(struct tsc2005 *ts) +/* must be called with ts->mutex held */ +static void __tsc2005_enable(struct tsc2005 *ts) { - if (--ts->disable_depth != 0) - return; tsc2005_start_scan(ts); - enable_irq(ts->spi->irq); - if (!ts->esd_timeout) - return; - mod_timer(&ts->esd_timer, - round_jiffies(jiffies + msecs_to_jiffies(ts->esd_timeout))); + + if (ts->esd_timeout && ts->set_reset) { + ts->last_valid_interrupt = jiffies; + schedule_delayed_work(&ts->esd_work, + round_jiffies(jiffies + + msecs_to_jiffies(ts->esd_timeout))); + } + } static ssize_t tsc2005_disable_show(struct device *dev, @@ -390,23 +380,29 @@ static ssize_t tsc2005_disable_store(struct device *dev, { struct spi_device *spi = to_spi_device(dev); struct tsc2005 *ts = spi_get_drvdata(spi); - unsigned long res; - int i; + unsigned long val; + int error; - if (strict_strtoul(buf, 10, &res) < 0) - return -EINVAL; - i = res ? 1 : 0; + error = strict_strtoul(buf, 10, &val); + if (error) + return error; mutex_lock(&ts->mutex); - if (i == ts->disabled) - goto out; - ts->disabled = i; - if (i) - tsc2005_disable(ts); - else - tsc2005_enable(ts); -out: + + if (!ts->suspended && ts->opened) { + if (val) { + if (!ts->disabled) + __tsc2005_disable(ts); + } else { + if (ts->disabled) + __tsc2005_enable(ts); + } + } + + ts->disabled = !!val; + mutex_unlock(&ts->mutex); + return count; } static DEVICE_ATTR(disable, 0664, tsc2005_disable_show, tsc2005_disable_store); @@ -428,7 +424,7 @@ static ssize_t tsc2005_selftest_show(struct device *dev, /* * Test TSC2005 communications via temp high register. */ - tsc2005_disable(ts); + __tsc2005_disable(ts); error = tsc2005_read(ts, TSC2005_REG_TEMP_HIGH, &temp_high_orig); if (error) { @@ -484,7 +480,7 @@ static ssize_t tsc2005_selftest_show(struct device *dev, } out: - tsc2005_enable(ts); + __tsc2005_enable(ts); mutex_unlock(&ts->mutex); return sprintf(buf, "%d\n", success); @@ -519,44 +515,79 @@ static const struct attribute_group tsc2005_attr_group = { .attrs = tsc2005_attrs, }; -static void tsc2005_esd_timer(unsigned long data) -{ - struct tsc2005 *ts = (struct tsc2005 *)data; - - schedule_work(&ts->esd_work); -} - static void tsc2005_esd_work(struct work_struct *work) { - struct tsc2005 *ts = container_of(work, struct tsc2005, esd_work); + struct tsc2005 *ts = container_of(work, struct tsc2005, esd_work.work); int error; u16 r; mutex_lock(&ts->mutex); - if (ts->disable_depth) + if (time_is_after_jiffies(ts->last_valid_interrupt + + msecs_to_jiffies(ts->esd_timeout))) goto out; - /* - * If we cannot read our known value from configuration register 0 then - * reset the controller as if from power-up and start scanning again. - */ + /* We should be able to read register without disabling interrupts. */ error = tsc2005_read(ts, TSC2005_REG_CFR0, &r); - if (error || - ((r ^ TSC2005_CFR0_INITVALUE) & TSC2005_CFR0_RW_MASK)) { - dev_info(&ts->spi->dev, "TSC2005 not responding - resetting\n"); - ts->set_reset(false); - tsc2005_update_pen_state(ts, 0, 0, 0); - usleep_range(100, 500); /* only 10us required */ - ts->set_reset(true); - tsc2005_start_scan(ts); + if (!error && + !((r ^ TSC2005_CFR0_INITVALUE) & TSC2005_CFR0_RW_MASK)) { + goto out; } - /* re-arm the watchdog */ - mod_timer(&ts->esd_timer, - round_jiffies(jiffies + msecs_to_jiffies(ts->esd_timeout))); + /* + * If we could not read our known value from configuration register 0 + * then we should reset the controller as if from power-up and start + * scanning again. + */ + dev_info(&ts->spi->dev, "TSC2005 not responding - resetting\n"); + + disable_irq(ts->spi->irq); + del_timer_sync(&ts->penup_timer); + + tsc2005_update_pen_state(ts, 0, 0, 0); + + ts->set_reset(false); + usleep_range(100, 500); /* only 10us required */ + ts->set_reset(true); + + enable_irq(ts->spi->irq); + tsc2005_start_scan(ts); out: + /* re-arm the watchdog */ + schedule_delayed_work(&ts->esd_work, + round_jiffies(jiffies + + msecs_to_jiffies(ts->esd_timeout))); + mutex_unlock(&ts->mutex); +} + +static int tsc2005_open(struct input_dev *input) +{ + struct tsc2005 *ts = input_get_drvdata(input); + + mutex_lock(&ts->mutex); + + if (!ts->suspended && !ts->disabled) + __tsc2005_enable(ts); + + ts->opened = true; + + mutex_unlock(&ts->mutex); + + return 0; +} + +static void tsc2005_close(struct input_dev *input) +{ + struct tsc2005 *ts = input_get_drvdata(input); + + mutex_lock(&ts->mutex); + + if (!ts->suspended && !ts->disabled) + __tsc2005_disable(ts); + + ts->opened = false; + mutex_unlock(&ts->mutex); } @@ -628,8 +659,7 @@ static int __devinit tsc2005_probe(struct spi_device *spi) spin_lock_init(&ts->lock); setup_timer(&ts->penup_timer, tsc2005_penup_timer, (unsigned long)ts); - setup_timer(&ts->esd_timer, tsc2005_esd_timer, (unsigned long)ts); - INIT_WORK(&ts->esd_work, tsc2005_esd_work); + INIT_DELAYED_WORK(&ts->esd_work, tsc2005_esd_work); tsc2005_setup_spi_xfer(ts); @@ -647,6 +677,14 @@ static int __devinit tsc2005_probe(struct spi_device *spi) input_set_abs_params(input_dev, ABS_Y, 0, max_y, fudge_y, 0); input_set_abs_params(input_dev, ABS_PRESSURE, 0, max_p, fudge_p, 0); + input_dev->open = tsc2005_open; + input_dev->close = tsc2005_close; + + input_set_drvdata(input_dev, ts); + + /* Ensure the touchscreen is off */ + tsc2005_stop_scan(ts); + error = request_threaded_irq(spi->irq, NULL, tsc2005_irq_thread, IRQF_TRIGGER_RISING, "tsc2005", ts); if (error) { @@ -669,14 +707,6 @@ static int __devinit tsc2005_probe(struct spi_device *spi) goto err_remove_sysfs; } - tsc2005_start_scan(ts); - - if (ts->esd_timeout && ts->set_reset) { - /* start the optional ESD watchdog */ - mod_timer(&ts->esd_timer, round_jiffies(jiffies + - msecs_to_jiffies(ts->esd_timeout))); - } - set_irq_wake(spi->irq, 1); return 0; @@ -697,16 +727,6 @@ static int __devexit tsc2005_remove(struct spi_device *spi) sysfs_remove_group(&ts->spi->dev.kobj, &tsc2005_attr_group); - mutex_lock(&ts->mutex); - tsc2005_disable(ts); - mutex_unlock(&ts->mutex); - - if (ts->esd_timeout) - del_timer_sync(&ts->esd_timer); - del_timer_sync(&ts->penup_timer); - - flush_work(&ts->esd_work); - free_irq(ts->spi->irq, ts); input_unregister_device(ts->idev); kfree(ts); @@ -722,7 +742,12 @@ static int tsc2005_suspend(struct device *dev) struct tsc2005 *ts = spi_get_drvdata(spi); mutex_lock(&ts->mutex); - tsc2005_disable(ts); + + if (!ts->suspended && !ts->disabled && ts->opened) + __tsc2005_disable(ts); + + ts->suspended = true; + mutex_unlock(&ts->mutex); return 0; @@ -734,7 +759,12 @@ static int tsc2005_resume(struct device *dev) struct tsc2005 *ts = spi_get_drvdata(spi); mutex_lock(&ts->mutex); - tsc2005_enable(ts); + + if (ts->suspended && !ts->disabled && ts->opened) + __tsc2005_enable(ts); + + ts->suspended = false; + mutex_unlock(&ts->mutex); return 0; -- GitLab From 5cb81d19bae47adcb073a5e5a3bc40dd252f239e Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Wed, 16 Mar 2011 22:11:41 -0700 Subject: [PATCH 0765/2822] Input: tsc2005 - remove 'disable' sysfs attribute I believe that enable/disable functionality should not be implemented on the individual driver level but rather in device core, potentially reusing parts of PM framework. Therefore the driver-specific "disable" attribute is removed from the mainline driver. Tested-by: Aaro Koskinen Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/tsc2005.c | 52 +++-------------------------- 1 file changed, 4 insertions(+), 48 deletions(-) diff --git a/drivers/input/touchscreen/tsc2005.c b/drivers/input/touchscreen/tsc2005.c index 3e1c9c297f330..87420616efa49 100644 --- a/drivers/input/touchscreen/tsc2005.c +++ b/drivers/input/touchscreen/tsc2005.c @@ -138,7 +138,6 @@ struct tsc2005 { unsigned int x_plate_ohm; - bool disabled; bool opened; bool suspended; @@ -365,48 +364,6 @@ static void __tsc2005_enable(struct tsc2005 *ts) } -static ssize_t tsc2005_disable_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct spi_device *spi = to_spi_device(dev); - struct tsc2005 *ts = spi_get_drvdata(spi); - - return sprintf(buf, "%u\n", ts->disabled); -} - -static ssize_t tsc2005_disable_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct spi_device *spi = to_spi_device(dev); - struct tsc2005 *ts = spi_get_drvdata(spi); - unsigned long val; - int error; - - error = strict_strtoul(buf, 10, &val); - if (error) - return error; - - mutex_lock(&ts->mutex); - - if (!ts->suspended && ts->opened) { - if (val) { - if (!ts->disabled) - __tsc2005_disable(ts); - } else { - if (ts->disabled) - __tsc2005_enable(ts); - } - } - - ts->disabled = !!val; - - mutex_unlock(&ts->mutex); - - return count; -} -static DEVICE_ATTR(disable, 0664, tsc2005_disable_show, tsc2005_disable_store); - static ssize_t tsc2005_selftest_show(struct device *dev, struct device_attribute *attr, char *buf) @@ -489,7 +446,6 @@ out: static DEVICE_ATTR(selftest, S_IRUGO, tsc2005_selftest_show, NULL); static struct attribute *tsc2005_attrs[] = { - &dev_attr_disable.attr, &dev_attr_selftest.attr, NULL }; @@ -567,7 +523,7 @@ static int tsc2005_open(struct input_dev *input) mutex_lock(&ts->mutex); - if (!ts->suspended && !ts->disabled) + if (!ts->suspended) __tsc2005_enable(ts); ts->opened = true; @@ -583,7 +539,7 @@ static void tsc2005_close(struct input_dev *input) mutex_lock(&ts->mutex); - if (!ts->suspended && !ts->disabled) + if (!ts->suspended) __tsc2005_disable(ts); ts->opened = false; @@ -743,7 +699,7 @@ static int tsc2005_suspend(struct device *dev) mutex_lock(&ts->mutex); - if (!ts->suspended && !ts->disabled && ts->opened) + if (!ts->suspended && ts->opened) __tsc2005_disable(ts); ts->suspended = true; @@ -760,7 +716,7 @@ static int tsc2005_resume(struct device *dev) mutex_lock(&ts->mutex); - if (ts->suspended && !ts->disabled && ts->opened) + if (ts->suspended && ts->opened) __tsc2005_enable(ts); ts->suspended = false; -- GitLab From 9b6096a65f99a89dfd8328c4e469e7b53b3ae04a Mon Sep 17 00:00:00 2001 From: Shaohua Li Date: Thu, 17 Mar 2011 10:47:06 +0100 Subject: [PATCH 0766/2822] mm: make generic_writepages() use plugging This recovers a performance regression caused by the removal of the per-device plugging. Signed-off-by: Jens Axboe --- mm/page-writeback.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/mm/page-writeback.c b/mm/page-writeback.c index cc0ede169e41d..24b7ac2bc36b5 100644 --- a/mm/page-writeback.c +++ b/mm/page-writeback.c @@ -1039,11 +1039,17 @@ static int __writepage(struct page *page, struct writeback_control *wbc, int generic_writepages(struct address_space *mapping, struct writeback_control *wbc) { + struct blk_plug plug; + int ret; + /* deal with chardevs and other special file */ if (!mapping->a_ops->writepage) return 0; - return write_cache_pages(mapping, wbc, __writepage, mapping); + blk_start_plug(&plug); + ret = write_cache_pages(mapping, wbc, __writepage, mapping); + blk_finish_plug(&plug); + return ret; } EXPORT_SYMBOL(generic_writepages); -- GitLab From 4ee2491ed8569f370bf4c1a4c046a6efb8032bd2 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Thu, 17 Mar 2011 10:51:40 +0100 Subject: [PATCH 0767/2822] fs: make fsync_buffers_list() plug It used WRITE_SYNC_PLUG before and potentially submits a batch of IO, so lets enable plugging for this case. Signed-off-by: Jens Axboe --- fs/buffer.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/fs/buffer.c b/fs/buffer.c index 42534f67d71b2..2e6b1a387b7eb 100644 --- a/fs/buffer.c +++ b/fs/buffer.c @@ -743,8 +743,10 @@ static int fsync_buffers_list(spinlock_t *lock, struct list_head *list) struct list_head tmp; struct address_space *mapping; int err = 0, err2; + struct blk_plug plug; INIT_LIST_HEAD(&tmp); + blk_start_plug(&plug); spin_lock(lock); while (!list_empty(list)) { @@ -781,6 +783,10 @@ static int fsync_buffers_list(spinlock_t *lock, struct list_head *list) } } + spin_unlock(lock); + blk_finish_plug(&plug); + spin_lock(lock); + while (!list_empty(&tmp)) { bh = BH_ENTRY(tmp.prev); get_bh(bh); -- GitLab From 65ab80279d7c323ce151e858d951e2684df72a97 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Thu, 17 Mar 2011 10:56:45 +0100 Subject: [PATCH 0768/2822] jbd: finish conversion from WRITE_SYNC_PLUG to WRITE_SYNC and explicit plugging 'write_op' was still used, even though it was always WRITE_SYNC now. Add plugging around the cases where it submits IO, and flush them before we end up waiting for that IO. Signed-off-by: Jens Axboe --- fs/jbd/commit.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/fs/jbd/commit.c b/fs/jbd/commit.c index 66be299acb1b8..da871ee084d36 100644 --- a/fs/jbd/commit.c +++ b/fs/jbd/commit.c @@ -20,6 +20,7 @@ #include #include #include +#include /* * Default IO end handler for temporary BJ_IO buffer_heads. @@ -294,7 +295,7 @@ void journal_commit_transaction(journal_t *journal) int first_tag = 0; int tag_flag; int i; - int write_op = WRITE_SYNC; + struct blk_plug plug; /* * First job: lock down the current transaction and wait for @@ -327,13 +328,6 @@ void journal_commit_transaction(journal_t *journal) spin_lock(&journal->j_state_lock); commit_transaction->t_state = T_LOCKED; - /* - * Use plugged writes here, since we want to submit several before - * we unplug the device. We don't do explicit unplugging in here, - * instead we rely on sync_buffer() doing the unplug for us. - */ - if (commit_transaction->t_synchronous_commit) - write_op = WRITE_SYNC; spin_lock(&commit_transaction->t_handle_lock); while (commit_transaction->t_updates) { DEFINE_WAIT(wait); @@ -418,8 +412,10 @@ void journal_commit_transaction(journal_t *journal) * Now start flushing things to disk, in the order they appear * on the transaction lists. Data blocks go first. */ + blk_start_plug(&plug); err = journal_submit_data_buffers(journal, commit_transaction, - write_op); + WRITE_SYNC); + blk_finish_plug(&plug); /* * Wait for all previously submitted IO to complete. @@ -480,7 +476,9 @@ void journal_commit_transaction(journal_t *journal) err = 0; } - journal_write_revoke_records(journal, commit_transaction, write_op); + blk_start_plug(&plug); + + journal_write_revoke_records(journal, commit_transaction, WRITE_SYNC); /* * If we found any dirty or locked buffers, then we should have @@ -650,7 +648,7 @@ start_journal_io: clear_buffer_dirty(bh); set_buffer_uptodate(bh); bh->b_end_io = journal_end_buffer_io_sync; - submit_bh(write_op, bh); + submit_bh(WRITE_SYNC, bh); } cond_resched(); @@ -661,6 +659,8 @@ start_journal_io: } } + blk_finish_plug(&plug); + /* Lo and behold: we have just managed to send a transaction to the log. Before we can commit it, wait for the IO so far to complete. Control buffers being written are on the -- GitLab From 82f04ab47e1d94d78503591a7460b2cad9601ede Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Thu, 17 Mar 2011 11:01:52 +0100 Subject: [PATCH 0769/2822] jbd2: finish conversion from WRITE_SYNC_PLUG to WRITE_SYNC and explicit plugging 'write_op' was still used, even though it was always WRITE_SYNC now. Add plugging around the cases where it submits IO, and flush them before we end up waiting for that IO. Signed-off-by: Jens Axboe --- fs/jbd2/commit.c | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/fs/jbd2/commit.c b/fs/jbd2/commit.c index 3da1cc4346d5e..fa36d7662b217 100644 --- a/fs/jbd2/commit.c +++ b/fs/jbd2/commit.c @@ -329,7 +329,7 @@ void jbd2_journal_commit_transaction(journal_t *journal) int tag_bytes = journal_tag_bytes(journal); struct buffer_head *cbh = NULL; /* For transactional checksums */ __u32 crc32_sum = ~0; - int write_op = WRITE_SYNC; + struct blk_plug plug; /* * First job: lock down the current transaction and wait for @@ -363,13 +363,6 @@ void jbd2_journal_commit_transaction(journal_t *journal) write_lock(&journal->j_state_lock); commit_transaction->t_state = T_LOCKED; - /* - * Use plugged writes here, since we want to submit several before - * we unplug the device. We don't do explicit unplugging in here, - * instead we rely on sync_buffer() doing the unplug for us. - */ - if (commit_transaction->t_synchronous_commit) - write_op = WRITE_SYNC; trace_jbd2_commit_locking(journal, commit_transaction); stats.run.rs_wait = commit_transaction->t_max_wait; stats.run.rs_locked = jiffies; @@ -469,8 +462,10 @@ void jbd2_journal_commit_transaction(journal_t *journal) if (err) jbd2_journal_abort(journal, err); + blk_start_plug(&plug); jbd2_journal_write_revoke_records(journal, commit_transaction, - write_op); + WRITE_SYNC); + blk_finish_plug(&plug); jbd_debug(3, "JBD: commit phase 2\n"); @@ -497,6 +492,7 @@ void jbd2_journal_commit_transaction(journal_t *journal) err = 0; descriptor = NULL; bufs = 0; + blk_start_plug(&plug); while (commit_transaction->t_buffers) { /* Find the next buffer to be journaled... */ @@ -658,7 +654,7 @@ start_journal_io: clear_buffer_dirty(bh); set_buffer_uptodate(bh); bh->b_end_io = journal_end_buffer_io_sync; - submit_bh(write_op, bh); + submit_bh(WRITE_SYNC, bh); } cond_resched(); stats.run.rs_blocks_logged += bufs; @@ -699,6 +695,8 @@ start_journal_io: __jbd2_journal_abort_hard(journal); } + blk_finish_plug(&plug); + /* Lo and behold: we have just managed to send a transaction to the log. Before we can commit it, wait for the IO so far to complete. Control buffers being written are on the -- GitLab From a91a2785b200864aef2270ed6a3babac7a253a20 Mon Sep 17 00:00:00 2001 From: "Martin K. Petersen" Date: Thu, 17 Mar 2011 11:11:05 +0100 Subject: [PATCH 0770/2822] block: Require subsystems to explicitly allocate bio_set integrity mempool MD and DM create a new bio_set for every metadevice. Each bio_set has an integrity mempool attached regardless of whether the metadevice is capable of passing integrity metadata. This is a waste of memory. Instead we defer the allocation decision to MD and DM since we know at metadevice creation time whether integrity passthrough is needed or not. Automatic integrity mempool allocation can then be removed from bioset_create() and we make an explicit integrity allocation for the fs_bio_set. Signed-off-by: Martin K. Petersen Reported-by: Zdenek Kabelac Acked-by: Mike Snitzer Signed-off-by: Jens Axboe --- drivers/md/dm-table.c | 7 +++++-- drivers/md/dm.c | 12 +++++++++--- drivers/md/dm.h | 2 +- drivers/md/linear.c | 3 +-- drivers/md/md.c | 8 ++++++-- drivers/md/multipath.c | 7 +++++-- drivers/md/raid0.c | 3 +-- drivers/md/raid1.c | 5 ++--- drivers/md/raid10.c | 7 +++++-- fs/bio-integrity.c | 3 +++ fs/bio.c | 6 +++--- 11 files changed, 41 insertions(+), 22 deletions(-) diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c index f50a7b9522579..416d4e258df6d 100644 --- a/drivers/md/dm-table.c +++ b/drivers/md/dm-table.c @@ -55,6 +55,7 @@ struct dm_table { struct dm_target *targets; unsigned discards_supported:1; + unsigned integrity_supported:1; /* * Indicates the rw permissions for the new logical @@ -859,7 +860,7 @@ int dm_table_alloc_md_mempools(struct dm_table *t) return -EINVAL; } - t->mempools = dm_alloc_md_mempools(type); + t->mempools = dm_alloc_md_mempools(type, t->integrity_supported); if (!t->mempools) return -ENOMEM; @@ -935,8 +936,10 @@ static int dm_table_prealloc_integrity(struct dm_table *t, struct mapped_device struct dm_dev_internal *dd; list_for_each_entry(dd, devices, list) - if (bdev_get_integrity(dd->dm_dev.bdev)) + if (bdev_get_integrity(dd->dm_dev.bdev)) { + t->integrity_supported = 1; return blk_integrity_register(dm_disk(md), NULL); + } return 0; } diff --git a/drivers/md/dm.c b/drivers/md/dm.c index d22b9905c1682..88820704a1916 100644 --- a/drivers/md/dm.c +++ b/drivers/md/dm.c @@ -2620,9 +2620,10 @@ int dm_noflush_suspending(struct dm_target *ti) } EXPORT_SYMBOL_GPL(dm_noflush_suspending); -struct dm_md_mempools *dm_alloc_md_mempools(unsigned type) +struct dm_md_mempools *dm_alloc_md_mempools(unsigned type, unsigned integrity) { struct dm_md_mempools *pools = kmalloc(sizeof(*pools), GFP_KERNEL); + unsigned int pool_size = (type == DM_TYPE_BIO_BASED) ? 16 : MIN_IOS; if (!pools) return NULL; @@ -2639,13 +2640,18 @@ struct dm_md_mempools *dm_alloc_md_mempools(unsigned type) if (!pools->tio_pool) goto free_io_pool_and_out; - pools->bs = (type == DM_TYPE_BIO_BASED) ? - bioset_create(16, 0) : bioset_create(MIN_IOS, 0); + pools->bs = bioset_create(pool_size, 0); if (!pools->bs) goto free_tio_pool_and_out; + if (integrity && bioset_integrity_create(pools->bs, pool_size)) + goto free_bioset_and_out; + return pools; +free_bioset_and_out: + bioset_free(pools->bs); + free_tio_pool_and_out: mempool_destroy(pools->tio_pool); diff --git a/drivers/md/dm.h b/drivers/md/dm.h index 0c2dd5f4af765..1aaf16746da86 100644 --- a/drivers/md/dm.h +++ b/drivers/md/dm.h @@ -149,7 +149,7 @@ void dm_kcopyd_exit(void); /* * Mempool operations */ -struct dm_md_mempools *dm_alloc_md_mempools(unsigned type); +struct dm_md_mempools *dm_alloc_md_mempools(unsigned type, unsigned integrity); void dm_free_md_mempools(struct dm_md_mempools *pools); #endif diff --git a/drivers/md/linear.c b/drivers/md/linear.c index 338804f8fb3b0..abfb59a61ede7 100644 --- a/drivers/md/linear.c +++ b/drivers/md/linear.c @@ -210,8 +210,7 @@ static int linear_run (mddev_t *mddev) blk_queue_merge_bvec(mddev->queue, linear_mergeable_bvec); mddev->queue->backing_dev_info.congested_fn = linear_congested; mddev->queue->backing_dev_info.congested_data = mddev; - md_integrity_register(mddev); - return 0; + return md_integrity_register(mddev); } static void free_conf(struct rcu_head *head) diff --git a/drivers/md/md.c b/drivers/md/md.c index 86ba66c0b28a3..1876761f1828f 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -1803,8 +1803,12 @@ int md_integrity_register(mddev_t *mddev) mdname(mddev)); return -EINVAL; } - printk(KERN_NOTICE "md: data integrity on %s enabled\n", - mdname(mddev)); + printk(KERN_NOTICE "md: data integrity enabled on %s\n", mdname(mddev)); + if (bioset_integrity_create(mddev->bio_set, BIO_POOL_SIZE)) { + printk(KERN_ERR "md: failed to create integrity pool for %s\n", + mdname(mddev)); + return -EINVAL; + } return 0; } EXPORT_SYMBOL(md_integrity_register); diff --git a/drivers/md/multipath.c b/drivers/md/multipath.c index 5e694b151c308..c358909909856 100644 --- a/drivers/md/multipath.c +++ b/drivers/md/multipath.c @@ -315,7 +315,7 @@ static int multipath_remove_disk(mddev_t *mddev, int number) p->rdev = rdev; goto abort; } - md_integrity_register(mddev); + err = md_integrity_register(mddev); } abort: @@ -489,7 +489,10 @@ static int multipath_run (mddev_t *mddev) mddev->queue->backing_dev_info.congested_fn = multipath_congested; mddev->queue->backing_dev_info.congested_data = mddev; - md_integrity_register(mddev); + + if (md_integrity_register(mddev)) + goto out_free_conf; + return 0; out_free_conf: diff --git a/drivers/md/raid0.c b/drivers/md/raid0.c index 95916fd6394af..e86bf3682e1e2 100644 --- a/drivers/md/raid0.c +++ b/drivers/md/raid0.c @@ -379,8 +379,7 @@ static int raid0_run(mddev_t *mddev) blk_queue_merge_bvec(mddev->queue, raid0_mergeable_bvec); dump_zones(mddev); - md_integrity_register(mddev); - return 0; + return md_integrity_register(mddev); } static int raid0_stop(mddev_t *mddev) diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c index 8f34ad5c478ba..c2a21ae56d977 100644 --- a/drivers/md/raid1.c +++ b/drivers/md/raid1.c @@ -1132,7 +1132,7 @@ static int raid1_remove_disk(mddev_t *mddev, int number) p->rdev = rdev; goto abort; } - md_integrity_register(mddev); + err = md_integrity_register(mddev); } abort: @@ -2017,8 +2017,7 @@ static int run(mddev_t *mddev) mddev->queue->backing_dev_info.congested_fn = raid1_congested; mddev->queue->backing_dev_info.congested_data = mddev; - md_integrity_register(mddev); - return 0; + return md_integrity_register(mddev); } static int stop(mddev_t *mddev) diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c index c0d0f5f7e407f..f7b62370b3744 100644 --- a/drivers/md/raid10.c +++ b/drivers/md/raid10.c @@ -1188,7 +1188,7 @@ static int raid10_remove_disk(mddev_t *mddev, int number) p->rdev = rdev; goto abort; } - md_integrity_register(mddev); + err = md_integrity_register(mddev); } abort: @@ -2343,7 +2343,10 @@ static int run(mddev_t *mddev) if (conf->near_copies < conf->raid_disks) blk_queue_merge_bvec(mddev->queue, raid10_mergeable_bvec); - md_integrity_register(mddev); + + if (md_integrity_register(mddev)) + goto out_free_conf; + return 0; out_free_conf: diff --git a/fs/bio-integrity.c b/fs/bio-integrity.c index e49cce234c653..9c5e6b2cd11a8 100644 --- a/fs/bio-integrity.c +++ b/fs/bio-integrity.c @@ -761,6 +761,9 @@ int bioset_integrity_create(struct bio_set *bs, int pool_size) { unsigned int max_slab = vecs_to_idx(BIO_MAX_PAGES); + if (bs->bio_integrity_pool) + return 0; + bs->bio_integrity_pool = mempool_create_slab_pool(pool_size, bip_slab[max_slab].slab); diff --git a/fs/bio.c b/fs/bio.c index 5694b756ed019..85e2eabb1f815 100644 --- a/fs/bio.c +++ b/fs/bio.c @@ -1636,9 +1636,6 @@ struct bio_set *bioset_create(unsigned int pool_size, unsigned int front_pad) if (!bs->bio_pool) goto bad; - if (bioset_integrity_create(bs, pool_size)) - goto bad; - if (!biovec_create_pools(bs, pool_size)) return bs; @@ -1682,6 +1679,9 @@ static int __init init_bio(void) if (!fs_bio_set) panic("bio: can't allocate bios\n"); + if (bioset_integrity_create(fs_bio_set, BIO_POOL_SIZE)) + panic("bio: can't create integrity pool\n"); + bio_split_pool = mempool_create_kmalloc_pool(BIO_SPLIT_ENTRIES, sizeof(struct bio_pair)); if (!bio_split_pool) -- GitLab From 95f28604a65b1c40b6c6cd95e58439cd7ded3add Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Thu, 17 Mar 2011 11:13:12 +0100 Subject: [PATCH 0771/2822] fs: assign sb->s_bdi to default_backing_dev_info if the bdi is going away We don't have proper reference counting for this yet, so we run into cases where the device is pulled and we OOPS on flushing the fs data. This happens even though the dirty inodes have already been migrated to the default_backing_dev_info. Reported-by: Torsten Hilbrich Tested-by: Torsten Hilbrich Cc: stable@kernel.org Signed-off-by: Jens Axboe --- fs/super.c | 2 ++ fs/sync.c | 4 ++-- mm/backing-dev.c | 2 +- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/fs/super.c b/fs/super.c index 7e9dd4cc2c011..0d89e93f654e1 100644 --- a/fs/super.c +++ b/fs/super.c @@ -71,6 +71,7 @@ static struct super_block *alloc_super(struct file_system_type *type) #else INIT_LIST_HEAD(&s->s_files); #endif + s->s_bdi = &default_backing_dev_info; INIT_LIST_HEAD(&s->s_instances); INIT_HLIST_BL_HEAD(&s->s_anon); INIT_LIST_HEAD(&s->s_inodes); @@ -1003,6 +1004,7 @@ vfs_kern_mount(struct file_system_type *type, int flags, const char *name, void } BUG_ON(!mnt->mnt_sb); WARN_ON(!mnt->mnt_sb->s_bdi); + WARN_ON(mnt->mnt_sb->s_bdi == &default_backing_dev_info); mnt->mnt_sb->s_flags |= MS_BORN; error = security_sb_kern_mount(mnt->mnt_sb, flags, secdata); diff --git a/fs/sync.c b/fs/sync.c index ba76b9623e7e8..412dc89163d31 100644 --- a/fs/sync.c +++ b/fs/sync.c @@ -33,7 +33,7 @@ static int __sync_filesystem(struct super_block *sb, int wait) * This should be safe, as we require bdi backing to actually * write out data in the first place */ - if (!sb->s_bdi || sb->s_bdi == &noop_backing_dev_info) + if (sb->s_bdi == &noop_backing_dev_info) return 0; if (sb->s_qcop && sb->s_qcop->quota_sync) @@ -79,7 +79,7 @@ EXPORT_SYMBOL_GPL(sync_filesystem); static void sync_one_sb(struct super_block *sb, void *arg) { - if (!(sb->s_flags & MS_RDONLY) && sb->s_bdi) + if (!(sb->s_flags & MS_RDONLY)) __sync_filesystem(sb, *(int *)arg); } /* diff --git a/mm/backing-dev.c b/mm/backing-dev.c index c91e139a652e7..8fe9d34079213 100644 --- a/mm/backing-dev.c +++ b/mm/backing-dev.c @@ -598,7 +598,7 @@ static void bdi_prune_sb(struct backing_dev_info *bdi) spin_lock(&sb_lock); list_for_each_entry(sb, &super_blocks, s_list) { if (sb->s_bdi == bdi) - sb->s_bdi = NULL; + sb->s_bdi = &default_backing_dev_info; } spin_unlock(&sb_lock); } -- GitLab From e1b702cf224df446b4ce0416dfb02858e7cc068b Mon Sep 17 00:00:00 2001 From: Mike Waychison Date: Mon, 14 Mar 2011 23:34:25 -0700 Subject: [PATCH 0772/2822] KBuild: silence "'scripts/unifdef' is up to date." While changing our build system over to use the headers_install target as part of our klibc build, the following message started showing up in our logs: make[2]: `scripts/unifdef' is up to date. It turns out that the build blindly invokes a recursive make on this target, which causes make to emit this message when the target is already up to date. This isn't seen for most targets as the rest of the build relies primarily on the default target and on PHONY targets when invoking make recursively. Silence the above message when building unifdef as part of headers_install by hiding it behind a new PHONY target called "build_unifdef" that has an empty recipe. Signed-off-by: Mike Waychison Acked-by: WANG Cong Signed-off-by: Michal Marek --- Makefile | 2 +- scripts/Makefile | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 2b1e37da2bb59..0bf29dcc66fc8 100644 --- a/Makefile +++ b/Makefile @@ -1022,7 +1022,7 @@ hdr-dst = $(if $(KBUILD_HEADERS), dst=include/asm-$(hdr-arch), dst=include/asm) PHONY += __headers __headers: include/linux/version.h scripts_basic FORCE - $(Q)$(MAKE) $(build)=scripts scripts/unifdef + $(Q)$(MAKE) $(build)=scripts build_unifdef PHONY += headers_install_all headers_install_all: diff --git a/scripts/Makefile b/scripts/Makefile index 2e088109fbd52..fcea26168bca7 100644 --- a/scripts/Makefile +++ b/scripts/Makefile @@ -18,6 +18,11 @@ always := $(hostprogs-y) $(hostprogs-m) # The following hostprogs-y programs are only build on demand hostprogs-y += unifdef +# This target is used internally to avoid "is up to date" messages +PHONY += build_unifdef +build_unifdef: scripts/unifdef FORCE + @: + subdir-$(CONFIG_MODVERSIONS) += genksyms subdir-y += mod subdir-$(CONFIG_SECURITY_SELINUX) += selinux -- GitLab From 00759c0ea0d3b4c918539ddd7cbbfbbb39a38fc7 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Tue, 15 Mar 2011 14:13:47 -0700 Subject: [PATCH 0773/2822] modpost: fix trailing comma Consolidate locations that print a section whitelist into calls to print_section_list(). Fix print_section_list() so that it does not print a trailing comma & space: If the reference is valid then annotate the variable with __init* or __refdata (see linux/init.h) or name the variable: *_template, *_timer, *_sht, *_ops, *_probe, *_probe_one, *_console, becomes: If the reference is valid then annotate the variable with __init* or __refdata (see linux/init.h) or name the variable: *_template, *_timer, *_sht, *_ops, *_probe, *_probe_one, *_console Signed-off-by: Randy Dunlap Signed-off-by: Michal Marek --- scripts/mod/modpost.c | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c index e8fba959fffb4..cd104afcc5f27 100644 --- a/scripts/mod/modpost.c +++ b/scripts/mod/modpost.c @@ -1248,6 +1248,19 @@ static int is_function(Elf_Sym *sym) return -1; } +static void print_section_list(const char * const list[20]) +{ + const char *const *s = list; + + while (*s) { + fprintf(stderr, "%s", *s); + s++; + if (*s) + fprintf(stderr, ", "); + } + fprintf(stderr, "\n"); +} + /* * Print a warning about a section mismatch. * Try to find symbols near it so user can find it. @@ -1304,7 +1317,6 @@ static void report_sec_mismatch(const char *modname, break; case DATA_TO_ANY_INIT: { prl_to = sec2annotation(tosec); - const char *const *s = mismatch->symbol_white_list; fprintf(stderr, "The variable %s references\n" "the %s %s%s%s\n" @@ -1312,9 +1324,7 @@ static void report_sec_mismatch(const char *modname, "variable with __init* or __refdata (see linux/init.h) " "or name the variable:\n", fromsym, to, prl_to, tosym, to_p); - while (*s) - fprintf(stderr, "%s, ", *s++); - fprintf(stderr, "\n"); + print_section_list(mismatch->symbol_white_list); free(prl_to); break; } @@ -1329,7 +1339,6 @@ static void report_sec_mismatch(const char *modname, break; case DATA_TO_ANY_EXIT: { prl_to = sec2annotation(tosec); - const char *const *s = mismatch->symbol_white_list; fprintf(stderr, "The variable %s references\n" "the %s %s%s%s\n" @@ -1337,9 +1346,7 @@ static void report_sec_mismatch(const char *modname, "variable with __exit* (see linux/init.h) or " "name the variable:\n", fromsym, to, prl_to, tosym, to_p); - while (*s) - fprintf(stderr, "%s, ", *s++); - fprintf(stderr, "\n"); + print_section_list(mismatch->symbol_white_list); free(prl_to); break; } -- GitLab From ed3cd4a86562eee79de25b567a00e648cc3dc2bf Mon Sep 17 00:00:00 2001 From: matt mooney Date: Fri, 14 Jan 2011 06:12:24 -0800 Subject: [PATCH 0774/2822] kernel: change to new flag variable Replace EXTRA_CFLAGS with ccflags-y. Signed-off-by: matt mooney Acked-by: WANG Cong Signed-off-by: Michal Marek --- kernel/gcov/Makefile | 2 +- kernel/power/Makefile | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/kernel/gcov/Makefile b/kernel/gcov/Makefile index 3f761001d517e..e97ca59e2520d 100644 --- a/kernel/gcov/Makefile +++ b/kernel/gcov/Makefile @@ -1,3 +1,3 @@ -EXTRA_CFLAGS := -DSRCTREE='"$(srctree)"' -DOBJTREE='"$(objtree)"' +ccflags-y := -DSRCTREE='"$(srctree)"' -DOBJTREE='"$(objtree)"' obj-$(CONFIG_GCOV_KERNEL) := base.o fs.o gcc_3_4.o diff --git a/kernel/power/Makefile b/kernel/power/Makefile index c350e18b53e3f..c5ebc6a906439 100644 --- a/kernel/power/Makefile +++ b/kernel/power/Makefile @@ -1,4 +1,5 @@ -ccflags-$(CONFIG_PM_DEBUG) := -DDEBUG + +ccflags-$(CONFIG_PM_DEBUG) := -DDEBUG obj-$(CONFIG_PM) += main.o obj-$(CONFIG_PM_SLEEP) += console.o -- GitLab From 21f0b311c6c08db6b15fd6299fe6601fec60eeb5 Mon Sep 17 00:00:00 2001 From: matt mooney Date: Fri, 14 Jan 2011 06:12:26 -0800 Subject: [PATCH 0775/2822] arm: change to new flag variables Replace EXTRA_CFLAGS with ccflags-y and EXTRA_AFLAGS with asflags-y. Signed-off-by: matt mooney Acked-by: WANG Cong Signed-off-by: Michal Marek --- arch/arm/boot/compressed/Makefile | 4 ++-- arch/arm/vfp/Makefile | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/arm/boot/compressed/Makefile b/arch/arm/boot/compressed/Makefile index 0a8f748e506ad..0a53b8aa2e3d7 100644 --- a/arch/arm/boot/compressed/Makefile +++ b/arch/arm/boot/compressed/Makefile @@ -80,8 +80,8 @@ ORIG_CFLAGS := $(KBUILD_CFLAGS) KBUILD_CFLAGS = $(subst -pg, , $(ORIG_CFLAGS)) endif -EXTRA_CFLAGS := -fpic -fno-builtin -EXTRA_AFLAGS := -Wa,-march=all +ccflags-y := -fpic -fno-builtin +asflags-y := -Wa,-march=all # Supply ZRELADDR to the decompressor via a linker symbol. ifneq ($(CONFIG_AUTO_ZRELADDR),y) diff --git a/arch/arm/vfp/Makefile b/arch/arm/vfp/Makefile index 39f6d8e1af730..6de73aab01959 100644 --- a/arch/arm/vfp/Makefile +++ b/arch/arm/vfp/Makefile @@ -4,8 +4,8 @@ # Copyright (C) 2001 ARM Limited # -# EXTRA_CFLAGS := -DDEBUG -# EXTRA_AFLAGS := -DDEBUG +# ccflags-y := -DDEBUG +# asflags-y := -DDEBUG KBUILD_AFLAGS :=$(KBUILD_AFLAGS:-msoft-float=-Wa,-mfpu=softvfp+vfp) LDFLAGS +=--no-warn-mismatch -- GitLab From 6ae8f8b8c50f6929fa99a662f6636a63ba76f93e Mon Sep 17 00:00:00 2001 From: matt mooney Date: Fri, 14 Jan 2011 06:12:27 -0800 Subject: [PATCH 0776/2822] h8300: change to new flag variable Replace EXTRA_AFLAGS with asflags-y. Signed-off-by: matt mooney Acked-by: WANG Cong Signed-off-by: Michal Marek --- arch/h8300/boot/compressed/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/h8300/boot/compressed/Makefile b/arch/h8300/boot/compressed/Makefile index d6189e057ed35..6745cb1ffb4f7 100644 --- a/arch/h8300/boot/compressed/Makefile +++ b/arch/h8300/boot/compressed/Makefile @@ -5,7 +5,7 @@ # targets := vmlinux vmlinux.bin vmlinux.bin.gz head.o misc.o piggy.o -EXTRA_AFLAGS := -traditional +asflags-y := -traditional OBJECTS = $(obj)/head.o $(obj)/misc.o -- GitLab From 4800cd8311f8a16a9a9f8515f2793d5761c44c41 Mon Sep 17 00:00:00 2001 From: matt mooney Date: Fri, 14 Jan 2011 06:12:28 -0800 Subject: [PATCH 0777/2822] ia64: change to new flag variables Replace EXTRA_CFLAGS with ccflags-y and EXTRA_AFLAGS with asflags-y. Signed-off-by: matt mooney Acked-by: WANG Cong Signed-off-by: Michal Marek --- arch/ia64/kvm/Makefile | 4 ++-- arch/ia64/sn/kernel/Makefile | 2 +- arch/ia64/sn/kernel/sn2/Makefile | 2 +- arch/ia64/sn/pci/Makefile | 2 +- arch/ia64/sn/pci/pcibr/Makefile | 2 +- arch/ia64/uv/kernel/Makefile | 2 +- 6 files changed, 7 insertions(+), 7 deletions(-) diff --git a/arch/ia64/kvm/Makefile b/arch/ia64/kvm/Makefile index 1089b3e918ace..db3d7c5d10711 100644 --- a/arch/ia64/kvm/Makefile +++ b/arch/ia64/kvm/Makefile @@ -45,8 +45,8 @@ FORCE : $(obj)/$(offsets-file) # Makefile for Kernel-based Virtual Machine module # -EXTRA_CFLAGS += -Ivirt/kvm -Iarch/ia64/kvm/ -EXTRA_AFLAGS += -Ivirt/kvm -Iarch/ia64/kvm/ +ccflags-y := -Ivirt/kvm -Iarch/ia64/kvm/ +asflags-y := -Ivirt/kvm -Iarch/ia64/kvm/ common-objs = $(addprefix ../../../virt/kvm/, kvm_main.o ioapic.o \ coalesced_mmio.o irq_comm.o assigned-dev.o) diff --git a/arch/ia64/sn/kernel/Makefile b/arch/ia64/sn/kernel/Makefile index 0591038735af5..d27df1d45da7b 100644 --- a/arch/ia64/sn/kernel/Makefile +++ b/arch/ia64/sn/kernel/Makefile @@ -7,7 +7,7 @@ # Copyright (C) 1999,2001-2006,2008 Silicon Graphics, Inc. All Rights Reserved. # -EXTRA_CFLAGS += -Iarch/ia64/sn/include +ccflags-y := -Iarch/ia64/sn/include obj-y += setup.o bte.o bte_error.o irq.o mca.o idle.o \ huberror.o io_acpi_init.o io_common.o \ diff --git a/arch/ia64/sn/kernel/sn2/Makefile b/arch/ia64/sn/kernel/sn2/Makefile index 08e6565dc908d..3d09108d42776 100644 --- a/arch/ia64/sn/kernel/sn2/Makefile +++ b/arch/ia64/sn/kernel/sn2/Makefile @@ -9,7 +9,7 @@ # sn2 specific kernel files # -EXTRA_CFLAGS += -Iarch/ia64/sn/include +ccflags-y := -Iarch/ia64/sn/include obj-y += cache.o io.o ptc_deadlock.o sn2_smp.o sn_proc_fs.o \ prominfo_proc.o timer.o timer_interrupt.o sn_hwperf.o diff --git a/arch/ia64/sn/pci/Makefile b/arch/ia64/sn/pci/Makefile index ad4ef34dfe263..df2a901454266 100644 --- a/arch/ia64/sn/pci/Makefile +++ b/arch/ia64/sn/pci/Makefile @@ -7,6 +7,6 @@ # # Makefile for the sn pci general routines. -EXTRA_CFLAGS += -Iarch/ia64/sn/include +ccflags-y := -Iarch/ia64/sn/include obj-y := pci_dma.o tioca_provider.o tioce_provider.o pcibr/ diff --git a/arch/ia64/sn/pci/pcibr/Makefile b/arch/ia64/sn/pci/pcibr/Makefile index 01192d3247dde..396bcae36309a 100644 --- a/arch/ia64/sn/pci/pcibr/Makefile +++ b/arch/ia64/sn/pci/pcibr/Makefile @@ -7,7 +7,7 @@ # # Makefile for the sn2 io routines. -EXTRA_CFLAGS += -Iarch/ia64/sn/include +ccflags-y := -Iarch/ia64/sn/include obj-y += pcibr_dma.o pcibr_reg.o \ pcibr_ate.o pcibr_provider.o diff --git a/arch/ia64/uv/kernel/Makefile b/arch/ia64/uv/kernel/Makefile index 8d92b4684d8e0..124e441d383d8 100644 --- a/arch/ia64/uv/kernel/Makefile +++ b/arch/ia64/uv/kernel/Makefile @@ -7,7 +7,7 @@ # Copyright (C) 2008 Silicon Graphics, Inc. All Rights Reserved. # -EXTRA_CFLAGS += -Iarch/ia64/sn/include +ccflags-y := -Iarch/ia64/sn/include obj-y += setup.o obj-$(CONFIG_IA64_GENERIC) += machvec.o -- GitLab From 9cce34ba6e292f9d33c4f8c151713be1c97b0995 Mon Sep 17 00:00:00 2001 From: matt mooney Date: Fri, 14 Jan 2011 06:12:30 -0800 Subject: [PATCH 0778/2822] microblaze: change to new flag variable Replace EXTRA_CFLAGS with ccflags-y. Signed-off-by: matt mooney Acked-by: WANG Cong Signed-off-by: Michal Marek --- arch/microblaze/kernel/cpu/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/microblaze/kernel/cpu/Makefile b/arch/microblaze/kernel/cpu/Makefile index 59cc7bceaf8c4..fceed4edea419 100644 --- a/arch/microblaze/kernel/cpu/Makefile +++ b/arch/microblaze/kernel/cpu/Makefile @@ -6,7 +6,7 @@ ifdef CONFIG_FUNCTION_TRACER CFLAGS_REMOVE_cache.o = -pg endif -EXTRA_CFLAGS += -DCPU_MAJOR=$(CPU_MAJOR) -DCPU_MINOR=$(CPU_MINOR) \ +ccflags-y := -DCPU_MAJOR=$(CPU_MAJOR) -DCPU_MINOR=$(CPU_MINOR) \ -DCPU_REV=$(CPU_REV) obj-y += cache.o cpuinfo.o cpuinfo-pvr-full.o cpuinfo-static.o mb.o pvr.o -- GitLab From e3726304a242e94a87d7b5427d88427acead7c02 Mon Sep 17 00:00:00 2001 From: matt mooney Date: Fri, 14 Jan 2011 06:12:31 -0800 Subject: [PATCH 0779/2822] mips: change to new flag variable Replace EXTRA_CFLAGS with ccflags-y. Signed-off-by: matt mooney Acked-by: WANG Cong Signed-off-by: Michal Marek --- arch/mips/Makefile | 4 ++-- arch/mips/bcm63xx/boards/Makefile | 2 +- arch/mips/fw/arc/Makefile | 2 +- arch/mips/jz4740/Makefile | 2 +- arch/mips/oprofile/Makefile | 2 +- arch/mips/pmc-sierra/yosemite/Makefile | 2 +- arch/mips/powertv/Makefile | 2 +- arch/mips/powertv/asic/Makefile | 2 +- arch/mips/powertv/pci/Makefile | 2 +- 9 files changed, 10 insertions(+), 10 deletions(-) diff --git a/arch/mips/Makefile b/arch/mips/Makefile index 7c1102e41fe25..ac1d5b611a27d 100644 --- a/arch/mips/Makefile +++ b/arch/mips/Makefile @@ -286,11 +286,11 @@ CLEAN_FILES += vmlinux.32 vmlinux.64 archprepare: ifdef CONFIG_MIPS32_N32 @echo ' Checking missing-syscalls for N32' - $(Q)$(MAKE) $(build)=. missing-syscalls EXTRA_CFLAGS="-mabi=n32" + $(Q)$(MAKE) $(build)=. missing-syscalls ccflags-y="-mabi=n32" endif ifdef CONFIG_MIPS32_O32 @echo ' Checking missing-syscalls for O32' - $(Q)$(MAKE) $(build)=. missing-syscalls EXTRA_CFLAGS="-mabi=32" + $(Q)$(MAKE) $(build)=. missing-syscalls ccflags-y="-mabi=32" endif install: diff --git a/arch/mips/bcm63xx/boards/Makefile b/arch/mips/bcm63xx/boards/Makefile index e5cc86dc1da83..9f64fb4140774 100644 --- a/arch/mips/bcm63xx/boards/Makefile +++ b/arch/mips/bcm63xx/boards/Makefile @@ -1,3 +1,3 @@ obj-$(CONFIG_BOARD_BCM963XX) += board_bcm963xx.o -EXTRA_CFLAGS += -Werror +ccflags-y := -Werror diff --git a/arch/mips/fw/arc/Makefile b/arch/mips/fw/arc/Makefile index e0aaad482b0eb..5314b37aff2c4 100644 --- a/arch/mips/fw/arc/Makefile +++ b/arch/mips/fw/arc/Makefile @@ -9,4 +9,4 @@ lib-$(CONFIG_ARC_MEMORY) += memory.o lib-$(CONFIG_ARC_CONSOLE) += arc_con.o lib-$(CONFIG_ARC_PROMLIB) += promlib.o -EXTRA_CFLAGS += -Werror +ccflags-y := -Werror diff --git a/arch/mips/jz4740/Makefile b/arch/mips/jz4740/Makefile index a604eaeb6c085..a9dff33212518 100644 --- a/arch/mips/jz4740/Makefile +++ b/arch/mips/jz4740/Makefile @@ -17,4 +17,4 @@ obj-$(CONFIG_JZ4740_QI_LB60) += board-qi_lb60.o obj-$(CONFIG_PM) += pm.o -EXTRA_CFLAGS += -Werror -Wall +ccflags-y := -Werror -Wall diff --git a/arch/mips/oprofile/Makefile b/arch/mips/oprofile/Makefile index 02cc65e52d11b..4b9d7044e26c2 100644 --- a/arch/mips/oprofile/Makefile +++ b/arch/mips/oprofile/Makefile @@ -1,4 +1,4 @@ -EXTRA_CFLAGS := -Werror +ccflags-y := -Werror obj-$(CONFIG_OPROFILE) += oprofile.o diff --git a/arch/mips/pmc-sierra/yosemite/Makefile b/arch/mips/pmc-sierra/yosemite/Makefile index b16f95c3df654..02f5fb94ea280 100644 --- a/arch/mips/pmc-sierra/yosemite/Makefile +++ b/arch/mips/pmc-sierra/yosemite/Makefile @@ -6,4 +6,4 @@ obj-y += irq.o prom.o py-console.o setup.o obj-$(CONFIG_SMP) += smp.o -EXTRA_CFLAGS += -Werror +ccflags-y := -Werror diff --git a/arch/mips/powertv/Makefile b/arch/mips/powertv/Makefile index baf6e9092a9f8..348d2e850ef51 100644 --- a/arch/mips/powertv/Makefile +++ b/arch/mips/powertv/Makefile @@ -28,4 +28,4 @@ obj-y += init.o ioremap.o memory.o powertv_setup.o reset.o time.o \ obj-$(CONFIG_USB) += powertv-usb.o -EXTRA_CFLAGS += -Wall +ccflags-y := -Wall diff --git a/arch/mips/powertv/asic/Makefile b/arch/mips/powertv/asic/Makefile index f0e95dc0ac97b..d810a33182a4a 100644 --- a/arch/mips/powertv/asic/Makefile +++ b/arch/mips/powertv/asic/Makefile @@ -20,4 +20,4 @@ obj-y += asic-calliope.o asic-cronus.o asic-gaia.o asic-zeus.o \ asic_devices.o asic_int.o irq_asic.o prealloc-calliope.o \ prealloc-cronus.o prealloc-cronuslite.o prealloc-gaia.o prealloc-zeus.o -EXTRA_CFLAGS += -Wall -Werror +ccflags-y := -Wall -Werror diff --git a/arch/mips/powertv/pci/Makefile b/arch/mips/powertv/pci/Makefile index f5c62462fc9da..5783201cd2c81 100644 --- a/arch/mips/powertv/pci/Makefile +++ b/arch/mips/powertv/pci/Makefile @@ -18,4 +18,4 @@ obj-$(CONFIG_PCI) += fixup-powertv.o -EXTRA_CFLAGS += -Wall -Werror +ccflags-y := -Wall -Werror -- GitLab From c73028a028876f7fd72ec0e114b0226d17e917d3 Mon Sep 17 00:00:00 2001 From: matt mooney Date: Fri, 14 Jan 2011 06:12:32 -0800 Subject: [PATCH 0780/2822] s390: change to new flag variable Replace EXTRA_CFLAGS with ccflags-y. Signed-off-by: matt mooney Acked-by: WANG Cong Signed-off-by: Michal Marek --- arch/s390/boot/Makefile | 2 +- arch/s390/kvm/Makefile | 2 +- arch/s390/math-emu/Makefile | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/s390/boot/Makefile b/arch/s390/boot/Makefile index 8800cf0906947..635d677d3281e 100644 --- a/arch/s390/boot/Makefile +++ b/arch/s390/boot/Makefile @@ -6,7 +6,7 @@ COMPILE_VERSION := __linux_compile_version_id__`hostname | \ tr -c '[0-9A-Za-z]' '_'`__`date | \ tr -c '[0-9A-Za-z]' '_'`_t -EXTRA_CFLAGS := -DCOMPILE_VERSION=$(COMPILE_VERSION) -gstabs -I. +ccflags-y := -DCOMPILE_VERSION=$(COMPILE_VERSION) -gstabs -I. targets := image targets += bzImage diff --git a/arch/s390/kvm/Makefile b/arch/s390/kvm/Makefile index e5221ec0b8e3e..860d26514c08d 100644 --- a/arch/s390/kvm/Makefile +++ b/arch/s390/kvm/Makefile @@ -8,7 +8,7 @@ common-objs = $(addprefix ../../../virt/kvm/, kvm_main.o) -EXTRA_CFLAGS += -Ivirt/kvm -Iarch/s390/kvm +ccflags-y := -Ivirt/kvm -Iarch/s390/kvm kvm-objs := $(common-objs) kvm-s390.o sie64a.o intercept.o interrupt.o priv.o sigp.o diag.o obj-$(CONFIG_KVM) += kvm.o diff --git a/arch/s390/math-emu/Makefile b/arch/s390/math-emu/Makefile index c84890341052c..51d399549f604 100644 --- a/arch/s390/math-emu/Makefile +++ b/arch/s390/math-emu/Makefile @@ -4,4 +4,4 @@ obj-$(CONFIG_MATHEMU) := math.o -EXTRA_CFLAGS := -I$(src) -Iinclude/math-emu -w +ccflags-y := -I$(src) -Iinclude/math-emu -w -- GitLab From 9b8c24fac8f030a3369a8bc6bf990534a7ca6ce8 Mon Sep 17 00:00:00 2001 From: matt mooney Date: Fri, 14 Jan 2011 06:12:33 -0800 Subject: [PATCH 0781/2822] um: change to new flag variables Replace EXTRA_CFLAGS with ccflags-y and EXTRA_AFLAGS with asflags-y. Signed-off-by: matt mooney Acked-by: WANG Cong Signed-off-by: Michal Marek --- arch/um/sys-ppc/Makefile | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/arch/um/sys-ppc/Makefile b/arch/um/sys-ppc/Makefile index b8bc844fd2c46..20d363bd70041 100644 --- a/arch/um/sys-ppc/Makefile +++ b/arch/um/sys-ppc/Makefile @@ -6,7 +6,7 @@ OBJ = built-in.o OBJS = ptrace.o sigcontext.o checksum.o miscthings.o misc.o \ ptrace_user.o sysrq.o -EXTRA_AFLAGS := -DCONFIG_PPC32 -I. -I$(srctree)/arch/ppc/kernel +asflags-y := -DCONFIG_PPC32 -I. -I$(srctree)/arch/ppc/kernel all: $(OBJ) @@ -15,10 +15,10 @@ $(OBJ): $(OBJS) $(LD) $(LINKFLAGS) --start-group $^ --end-group -o $@ ptrace_user.o: ptrace_user.c - $(CC) -D__KERNEL__ $(USER_CFLAGS) $(EXTRA_CFLAGS) -c -o $@ $< + $(CC) -D__KERNEL__ $(USER_CFLAGS) $(ccflags-y) -c -o $@ $< sigcontext.o: sigcontext.c - $(CC) $(USER_CFLAGS) $(EXTRA_CFLAGS) -c -o $@ $< + $(CC) $(USER_CFLAGS) $(ccflags-y) -c -o $@ $< checksum.S: rm -f $@ @@ -53,13 +53,13 @@ ppc_defs.h: mk_defs.c ppc_defs.head \ checksum.o: checksum.S rm -f asm ln -s $(srctree)/include/asm-ppc asm - $(CC) $(EXTRA_AFLAGS) $(KBUILD_AFLAGS) -D__ASSEMBLY__ -D__UM_PPC__ -c $< -o $*.o + $(CC) $(asflags-y) $(KBUILD_AFLAGS) -D__ASSEMBLY__ -D__UM_PPC__ -c $< -o $*.o rm -f asm misc.o: misc.S ppc_defs.h rm -f asm ln -s $(srctree)/include/asm-ppc asm - $(CC) $(EXTRA_AFLAGS) $(KBUILD_AFLAGS) -D__ASSEMBLY__ -D__UM_PPC__ -c $< -o $*.o + $(CC) $(asflags-y) $(KBUILD_AFLAGS) -D__ASSEMBLY__ -D__UM_PPC__ -c $< -o $*.o rm -f asm clean-files := $(OBJS) ppc_defs.h checksum.S mk_defs.c -- GitLab From 3996eabbab5597d27d5140e1d8f9e3f1145f8b40 Mon Sep 17 00:00:00 2001 From: matt mooney Date: Fri, 14 Jan 2011 06:12:34 -0800 Subject: [PATCH 0782/2822] xtensa: change to new flag variable Replace EXTRA_CFLAGS with ccflags-y. Signed-off-by: matt mooney Acked-by: WANG Cong Signed-off-by: Michal Marek --- arch/xtensa/boot/Makefile | 2 +- arch/xtensa/boot/lib/Makefile | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/xtensa/boot/Makefile b/arch/xtensa/boot/Makefile index 40aa55b485be9..70fd1453e172a 100644 --- a/arch/xtensa/boot/Makefile +++ b/arch/xtensa/boot/Makefile @@ -14,7 +14,7 @@ HOSTFLAGS += -Iarch/$(ARCH)/boot/include BIG_ENDIAN := $(shell echo -e __XTENSA_EB__ | $(CC) -E - | grep -v "\#") -export EXTRA_CFLAGS +export ccflags-y export BIG_ENDIAN subdir-y := lib diff --git a/arch/xtensa/boot/lib/Makefile b/arch/xtensa/boot/lib/Makefile index d3d2aa2d883aa..ad8952e8a07f6 100644 --- a/arch/xtensa/boot/lib/Makefile +++ b/arch/xtensa/boot/lib/Makefile @@ -6,7 +6,7 @@ zlib := inffast.c inflate.c inftrees.c lib-y += $(zlib:.c=.o) zmem.o -EXTRA_CFLAGS += -Ilib/zlib_inflate +ccflags-y := -Ilib/zlib_inflate quiet_cmd_copy_zlib = COPY $@ cmd_copy_zlib = cat $< > $@ -- GitLab From 0ccd234ca04b09a156f8771af316ac9de2fa7312 Mon Sep 17 00:00:00 2001 From: matt mooney Date: Fri, 14 Jan 2011 06:12:35 -0800 Subject: [PATCH 0783/2822] fs: change to new flag variable Replace EXTRA_CFLAGS with ccflags-y. And change ntfs-objs to ntfs-y for cleaner conditional inclusion. Signed-off-by: matt mooney Acked-by: WANG Cong Signed-off-by: Michal Marek --- fs/affs/Makefile | 2 +- fs/coda/Makefile | 2 +- fs/gfs2/Makefile | 2 +- fs/jfs/Makefile | 2 +- fs/ncpfs/Makefile | 2 +- fs/ntfs/Makefile | 19 +++++++------------ fs/ocfs2/Makefile | 4 ++-- fs/ocfs2/dlm/Makefile | 2 +- fs/ocfs2/dlmfs/Makefile | 2 +- fs/reiserfs/Makefile | 4 +--- fs/xfs/Makefile | 7 ++----- 11 files changed, 19 insertions(+), 29 deletions(-) diff --git a/fs/affs/Makefile b/fs/affs/Makefile index b2c4f54446f3c..3988b4a78339a 100644 --- a/fs/affs/Makefile +++ b/fs/affs/Makefile @@ -2,7 +2,7 @@ # Makefile for the Linux affs filesystem routines. # -#EXTRA_CFLAGS=-DDEBUG=1 +#ccflags-y := -DDEBUG=1 obj-$(CONFIG_AFFS_FS) += affs.o diff --git a/fs/coda/Makefile b/fs/coda/Makefile index 6c22e61da3977..1bab69a0d3476 100644 --- a/fs/coda/Makefile +++ b/fs/coda/Makefile @@ -9,4 +9,4 @@ coda-objs := psdev.o cache.o cnode.o inode.o dir.o file.o upcall.o \ # If you want debugging output, please uncomment the following line. -# EXTRA_CFLAGS += -DDEBUG -DDEBUG_SMB_MALLOC=1 +# ccflags-y := -DDEBUG -DDEBUG_SMB_MALLOC=1 diff --git a/fs/gfs2/Makefile b/fs/gfs2/Makefile index 21f7e46da4c01..f3d23ef4e876a 100644 --- a/fs/gfs2/Makefile +++ b/fs/gfs2/Makefile @@ -1,4 +1,4 @@ -EXTRA_CFLAGS := -I$(src) +ccflags-y := -I$(src) obj-$(CONFIG_GFS2_FS) += gfs2.o gfs2-y := acl.o bmap.o dir.o xattr.o glock.o \ glops.o inode.o log.o lops.o main.o meta_io.o \ diff --git a/fs/jfs/Makefile b/fs/jfs/Makefile index 3adb6395e42de..a58fa72d7e59e 100644 --- a/fs/jfs/Makefile +++ b/fs/jfs/Makefile @@ -13,4 +13,4 @@ jfs-y := super.o file.o inode.o namei.o jfs_mount.o jfs_umount.o \ jfs-$(CONFIG_JFS_POSIX_ACL) += acl.o -EXTRA_CFLAGS += -D_JFS_4K +ccflags-y := -D_JFS_4K diff --git a/fs/ncpfs/Makefile b/fs/ncpfs/Makefile index 68ea095100a81..c66af563f2cee 100644 --- a/fs/ncpfs/Makefile +++ b/fs/ncpfs/Makefile @@ -11,6 +11,6 @@ ncpfs-$(CONFIG_NCPFS_EXTRAS) += symlink.o ncpfs-$(CONFIG_NCPFS_NFS_NS) += symlink.o # If you want debugging output, please uncomment the following line -# EXTRA_CFLAGS += -DDEBUG_NCP=1 +# ccflags-y := -DDEBUG_NCP=1 CFLAGS_ncplib_kernel.o := -finline-functions diff --git a/fs/ntfs/Makefile b/fs/ntfs/Makefile index 4ff028fcfd6e3..30206b238433b 100644 --- a/fs/ntfs/Makefile +++ b/fs/ntfs/Makefile @@ -2,18 +2,13 @@ obj-$(CONFIG_NTFS_FS) += ntfs.o -ntfs-objs := aops.o attrib.o collate.o compress.o debug.o dir.o file.o \ - index.o inode.o mft.o mst.o namei.o runlist.o super.o sysctl.o \ - unistr.o upcase.o +ntfs-y := aops.o attrib.o collate.o compress.o debug.o dir.o file.o \ + index.o inode.o mft.o mst.o namei.o runlist.o super.o sysctl.o \ + unistr.o upcase.o -EXTRA_CFLAGS = -DNTFS_VERSION=\"2.1.30\" +ntfs-$(CONFIG_NTFS_RW) += bitmap.o lcnalloc.o logfile.o quota.o usnjrnl.o -ifeq ($(CONFIG_NTFS_DEBUG),y) -EXTRA_CFLAGS += -DDEBUG -endif +ccflags-y := -DNTFS_VERSION=\"2.1.30\" +ccflags-$(CONFIG_NTFS_DEBUG) += -DDEBUG +ccflags-$(CONFIG_NTFS_RW) += -DNTFS_RW -ifeq ($(CONFIG_NTFS_RW),y) -EXTRA_CFLAGS += -DNTFS_RW - -ntfs-objs += bitmap.o lcnalloc.o logfile.o quota.o usnjrnl.o -endif diff --git a/fs/ocfs2/Makefile b/fs/ocfs2/Makefile index 07d9fd8543502..d8a0313e99e6a 100644 --- a/fs/ocfs2/Makefile +++ b/fs/ocfs2/Makefile @@ -1,6 +1,6 @@ -EXTRA_CFLAGS += -Ifs/ocfs2 +ccflags-y := -Ifs/ocfs2 -EXTRA_CFLAGS += -DCATCH_BH_JBD_RACES +ccflags-y += -DCATCH_BH_JBD_RACES obj-$(CONFIG_OCFS2_FS) += \ ocfs2.o \ diff --git a/fs/ocfs2/dlm/Makefile b/fs/ocfs2/dlm/Makefile index dcebf0d920fa1..c8a044efbb150 100644 --- a/fs/ocfs2/dlm/Makefile +++ b/fs/ocfs2/dlm/Makefile @@ -1,4 +1,4 @@ -EXTRA_CFLAGS += -Ifs/ocfs2 +ccflags-y := -Ifs/ocfs2 obj-$(CONFIG_OCFS2_FS_O2CB) += ocfs2_dlm.o diff --git a/fs/ocfs2/dlmfs/Makefile b/fs/ocfs2/dlmfs/Makefile index df69b4856d0d8..f14be89a67016 100644 --- a/fs/ocfs2/dlmfs/Makefile +++ b/fs/ocfs2/dlmfs/Makefile @@ -1,4 +1,4 @@ -EXTRA_CFLAGS += -Ifs/ocfs2 +ccflags-y := -Ifs/ocfs2 obj-$(CONFIG_OCFS2_FS) += ocfs2_dlmfs.o diff --git a/fs/reiserfs/Makefile b/fs/reiserfs/Makefile index 792b3cb2cd18a..3c3b00165114c 100644 --- a/fs/reiserfs/Makefile +++ b/fs/reiserfs/Makefile @@ -31,9 +31,7 @@ endif # and causing a panic. Since this behavior only affects ppc32, this ifeq # will work around it. If any other architecture displays this behavior, # add it here. -ifeq ($(CONFIG_PPC32),y) -EXTRA_CFLAGS := $(call cc-ifversion, -lt, 0400, -O1) -endif +ccflags-$(CONFIG_PPC32) := $(call cc-ifversion, -lt, 0400, -O1) TAGS: etags *.c diff --git a/fs/xfs/Makefile b/fs/xfs/Makefile index faca449970995..82b1371775c06 100644 --- a/fs/xfs/Makefile +++ b/fs/xfs/Makefile @@ -16,14 +16,11 @@ # Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # -EXTRA_CFLAGS += -I$(src) -I$(src)/linux-2.6 +ccflags-y := -I$(src) -I$(src)/linux-2.6 +ccflags-$(CONFIG_XFS_DEBUG) += -g XFS_LINUX := linux-2.6 -ifeq ($(CONFIG_XFS_DEBUG),y) - EXTRA_CFLAGS += -g -endif - obj-$(CONFIG_XFS_FS) += xfs.o xfs-y += linux-2.6/xfs_trace.o -- GitLab From 8ec3b8432e4fe8d452f88f1ed9a3450e715bb797 Mon Sep 17 00:00:00 2001 From: matt mooney Date: Fri, 14 Jan 2011 06:12:36 -0800 Subject: [PATCH 0784/2822] char: change to new flag variable Replace EXTRA_CFLAGS with ccflags-y. Signed-off-by: matt mooney Acked-by: WANG Cong Signed-off-by: Michal Marek --- drivers/char/mwave/Makefile | 4 ++-- drivers/char/mwave/README | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/char/mwave/Makefile b/drivers/char/mwave/Makefile index 26b4fce217b64..efa6a82e543dc 100644 --- a/drivers/char/mwave/Makefile +++ b/drivers/char/mwave/Makefile @@ -9,7 +9,7 @@ obj-$(CONFIG_MWAVE) += mwave.o mwave-y := mwavedd.o smapi.o tp3780i.o 3780i.o # To have the mwave driver disable other uarts if necessary -# EXTRA_CFLAGS += -DMWAVE_FUTZ_WITH_OTHER_DEVICES +# ccflags-y := -DMWAVE_FUTZ_WITH_OTHER_DEVICES # To compile in lots (~20 KiB) of run-time enablable printk()s for debugging: -ccflags-y := -DMW_TRACE +ccflags-y += -DMW_TRACE diff --git a/drivers/char/mwave/README b/drivers/char/mwave/README index 480251fc78e28..c2a58f428bc84 100644 --- a/drivers/char/mwave/README +++ b/drivers/char/mwave/README @@ -11,7 +11,7 @@ are not saved by the BIOS and so do not persist after unload and reload. 0x0008 tp3780i tracing Tracing only occurs if the driver has been compiled with the - MW_TRACE macro #defined (i.e. let EXTRA_CFLAGS += -DMW_TRACE + MW_TRACE macro #defined (i.e. let ccflags-y := -DMW_TRACE in the Makefile). mwave_3780i_irq=5/7/10/11/15 -- GitLab From 990710ca5ddf28aef9c34594b3ffe71544e5faa4 Mon Sep 17 00:00:00 2001 From: matt mooney Date: Fri, 14 Jan 2011 06:12:37 -0800 Subject: [PATCH 0785/2822] dma: change to new flag variable Replace EXTRA_CFLAGS with ccflags-y. Signed-off-by: matt mooney Acked-by: WANG Cong Signed-off-by: Michal Marek --- drivers/dma/Makefile | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/drivers/dma/Makefile b/drivers/dma/Makefile index 64b21f5cd740f..1be065a62f8c6 100644 --- a/drivers/dma/Makefile +++ b/drivers/dma/Makefile @@ -1,9 +1,5 @@ -ifeq ($(CONFIG_DMADEVICES_DEBUG),y) - ccflags-y += -DDEBUG -endif -ifeq ($(CONFIG_DMADEVICES_VDEBUG),y) - ccflags-y += -DVERBOSE_DEBUG -endif +ccflags-$(CONFIG_DMADEVICES_DEBUG) := -DDEBUG +ccflags-$(CONFIG_DMADEVICES_VDEBUG) += -DVERBOSE_DEBUG obj-$(CONFIG_DMA_ENGINE) += dmaengine.o obj-$(CONFIG_NET_DMA) += iovlock.o -- GitLab From 5c39e31195f49f6725f04b22921eca2388a3f909 Mon Sep 17 00:00:00 2001 From: matt mooney Date: Fri, 14 Jan 2011 06:12:38 -0800 Subject: [PATCH 0786/2822] hwmon: change to new flag variable Replace EXTRA_CFLAGS with ccflags-y. Signed-off-by: matt mooney Acked-by: WANG Cong Acked-by: Guenter Roeck Signed-off-by: Michal Marek --- drivers/hwmon/Makefile | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile index dde02d99c2386..974f9cc766b21 100644 --- a/drivers/hwmon/Makefile +++ b/drivers/hwmon/Makefile @@ -112,7 +112,5 @@ obj-$(CONFIG_SENSORS_W83L786NG) += w83l786ng.o obj-$(CONFIG_SENSORS_WM831X) += wm831x-hwmon.o obj-$(CONFIG_SENSORS_WM8350) += wm8350-hwmon.o -ifeq ($(CONFIG_HWMON_DEBUG_CHIP),y) -EXTRA_CFLAGS += -DDEBUG -endif +ccflags-$(CONFIG_HWMON_DEBUG_CHIP) := -DDEBUG -- GitLab From 732f36d82fc4acfd2fa77c939494edeee390b080 Mon Sep 17 00:00:00 2001 From: matt mooney Date: Fri, 14 Jan 2011 06:12:39 -0800 Subject: [PATCH 0787/2822] ide: change to new flag variable Replace EXTRA_CFLAGS with ccflags-y. Signed-off-by: matt mooney Acked-by: WANG Cong Acked-by: David S. Miller Signed-off-by: Michal Marek --- drivers/ide/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/ide/Makefile b/drivers/ide/Makefile index 81df925f0e8b9..7f879b2397b0e 100644 --- a/drivers/ide/Makefile +++ b/drivers/ide/Makefile @@ -2,7 +2,7 @@ # link order is important here # -EXTRA_CFLAGS += -Idrivers/ide +ccflags-y := -Idrivers/ide ide-core-y += ide.o ide-ioctls.o ide-io.o ide-iops.o ide-lib.o ide-probe.o \ ide-taskfile.o ide-pm.o ide-park.o ide-sysfs.o ide-devsets.o \ -- GitLab From 76e150392402c154036db94fcc295469fce48c66 Mon Sep 17 00:00:00 2001 From: matt mooney Date: Fri, 14 Jan 2011 06:12:40 -0800 Subject: [PATCH 0788/2822] ieee802154: change to new flag variable Replace EXTRA_CFLAGS with ccflags-y. Signed-off-by: matt mooney Acked-by: WANG Cong Acked-by: Dmitry Eremin-Solenikov Signed-off-by: Michal Marek --- drivers/ieee802154/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/ieee802154/Makefile b/drivers/ieee802154/Makefile index e0e8e1a184ffa..68999137dedfe 100644 --- a/drivers/ieee802154/Makefile +++ b/drivers/ieee802154/Makefile @@ -1,3 +1,3 @@ obj-$(CONFIG_IEEE802154_FAKEHARD) += fakehard.o -EXTRA_CFLAGS += -DDEBUG -DCONFIG_FFD +ccflags-y := -DDEBUG -DCONFIG_FFD -- GitLab From f656c25b71b986b98dce2f8d268524f792b7e43f Mon Sep 17 00:00:00 2001 From: matt mooney Date: Fri, 14 Jan 2011 06:12:41 -0800 Subject: [PATCH 0789/2822] isdn: change to new flag variable Replace EXTRA_CFLAGS with ccflags-y. Signed-off-by: matt mooney Acked-by: WANG Cong Acked-by: David S. Miller Signed-off-by: Michal Marek --- drivers/isdn/hisax/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/isdn/hisax/Makefile b/drivers/isdn/hisax/Makefile index ab638b083df9c..646368fe41c94 100644 --- a/drivers/isdn/hisax/Makefile +++ b/drivers/isdn/hisax/Makefile @@ -4,7 +4,7 @@ # Define maximum number of cards -EXTRA_CFLAGS += -DHISAX_MAX_CARDS=$(CONFIG_HISAX_MAX_CARDS) +ccflags-y := -DHISAX_MAX_CARDS=$(CONFIG_HISAX_MAX_CARDS) obj-$(CONFIG_ISDN_DRV_HISAX) += hisax.o obj-$(CONFIG_HISAX_SEDLBAUER_CS) += sedlbauer_cs.o -- GitLab From 41d9c644fc4dd5fa399682c0f8d0d1f79b77a199 Mon Sep 17 00:00:00 2001 From: matt mooney Date: Fri, 14 Jan 2011 06:12:42 -0800 Subject: [PATCH 0790/2822] memstick: change to new flag variable The EXTRA_CFLAGS assignment in memstick/Makefile was not accomplishing anything because this flag only has effect on sources at the same level as the makefile (i.e., per directory). Since both core/ and host/ rely on MEMSTICK_DEBUG, the subdir-ccflags-y variant seems to be the appropriate choice. Signed-off-by: matt mooney Acked-by: WANG Cong Signed-off-by: Michal Marek --- drivers/memstick/Makefile | 4 +--- drivers/memstick/core/Makefile | 4 ---- drivers/memstick/host/Makefile | 4 ---- 3 files changed, 1 insertion(+), 11 deletions(-) diff --git a/drivers/memstick/Makefile b/drivers/memstick/Makefile index dc160fb435150..98623590c7fe0 100644 --- a/drivers/memstick/Makefile +++ b/drivers/memstick/Makefile @@ -2,9 +2,7 @@ # Makefile for the kernel MemoryStick device drivers. # -ifeq ($(CONFIG_MEMSTICK_DEBUG),y) - EXTRA_CFLAGS += -DDEBUG -endif +subdir-ccflags-$(CONFIG_MEMSTICK_DEBUG) := -DDEBUG obj-$(CONFIG_MEMSTICK) += core/ obj-$(CONFIG_MEMSTICK) += host/ diff --git a/drivers/memstick/core/Makefile b/drivers/memstick/core/Makefile index 8b2b5293877e0..ecd0299377386 100644 --- a/drivers/memstick/core/Makefile +++ b/drivers/memstick/core/Makefile @@ -2,10 +2,6 @@ # Makefile for the kernel MemoryStick core. # -ifeq ($(CONFIG_MEMSTICK_DEBUG),y) - EXTRA_CFLAGS += -DDEBUG -endif - obj-$(CONFIG_MEMSTICK) += memstick.o obj-$(CONFIG_MSPRO_BLOCK) += mspro_block.o diff --git a/drivers/memstick/host/Makefile b/drivers/memstick/host/Makefile index 12530e4311d31..a1815e9dd0193 100644 --- a/drivers/memstick/host/Makefile +++ b/drivers/memstick/host/Makefile @@ -2,9 +2,5 @@ # Makefile for MemoryStick host controller drivers # -ifeq ($(CONFIG_MEMSTICK_DEBUG),y) - EXTRA_CFLAGS += -DDEBUG -endif - obj-$(CONFIG_MEMSTICK_TIFM_MS) += tifm_ms.o obj-$(CONFIG_MEMSTICK_JMICRON_38X) += jmb38x_ms.o -- GitLab From d100d406044b76475c7baec72ab6770306ea1a8d Mon Sep 17 00:00:00 2001 From: matt mooney Date: Fri, 14 Jan 2011 06:12:43 -0800 Subject: [PATCH 0791/2822] message: change to new flag variable Replace EXTRA_CFLAGS with ccflags-y. Signed-off-by: matt mooney Acked-by: WANG Cong Signed-off-by: Michal Marek --- drivers/message/fusion/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/message/fusion/Makefile b/drivers/message/fusion/Makefile index 95c9532cb07ca..d182a24b31955 100644 --- a/drivers/message/fusion/Makefile +++ b/drivers/message/fusion/Makefile @@ -2,7 +2,7 @@ # enable verbose logging # CONFIG_FUSION_LOGGING needs to be enabled in Kconfig -#EXTRA_CFLAGS += -DMPT_DEBUG_VERBOSE +#ccflags-y := -DMPT_DEBUG_VERBOSE #=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-} LSI_LOGIC -- GitLab From 8ac727c1e65ba98fc2d82bb28288312cc3b7473b Mon Sep 17 00:00:00 2001 From: matt mooney Date: Fri, 14 Jan 2011 06:12:44 -0800 Subject: [PATCH 0792/2822] misc: change to new flag variable Replace EXTRA_CFLAGS with ccflags-y. Signed-off-by: matt mooney Acked-by: WANG Cong Signed-off-by: Michal Marek --- drivers/misc/cb710/Makefile | 4 +--- drivers/misc/sgi-gru/Makefile | 4 +--- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/drivers/misc/cb710/Makefile b/drivers/misc/cb710/Makefile index 7b80cbf1a609b..467c8e9ca3c94 100644 --- a/drivers/misc/cb710/Makefile +++ b/drivers/misc/cb710/Makefile @@ -1,6 +1,4 @@ -ifeq ($(CONFIG_CB710_DEBUG),y) - EXTRA_CFLAGS += -DDEBUG -endif +ccflags-$(CONFIG_CB710_DEBUG) := -DDEBUG obj-$(CONFIG_CB710_CORE) += cb710.o diff --git a/drivers/misc/sgi-gru/Makefile b/drivers/misc/sgi-gru/Makefile index 7c4c306dfa8a4..0003a1d56f7f6 100644 --- a/drivers/misc/sgi-gru/Makefile +++ b/drivers/misc/sgi-gru/Makefile @@ -1,6 +1,4 @@ -ifdef CONFIG_SGI_GRU_DEBUG - EXTRA_CFLAGS += -DDEBUG -endif +ccflags-$(CONFIG_SGI_GRU_DEBUG) := -DDEBUG obj-$(CONFIG_SGI_GRU) := gru.o gru-y := grufile.o grumain.o grufault.o grutlbpurge.o gruprocfs.o grukservices.o gruhandles.o grukdump.o -- GitLab From 5a8b7cdc7424d63467cff1d20461acf48ffcb72f Mon Sep 17 00:00:00 2001 From: matt mooney Date: Fri, 14 Jan 2011 06:12:45 -0800 Subject: [PATCH 0793/2822] net: change to new flag variable Replace EXTRA_CFLAGS with ccflags-y. Signed-off-by: matt mooney Acked-by: WANG Cong Acked-by: Sjur Braendeland Acked-by: David S. Miller Acked-by: John W. Linville Signed-off-by: Michal Marek --- drivers/net/caif/Makefile | 4 +--- drivers/net/skfp/Makefile | 2 +- drivers/net/wan/lmc/Makefile | 2 +- drivers/net/wireless/hostap/hostap_config.h | 4 ++-- drivers/net/wireless/zd1211rw/Makefile | 4 +--- 5 files changed, 6 insertions(+), 10 deletions(-) diff --git a/drivers/net/caif/Makefile b/drivers/net/caif/Makefile index b38d987da67d9..9560b9d624bd5 100644 --- a/drivers/net/caif/Makefile +++ b/drivers/net/caif/Makefile @@ -1,6 +1,4 @@ -ifeq ($(CONFIG_CAIF_DEBUG),y) -EXTRA_CFLAGS += -DDEBUG -endif +ccflags-$(CONFIG_CAIF_DEBUG) := -DDEBUG # Serial interface obj-$(CONFIG_CAIF_TTY) += caif_serial.o diff --git a/drivers/net/skfp/Makefile b/drivers/net/skfp/Makefile index cb23580fcffa5..b0be0234abf6a 100644 --- a/drivers/net/skfp/Makefile +++ b/drivers/net/skfp/Makefile @@ -17,4 +17,4 @@ skfp-objs := skfddi.o hwmtm.o fplustm.o smt.o cfm.o \ # projects. To keep the source common for all those drivers (and # thus simplify fixes to it), please do not clean it up! -EXTRA_CFLAGS += -Idrivers/net/skfp -DPCI -DMEM_MAPPED_IO -Wno-strict-prototypes +ccflags-y := -Idrivers/net/skfp -DPCI -DMEM_MAPPED_IO -Wno-strict-prototypes diff --git a/drivers/net/wan/lmc/Makefile b/drivers/net/wan/lmc/Makefile index dabdcfed4efd1..609710d64eb5c 100644 --- a/drivers/net/wan/lmc/Makefile +++ b/drivers/net/wan/lmc/Makefile @@ -14,4 +14,4 @@ lmc-objs := lmc_debug.o lmc_media.o lmc_main.o lmc_proto.o # -DDEBUG \ # -DLMC_PACKET_LOG -EXTRA_CFLAGS += -I. $(DBGDEF) +ccflags-y := -I. $(DBGDEF) diff --git a/drivers/net/wireless/hostap/hostap_config.h b/drivers/net/wireless/hostap/hostap_config.h index 30acd39d76a28..2c8f71f0ed456 100644 --- a/drivers/net/wireless/hostap/hostap_config.h +++ b/drivers/net/wireless/hostap/hostap_config.h @@ -30,9 +30,9 @@ /* Following defines can be used to remove unneeded parts of the driver, e.g., * to limit the size of the kernel module. Definitions can be added here in - * hostap_config.h or they can be added to make command with EXTRA_CFLAGS, + * hostap_config.h or they can be added to make command with ccflags-y, * e.g., - * 'make pccard EXTRA_CFLAGS="-DPRISM2_NO_DEBUG -DPRISM2_NO_PROCFS_DEBUG"' + * 'make pccard ccflags-y="-DPRISM2_NO_DEBUG -DPRISM2_NO_PROCFS_DEBUG"' */ /* Do not include debug messages into the driver */ diff --git a/drivers/net/wireless/zd1211rw/Makefile b/drivers/net/wireless/zd1211rw/Makefile index 1907eafb9b16b..5728a918e508b 100644 --- a/drivers/net/wireless/zd1211rw/Makefile +++ b/drivers/net/wireless/zd1211rw/Makefile @@ -5,7 +5,5 @@ zd1211rw-objs := zd_chip.o zd_mac.o \ zd_rf_al7230b.o zd_rf_uw2453.o \ zd_rf.o zd_usb.o -ifeq ($(CONFIG_ZD1211RW_DEBUG),y) -EXTRA_CFLAGS += -DDEBUG -endif +ccflags-$(CONFIG_ZD1211RW_DEBUG) := -DDEBUG -- GitLab From 26a082dc5334ee003167bb9feeee681c150e5b11 Mon Sep 17 00:00:00 2001 From: matt mooney Date: Fri, 14 Jan 2011 06:12:46 -0800 Subject: [PATCH 0794/2822] pps: change to new flag variable Replace EXTRA_CFLAGS with ccflags-y. Signed-off-by: matt mooney Acked-by: WANG Cong Signed-off-by: Michal Marek --- drivers/pps/clients/Makefile | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/pps/clients/Makefile b/drivers/pps/clients/Makefile index 42517da07049e..4feb7e9e71ee6 100644 --- a/drivers/pps/clients/Makefile +++ b/drivers/pps/clients/Makefile @@ -6,6 +6,4 @@ obj-$(CONFIG_PPS_CLIENT_KTIMER) += pps-ktimer.o obj-$(CONFIG_PPS_CLIENT_LDISC) += pps-ldisc.o obj-$(CONFIG_PPS_CLIENT_PARPORT) += pps_parport.o -ifeq ($(CONFIG_PPS_DEBUG),y) -EXTRA_CFLAGS += -DDEBUG -endif +ccflags-$(CONFIG_PPS_DEBUG) := -DDEBUG -- GitLab From 4ebdd58f46d305c2ab382b6193d4ed0cd201b0dc Mon Sep 17 00:00:00 2001 From: matt mooney Date: Fri, 14 Jan 2011 06:12:47 -0800 Subject: [PATCH 0795/2822] rapidio: change to new flag variable switches/ depends on RAPIDIO_DEBUG so the subdir-ccflags-y variant seems to be appropriate here. Signed-off-by: matt mooney Acked-by: WANG Cong Signed-off-by: Michal Marek --- drivers/rapidio/Makefile | 4 +--- drivers/rapidio/switches/Makefile | 4 ---- 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/drivers/rapidio/Makefile b/drivers/rapidio/Makefile index b6139fe187bfe..89b8eca825b55 100644 --- a/drivers/rapidio/Makefile +++ b/drivers/rapidio/Makefile @@ -5,6 +5,4 @@ obj-y += rio.o rio-access.o rio-driver.o rio-scan.o rio-sysfs.o obj-$(CONFIG_RAPIDIO) += switches/ -ifeq ($(CONFIG_RAPIDIO_DEBUG),y) -EXTRA_CFLAGS += -DDEBUG -endif +subdir-ccflags-$(CONFIG_RAPIDIO_DEBUG) := -DDEBUG diff --git a/drivers/rapidio/switches/Makefile b/drivers/rapidio/switches/Makefile index 48d67a6b98c89..c4d3acc3c7156 100644 --- a/drivers/rapidio/switches/Makefile +++ b/drivers/rapidio/switches/Makefile @@ -7,7 +7,3 @@ obj-$(CONFIG_RAPIDIO_CPS_XX) += idtcps.o obj-$(CONFIG_RAPIDIO_TSI568) += tsi568.o obj-$(CONFIG_RAPIDIO_TSI500) += tsi500.o obj-$(CONFIG_RAPIDIO_CPS_GEN2) += idt_gen2.o - -ifeq ($(CONFIG_RAPIDIO_DEBUG),y) -EXTRA_CFLAGS += -DDEBUG -endif -- GitLab From 76aea3e9fe1e6b74e8f7c75324fde940701346d4 Mon Sep 17 00:00:00 2001 From: matt mooney Date: Fri, 14 Jan 2011 06:12:48 -0800 Subject: [PATCH 0796/2822] rtc: change to new flag variable Replace EXTRA_CFLAGS with ccflags-y. Signed-off-by: matt mooney Acked-by: WANG Cong Signed-off-by: Michal Marek --- drivers/rtc/Makefile | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile index 2afdaf3ff9866..5f6c3838dcf6a 100644 --- a/drivers/rtc/Makefile +++ b/drivers/rtc/Makefile @@ -2,9 +2,7 @@ # Makefile for RTC class/drivers. # -ifeq ($(CONFIG_RTC_DEBUG),y) - EXTRA_CFLAGS += -DDEBUG -endif +ccflags-$(CONFIG_RTC_DEBUG) := -DDEBUG obj-$(CONFIG_RTC_LIB) += rtc-lib.o obj-$(CONFIG_RTC_HCTOSYS) += hctosys.o -- GitLab From bfbec92075a296eaaddd53b3327ccc259b377299 Mon Sep 17 00:00:00 2001 From: matt mooney Date: Fri, 14 Jan 2011 06:12:49 -0800 Subject: [PATCH 0797/2822] scsi: change to new flag variable Replace EXTRA_CFLAGS with ccflags-y. Signed-off-by: matt mooney Acked-by: WANG Cong Signed-off-by: Michal Marek --- drivers/scsi/aacraid/Makefile | 2 +- drivers/scsi/aic94xx/Makefile | 4 +--- drivers/scsi/libsas/Makefile | 2 +- drivers/scsi/lpfc/Makefile | 6 ++---- drivers/scsi/mvsas/Makefile | 4 +--- drivers/scsi/pcmcia/Makefile | 2 +- 6 files changed, 7 insertions(+), 13 deletions(-) diff --git a/drivers/scsi/aacraid/Makefile b/drivers/scsi/aacraid/Makefile index f1cca4ee54100..92df4d6b6147c 100644 --- a/drivers/scsi/aacraid/Makefile +++ b/drivers/scsi/aacraid/Makefile @@ -5,4 +5,4 @@ obj-$(CONFIG_SCSI_AACRAID) := aacraid.o aacraid-objs := linit.o aachba.o commctrl.o comminit.o commsup.o \ dpcsup.o rx.o sa.o rkt.o nark.o -EXTRA_CFLAGS := -Idrivers/scsi +ccflags-y := -Idrivers/scsi diff --git a/drivers/scsi/aic94xx/Makefile b/drivers/scsi/aic94xx/Makefile index e78ce0fa44d2d..c0a15c7545850 100644 --- a/drivers/scsi/aic94xx/Makefile +++ b/drivers/scsi/aic94xx/Makefile @@ -22,9 +22,7 @@ # along with the aic94xx driver; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -ifeq ($(CONFIG_AIC94XX_DEBUG),y) - EXTRA_CFLAGS += -DASD_DEBUG -DASD_ENTER_EXIT -endif +ccflags-$(CONFIG_AIC94XX_DEBUG) := -DASD_DEBUG -DASD_ENTER_EXIT obj-$(CONFIG_SCSI_AIC94XX) += aic94xx.o aic94xx-y += aic94xx_init.o \ diff --git a/drivers/scsi/libsas/Makefile b/drivers/scsi/libsas/Makefile index 1ad1323c60fa0..ae48b52e7645e 100644 --- a/drivers/scsi/libsas/Makefile +++ b/drivers/scsi/libsas/Makefile @@ -36,4 +36,4 @@ libsas-y += sas_init.o \ sas_scsi_host.o \ sas_task.o libsas-$(CONFIG_SCSI_SAS_ATA) += sas_ata.o -libsas-$(CONFIG_SCSI_SAS_HOST_SMP) += sas_host_smp.o \ No newline at end of file +libsas-$(CONFIG_SCSI_SAS_HOST_SMP) += sas_host_smp.o diff --git a/drivers/scsi/lpfc/Makefile b/drivers/scsi/lpfc/Makefile index ad05d6edb8f69..14de249917f8c 100644 --- a/drivers/scsi/lpfc/Makefile +++ b/drivers/scsi/lpfc/Makefile @@ -19,10 +19,8 @@ # *******************************************************************/ ###################################################################### -ifneq ($(GCOV),) - EXTRA_CFLAGS += -fprofile-arcs -ftest-coverage - EXTRA_CFLAGS += -O0 -endif +ccflags-$(GCOV) := -fprofile-arcs -ftest-coverage +ccflags-$(GCOV) += -O0 obj-$(CONFIG_SCSI_LPFC) := lpfc.o diff --git a/drivers/scsi/mvsas/Makefile b/drivers/scsi/mvsas/Makefile index 52ac4264677d3..ffbf759e46f1e 100644 --- a/drivers/scsi/mvsas/Makefile +++ b/drivers/scsi/mvsas/Makefile @@ -21,9 +21,7 @@ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 # USA -ifeq ($(CONFIG_SCSI_MVSAS_DEBUG),y) - EXTRA_CFLAGS += -DMV_DEBUG -endif +ccflags-$(CONFIG_SCSI_MVSAS_DEBUG) := -DMV_DEBUG obj-$(CONFIG_SCSI_MVSAS) += mvsas.o mvsas-y += mv_init.o \ diff --git a/drivers/scsi/pcmcia/Makefile b/drivers/scsi/pcmcia/Makefile index eca379059db65..683bf148b5b76 100644 --- a/drivers/scsi/pcmcia/Makefile +++ b/drivers/scsi/pcmcia/Makefile @@ -1,5 +1,5 @@ -EXTRA_CFLAGS += -Idrivers/scsi +ccflags-y := -Idrivers/scsi # 16-bit client drivers obj-$(CONFIG_PCMCIA_QLOGIC) += qlogic_cs.o -- GitLab From 22942c00a6ad6e9e93b53811a6de72c821c15d22 Mon Sep 17 00:00:00 2001 From: matt mooney Date: Fri, 14 Jan 2011 06:12:50 -0800 Subject: [PATCH 0798/2822] video: change to new flag variable Replace EXTRA_CFLAGS with ccflags-y. Signed-off-by: matt mooney Acked-by: WANG Cong Signed-off-by: Michal Marek --- drivers/video/intelfb/Makefile | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/video/intelfb/Makefile b/drivers/video/intelfb/Makefile index 6c782d3ae1bed..f7d631ebee8e3 100644 --- a/drivers/video/intelfb/Makefile +++ b/drivers/video/intelfb/Makefile @@ -4,7 +4,4 @@ intelfb-y := intelfbdrv.o intelfbhw.o intelfb-$(CONFIG_FB_INTEL_I2C) += intelfb_i2c.o intelfb-objs := $(intelfb-y) -ifdef CONFIG_FB_INTEL_DEBUG -#EXTRA_CFLAGS += -DDEBUG -DVERBOSE -DREGDUMP -EXTRA_CFLAGS += -DDEBUG -DREGDUMP -endif +ccflags-$(CONFIG_FB_INTEL_DEBUG) := -DDEBUG -DREGDUMP -- GitLab From f0ff1357ce391265edbf844792da7da9a694f4bd Mon Sep 17 00:00:00 2001 From: Stephen Rothwell Date: Thu, 17 Mar 2011 15:02:51 +0100 Subject: [PATCH 0799/2822] drbd: need include for bitops functions declarations Signed-off-by: Stephen Rothwell Signed-off-by: Jens Axboe --- drivers/block/drbd/drbd_bitmap.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/block/drbd/drbd_bitmap.c b/drivers/block/drbd/drbd_bitmap.c index b62dd5f26c5d9..f0ae63d2df655 100644 --- a/drivers/block/drbd/drbd_bitmap.c +++ b/drivers/block/drbd/drbd_bitmap.c @@ -28,6 +28,9 @@ #include #include #include + +#include + #include "drbd_int.h" -- GitLab From 9c281f13b68da49764cbc8d7d610c2f229a0f9a0 Mon Sep 17 00:00:00 2001 From: Michal Marek Date: Thu, 20 Jan 2011 15:23:08 +0100 Subject: [PATCH 0800/2822] genksyms: Do not paste the bison header file to lex.c The header is already #included, no need to include it a second time. lex.c_shipped was regenerated using flex-2.5.35. Signed-off-by: Michal Marek Acked-by: Sam Ravnborg --- scripts/genksyms/Makefile | 4 +- scripts/genksyms/lex.c_shipped | 150 ++------------------------------- 2 files changed, 7 insertions(+), 147 deletions(-) diff --git a/scripts/genksyms/Makefile b/scripts/genksyms/Makefile index e420fe440019f..13d03cf05d951 100644 --- a/scripts/genksyms/Makefile +++ b/scripts/genksyms/Makefile @@ -28,9 +28,9 @@ $(obj)/keywords.c: $(obj)/keywords.gperf FORCE # flex quiet_cmd_lex.c = FLEX $@ - cmd_lex.c = flex -o$@ -d $< $(obj)/parse.h + cmd_lex.c = flex -o$@ -d $< -$(obj)/lex.c: $(obj)/lex.l $(obj)/parse.h $(obj)/keywords.c FORCE +$(obj)/lex.c: $(obj)/lex.l $(obj)/keywords.c FORCE $(call if_changed,lex.c) cp $@ $@_shipped diff --git a/scripts/genksyms/lex.c_shipped b/scripts/genksyms/lex.c_shipped index 2ac23bcca5b53..b54044ac1fa7c 100644 --- a/scripts/genksyms/lex.c_shipped +++ b/scripts/genksyms/lex.c_shipped @@ -79,6 +79,7 @@ typedef int flex_int32_t; typedef unsigned char flex_uint8_t; typedef unsigned short int flex_uint16_t; typedef unsigned int flex_uint32_t; +#endif /* ! C99 */ /* Limits of integral types. */ #ifndef INT8_MIN @@ -109,8 +110,6 @@ typedef unsigned int flex_uint32_t; #define UINT32_MAX (4294967295U) #endif -#endif /* ! C99 */ - #endif /* ! FLEXINT_H */ /* %endif */ @@ -672,7 +671,7 @@ char *yytext; /* We don't do multiple input files. */ #define YY_NO_INPUT 1 -#line 676 "scripts/genksyms/lex.c" +#line 675 "scripts/genksyms/lex.c" #define INITIAL 0 #define V2_TOKENS 1 @@ -808,7 +807,7 @@ static int input (void ); if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \ { \ int c = '*'; \ - size_t n; \ + int n; \ for ( n = 0; n < max_size && \ (c = getc( yyin )) != EOF && c != '\n'; ++n ) \ buf[n] = (char) c; \ @@ -923,7 +922,7 @@ YY_DECL /* Keep track of our location in the original source files. */ -#line 927 "scripts/genksyms/lex.c" +#line 926 "scripts/genksyms/lex.c" if ( !(yy_init) ) { @@ -1114,7 +1113,7 @@ YY_RULE_SETUP #line 97 "scripts/genksyms/lex.l" ECHO; YY_BREAK -#line 1118 "scripts/genksyms/lex.c" +#line 1117 "scripts/genksyms/lex.c" case YY_STATE_EOF(INITIAL): case YY_STATE_EOF(V2_TOKENS): yyterminate(); @@ -2567,143 +2566,4 @@ fini: return token; } -/* A Bison parser, made by GNU Bison 2.3. */ - -/* Skeleton interface for Bison's Yacc-like parsers in C - - Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006 - Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2, or (at your option) - any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. */ - -/* As a special exception, you may create a larger work that contains - part or all of the Bison parser skeleton and distribute that work - under terms of your choice, so long as that work isn't itself a - parser generator using the skeleton or a modified version thereof - as a parser skeleton. Alternatively, if you modify or redistribute - the parser skeleton itself, you may (at your option) remove this - special exception, which will cause the skeleton and the resulting - Bison output files to be licensed under the GNU General Public - License without this special exception. - - This special exception was added by the Free Software Foundation in - version 2.2 of Bison. */ - -/* Tokens. */ -#ifndef YYTOKENTYPE -# define YYTOKENTYPE - /* Put the tokens into the symbol table, so that GDB and other debuggers - know about them. */ - enum yytokentype { - ASM_KEYW = 258, - ATTRIBUTE_KEYW = 259, - AUTO_KEYW = 260, - BOOL_KEYW = 261, - CHAR_KEYW = 262, - CONST_KEYW = 263, - DOUBLE_KEYW = 264, - ENUM_KEYW = 265, - EXTERN_KEYW = 266, - EXTENSION_KEYW = 267, - FLOAT_KEYW = 268, - INLINE_KEYW = 269, - INT_KEYW = 270, - LONG_KEYW = 271, - REGISTER_KEYW = 272, - RESTRICT_KEYW = 273, - SHORT_KEYW = 274, - SIGNED_KEYW = 275, - STATIC_KEYW = 276, - STRUCT_KEYW = 277, - TYPEDEF_KEYW = 278, - UNION_KEYW = 279, - UNSIGNED_KEYW = 280, - VOID_KEYW = 281, - VOLATILE_KEYW = 282, - TYPEOF_KEYW = 283, - EXPORT_SYMBOL_KEYW = 284, - ASM_PHRASE = 285, - ATTRIBUTE_PHRASE = 286, - BRACE_PHRASE = 287, - BRACKET_PHRASE = 288, - EXPRESSION_PHRASE = 289, - CHAR = 290, - DOTS = 291, - IDENT = 292, - INT = 293, - REAL = 294, - STRING = 295, - TYPE = 296, - OTHER = 297, - FILENAME = 298 - }; -#endif -/* Tokens. */ -#define ASM_KEYW 258 -#define ATTRIBUTE_KEYW 259 -#define AUTO_KEYW 260 -#define BOOL_KEYW 261 -#define CHAR_KEYW 262 -#define CONST_KEYW 263 -#define DOUBLE_KEYW 264 -#define ENUM_KEYW 265 -#define EXTERN_KEYW 266 -#define EXTENSION_KEYW 267 -#define FLOAT_KEYW 268 -#define INLINE_KEYW 269 -#define INT_KEYW 270 -#define LONG_KEYW 271 -#define REGISTER_KEYW 272 -#define RESTRICT_KEYW 273 -#define SHORT_KEYW 274 -#define SIGNED_KEYW 275 -#define STATIC_KEYW 276 -#define STRUCT_KEYW 277 -#define TYPEDEF_KEYW 278 -#define UNION_KEYW 279 -#define UNSIGNED_KEYW 280 -#define VOID_KEYW 281 -#define VOLATILE_KEYW 282 -#define TYPEOF_KEYW 283 -#define EXPORT_SYMBOL_KEYW 284 -#define ASM_PHRASE 285 -#define ATTRIBUTE_PHRASE 286 -#define BRACE_PHRASE 287 -#define BRACKET_PHRASE 288 -#define EXPRESSION_PHRASE 289 -#define CHAR 290 -#define DOTS 291 -#define IDENT 292 -#define INT 293 -#define REAL 294 -#define STRING 295 -#define TYPE 296 -#define OTHER 297 -#define FILENAME 298 - - - - -#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED -typedef int YYSTYPE; -# define yystype YYSTYPE /* obsolescent; will be withdrawn */ -# define YYSTYPE_IS_DECLARED 1 -# define YYSTYPE_IS_TRIVIAL 1 -#endif - -extern YYSTYPE yylval; - -- GitLab From 95f1d639ade8fdf9572ac8a926f62b29dd66eaba Mon Sep 17 00:00:00 2001 From: Michal Marek Date: Thu, 20 Jan 2011 16:19:58 +0100 Subject: [PATCH 0801/2822] genksyms: Simplify lexer The V2_TOKENS state is active all the time. Signed-off-by: Michal Marek Acked-by: Sam Ravnborg --- scripts/genksyms/lex.c_shipped | 250 ++++++++++++++++----------------- scripts/genksyms/lex.l | 11 +- 2 files changed, 123 insertions(+), 138 deletions(-) diff --git a/scripts/genksyms/lex.c_shipped b/scripts/genksyms/lex.c_shipped index b54044ac1fa7c..d0a0423361fd9 100644 --- a/scripts/genksyms/lex.c_shipped +++ b/scripts/genksyms/lex.c_shipped @@ -455,16 +455,16 @@ struct yy_trans_info flex_int32_t yy_verify; flex_int32_t yy_nxt; }; -static yyconst flex_int16_t yy_accept[76] = +static yyconst flex_int16_t yy_accept[73] = { 0, - 0, 0, 0, 0, 14, 12, 4, 3, 12, 7, - 12, 12, 7, 12, 12, 12, 12, 12, 9, 9, - 12, 12, 12, 4, 0, 5, 0, 7, 0, 6, - 0, 0, 0, 0, 0, 0, 2, 8, 10, 10, - 9, 0, 0, 9, 9, 0, 9, 0, 0, 11, - 0, 0, 0, 10, 0, 10, 9, 9, 0, 0, - 0, 0, 0, 0, 0, 10, 10, 0, 0, 0, - 0, 0, 0, 1, 0 + 0, 0, 14, 12, 4, 3, 12, 7, 12, 12, + 12, 12, 12, 9, 9, 12, 12, 7, 12, 12, + 4, 0, 5, 0, 7, 8, 0, 6, 0, 0, + 10, 10, 9, 0, 0, 9, 9, 0, 9, 0, + 0, 0, 0, 2, 0, 0, 11, 0, 10, 0, + 10, 9, 9, 0, 0, 0, 10, 10, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0 } ; static yyconst flex_int32_t yy_ec[256] = @@ -506,108 +506,104 @@ static yyconst flex_int32_t yy_meta[29] = 8, 7, 3, 3, 3, 1, 3, 1 } ; -static yyconst flex_int16_t yy_base[88] = +static yyconst flex_int16_t yy_base[85] = { 0, - 0, 147, 21, 140, 145, 284, 39, 284, 26, 0, - 32, 126, 40, 44, 115, 35, 36, 46, 50, 53, - 39, 61, 54, 79, 65, 284, 0, 0, 66, 284, - 0, 119, 79, 75, 123, 104, 284, 284, 107, 0, - 79, 73, 76, 76, 66, 0, 0, 85, 86, 284, - 133, 83, 91, 284, 99, 147, 284, 114, 122, 70, - 107, 141, 172, 151, 135, 181, 284, 137, 114, 157, - 149, 48, 45, 284, 284, 208, 214, 222, 230, 238, - 246, 250, 255, 256, 261, 267, 275 + 0, 145, 150, 266, 27, 266, 25, 0, 131, 23, + 23, 16, 23, 39, 31, 25, 39, 60, 22, 65, + 57, 43, 266, 0, 0, 266, 61, 266, 0, 128, + 74, 0, 113, 59, 62, 113, 52, 0, 0, 72, + 66, 110, 100, 266, 73, 74, 266, 70, 266, 90, + 103, 266, 84, 129, 108, 113, 143, 266, 107, 66, + 118, 137, 168, 120, 80, 91, 145, 143, 83, 41, + 266, 266, 190, 196, 204, 212, 220, 228, 232, 237, + 238, 243, 249, 257 } ; -static yyconst flex_int16_t yy_def[88] = +static yyconst flex_int16_t yy_def[85] = { 0, - 75, 1, 1, 3, 75, 75, 75, 75, 76, 77, - 78, 75, 77, 79, 75, 75, 75, 75, 75, 19, - 75, 75, 75, 75, 76, 75, 80, 77, 78, 75, - 81, 75, 76, 78, 79, 79, 75, 75, 75, 39, - 19, 82, 83, 75, 75, 84, 20, 76, 78, 75, - 79, 51, 85, 75, 75, 75, 75, 84, 79, 51, - 79, 79, 79, 51, 75, 75, 75, 86, 79, 63, - 86, 87, 87, 75, 0, 75, 75, 75, 75, 75, - 75, 75, 75, 75, 75, 75, 75 + 72, 1, 72, 72, 72, 72, 73, 74, 72, 72, + 75, 72, 72, 72, 14, 72, 72, 74, 72, 76, + 72, 73, 72, 77, 74, 72, 75, 72, 78, 72, + 72, 31, 14, 79, 80, 72, 72, 81, 15, 73, + 75, 76, 76, 72, 73, 75, 72, 82, 72, 72, + 72, 72, 81, 76, 54, 72, 72, 72, 76, 54, + 76, 76, 76, 54, 83, 76, 63, 83, 84, 84, + 72, 0, 72, 72, 72, 72, 72, 72, 72, 72, + 72, 72, 72, 72 } ; -static yyconst flex_int16_t yy_nxt[313] = +static yyconst flex_int16_t yy_nxt[295] = { 0, - 6, 7, 8, 7, 9, 6, 10, 6, 6, 11, - 6, 6, 12, 6, 6, 6, 6, 6, 6, 10, - 10, 10, 13, 10, 10, 6, 10, 6, 15, 16, - 26, 15, 17, 18, 19, 20, 20, 21, 15, 22, - 24, 30, 24, 38, 33, 36, 37, 74, 23, 34, - 74, 27, 38, 38, 38, 38, 38, 31, 32, 39, - 39, 39, 40, 41, 41, 42, 47, 47, 47, 26, - 43, 38, 44, 45, 46, 30, 44, 75, 38, 38, - 24, 38, 24, 26, 30, 40, 55, 55, 57, 26, - 27, 31, 57, 43, 35, 30, 64, 64, 64, 57, - - 31, 65, 65, 75, 27, 36, 37, 35, 59, 37, - 27, 31, 56, 56, 56, 59, 37, 51, 52, 52, - 39, 39, 39, 59, 37, 37, 68, 53, 54, 54, - 69, 50, 38, 54, 59, 37, 44, 45, 32, 37, - 44, 35, 59, 37, 75, 14, 60, 60, 66, 66, - 66, 37, 14, 72, 75, 61, 62, 63, 59, 61, - 56, 56, 56, 69, 64, 64, 64, 69, 67, 67, - 75, 75, 75, 67, 37, 35, 75, 75, 75, 61, - 62, 75, 75, 61, 75, 70, 70, 70, 75, 75, - 75, 70, 70, 70, 66, 66, 66, 75, 75, 75, - - 75, 75, 54, 54, 75, 75, 75, 54, 25, 25, - 25, 25, 25, 25, 25, 25, 28, 75, 75, 28, - 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, - 35, 35, 35, 35, 35, 35, 35, 35, 48, 75, - 48, 48, 48, 48, 48, 48, 49, 75, 49, 49, - 49, 49, 49, 49, 42, 42, 75, 42, 56, 75, - 56, 58, 58, 58, 66, 75, 66, 71, 71, 71, - 71, 71, 71, 71, 71, 73, 73, 73, 73, 73, - 73, 73, 73, 5, 75, 75, 75, 75, 75, 75, - 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, - - 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, - 75, 75 + 4, 5, 6, 5, 7, 4, 8, 9, 10, 11, + 9, 12, 13, 14, 15, 15, 16, 9, 17, 8, + 8, 8, 18, 8, 8, 4, 8, 19, 21, 23, + 21, 26, 28, 26, 26, 30, 31, 31, 31, 26, + 26, 26, 26, 71, 39, 39, 39, 23, 29, 26, + 24, 32, 33, 33, 34, 72, 26, 26, 21, 35, + 21, 36, 37, 38, 40, 36, 43, 44, 24, 41, + 28, 32, 50, 50, 52, 28, 23, 23, 52, 35, + 56, 56, 44, 28, 42, 71, 29, 31, 31, 31, + 42, 29, 59, 44, 48, 49, 49, 24, 24, 29, + + 49, 43, 44, 51, 51, 51, 36, 37, 59, 44, + 36, 65, 44, 54, 55, 55, 51, 51, 51, 59, + 44, 64, 64, 64, 58, 58, 57, 57, 57, 58, + 59, 44, 42, 64, 64, 64, 52, 72, 59, 44, + 47, 66, 60, 60, 42, 44, 59, 69, 26, 72, + 20, 61, 62, 63, 72, 61, 57, 57, 57, 66, + 72, 72, 72, 66, 49, 49, 72, 61, 62, 49, + 44, 61, 72, 72, 72, 72, 72, 72, 72, 72, + 72, 67, 67, 67, 72, 72, 72, 67, 67, 67, + 22, 22, 22, 22, 22, 22, 22, 22, 25, 72, + + 72, 25, 25, 25, 27, 27, 27, 27, 27, 27, + 27, 27, 42, 42, 42, 42, 42, 42, 42, 42, + 45, 72, 45, 45, 45, 45, 45, 45, 46, 72, + 46, 46, 46, 46, 46, 46, 34, 34, 72, 34, + 51, 72, 51, 53, 53, 53, 57, 72, 57, 68, + 68, 68, 68, 68, 68, 68, 68, 70, 70, 70, + 70, 70, 70, 70, 70, 3, 72, 72, 72, 72, + 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, + 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, + 72, 72, 72, 72 + } ; -static yyconst flex_int16_t yy_chk[313] = +static yyconst flex_int16_t yy_chk[295] = { 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, - 9, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 7, 11, 7, 16, 13, 14, 14, 73, 3, 13, - 72, 9, 16, 17, 17, 21, 21, 11, 18, 18, - 18, 18, 19, 19, 19, 19, 20, 20, 20, 25, - 19, 23, 19, 19, 19, 29, 19, 20, 22, 22, - 24, 23, 24, 33, 34, 42, 43, 43, 45, 48, - 25, 29, 45, 42, 60, 49, 52, 52, 52, 44, - - 34, 53, 53, 41, 33, 36, 36, 52, 61, 61, - 48, 49, 55, 55, 55, 69, 69, 36, 36, 36, - 39, 39, 39, 59, 59, 35, 59, 39, 39, 39, - 61, 32, 15, 39, 51, 51, 58, 58, 12, 68, - 58, 68, 62, 62, 5, 4, 51, 51, 65, 65, - 65, 71, 2, 71, 0, 51, 51, 51, 70, 51, - 56, 56, 56, 62, 64, 64, 64, 62, 56, 56, - 0, 0, 0, 56, 63, 64, 0, 0, 0, 70, - 70, 0, 0, 70, 0, 63, 63, 63, 0, 0, - 0, 63, 63, 63, 66, 66, 66, 0, 0, 0, - - 0, 0, 66, 66, 0, 0, 0, 66, 76, 76, - 76, 76, 76, 76, 76, 76, 77, 0, 0, 77, - 77, 77, 78, 78, 78, 78, 78, 78, 78, 78, - 79, 79, 79, 79, 79, 79, 79, 79, 80, 0, - 80, 80, 80, 80, 80, 80, 81, 0, 81, 81, - 81, 81, 81, 81, 82, 82, 0, 82, 83, 0, - 83, 84, 84, 84, 85, 0, 85, 86, 86, 86, - 86, 86, 86, 86, 86, 87, 87, 87, 87, 87, - 87, 87, 87, 75, 75, 75, 75, 75, 75, 75, - 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, - - 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, - 75, 75 + 1, 1, 1, 1, 1, 1, 1, 1, 5, 7, + 5, 10, 11, 12, 12, 13, 13, 13, 13, 19, + 10, 16, 16, 70, 15, 15, 15, 22, 11, 19, + 7, 14, 14, 14, 14, 15, 17, 17, 21, 14, + 21, 14, 14, 14, 18, 14, 20, 20, 22, 18, + 27, 34, 35, 35, 37, 41, 40, 45, 37, 34, + 48, 48, 65, 46, 65, 69, 27, 31, 31, 31, + 60, 41, 66, 66, 31, 31, 31, 40, 45, 46, + + 31, 43, 43, 50, 50, 50, 53, 53, 59, 59, + 53, 59, 42, 43, 43, 43, 51, 51, 51, 61, + 61, 55, 55, 55, 51, 51, 56, 56, 56, 51, + 54, 54, 55, 64, 64, 64, 36, 33, 62, 62, + 30, 61, 54, 54, 64, 68, 67, 68, 9, 3, + 2, 54, 54, 54, 0, 54, 57, 57, 57, 62, + 0, 0, 0, 62, 57, 57, 0, 67, 67, 57, + 63, 67, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 63, 63, 63, 0, 0, 0, 63, 63, 63, + 73, 73, 73, 73, 73, 73, 73, 73, 74, 0, + + 0, 74, 74, 74, 75, 75, 75, 75, 75, 75, + 75, 75, 76, 76, 76, 76, 76, 76, 76, 76, + 77, 0, 77, 77, 77, 77, 77, 77, 78, 0, + 78, 78, 78, 78, 78, 78, 79, 79, 0, 79, + 80, 0, 80, 81, 81, 81, 82, 0, 82, 83, + 83, 83, 83, 83, 83, 83, 83, 84, 84, 84, + 84, 84, 84, 84, 84, 72, 72, 72, 72, 72, + 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, + 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, + 72, 72, 72, 72 + } ; static yy_state_type yy_last_accepting_state; @@ -618,8 +614,8 @@ int yy_flex_debug = 1; static yyconst flex_int16_t yy_rule_linenum[13] = { 0, - 71, 72, 73, 76, 79, 80, 81, 87, 88, 89, - 91, 94 + 67, 68, 69, 72, 75, 76, 77, 83, 84, 85, + 87, 90 } ; /* The intent behind this definition is that it'll catch @@ -666,15 +662,11 @@ char *yytext; and then we categorize those basic tokens in the second stage. */ #define YY_DECL static int yylex1(void) -/* Version 2 checksumming does proper tokenization; version 1 wasn't - quite so pedantic. */ - /* We don't do multiple input files. */ #define YY_NO_INPUT 1 -#line 675 "scripts/genksyms/lex.c" +#line 668 "scripts/genksyms/lex.c" #define INITIAL 0 -#define V2_TOKENS 1 #ifndef YY_NO_UNISTD_H /* Special case for "unistd.h", since it is non-ANSI. We include it way @@ -917,12 +909,12 @@ YY_DECL register int yy_act; /* %% [7.0] user's declarations go here */ -#line 67 "scripts/genksyms/lex.l" +#line 63 "scripts/genksyms/lex.l" /* Keep track of our location in the original source files. */ -#line 926 "scripts/genksyms/lex.c" +#line 918 "scripts/genksyms/lex.c" if ( !(yy_init) ) { @@ -986,13 +978,13 @@ yy_match: while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; - if ( yy_current_state >= 76 ) + if ( yy_current_state >= 73 ) yy_c = yy_meta[(unsigned int) yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; ++yy_cp; } - while ( yy_base[yy_current_state] != 284 ); + while ( yy_base[yy_current_state] != 266 ); yy_find_action: /* %% [10.0] code to find the action number goes here */ @@ -1040,42 +1032,42 @@ do_action: /* This label is used only to access EOF actions. */ case 1: /* rule 1 can match eol */ YY_RULE_SETUP -#line 71 "scripts/genksyms/lex.l" +#line 67 "scripts/genksyms/lex.l" return FILENAME; YY_BREAK case 2: /* rule 2 can match eol */ YY_RULE_SETUP -#line 72 "scripts/genksyms/lex.l" +#line 68 "scripts/genksyms/lex.l" cur_line++; YY_BREAK case 3: /* rule 3 can match eol */ YY_RULE_SETUP -#line 73 "scripts/genksyms/lex.l" +#line 69 "scripts/genksyms/lex.l" cur_line++; YY_BREAK /* Ignore all other whitespace. */ case 4: YY_RULE_SETUP -#line 76 "scripts/genksyms/lex.l" +#line 72 "scripts/genksyms/lex.l" ; YY_BREAK case 5: /* rule 5 can match eol */ YY_RULE_SETUP -#line 79 "scripts/genksyms/lex.l" +#line 75 "scripts/genksyms/lex.l" return STRING; YY_BREAK case 6: /* rule 6 can match eol */ YY_RULE_SETUP -#line 80 "scripts/genksyms/lex.l" +#line 76 "scripts/genksyms/lex.l" return CHAR; YY_BREAK case 7: YY_RULE_SETUP -#line 81 "scripts/genksyms/lex.l" +#line 77 "scripts/genksyms/lex.l" return IDENT; YY_BREAK /* The Pedant requires that the other C multi-character tokens be @@ -1084,38 +1076,37 @@ return IDENT; around them properly. */ case 8: YY_RULE_SETUP -#line 87 "scripts/genksyms/lex.l" +#line 83 "scripts/genksyms/lex.l" return OTHER; YY_BREAK case 9: YY_RULE_SETUP -#line 88 "scripts/genksyms/lex.l" +#line 84 "scripts/genksyms/lex.l" return INT; YY_BREAK case 10: YY_RULE_SETUP -#line 89 "scripts/genksyms/lex.l" +#line 85 "scripts/genksyms/lex.l" return REAL; YY_BREAK case 11: YY_RULE_SETUP -#line 91 "scripts/genksyms/lex.l" +#line 87 "scripts/genksyms/lex.l" return DOTS; YY_BREAK /* All other tokens are single characters. */ case 12: YY_RULE_SETUP -#line 94 "scripts/genksyms/lex.l" +#line 90 "scripts/genksyms/lex.l" return yytext[0]; YY_BREAK case 13: YY_RULE_SETUP -#line 97 "scripts/genksyms/lex.l" +#line 93 "scripts/genksyms/lex.l" ECHO; YY_BREAK -#line 1117 "scripts/genksyms/lex.c" +#line 1109 "scripts/genksyms/lex.c" case YY_STATE_EOF(INITIAL): -case YY_STATE_EOF(V2_TOKENS): yyterminate(); case YY_END_OF_BUFFER: @@ -1428,7 +1419,7 @@ static int yy_get_next_buffer (void) while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; - if ( yy_current_state >= 76 ) + if ( yy_current_state >= 73 ) yy_c = yy_meta[(unsigned int) yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; @@ -1461,11 +1452,11 @@ static int yy_get_next_buffer (void) while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; - if ( yy_current_state >= 76 ) + if ( yy_current_state >= 73 ) yy_c = yy_meta[(unsigned int) yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; - yy_is_jam = (yy_current_state == 75); + yy_is_jam = (yy_current_state == 72); return yy_is_jam ? 0 : yy_current_state; } @@ -2251,7 +2242,7 @@ void yyfree (void * ptr ) /* %ok-for-header */ -#line 97 "scripts/genksyms/lex.l" +#line 93 "scripts/genksyms/lex.l" @@ -2293,7 +2284,6 @@ yylex(void) if (lexstate == ST_NOTSTARTED) { - BEGIN(V2_TOKENS); next_node = xmalloc(sizeof(*next_node)); next_node->next = NULL; lexstate = ST_NORMAL; diff --git a/scripts/genksyms/lex.l b/scripts/genksyms/lex.l index fe50ff9dacd08..4687b1d147dea 100644 --- a/scripts/genksyms/lex.l +++ b/scripts/genksyms/lex.l @@ -55,10 +55,6 @@ CHAR L?\'([^\\\']*\\.)*[^\\\']*\' MC_TOKEN ([~%^&*+=|<>/-]=)|(&&)|("||")|(->)|(<<)|(>>) -/* Version 2 checksumming does proper tokenization; version 1 wasn't - quite so pedantic. */ -%s V2_TOKENS - /* We don't do multiple input files. */ %option noyywrap @@ -84,9 +80,9 @@ MC_TOKEN ([~%^&*+=|<>/-]=)|(&&)|("||")|(->)|(<<)|(>>) recognized as tokens. We don't actually use them since we don't parse expressions, but we do want whitespace to be arranged around them properly. */ -{MC_TOKEN} return OTHER; -{INT} return INT; -{REAL} return REAL; +{MC_TOKEN} return OTHER; +{INT} return INT; +{REAL} return REAL; "..." return DOTS; @@ -134,7 +130,6 @@ yylex(void) if (lexstate == ST_NOTSTARTED) { - BEGIN(V2_TOKENS); next_node = xmalloc(sizeof(*next_node)); next_node->next = NULL; lexstate = ST_NORMAL; -- GitLab From 7ec8eda154cbdcabb5305d90fb0952973dcaa560 Mon Sep 17 00:00:00 2001 From: Michal Marek Date: Tue, 18 Jan 2011 16:28:06 +0100 Subject: [PATCH 0802/2822] genksyms: Simplify printing of symbol types Instead of special-casing SYM_NORMAL, do not map any name to it. Also explicitly set the single-letter name of the symbol type, which will be needed by a further patch. The only user-visible change is one debug printf. Signed-off-by: Michal Marek Acked-by: Sam Ravnborg --- scripts/genksyms/genksyms.c | 43 +++++++++++++++++++++++-------------- 1 file changed, 27 insertions(+), 16 deletions(-) diff --git a/scripts/genksyms/genksyms.c b/scripts/genksyms/genksyms.c index f99115ebe9254..2a1a3b84bebab 100644 --- a/scripts/genksyms/genksyms.c +++ b/scripts/genksyms/genksyms.c @@ -53,8 +53,15 @@ static int nsyms; static struct symbol *expansion_trail; static struct symbol *visited_symbols; -static const char *const symbol_type_name[] = { - "normal", "typedef", "enum", "struct", "union" +static const struct { + int n; + const char *name; +} symbol_types[] = { + [SYM_NORMAL] = { 0, NULL}, + [SYM_TYPEDEF] = {'t', "typedef"}, + [SYM_ENUM] = {'e', "enum"}, + [SYM_STRUCT] = {'s', "struct"}, + [SYM_UNION] = {'u', "union"}, }; static int equal_list(struct string_list *a, struct string_list *b); @@ -247,8 +254,12 @@ static struct symbol *__add_symbol(const char *name, enum symbol_type type, sym->is_override = 0; if (flag_debug) { - fprintf(debugfile, "Defn for %s %s == <", - symbol_type_name[type], name); + if (symbol_types[type].name) + fprintf(debugfile, "Defn for %s %s == <", + symbol_types[type].name, name); + else + fprintf(debugfile, "Defn for type%d %s == <", + type, name); if (is_extern) fputs("extern ", debugfile); print_list(debugfile, defn); @@ -346,8 +357,8 @@ static struct string_list *read_node(FILE *f) if (node.string[1] == '#') { int n; - for (n = 0; n < ARRAY_SIZE(symbol_type_name); n++) { - if (node.string[0] == symbol_type_name[n][0]) { + for (n = 0; n < ARRAY_SIZE(symbol_types); n++) { + if (node.string[0] == symbol_types[n].n) { node.tag = n; node.string += 2; return copy_node(&node); @@ -397,8 +408,8 @@ static void read_reference(FILE *f) static void print_node(FILE * f, struct string_list *list) { - if (list->tag != SYM_NORMAL) { - putc(symbol_type_name[list->tag][0], f); + if (symbol_types[list->tag].n) { + putc(symbol_types[list->tag].n, f); putc('#', f); } fputs(list->string, f); @@ -491,11 +502,11 @@ static unsigned long expand_and_crc_sym(struct symbol *sym, unsigned long crc) struct string_list *n, *t = NULL; error_with_pos("expand undefined %s %s", - symbol_type_name[cur->tag], + symbol_types[cur->tag].name, cur->string); n = xmalloc(sizeof(*n)); - n->string = xstrdup(symbol_type_name[cur->tag]); + n->string = xstrdup(symbol_types[cur->tag].name); n->tag = SYM_NORMAL; n->next = t; t = n; @@ -530,11 +541,11 @@ static unsigned long expand_and_crc_sym(struct symbol *sym, unsigned long crc) if (subsym->expansion_trail) { if (flag_dump_defs) { fprintf(debugfile, "%s %s ", - symbol_type_name[cur->tag], + symbol_types[cur->tag].name, cur->string); } - crc = partial_crc32(symbol_type_name[cur->tag], + crc = partial_crc32(symbol_types[cur->tag].name, crc); crc = partial_crc32_one(' ', crc); crc = partial_crc32(cur->string, crc); @@ -624,8 +635,8 @@ static void print_location(void) static void print_type_name(enum symbol_type type, const char *name) { - if (type != SYM_NORMAL) - fprintf(stderr, "%s %s", symbol_type_name[type], name); + if (symbol_types[type].name) + fprintf(stderr, "%s %s", symbol_types[type].name, name); else fprintf(stderr, "%s", name); } @@ -771,8 +782,8 @@ int main(int argc, char **argv) if (sym->is_override) fputs("override ", dumpfile); - if (sym->type != SYM_NORMAL) { - putc(symbol_type_name[sym->type][0], dumpfile); + if (symbol_types[sym->type].n) { + putc(symbol_types[sym->type].n, dumpfile); putc('#', dumpfile); } fputs(sym->name, dumpfile); -- GitLab From 68eb8563a1adf27fae18dde4c95fb796c17563df Mon Sep 17 00:00:00 2001 From: Michal Marek Date: Wed, 2 Feb 2011 23:52:13 +0100 Subject: [PATCH 0803/2822] genksyms: Add helpers for building string lists Signed-off-by: Michal Marek Acked-by: Sam Ravnborg --- scripts/genksyms/genksyms.c | 70 ++++++++++++++++++++----------------- 1 file changed, 38 insertions(+), 32 deletions(-) diff --git a/scripts/genksyms/genksyms.c b/scripts/genksyms/genksyms.c index 2a1a3b84bebab..d17b7a2b941f7 100644 --- a/scripts/genksyms/genksyms.c +++ b/scripts/genksyms/genksyms.c @@ -66,6 +66,8 @@ static const struct { static int equal_list(struct string_list *a, struct string_list *b); static void print_list(FILE * f, struct string_list *list); +static struct string_list *concat_list(struct string_list *start, ...); +static struct string_list *mk_node(const char *string); static void print_location(void); static void print_type_name(enum symbol_type type, const char *name); @@ -299,6 +301,35 @@ void free_list(struct string_list *s, struct string_list *e) } } +static struct string_list *mk_node(const char *string) +{ + struct string_list *newnode; + + newnode = xmalloc(sizeof(*newnode)); + newnode->string = xstrdup(string); + newnode->tag = SYM_NORMAL; + newnode->next = NULL; + + return newnode; +} + +static struct string_list *concat_list(struct string_list *start, ...) +{ + va_list ap; + struct string_list *n, *n2; + + if (!start) + return NULL; + for (va_start(ap, start); (n = va_arg(ap, struct string_list *));) { + for (n2 = n; n2->next; n2 = n2->next) + ; + n2->next = start; + start = n; + } + va_end(ap); + return start; +} + struct string_list *copy_node(struct string_list *node) { struct string_list *newnode; @@ -499,42 +530,17 @@ static unsigned long expand_and_crc_sym(struct symbol *sym, unsigned long crc) case SYM_ENUM: subsym = find_symbol(cur->string, cur->tag); if (!subsym) { - struct string_list *n, *t = NULL; + struct string_list *n; error_with_pos("expand undefined %s %s", symbol_types[cur->tag].name, cur->string); - - n = xmalloc(sizeof(*n)); - n->string = xstrdup(symbol_types[cur->tag].name); - n->tag = SYM_NORMAL; - n->next = t; - t = n; - - n = xmalloc(sizeof(*n)); - n->string = xstrdup(cur->string); - n->tag = SYM_NORMAL; - n->next = t; - t = n; - - n = xmalloc(sizeof(*n)); - n->string = xstrdup("{"); - n->tag = SYM_NORMAL; - n->next = t; - t = n; - - n = xmalloc(sizeof(*n)); - n->string = xstrdup("UNKNOWN"); - n->tag = SYM_NORMAL; - n->next = t; - t = n; - - n = xmalloc(sizeof(*n)); - n->string = xstrdup("}"); - n->tag = SYM_NORMAL; - n->next = t; - t = n; - + n = concat_list(mk_node + (symbol_types[cur->tag].name), + mk_node(cur->string), + mk_node("{"), + mk_node("UNKNOWN"), + mk_node("}"), NULL); subsym = add_symbol(cur->string, cur->tag, n, 0); } -- GitLab From 01762c4ec5f6f62c550304b9c70e824293cefdd0 Mon Sep 17 00:00:00 2001 From: Michal Marek Date: Tue, 15 Feb 2011 15:11:36 +0100 Subject: [PATCH 0804/2822] genksyms: simplify usage of find_symbol() Allow searching for symbols of an exact type. The lexer does this and a subsequent patch will add one more usage. Signed-off-by: Michal Marek Acked-by: Sam Ravnborg --- scripts/genksyms/genksyms.c | 10 ++++++---- scripts/genksyms/genksyms.h | 2 +- scripts/genksyms/lex.c_shipped | 3 +-- scripts/genksyms/lex.l | 3 +-- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/scripts/genksyms/genksyms.c b/scripts/genksyms/genksyms.c index d17b7a2b941f7..4a350816a9e8e 100644 --- a/scripts/genksyms/genksyms.c +++ b/scripts/genksyms/genksyms.c @@ -156,7 +156,7 @@ static enum symbol_type map_to_ns(enum symbol_type t) return t; } -struct symbol *find_symbol(const char *name, enum symbol_type ns) +struct symbol *find_symbol(const char *name, enum symbol_type ns, int exact) { unsigned long h = crc32(name) % HASH_BUCKETS; struct symbol *sym; @@ -167,6 +167,8 @@ struct symbol *find_symbol(const char *name, enum symbol_type ns) sym->is_declared) break; + if (exact && sym && sym->type != ns) + return NULL; return sym; } @@ -511,7 +513,7 @@ static unsigned long expand_and_crc_sym(struct symbol *sym, unsigned long crc) break; case SYM_TYPEDEF: - subsym = find_symbol(cur->string, cur->tag); + subsym = find_symbol(cur->string, cur->tag, 0); /* FIXME: Bad reference files can segfault here. */ if (subsym->expansion_trail) { if (flag_dump_defs) @@ -528,7 +530,7 @@ static unsigned long expand_and_crc_sym(struct symbol *sym, unsigned long crc) case SYM_STRUCT: case SYM_UNION: case SYM_ENUM: - subsym = find_symbol(cur->string, cur->tag); + subsym = find_symbol(cur->string, cur->tag, 0); if (!subsym) { struct string_list *n; @@ -582,7 +584,7 @@ void export_symbol(const char *name) { struct symbol *sym; - sym = find_symbol(name, SYM_NORMAL); + sym = find_symbol(name, SYM_NORMAL, 0); if (!sym) error_with_pos("export undefined symbol %s", name); else { diff --git a/scripts/genksyms/genksyms.h b/scripts/genksyms/genksyms.h index 25c4d40cefc13..9fdafb667e76e 100644 --- a/scripts/genksyms/genksyms.h +++ b/scripts/genksyms/genksyms.h @@ -58,7 +58,7 @@ typedef struct string_list **yystype; extern int cur_line; extern char *cur_filename; -struct symbol *find_symbol(const char *name, enum symbol_type ns); +struct symbol *find_symbol(const char *name, enum symbol_type ns, int exact); struct symbol *add_symbol(const char *name, enum symbol_type type, struct string_list *defn, int is_extern); void export_symbol(const char *); diff --git a/scripts/genksyms/lex.c_shipped b/scripts/genksyms/lex.c_shipped index d0a0423361fd9..f231c0810c602 100644 --- a/scripts/genksyms/lex.c_shipped +++ b/scripts/genksyms/lex.c_shipped @@ -2347,8 +2347,7 @@ repeat: } if (!suppress_type_lookup) { - struct symbol *sym = find_symbol(yytext, SYM_TYPEDEF); - if (sym && sym->type == SYM_TYPEDEF) + if (find_symbol(yytext, SYM_TYPEDEF, 1)) token = TYPE; } } diff --git a/scripts/genksyms/lex.l b/scripts/genksyms/lex.l index 4687b1d147dea..c125d06fbd365 100644 --- a/scripts/genksyms/lex.l +++ b/scripts/genksyms/lex.l @@ -193,8 +193,7 @@ repeat: } if (!suppress_type_lookup) { - struct symbol *sym = find_symbol(yytext, SYM_TYPEDEF); - if (sym && sym->type == SYM_TYPEDEF) + if (find_symbol(yytext, SYM_TYPEDEF, 1)) token = TYPE; } } -- GitLab From e37ddb82500393cb417c3ab0fe0726d9a8652372 Mon Sep 17 00:00:00 2001 From: Michal Marek Date: Thu, 3 Feb 2011 23:57:09 +0100 Subject: [PATCH 0805/2822] genksyms: Track changes to enum constants Enum constants can be used as array sizes; if the enum itself does not appear in the symbol expansion, a change in the enum constant will go unnoticed. Example patch that changes the ABI but does not change the checksum with current genksyms: | enum e { | E1, | E2, |+ E3, | E_MAX | }; | | struct s { | int a[E_MAX]; | } | | int f(struct s *s) { ... } | EXPORT_SYMBOL(f) Therefore, remember the value of each enum constant and expand each occurence to . The value is not actually computed, but instead an expression in the form (last explicitly assigned value) + N is used. This avoids having to parse and semantically understand whole of C. Note: The changes won't take effect until the lexer and parser are rebuilt by the next patch. Signed-off-by: Michal Marek Acked-by: Sam Ravnborg --- scripts/genksyms/genksyms.c | 71 ++++++++++++++++++++++++++++++++++--- scripts/genksyms/genksyms.h | 5 ++- scripts/genksyms/lex.l | 30 ++++++++++++++-- scripts/genksyms/parse.y | 34 +++++++++++++++--- 4 files changed, 127 insertions(+), 13 deletions(-) diff --git a/scripts/genksyms/genksyms.c b/scripts/genksyms/genksyms.c index 4a350816a9e8e..f9e75531ea039 100644 --- a/scripts/genksyms/genksyms.c +++ b/scripts/genksyms/genksyms.c @@ -62,6 +62,7 @@ static const struct { [SYM_ENUM] = {'e', "enum"}, [SYM_STRUCT] = {'s', "struct"}, [SYM_UNION] = {'u', "union"}, + [SYM_ENUM_CONST] = {'E', "enum constant"}, }; static int equal_list(struct string_list *a, struct string_list *b); @@ -149,10 +150,16 @@ static unsigned long crc32(const char *s) static enum symbol_type map_to_ns(enum symbol_type t) { - if (t == SYM_TYPEDEF) - t = SYM_NORMAL; - else if (t == SYM_UNION) - t = SYM_STRUCT; + switch (t) { + case SYM_ENUM_CONST: + case SYM_NORMAL: + case SYM_TYPEDEF: + return SYM_NORMAL; + case SYM_ENUM: + case SYM_STRUCT: + case SYM_UNION: + return SYM_STRUCT; + } return t; } @@ -191,10 +198,47 @@ static struct symbol *__add_symbol(const char *name, enum symbol_type type, struct string_list *defn, int is_extern, int is_reference) { - unsigned long h = crc32(name) % HASH_BUCKETS; + unsigned long h; struct symbol *sym; enum symbol_status status = STATUS_UNCHANGED; + /* The parser adds symbols in the order their declaration completes, + * so it is safe to store the value of the previous enum constant in + * a static variable. + */ + static int enum_counter; + static struct string_list *last_enum_expr; + + if (type == SYM_ENUM_CONST) { + if (defn) { + free_list(last_enum_expr, NULL); + last_enum_expr = copy_list_range(defn, NULL); + enum_counter = 1; + } else { + struct string_list *expr; + char buf[20]; + + snprintf(buf, sizeof(buf), "%d", enum_counter++); + if (last_enum_expr) { + expr = copy_list_range(last_enum_expr, NULL); + defn = concat_list(mk_node("("), + expr, + mk_node(")"), + mk_node("+"), + mk_node(buf), NULL); + } else { + defn = mk_node(buf); + } + } + } else if (type == SYM_ENUM) { + free_list(last_enum_expr, NULL); + last_enum_expr = NULL; + enum_counter = 0; + if (!name) + /* Anonymous enum definition, nothing more to do */ + return NULL; + } + h = crc32(name) % HASH_BUCKETS; for (sym = symtab[h]; sym; sym = sym->hash_next) { if (map_to_ns(sym->type) == map_to_ns(type) && strcmp(name, sym->name) == 0) { @@ -343,6 +387,22 @@ struct string_list *copy_node(struct string_list *node) return newnode; } +struct string_list *copy_list_range(struct string_list *start, + struct string_list *end) +{ + struct string_list *res, *n; + + if (start == end) + return NULL; + n = res = copy_node(start); + for (start = start->next; start != end; start = start->next) { + n->next = copy_node(start); + n = n->next; + } + n->next = NULL; + return res; +} + static int equal_list(struct string_list *a, struct string_list *b) { while (a && b) { @@ -512,6 +572,7 @@ static unsigned long expand_and_crc_sym(struct symbol *sym, unsigned long crc) crc = partial_crc32_one(' ', crc); break; + case SYM_ENUM_CONST: case SYM_TYPEDEF: subsym = find_symbol(cur->string, cur->tag, 0); /* FIXME: Bad reference files can segfault here. */ diff --git a/scripts/genksyms/genksyms.h b/scripts/genksyms/genksyms.h index 9fdafb667e76e..7ec52ae3846aa 100644 --- a/scripts/genksyms/genksyms.h +++ b/scripts/genksyms/genksyms.h @@ -26,7 +26,8 @@ #include enum symbol_type { - SYM_NORMAL, SYM_TYPEDEF, SYM_ENUM, SYM_STRUCT, SYM_UNION + SYM_NORMAL, SYM_TYPEDEF, SYM_ENUM, SYM_STRUCT, SYM_UNION, + SYM_ENUM_CONST }; enum symbol_status { @@ -66,6 +67,8 @@ void export_symbol(const char *); void free_node(struct string_list *list); void free_list(struct string_list *s, struct string_list *e); struct string_list *copy_node(struct string_list *); +struct string_list *copy_list_range(struct string_list *start, + struct string_list *end); int yylex(void); int yyparse(void); diff --git a/scripts/genksyms/lex.l b/scripts/genksyms/lex.l index c125d06fbd365..e4ddd493fec3e 100644 --- a/scripts/genksyms/lex.l +++ b/scripts/genksyms/lex.l @@ -99,12 +99,23 @@ MC_TOKEN ([~%^&*+=|<>/-]=)|(&&)|("||")|(->)|(<<)|(>>) /* Macros to append to our phrase collection list. */ +/* + * We mark any token, that that equals to a known enumerator, as + * SYM_ENUM_CONST. The parser will change this for struct and union tags later, + * the only problem is struct and union members: + * enum e { a, b }; struct s { int a, b; } + * but in this case, the only effect will be, that the ABI checksums become + * more volatile, which is acceptable. Also, such collisions are quite rare, + * so far it was only observed in include/linux/telephony.h. + */ #define _APP(T,L) do { \ cur_node = next_node; \ next_node = xmalloc(sizeof(*next_node)); \ next_node->next = cur_node; \ cur_node->string = memcpy(xmalloc(L+1), T, L+1); \ - cur_node->tag = SYM_NORMAL; \ + cur_node->tag = \ + find_symbol(cur_node->string, SYM_ENUM_CONST, 1)?\ + SYM_ENUM_CONST : SYM_NORMAL ; \ } while (0) #define APP _APP(yytext, yyleng) @@ -182,8 +193,8 @@ repeat: case STRUCT_KEYW: case UNION_KEYW: - dont_want_brace_phrase = 3; case ENUM_KEYW: + dont_want_brace_phrase = 3; suppress_type_lookup = 2; goto fini; @@ -312,7 +323,20 @@ repeat: ++count; APP; goto repeat; - case ')': case ']': case '}': + case '}': + /* is this the last line of an enum declaration? */ + if (count == 0) + { + /* Put back the token we just read so's we can find it again + after registering the expression. */ + unput(token); + + lexstate = ST_NORMAL; + token = EXPRESSION_PHRASE; + break; + } + /* FALLTHRU */ + case ')': case ']': --count; APP; goto repeat; diff --git a/scripts/genksyms/parse.y b/scripts/genksyms/parse.y index 09a265cd71939..ba5c242866c11 100644 --- a/scripts/genksyms/parse.y +++ b/scripts/genksyms/parse.y @@ -25,6 +25,7 @@ #include #include +#include #include "genksyms.h" static int is_typedef; @@ -227,16 +228,19 @@ type_specifier: add_symbol(i->string, SYM_UNION, s, is_extern); $$ = $3; } - | ENUM_KEYW IDENT BRACE_PHRASE + | ENUM_KEYW IDENT enum_body { struct string_list *s = *$3, *i = *$2, *r; r = copy_node(i); r->tag = SYM_ENUM; r->next = (*$1)->next; *$3 = r; (*$1)->next = NULL; add_symbol(i->string, SYM_ENUM, s, is_extern); $$ = $3; } - - /* Anonymous s/u/e definitions. Nothing needs doing. */ - | ENUM_KEYW BRACE_PHRASE { $$ = $2; } + /* + * Anonymous enum definition. Tell add_symbol() to restart its counter. + */ + | ENUM_KEYW enum_body + { add_symbol(NULL, SYM_ENUM, NULL, 0); $$ = $2; } + /* Anonymous s/u definitions. Nothing needs doing. */ | STRUCT_KEYW class_body { $$ = $2; } | UNION_KEYW class_body { $$ = $2; } ; @@ -449,6 +453,28 @@ attribute_opt: | attribute_opt ATTRIBUTE_PHRASE ; +enum_body: + '{' enumerator_list '}' { $$ = $3; } + | '{' enumerator_list ',' '}' { $$ = $4; } + ; + +enumerator_list: + enumerator + | enumerator_list ',' enumerator + +enumerator: + IDENT + { + const char *name = strdup((*$1)->string); + add_symbol(name, SYM_ENUM_CONST, NULL, 0); + } + | IDENT '=' EXPRESSION_PHRASE + { + const char *name = strdup((*$1)->string); + struct string_list *expr = copy_list_range(*$3, *$2); + add_symbol(name, SYM_ENUM_CONST, expr, 0); + } + asm_definition: ASM_PHRASE ';' { $$ = $2; } ; -- GitLab From 303fc01fb12d95cf9ab88c496df6651c887cef3c Mon Sep 17 00:00:00 2001 From: Michal Marek Date: Tue, 15 Feb 2011 16:04:35 +0100 Subject: [PATCH 0806/2822] genksyms: Regenerate lexer and parser Regenerated the parser after "genksyms: Track changes to enum constants". Signed-off-by: Michal Marek Acked-by: Sam Ravnborg --- scripts/genksyms/lex.c_shipped | 30 +- scripts/genksyms/parse.c_shipped | 1071 +++++++++++++++++------------- scripts/genksyms/parse.h_shipped | 72 +- 3 files changed, 661 insertions(+), 512 deletions(-) diff --git a/scripts/genksyms/lex.c_shipped b/scripts/genksyms/lex.c_shipped index f231c0810c602..af4939041e4b6 100644 --- a/scripts/genksyms/lex.c_shipped +++ b/scripts/genksyms/lex.c_shipped @@ -2253,12 +2253,23 @@ void yyfree (void * ptr ) /* Macros to append to our phrase collection list. */ +/* + * We mark any token, that that equals to a known enumerator, as + * SYM_ENUM_CONST. The parser will change this for struct and union tags later, + * the only problem is struct and union members: + * enum e { a, b }; struct s { int a, b; } + * but in this case, the only effect will be, that the ABI checksums become + * more volatile, which is acceptable. Also, such collisions are quite rare, + * so far it was only observed in include/linux/telephony.h. + */ #define _APP(T,L) do { \ cur_node = next_node; \ next_node = xmalloc(sizeof(*next_node)); \ next_node->next = cur_node; \ cur_node->string = memcpy(xmalloc(L+1), T, L+1); \ - cur_node->tag = SYM_NORMAL; \ + cur_node->tag = \ + find_symbol(cur_node->string, SYM_ENUM_CONST, 1)?\ + SYM_ENUM_CONST : SYM_NORMAL ; \ } while (0) #define APP _APP(yytext, yyleng) @@ -2336,8 +2347,8 @@ repeat: case STRUCT_KEYW: case UNION_KEYW: - dont_want_brace_phrase = 3; case ENUM_KEYW: + dont_want_brace_phrase = 3; suppress_type_lookup = 2; goto fini; @@ -2466,7 +2477,20 @@ repeat: ++count; APP; goto repeat; - case ')': case ']': case '}': + case '}': + /* is this the last line of an enum declaration? */ + if (count == 0) + { + /* Put back the token we just read so's we can find it again + after registering the expression. */ + unput(token); + + lexstate = ST_NORMAL; + token = EXPRESSION_PHRASE; + break; + } + /* FALLTHRU */ + case ')': case ']': --count; APP; goto repeat; diff --git a/scripts/genksyms/parse.c_shipped b/scripts/genksyms/parse.c_shipped index 809b949e495b5..1a0b8607fb0e5 100644 --- a/scripts/genksyms/parse.c_shipped +++ b/scripts/genksyms/parse.c_shipped @@ -1,24 +1,23 @@ -/* A Bison parser, made by GNU Bison 2.3. */ -/* Skeleton implementation for Bison's Yacc-like parsers in C +/* A Bison parser, made by GNU Bison 2.4.1. */ - Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006 +/* Skeleton implementation for Bison's Yacc-like parsers in C + + Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify + + This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2, or (at your option) - any later version. - + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. */ + along with this program. If not, see . */ /* As a special exception, you may create a larger work that contains part or all of the Bison parser skeleton and distribute that work @@ -29,7 +28,7 @@ special exception, which will cause the skeleton and the resulting Bison output files to be licensed under the GNU General Public License without this special exception. - + This special exception was added by the Free Software Foundation in version 2.2 of Bison. */ @@ -47,7 +46,7 @@ #define YYBISON 1 /* Bison version. */ -#define YYBISON_VERSION "2.3" +#define YYBISON_VERSION "2.4.1" /* Skeleton name. */ #define YYSKELETON_NAME "yacc.c" @@ -55,11 +54,75 @@ /* Pure parsers. */ #define YYPURE 0 +/* Push parsers. */ +#define YYPUSH 0 + +/* Pull parsers. */ +#define YYPULL 1 + /* Using locations. */ #define YYLSP_NEEDED 0 +/* Copy the first part of user declarations. */ + +/* Line 189 of yacc.c */ +#line 24 "scripts/genksyms/parse.y" + + +#include +#include +#include +#include "genksyms.h" + +static int is_typedef; +static int is_extern; +static char *current_name; +static struct string_list *decl_spec; + +static void yyerror(const char *); + +static inline void +remove_node(struct string_list **p) +{ + struct string_list *node = *p; + *p = node->next; + free_node(node); +} + +static inline void +remove_list(struct string_list **pb, struct string_list **pe) +{ + struct string_list *b = *pb, *e = *pe; + *pb = e; + free_list(b, e); +} + + + +/* Line 189 of yacc.c */ +#line 106 "scripts/genksyms/parse.c" + +/* Enabling traces. */ +#ifndef YYDEBUG +# define YYDEBUG 1 +#endif + +/* Enabling verbose error messages. */ +#ifdef YYERROR_VERBOSE +# undef YYERROR_VERBOSE +# define YYERROR_VERBOSE 1 +#else +# define YYERROR_VERBOSE 0 +#endif + +/* Enabling the token table. */ +#ifndef YYTOKEN_TABLE +# define YYTOKEN_TABLE 0 +#endif + + /* Tokens. */ #ifndef YYTOKENTYPE # define YYTOKENTYPE @@ -109,117 +172,22 @@ FILENAME = 298 }; #endif -/* Tokens. */ -#define ASM_KEYW 258 -#define ATTRIBUTE_KEYW 259 -#define AUTO_KEYW 260 -#define BOOL_KEYW 261 -#define CHAR_KEYW 262 -#define CONST_KEYW 263 -#define DOUBLE_KEYW 264 -#define ENUM_KEYW 265 -#define EXTERN_KEYW 266 -#define EXTENSION_KEYW 267 -#define FLOAT_KEYW 268 -#define INLINE_KEYW 269 -#define INT_KEYW 270 -#define LONG_KEYW 271 -#define REGISTER_KEYW 272 -#define RESTRICT_KEYW 273 -#define SHORT_KEYW 274 -#define SIGNED_KEYW 275 -#define STATIC_KEYW 276 -#define STRUCT_KEYW 277 -#define TYPEDEF_KEYW 278 -#define UNION_KEYW 279 -#define UNSIGNED_KEYW 280 -#define VOID_KEYW 281 -#define VOLATILE_KEYW 282 -#define TYPEOF_KEYW 283 -#define EXPORT_SYMBOL_KEYW 284 -#define ASM_PHRASE 285 -#define ATTRIBUTE_PHRASE 286 -#define BRACE_PHRASE 287 -#define BRACKET_PHRASE 288 -#define EXPRESSION_PHRASE 289 -#define CHAR 290 -#define DOTS 291 -#define IDENT 292 -#define INT 293 -#define REAL 294 -#define STRING 295 -#define TYPE 296 -#define OTHER 297 -#define FILENAME 298 - - - - -/* Copy the first part of user declarations. */ -#line 24 "scripts/genksyms/parse.y" - - -#include -#include -#include "genksyms.h" - -static int is_typedef; -static int is_extern; -static char *current_name; -static struct string_list *decl_spec; - -static void yyerror(const char *); - -static inline void -remove_node(struct string_list **p) -{ - struct string_list *node = *p; - *p = node->next; - free_node(node); -} - -static inline void -remove_list(struct string_list **pb, struct string_list **pe) -{ - struct string_list *b = *pb, *e = *pe; - *pb = e; - free_list(b, e); -} - - - -/* Enabling traces. */ -#ifndef YYDEBUG -# define YYDEBUG 1 -#endif -/* Enabling verbose error messages. */ -#ifdef YYERROR_VERBOSE -# undef YYERROR_VERBOSE -# define YYERROR_VERBOSE 1 -#else -# define YYERROR_VERBOSE 0 -#endif -/* Enabling the token table. */ -#ifndef YYTOKEN_TABLE -# define YYTOKEN_TABLE 0 -#endif #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED typedef int YYSTYPE; +# define YYSTYPE_IS_TRIVIAL 1 # define yystype YYSTYPE /* obsolescent; will be withdrawn */ # define YYSTYPE_IS_DECLARED 1 -# define YYSTYPE_IS_TRIVIAL 1 #endif - /* Copy the second part of user declarations. */ -/* Line 216 of yacc.c. */ -#line 223 "scripts/genksyms/parse.c" +/* Line 264 of yacc.c */ +#line 191 "scripts/genksyms/parse.c" #ifdef short # undef short @@ -294,14 +262,14 @@ typedef short int yytype_int16; #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) static int -YYID (int i) +YYID (int yyi) #else static int -YYID (i) - int i; +YYID (yyi) + int yyi; #endif { - return i; + return yyi; } #endif @@ -382,9 +350,9 @@ void free (void *); /* INFRINGES ON USER NAME SPACE */ /* A type that is properly aligned for any stack member. */ union yyalloc { - yytype_int16 yyss; - YYSTYPE yyvs; - }; + yytype_int16 yyss_alloc; + YYSTYPE yyvs_alloc; +}; /* The size of the maximum gap between one aligned stack and the next. */ # define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1) @@ -418,12 +386,12 @@ union yyalloc elements in the stack, and YYPTR gives the new location of the stack. Advance YYPTR to a properly aligned location for the next stack. */ -# define YYSTACK_RELOCATE(Stack) \ +# define YYSTACK_RELOCATE(Stack_alloc, Stack) \ do \ { \ YYSIZE_T yynewbytes; \ - YYCOPY (&yyptr->Stack, Stack, yysize); \ - Stack = &yyptr->Stack; \ + YYCOPY (&yyptr->Stack_alloc, Stack, yysize); \ + Stack = &yyptr->Stack_alloc; \ yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \ yyptr += yynewbytes / sizeof (*yyptr); \ } \ @@ -434,16 +402,16 @@ union yyalloc /* YYFINAL -- State number of the termination state. */ #define YYFINAL 4 /* YYLAST -- Last index in YYTABLE. */ -#define YYLAST 523 +#define YYLAST 532 /* YYNTOKENS -- Number of terminals. */ #define YYNTOKENS 53 /* YYNNTS -- Number of nonterminals. */ -#define YYNNTS 46 +#define YYNNTS 49 /* YYNRULES -- Number of rules. */ -#define YYNRULES 126 +#define YYNRULES 132 /* YYNRULES -- Number of states. */ -#define YYNSTATES 178 +#define YYNSTATES 188 /* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */ #define YYUNDEFTOK 2 @@ -504,7 +472,8 @@ static const yytype_uint16 yyprhs[] = 239, 242, 245, 247, 248, 250, 252, 257, 262, 265, 269, 273, 277, 278, 280, 283, 287, 291, 292, 294, 296, 299, 303, 306, 307, 309, 311, 315, 318, 321, - 323, 326, 327, 330, 333, 334, 336 + 323, 326, 327, 330, 334, 339, 341, 345, 347, 351, + 354, 355, 357 }; /* YYRHS -- A `-1'-separated list of the rules' RHS. */ @@ -512,16 +481,16 @@ static const yytype_int8 yyrhs[] = { 54, 0, -1, 55, -1, 54, 55, -1, -1, 56, 57, -1, -1, 12, 23, 58, 60, -1, -1, 23, - 59, 60, -1, 60, -1, 84, -1, 96, -1, 98, + 59, 60, -1, 60, -1, 84, -1, 99, -1, 101, -1, 1, 44, -1, 1, 45, -1, 64, 61, 44, -1, -1, 62, -1, 63, -1, 62, 46, 63, -1, - 74, 97, 95, 85, -1, -1, 65, -1, 66, -1, + 74, 100, 95, 85, -1, -1, 65, -1, 66, -1, 65, 66, -1, 67, -1, 68, -1, 5, -1, 17, -1, 21, -1, 11, -1, 14, -1, 69, -1, 73, -1, 28, 47, 65, 48, 49, -1, 28, 47, 65, 49, -1, 22, 37, -1, 24, 37, -1, 10, 37, -1, 22, 37, 87, -1, 24, 37, 87, -1, 10, - 37, 32, -1, 10, 32, -1, 22, 87, -1, 24, + 37, 96, -1, 10, 96, -1, 22, 87, -1, 24, 87, -1, 7, -1, 19, -1, 15, -1, 16, -1, 20, -1, 25, -1, 13, -1, 9, -1, 26, -1, 6, -1, 41, -1, 48, 71, -1, -1, 72, -1, @@ -543,26 +512,29 @@ static const yytype_int8 yyrhs[] = 91, 44, -1, 1, 44, -1, -1, 92, -1, 93, -1, 92, 46, 93, -1, 76, 95, -1, 37, 94, -1, 94, -1, 52, 34, -1, -1, 95, 31, -1, - 30, 44, -1, -1, 30, -1, 29, 47, 37, 49, - 44, -1 + 51, 97, 45, -1, 51, 97, 46, 45, -1, 98, + -1, 97, 46, 98, -1, 37, -1, 37, 50, 34, + -1, 30, 44, -1, -1, 30, -1, 29, 47, 37, + 49, 44, -1 }; /* YYRLINE[YYN] -- source line where rule number YYN was defined. */ static const yytype_uint16 yyrline[] = { - 0, 103, 103, 104, 108, 108, 114, 114, 116, 116, - 118, 119, 120, 121, 122, 123, 127, 141, 142, 146, - 154, 167, 173, 174, 178, 179, 183, 189, 193, 194, - 195, 196, 197, 201, 202, 203, 204, 208, 210, 212, - 216, 223, 230, 239, 240, 241, 245, 246, 247, 248, - 249, 250, 251, 252, 253, 254, 255, 259, 264, 265, - 269, 270, 274, 274, 274, 275, 283, 284, 288, 297, - 299, 301, 303, 305, 312, 313, 317, 318, 319, 321, - 323, 325, 327, 332, 333, 334, 338, 339, 343, 344, - 349, 354, 356, 360, 361, 369, 373, 375, 377, 379, - 381, 386, 395, 396, 401, 406, 407, 411, 412, 416, - 417, 421, 423, 428, 429, 433, 434, 438, 439, 440, - 444, 448, 449, 453, 457, 458, 462 + 0, 104, 104, 105, 109, 109, 115, 115, 117, 117, + 119, 120, 121, 122, 123, 124, 128, 142, 143, 147, + 155, 168, 174, 175, 179, 180, 184, 190, 194, 195, + 196, 197, 198, 202, 203, 204, 205, 209, 211, 213, + 217, 224, 231, 241, 244, 245, 249, 250, 251, 252, + 253, 254, 255, 256, 257, 258, 259, 263, 268, 269, + 273, 274, 278, 278, 278, 279, 287, 288, 292, 301, + 303, 305, 307, 309, 316, 317, 321, 322, 323, 325, + 327, 329, 331, 336, 337, 338, 342, 343, 347, 348, + 353, 358, 360, 364, 365, 373, 377, 379, 381, 383, + 385, 390, 399, 400, 405, 410, 411, 415, 416, 420, + 421, 425, 427, 432, 433, 437, 438, 442, 443, 444, + 448, 452, 453, 457, 458, 462, 463, 466, 471, 479, + 483, 484, 488 }; #endif @@ -581,8 +553,8 @@ static const char *const yytname[] = "ATTRIBUTE_PHRASE", "BRACE_PHRASE", "BRACKET_PHRASE", "EXPRESSION_PHRASE", "CHAR", "DOTS", "IDENT", "INT", "REAL", "STRING", "TYPE", "OTHER", "FILENAME", "';'", "'}'", "','", "'('", "'*'", "')'", - "'='", "'{'", "':'", "$accept", "declaration_seq", "declaration", "@1", - "declaration1", "@2", "@3", "simple_declaration", + "'='", "'{'", "':'", "$accept", "declaration_seq", "declaration", "$@1", + "declaration1", "$@2", "$@3", "simple_declaration", "init_declarator_list_opt", "init_declarator_list", "init_declarator", "decl_specifier_seq_opt", "decl_specifier_seq", "decl_specifier", "storage_class_specifier", "type_specifier", "simple_type_specifier", @@ -596,7 +568,8 @@ static const char *const yytname[] = "member_specification", "member_declaration", "member_declarator_list_opt", "member_declarator_list", "member_declarator", "member_bitfield_declarator", "attribute_opt", - "asm_definition", "asm_phrase_opt", "export_definition", 0 + "enum_body", "enumerator_list", "enumerator", "asm_definition", + "asm_phrase_opt", "export_definition", 0 }; #endif @@ -629,7 +602,8 @@ static const yytype_uint8 yyr1[] = 81, 82, 82, 83, 83, 83, 83, 83, 83, 83, 83, 84, 85, 85, 86, 87, 87, 88, 88, 89, 89, 90, 90, 91, 91, 92, 92, 93, 93, 93, - 94, 95, 95, 96, 97, 97, 98 + 94, 95, 95, 96, 96, 97, 97, 98, 98, 99, + 100, 100, 101 }; /* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */ @@ -647,7 +621,8 @@ static const yytype_uint8 yyr2[] = 2, 2, 1, 0, 1, 1, 4, 4, 2, 3, 3, 3, 0, 1, 2, 3, 3, 0, 1, 1, 2, 3, 2, 0, 1, 1, 3, 2, 2, 1, - 2, 0, 2, 2, 0, 1, 5 + 2, 0, 2, 3, 4, 1, 3, 1, 3, 2, + 0, 1, 5 }; /* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state @@ -659,17 +634,18 @@ static const yytype_uint8 yydefact[] = 62, 53, 0, 31, 0, 52, 32, 48, 49, 29, 65, 47, 50, 30, 0, 8, 0, 51, 54, 63, 0, 0, 0, 64, 56, 5, 10, 17, 23, 24, - 26, 27, 33, 34, 11, 12, 13, 14, 15, 43, - 39, 6, 37, 0, 44, 22, 38, 45, 0, 0, - 123, 68, 0, 58, 0, 18, 19, 0, 124, 67, - 25, 42, 22, 40, 0, 113, 0, 0, 109, 9, - 17, 41, 0, 0, 0, 0, 57, 59, 60, 16, - 0, 66, 125, 101, 121, 71, 0, 7, 112, 106, - 76, 77, 0, 0, 0, 121, 75, 0, 114, 115, - 119, 105, 0, 110, 124, 0, 36, 0, 73, 72, - 61, 20, 102, 0, 93, 0, 84, 87, 88, 118, + 26, 27, 33, 34, 11, 12, 13, 14, 15, 39, + 0, 43, 6, 37, 0, 44, 22, 38, 45, 0, + 0, 129, 68, 0, 58, 0, 18, 19, 0, 130, + 67, 25, 42, 127, 0, 125, 22, 40, 0, 113, + 0, 0, 109, 9, 17, 41, 0, 0, 0, 0, + 57, 59, 60, 16, 0, 66, 131, 101, 121, 71, + 0, 0, 123, 0, 7, 112, 106, 76, 77, 0, + 0, 0, 121, 75, 0, 114, 115, 119, 105, 0, + 110, 130, 0, 36, 0, 73, 72, 61, 20, 102, + 0, 93, 0, 84, 87, 88, 128, 124, 126, 118, 0, 76, 0, 120, 74, 117, 80, 0, 111, 0, - 35, 126, 122, 0, 21, 103, 70, 94, 56, 0, + 35, 132, 122, 0, 21, 103, 70, 94, 56, 0, 93, 90, 92, 69, 83, 0, 82, 81, 0, 0, 116, 104, 0, 95, 0, 91, 98, 0, 85, 89, 79, 78, 100, 99, 0, 0, 97, 96 @@ -678,46 +654,47 @@ static const yytype_uint8 yydefact[] = /* YYDEFGOTO[NTERM-NUM]. */ static const yytype_int16 yydefgoto[] = { - -1, 1, 2, 3, 35, 72, 55, 36, 64, 65, - 66, 75, 38, 39, 40, 41, 42, 67, 86, 87, - 43, 114, 69, 105, 106, 125, 126, 127, 128, 151, - 152, 44, 144, 145, 54, 76, 77, 78, 107, 108, - 109, 110, 122, 45, 94, 46 + -1, 1, 2, 3, 35, 76, 56, 36, 65, 66, + 67, 79, 38, 39, 40, 41, 42, 68, 90, 91, + 43, 121, 70, 112, 113, 132, 133, 134, 135, 161, + 162, 44, 154, 155, 55, 80, 81, 82, 114, 115, + 116, 117, 129, 51, 74, 75, 45, 98, 46 }; /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing STATE-NUM. */ -#define YYPACT_NINF -134 +#define YYPACT_NINF -135 static const yytype_int16 yypact[] = { - -134, 16, -134, 312, -134, -134, 20, -134, -134, -134, - -134, -134, -18, -134, -3, -134, -134, -134, -134, -134, - -134, -134, -134, -134, -26, -134, -25, -134, -134, -134, - -7, 5, 27, -134, -134, -134, -134, 46, 482, -134, - -134, -134, -134, -134, -134, -134, -134, -134, -134, -134, - -8, -134, 30, 97, -134, 482, 30, -134, 482, 7, - -134, -134, 12, 10, 42, 55, -134, 46, -15, 15, - -134, -134, 482, -134, 25, 26, 47, 145, -134, -134, - 46, -134, 356, 39, 71, 77, -134, 10, -134, -134, - 46, -134, -134, -134, -134, -134, 193, -134, -134, -134, - 75, -134, 6, 95, 43, -134, 28, 86, 85, -134, - -134, -134, 88, -134, 103, 87, -134, 91, -134, -134, - -134, -134, -23, 90, 401, 94, 101, 102, -134, -134, - 98, -134, 108, -134, -134, 109, -134, 230, -134, 26, - -134, -134, -134, 134, -134, -134, -134, -134, -134, 9, - 48, -134, 35, -134, -134, 445, -134, -134, 125, 126, - -134, -134, 128, -134, 129, -134, -134, 267, -134, -134, - -134, -134, -134, -134, 130, 131, -134, -134 + -135, 20, -135, 321, -135, -135, 30, -135, -135, -135, + -135, -135, -28, -135, 2, -135, -135, -135, -135, -135, + -135, -135, -135, -135, -6, -135, 9, -135, -135, -135, + -5, 15, -17, -135, -135, -135, -135, 18, 491, -135, + -135, -135, -135, -135, -135, -135, -135, -135, -135, -22, + 31, -135, -135, 19, 106, -135, 491, 19, -135, 491, + 50, -135, -135, 11, -3, 51, 57, -135, 18, -14, + 14, -135, -135, 48, 46, -135, 491, -135, 33, 32, + 59, 154, -135, -135, 18, -135, 365, 56, 60, 61, + -135, -3, -135, -135, 18, -135, -135, -135, -135, -135, + 202, 74, -135, -23, -135, -135, -135, 77, -135, 16, + 101, 49, -135, 34, 92, 93, -135, -135, -135, 94, + -135, 110, 95, -135, 97, -135, -135, -135, -135, -20, + 96, 410, 99, 113, 100, -135, -135, -135, -135, -135, + 103, -135, 107, -135, -135, 111, -135, 239, -135, 32, + -135, -135, -135, 123, -135, -135, -135, -135, -135, 3, + 52, -135, 38, -135, -135, 454, -135, -135, 117, 128, + -135, -135, 134, -135, 135, -135, -135, 276, -135, -135, + -135, -135, -135, -135, 137, 138, -135, -135 }; /* YYPGOTO[NTERM-NUM]. */ static const yytype_int16 yypgoto[] = { - -134, -134, 180, -134, -134, -134, -134, -33, -134, -134, - 93, 0, -58, -37, -134, -134, -134, -73, -134, -134, - -54, -32, -134, -81, -134, -133, -134, -134, 29, -50, - -134, -134, -134, -134, -20, -134, -134, 110, -134, -134, - 49, 96, 80, -134, -134, -134 + -135, -135, 187, -135, -135, -135, -135, -50, -135, -135, + 98, 0, -59, -37, -135, -135, -135, -77, -135, -135, + -54, -30, -135, -90, -135, -134, -135, -135, 24, -58, + -135, -135, -135, -135, -18, -135, -135, 109, -135, -135, + 44, 87, 84, 148, -135, 102, -135, -135, -135 }; /* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If @@ -727,116 +704,118 @@ static const yytype_int16 yypgoto[] = #define YYTABLE_NINF -109 static const yytype_int16 yytable[] = { - 82, 70, 104, 37, 159, 68, 57, 130, 142, 88, - 162, 52, 56, 84, 49, 92, 4, 93, 10, 50, - 51, 132, 79, 134, 71, 53, 53, 143, 20, 104, - 85, 104, 73, 120, 175, 91, 81, 29, 124, 97, - 58, 33, -93, 131, 83, 70, 147, 101, 95, 61, - 163, 150, 59, 102, 63, 80, 149, 63, -93, 62, - 63, 136, 96, 100, 47, 48, 104, 101, 166, 98, - 99, 60, 80, 102, 63, 137, 150, 150, 103, 124, - 131, 53, 167, 61, 101, 147, 89, 70, 117, 163, - 102, 63, 111, 62, 63, 149, 63, 124, 74, 164, - 165, 90, 7, 8, 9, 10, 11, 12, 13, 124, - 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, - 118, 26, 27, 28, 29, 30, 119, 103, 33, 133, - 138, 139, 98, 92, -22, 141, 140, 154, 34, 146, - 142, -22, -107, 153, -22, -22, 112, 156, 155, -22, - 7, 8, 9, 10, 11, 12, 13, 157, 15, 16, - 17, 18, 19, 20, 21, 22, 23, 24, 161, 26, - 27, 28, 29, 30, 170, 171, 33, 172, 173, 176, - 177, 5, -22, 121, 169, 135, 34, 113, 160, -22, - -108, 0, -22, -22, 123, 0, 129, -22, 7, 8, - 9, 10, 11, 12, 13, 0, 15, 16, 17, 18, - 19, 20, 21, 22, 23, 24, 0, 26, 27, 28, - 29, 30, 0, 0, 33, 0, 0, 0, 0, -86, - 0, 158, 0, 0, 34, 7, 8, 9, 10, 11, - 12, 13, -86, 15, 16, 17, 18, 19, 20, 21, - 22, 23, 24, 0, 26, 27, 28, 29, 30, 0, - 0, 33, 0, 0, 0, 0, -86, 0, 174, 0, - 0, 34, 7, 8, 9, 10, 11, 12, 13, -86, - 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, - 0, 26, 27, 28, 29, 30, 0, 0, 33, 0, - 0, 0, 0, -86, 0, 0, 0, 0, 34, 0, - 0, 0, 0, 6, 0, 0, -86, 7, 8, 9, - 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, - 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, - 30, 31, 32, 33, 0, 0, 0, 0, 0, -22, - 0, 0, 0, 34, 0, 0, -22, 0, 0, -22, - -22, 7, 8, 9, 10, 11, 12, 13, 0, 15, + 86, 71, 111, 37, 172, 10, 83, 69, 58, 49, + 92, 152, 88, 169, 73, 20, 96, 140, 97, 142, + 4, 144, 137, 50, 29, 52, 104, 61, 33, 50, + 153, 53, 111, 89, 111, 77, -93, 127, 95, 85, + 157, 131, 59, 185, 173, 54, 57, 99, 62, 71, + 159, 64, -93, 141, 160, 62, 84, 108, 63, 64, + 54, 100, 60, 109, 64, 63, 64, 146, 73, 107, + 54, 176, 111, 108, 47, 48, 84, 105, 106, 109, + 64, 147, 160, 160, 110, 177, 141, 87, 131, 157, + 108, 102, 103, 173, 71, 93, 109, 64, 101, 159, + 64, 174, 175, 94, 118, 124, 131, 78, 136, 125, + 126, 7, 8, 9, 10, 11, 12, 13, 131, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 110, + 26, 27, 28, 29, 30, 143, 148, 33, 105, 149, + 96, 151, 152, -22, 150, 156, 165, 34, 163, 164, + -22, -107, 166, -22, -22, 119, 167, 171, -22, 7, + 8, 9, 10, 11, 12, 13, 180, 15, 16, 17, + 18, 19, 20, 21, 22, 23, 24, 181, 26, 27, + 28, 29, 30, 182, 183, 33, 186, 187, 5, 179, + 120, -22, 128, 170, 139, 34, 145, 72, -22, -108, + 0, -22, -22, 130, 0, 138, -22, 7, 8, 9, + 10, 11, 12, 13, 0, 15, 16, 17, 18, 19, + 20, 21, 22, 23, 24, 0, 26, 27, 28, 29, + 30, 0, 0, 33, 0, 0, 0, 0, -86, 0, + 168, 0, 0, 34, 7, 8, 9, 10, 11, 12, + 13, -86, 15, 16, 17, 18, 19, 20, 21, 22, + 23, 24, 0, 26, 27, 28, 29, 30, 0, 0, + 33, 0, 0, 0, 0, -86, 0, 184, 0, 0, + 34, 7, 8, 9, 10, 11, 12, 13, -86, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 0, 26, 27, 28, 29, 30, 0, 0, 33, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 34, 0, 0, - 0, 0, 0, 0, 115, 116, 7, 8, 9, 10, - 11, 12, 13, 0, 15, 16, 17, 18, 19, 20, - 21, 22, 23, 24, 0, 26, 27, 28, 29, 30, - 0, 0, 33, 0, 0, 0, 0, 0, 147, 0, - 0, 0, 148, 0, 0, 0, 0, 0, 149, 63, + 0, 0, -86, 0, 0, 0, 0, 34, 0, 0, + 0, 0, 6, 0, 0, -86, 7, 8, 9, 10, + 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, + 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, + 31, 32, 33, 0, 0, 0, 0, 0, -22, 0, + 0, 0, 34, 0, 0, -22, 0, 0, -22, -22, 7, 8, 9, 10, 11, 12, 13, 0, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 0, 26, 27, 28, 29, 30, 0, 0, 33, 0, 0, 0, - 0, 168, 0, 0, 0, 0, 34, 7, 8, 9, - 10, 11, 12, 13, 0, 15, 16, 17, 18, 19, - 20, 21, 22, 23, 24, 0, 26, 27, 28, 29, - 30, 0, 0, 33, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 34 + 0, 0, 0, 0, 0, 0, 34, 0, 0, 0, + 0, 0, 0, 122, 123, 7, 8, 9, 10, 11, + 12, 13, 0, 15, 16, 17, 18, 19, 20, 21, + 22, 23, 24, 0, 26, 27, 28, 29, 30, 0, + 0, 33, 0, 0, 0, 0, 0, 157, 0, 0, + 0, 158, 0, 0, 0, 0, 0, 159, 64, 7, + 8, 9, 10, 11, 12, 13, 0, 15, 16, 17, + 18, 19, 20, 21, 22, 23, 24, 0, 26, 27, + 28, 29, 30, 0, 0, 33, 0, 0, 0, 0, + 178, 0, 0, 0, 0, 34, 7, 8, 9, 10, + 11, 12, 13, 0, 15, 16, 17, 18, 19, 20, + 21, 22, 23, 24, 0, 26, 27, 28, 29, 30, + 0, 0, 33, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 34 }; static const yytype_int16 yycheck[] = { - 58, 38, 75, 3, 137, 37, 26, 1, 31, 63, - 1, 37, 37, 1, 32, 30, 0, 32, 8, 37, - 23, 102, 55, 104, 32, 51, 51, 50, 18, 102, - 62, 104, 52, 87, 167, 67, 56, 27, 96, 72, - 47, 31, 33, 37, 37, 82, 37, 41, 33, 37, - 41, 124, 47, 47, 48, 55, 47, 48, 49, 47, - 48, 33, 47, 37, 44, 45, 139, 41, 33, 44, - 45, 44, 72, 47, 48, 47, 149, 150, 52, 137, - 37, 51, 47, 37, 41, 37, 44, 124, 49, 41, - 47, 48, 45, 47, 48, 47, 48, 155, 1, 149, - 150, 46, 5, 6, 7, 8, 9, 10, 11, 167, - 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, - 49, 24, 25, 26, 27, 28, 49, 52, 31, 34, - 44, 46, 44, 30, 37, 44, 49, 36, 41, 49, - 31, 44, 45, 49, 47, 48, 1, 49, 46, 52, - 5, 6, 7, 8, 9, 10, 11, 49, 13, 14, - 15, 16, 17, 18, 19, 20, 21, 22, 34, 24, - 25, 26, 27, 28, 49, 49, 31, 49, 49, 49, - 49, 1, 37, 90, 155, 105, 41, 77, 139, 44, - 45, -1, 47, 48, 1, -1, 100, 52, 5, 6, - 7, 8, 9, 10, 11, -1, 13, 14, 15, 16, - 17, 18, 19, 20, 21, 22, -1, 24, 25, 26, - 27, 28, -1, -1, 31, -1, -1, -1, -1, 36, - -1, 1, -1, -1, 41, 5, 6, 7, 8, 9, - 10, 11, 49, 13, 14, 15, 16, 17, 18, 19, - 20, 21, 22, -1, 24, 25, 26, 27, 28, -1, - -1, 31, -1, -1, -1, -1, 36, -1, 1, -1, - -1, 41, 5, 6, 7, 8, 9, 10, 11, 49, - 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, - -1, 24, 25, 26, 27, 28, -1, -1, 31, -1, - -1, -1, -1, 36, -1, -1, -1, -1, 41, -1, - -1, -1, -1, 1, -1, -1, 49, 5, 6, 7, - 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, - 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, - 28, 29, 30, 31, -1, -1, -1, -1, -1, 37, - -1, -1, -1, 41, -1, -1, 44, -1, -1, 47, - 48, 5, 6, 7, 8, 9, 10, 11, -1, 13, + 59, 38, 79, 3, 1, 8, 56, 37, 26, 37, + 64, 31, 1, 147, 37, 18, 30, 1, 32, 109, + 0, 111, 45, 51, 27, 23, 76, 44, 31, 51, + 50, 37, 109, 63, 111, 53, 33, 91, 68, 57, + 37, 100, 47, 177, 41, 51, 37, 33, 37, 86, + 47, 48, 49, 37, 131, 37, 56, 41, 47, 48, + 51, 47, 47, 47, 48, 47, 48, 33, 37, 37, + 51, 33, 149, 41, 44, 45, 76, 44, 45, 47, + 48, 47, 159, 160, 52, 47, 37, 37, 147, 37, + 41, 45, 46, 41, 131, 44, 47, 48, 50, 47, + 48, 159, 160, 46, 45, 49, 165, 1, 34, 49, + 49, 5, 6, 7, 8, 9, 10, 11, 177, 13, + 14, 15, 16, 17, 18, 19, 20, 21, 22, 52, + 24, 25, 26, 27, 28, 34, 44, 31, 44, 46, + 30, 44, 31, 37, 49, 49, 46, 41, 49, 36, + 44, 45, 49, 47, 48, 1, 49, 34, 52, 5, + 6, 7, 8, 9, 10, 11, 49, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 49, 24, 25, + 26, 27, 28, 49, 49, 31, 49, 49, 1, 165, + 81, 37, 94, 149, 107, 41, 112, 49, 44, 45, + -1, 47, 48, 1, -1, 103, 52, 5, 6, 7, + 8, 9, 10, 11, -1, 13, 14, 15, 16, 17, + 18, 19, 20, 21, 22, -1, 24, 25, 26, 27, + 28, -1, -1, 31, -1, -1, -1, -1, 36, -1, + 1, -1, -1, 41, 5, 6, 7, 8, 9, 10, + 11, 49, 13, 14, 15, 16, 17, 18, 19, 20, + 21, 22, -1, 24, 25, 26, 27, 28, -1, -1, + 31, -1, -1, -1, -1, 36, -1, 1, -1, -1, + 41, 5, 6, 7, 8, 9, 10, 11, 49, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, -1, 24, 25, 26, 27, 28, -1, -1, 31, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 41, -1, -1, - -1, -1, -1, -1, 48, 49, 5, 6, 7, 8, - 9, 10, 11, -1, 13, 14, 15, 16, 17, 18, - 19, 20, 21, 22, -1, 24, 25, 26, 27, 28, - -1, -1, 31, -1, -1, -1, -1, -1, 37, -1, - -1, -1, 41, -1, -1, -1, -1, -1, 47, 48, + -1, -1, 36, -1, -1, -1, -1, 41, -1, -1, + -1, -1, 1, -1, -1, 49, 5, 6, 7, 8, + 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, + 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, + 29, 30, 31, -1, -1, -1, -1, -1, 37, -1, + -1, -1, 41, -1, -1, 44, -1, -1, 47, 48, 5, 6, 7, 8, 9, 10, 11, -1, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, -1, 24, 25, 26, 27, 28, -1, -1, 31, -1, -1, -1, - -1, 36, -1, -1, -1, -1, 41, 5, 6, 7, - 8, 9, 10, 11, -1, 13, 14, 15, 16, 17, - 18, 19, 20, 21, 22, -1, 24, 25, 26, 27, - 28, -1, -1, 31, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 41 + -1, -1, -1, -1, -1, -1, 41, -1, -1, -1, + -1, -1, -1, 48, 49, 5, 6, 7, 8, 9, + 10, 11, -1, 13, 14, 15, 16, 17, 18, 19, + 20, 21, 22, -1, 24, 25, 26, 27, 28, -1, + -1, 31, -1, -1, -1, -1, -1, 37, -1, -1, + -1, 41, -1, -1, -1, -1, -1, 47, 48, 5, + 6, 7, 8, 9, 10, 11, -1, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, -1, 24, 25, + 26, 27, 28, -1, -1, 31, -1, -1, -1, -1, + 36, -1, -1, -1, -1, 41, 5, 6, 7, 8, + 9, 10, 11, -1, 13, 14, 15, 16, 17, 18, + 19, 20, 21, 22, -1, 24, 25, 26, 27, 28, + -1, -1, 31, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 41 }; /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing @@ -847,15 +826,16 @@ static const yytype_uint8 yystos[] = 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 41, 57, 60, 64, 65, 66, - 67, 68, 69, 73, 84, 96, 98, 44, 45, 32, - 37, 23, 37, 51, 87, 59, 37, 87, 47, 47, - 44, 37, 47, 48, 61, 62, 63, 70, 74, 75, - 66, 32, 58, 87, 1, 64, 88, 89, 90, 60, - 64, 87, 65, 37, 1, 74, 71, 72, 73, 44, - 46, 74, 30, 32, 97, 33, 47, 60, 44, 45, - 37, 41, 47, 52, 70, 76, 77, 91, 92, 93, - 94, 45, 1, 90, 74, 48, 49, 49, 49, 49, - 73, 63, 95, 1, 65, 78, 79, 80, 81, 94, + 67, 68, 69, 73, 84, 99, 101, 44, 45, 37, + 51, 96, 23, 37, 51, 87, 59, 37, 87, 47, + 47, 44, 37, 47, 48, 61, 62, 63, 70, 74, + 75, 66, 96, 37, 97, 98, 58, 87, 1, 64, + 88, 89, 90, 60, 64, 87, 65, 37, 1, 74, + 71, 72, 73, 44, 46, 74, 30, 32, 100, 33, + 47, 50, 45, 46, 60, 44, 45, 37, 41, 47, + 52, 70, 76, 77, 91, 92, 93, 94, 45, 1, + 90, 74, 48, 49, 49, 49, 49, 73, 63, 95, + 1, 65, 78, 79, 80, 81, 34, 45, 98, 94, 1, 37, 76, 34, 76, 95, 33, 47, 44, 46, 49, 44, 31, 50, 85, 86, 49, 37, 41, 47, 70, 82, 83, 49, 36, 46, 49, 49, 1, 78, @@ -1045,17 +1025,20 @@ yy_symbol_print (yyoutput, yytype, yyvaluep) #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) static void -yy_stack_print (yytype_int16 *bottom, yytype_int16 *top) +yy_stack_print (yytype_int16 *yybottom, yytype_int16 *yytop) #else static void -yy_stack_print (bottom, top) - yytype_int16 *bottom; - yytype_int16 *top; +yy_stack_print (yybottom, yytop) + yytype_int16 *yybottom; + yytype_int16 *yytop; #endif { YYFPRINTF (stderr, "Stack now"); - for (; bottom <= top; ++bottom) - YYFPRINTF (stderr, " %d", *bottom); + for (; yybottom <= yytop; yybottom++) + { + int yybot = *yybottom; + YYFPRINTF (stderr, " %d", yybot); + } YYFPRINTF (stderr, "\n"); } @@ -1089,11 +1072,11 @@ yy_reduce_print (yyvsp, yyrule) /* The symbols being reduced. */ for (yyi = 0; yyi < yynrhs; yyi++) { - fprintf (stderr, " $%d = ", yyi + 1); + YYFPRINTF (stderr, " $%d = ", yyi + 1); yy_symbol_print (stderr, yyrhs[yyprhs[yyrule] + yyi], &(yyvsp[(yyi + 1) - (yynrhs)]) ); - fprintf (stderr, "\n"); + YYFPRINTF (stderr, "\n"); } } @@ -1373,10 +1356,8 @@ yydestruct (yymsg, yytype, yyvaluep) break; } } - /* Prevent warnings from -Wmissing-prototypes. */ - #ifdef YYPARSE_PARAM #if defined __STDC__ || defined __cplusplus int yyparse (void *YYPARSE_PARAM); @@ -1392,11 +1373,10 @@ int yyparse (); #endif /* ! YYPARSE_PARAM */ - -/* The look-ahead symbol. */ +/* The lookahead symbol. */ int yychar; -/* The semantic value of the look-ahead symbol. */ +/* The semantic value of the lookahead symbol. */ YYSTYPE yylval; /* Number of syntax errors so far. */ @@ -1404,9 +1384,9 @@ int yynerrs; -/*----------. -| yyparse. | -`----------*/ +/*-------------------------. +| yyparse or yypush_parse. | +`-------------------------*/ #ifdef YYPARSE_PARAM #if (defined __STDC__ || defined __C99__FUNC__ \ @@ -1430,66 +1410,68 @@ yyparse () #endif #endif { - - int yystate; - int yyn; - int yyresult; - /* Number of tokens to shift before error messages enabled. */ - int yyerrstatus; - /* Look-ahead token as an internal (translated) token number. */ - int yytoken = 0; -#if YYERROR_VERBOSE - /* Buffer for error messages, and its allocated size. */ - char yymsgbuf[128]; - char *yymsg = yymsgbuf; - YYSIZE_T yymsg_alloc = sizeof yymsgbuf; -#endif - /* Three stacks and their tools: - `yyss': related to states, - `yyvs': related to semantic values, - `yyls': related to locations. - Refer to the stacks thru separate pointers, to allow yyoverflow - to reallocate them elsewhere. */ + int yystate; + /* Number of tokens to shift before error messages enabled. */ + int yyerrstatus; - /* The state stack. */ - yytype_int16 yyssa[YYINITDEPTH]; - yytype_int16 *yyss = yyssa; - yytype_int16 *yyssp; + /* The stacks and their tools: + `yyss': related to states. + `yyvs': related to semantic values. - /* The semantic value stack. */ - YYSTYPE yyvsa[YYINITDEPTH]; - YYSTYPE *yyvs = yyvsa; - YYSTYPE *yyvsp; + Refer to the stacks thru separate pointers, to allow yyoverflow + to reallocate them elsewhere. */ + /* The state stack. */ + yytype_int16 yyssa[YYINITDEPTH]; + yytype_int16 *yyss; + yytype_int16 *yyssp; + /* The semantic value stack. */ + YYSTYPE yyvsa[YYINITDEPTH]; + YYSTYPE *yyvs; + YYSTYPE *yyvsp; -#define YYPOPSTACK(N) (yyvsp -= (N), yyssp -= (N)) - - YYSIZE_T yystacksize = YYINITDEPTH; + YYSIZE_T yystacksize; + int yyn; + int yyresult; + /* Lookahead token as an internal (translated) token number. */ + int yytoken; /* The variables used to return semantic value and location from the action routines. */ YYSTYPE yyval; +#if YYERROR_VERBOSE + /* Buffer for error messages, and its allocated size. */ + char yymsgbuf[128]; + char *yymsg = yymsgbuf; + YYSIZE_T yymsg_alloc = sizeof yymsgbuf; +#endif + +#define YYPOPSTACK(N) (yyvsp -= (N), yyssp -= (N)) /* The number of symbols on the RHS of the reduced rule. Keep to zero when no symbol should be popped. */ int yylen = 0; + yytoken = 0; + yyss = yyssa; + yyvs = yyvsa; + yystacksize = YYINITDEPTH; + YYDPRINTF ((stderr, "Starting parse\n")); yystate = 0; yyerrstatus = 0; yynerrs = 0; - yychar = YYEMPTY; /* Cause a token to be read. */ + yychar = YYEMPTY; /* Cause a token to be read. */ /* Initialize stack pointers. Waste one element of value and location stack so that they stay on the same level as the state stack. The wasted elements are never initialized. */ - yyssp = yyss; yyvsp = yyvs; @@ -1519,7 +1501,6 @@ yyparse () YYSTYPE *yyvs1 = yyvs; yytype_int16 *yyss1 = yyss; - /* Each stack pointer address is followed by the size of the data in use in that stack, in bytes. This used to be a conditional around just the two extra args, but that might @@ -1527,7 +1508,6 @@ yyparse () yyoverflow (YY_("memory exhausted"), &yyss1, yysize * sizeof (*yyssp), &yyvs1, yysize * sizeof (*yyvsp), - &yystacksize); yyss = yyss1; @@ -1550,9 +1530,8 @@ yyparse () (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize)); if (! yyptr) goto yyexhaustedlab; - YYSTACK_RELOCATE (yyss); - YYSTACK_RELOCATE (yyvs); - + YYSTACK_RELOCATE (yyss_alloc, yyss); + YYSTACK_RELOCATE (yyvs_alloc, yyvs); # undef YYSTACK_RELOCATE if (yyss1 != yyssa) YYSTACK_FREE (yyss1); @@ -1563,7 +1542,6 @@ yyparse () yyssp = yyss + yysize - 1; yyvsp = yyvs + yysize - 1; - YYDPRINTF ((stderr, "Stack size increased to %lu\n", (unsigned long int) yystacksize)); @@ -1573,6 +1551,9 @@ yyparse () YYDPRINTF ((stderr, "Entering state %d\n", yystate)); + if (yystate == YYFINAL) + YYACCEPT; + goto yybackup; /*-----------. @@ -1581,16 +1562,16 @@ yyparse () yybackup: /* Do appropriate processing given the current state. Read a - look-ahead token if we need one and don't already have one. */ + lookahead token if we need one and don't already have one. */ - /* First try to decide what to do without reference to look-ahead token. */ + /* First try to decide what to do without reference to lookahead token. */ yyn = yypact[yystate]; if (yyn == YYPACT_NINF) goto yydefault; - /* Not known => get a look-ahead token if don't already have one. */ + /* Not known => get a lookahead token if don't already have one. */ - /* YYCHAR is either YYEMPTY or YYEOF or a valid look-ahead symbol. */ + /* YYCHAR is either YYEMPTY or YYEOF or a valid lookahead symbol. */ if (yychar == YYEMPTY) { YYDPRINTF ((stderr, "Reading a token: ")); @@ -1622,20 +1603,16 @@ yybackup: goto yyreduce; } - if (yyn == YYFINAL) - YYACCEPT; - /* Count tokens shifted since error; after three, turn off error status. */ if (yyerrstatus) yyerrstatus--; - /* Shift the look-ahead token. */ + /* Shift the lookahead token. */ YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc); - /* Discard the shifted token unless it is eof. */ - if (yychar != YYEOF) - yychar = YYEMPTY; + /* Discard the shifted token. */ + yychar = YYEMPTY; yystate = yyn; *++yyvsp = yylval; @@ -1675,47 +1652,65 @@ yyreduce: switch (yyn) { case 4: -#line 108 "scripts/genksyms/parse.y" + +/* Line 1455 of yacc.c */ +#line 109 "scripts/genksyms/parse.y" { is_typedef = 0; is_extern = 0; current_name = NULL; decl_spec = NULL; ;} break; case 5: -#line 110 "scripts/genksyms/parse.y" + +/* Line 1455 of yacc.c */ +#line 111 "scripts/genksyms/parse.y" { free_list(*(yyvsp[(2) - (2)]), NULL); *(yyvsp[(2) - (2)]) = NULL; ;} break; case 6: -#line 114 "scripts/genksyms/parse.y" + +/* Line 1455 of yacc.c */ +#line 115 "scripts/genksyms/parse.y" { is_typedef = 1; ;} break; case 7: -#line 115 "scripts/genksyms/parse.y" + +/* Line 1455 of yacc.c */ +#line 116 "scripts/genksyms/parse.y" { (yyval) = (yyvsp[(4) - (4)]); ;} break; case 8: -#line 116 "scripts/genksyms/parse.y" + +/* Line 1455 of yacc.c */ +#line 117 "scripts/genksyms/parse.y" { is_typedef = 1; ;} break; case 9: -#line 117 "scripts/genksyms/parse.y" + +/* Line 1455 of yacc.c */ +#line 118 "scripts/genksyms/parse.y" { (yyval) = (yyvsp[(3) - (3)]); ;} break; case 14: -#line 122 "scripts/genksyms/parse.y" + +/* Line 1455 of yacc.c */ +#line 123 "scripts/genksyms/parse.y" { (yyval) = (yyvsp[(2) - (2)]); ;} break; case 15: -#line 123 "scripts/genksyms/parse.y" + +/* Line 1455 of yacc.c */ +#line 124 "scripts/genksyms/parse.y" { (yyval) = (yyvsp[(2) - (2)]); ;} break; case 16: -#line 128 "scripts/genksyms/parse.y" + +/* Line 1455 of yacc.c */ +#line 129 "scripts/genksyms/parse.y" { if (current_name) { struct string_list *decl = (*(yyvsp[(3) - (3)]))->next; (*(yyvsp[(3) - (3)]))->next = NULL; @@ -1729,12 +1724,16 @@ yyreduce: break; case 17: -#line 141 "scripts/genksyms/parse.y" + +/* Line 1455 of yacc.c */ +#line 142 "scripts/genksyms/parse.y" { (yyval) = NULL; ;} break; case 19: -#line 147 "scripts/genksyms/parse.y" + +/* Line 1455 of yacc.c */ +#line 148 "scripts/genksyms/parse.y" { struct string_list *decl = *(yyvsp[(1) - (1)]); *(yyvsp[(1) - (1)]) = NULL; add_symbol(current_name, @@ -1745,7 +1744,9 @@ yyreduce: break; case 20: -#line 155 "scripts/genksyms/parse.y" + +/* Line 1455 of yacc.c */ +#line 156 "scripts/genksyms/parse.y" { struct string_list *decl = *(yyvsp[(3) - (3)]); *(yyvsp[(3) - (3)]) = NULL; free_list(*(yyvsp[(2) - (3)]), NULL); @@ -1758,27 +1759,37 @@ yyreduce: break; case 21: -#line 168 "scripts/genksyms/parse.y" + +/* Line 1455 of yacc.c */ +#line 169 "scripts/genksyms/parse.y" { (yyval) = (yyvsp[(4) - (4)]) ? (yyvsp[(4) - (4)]) : (yyvsp[(3) - (4)]) ? (yyvsp[(3) - (4)]) : (yyvsp[(2) - (4)]) ? (yyvsp[(2) - (4)]) : (yyvsp[(1) - (4)]); ;} break; case 22: -#line 173 "scripts/genksyms/parse.y" + +/* Line 1455 of yacc.c */ +#line 174 "scripts/genksyms/parse.y" { decl_spec = NULL; ;} break; case 24: -#line 178 "scripts/genksyms/parse.y" + +/* Line 1455 of yacc.c */ +#line 179 "scripts/genksyms/parse.y" { decl_spec = *(yyvsp[(1) - (1)]); ;} break; case 25: -#line 179 "scripts/genksyms/parse.y" + +/* Line 1455 of yacc.c */ +#line 180 "scripts/genksyms/parse.y" { decl_spec = *(yyvsp[(2) - (2)]); ;} break; case 26: -#line 184 "scripts/genksyms/parse.y" + +/* Line 1455 of yacc.c */ +#line 185 "scripts/genksyms/parse.y" { /* Version 2 checksumming ignores storage class, as that is really irrelevant to the linkage. */ remove_node((yyvsp[(1) - (1)])); @@ -1787,32 +1798,44 @@ yyreduce: break; case 31: -#line 196 "scripts/genksyms/parse.y" + +/* Line 1455 of yacc.c */ +#line 197 "scripts/genksyms/parse.y" { is_extern = 1; (yyval) = (yyvsp[(1) - (1)]); ;} break; case 32: -#line 197 "scripts/genksyms/parse.y" + +/* Line 1455 of yacc.c */ +#line 198 "scripts/genksyms/parse.y" { is_extern = 0; (yyval) = (yyvsp[(1) - (1)]); ;} break; case 37: -#line 209 "scripts/genksyms/parse.y" + +/* Line 1455 of yacc.c */ +#line 210 "scripts/genksyms/parse.y" { remove_node((yyvsp[(1) - (2)])); (*(yyvsp[(2) - (2)]))->tag = SYM_STRUCT; (yyval) = (yyvsp[(2) - (2)]); ;} break; case 38: -#line 211 "scripts/genksyms/parse.y" + +/* Line 1455 of yacc.c */ +#line 212 "scripts/genksyms/parse.y" { remove_node((yyvsp[(1) - (2)])); (*(yyvsp[(2) - (2)]))->tag = SYM_UNION; (yyval) = (yyvsp[(2) - (2)]); ;} break; case 39: -#line 213 "scripts/genksyms/parse.y" + +/* Line 1455 of yacc.c */ +#line 214 "scripts/genksyms/parse.y" { remove_node((yyvsp[(1) - (2)])); (*(yyvsp[(2) - (2)]))->tag = SYM_ENUM; (yyval) = (yyvsp[(2) - (2)]); ;} break; case 40: -#line 217 "scripts/genksyms/parse.y" + +/* Line 1455 of yacc.c */ +#line 218 "scripts/genksyms/parse.y" { struct string_list *s = *(yyvsp[(3) - (3)]), *i = *(yyvsp[(2) - (3)]), *r; r = copy_node(i); r->tag = SYM_STRUCT; r->next = (*(yyvsp[(1) - (3)]))->next; *(yyvsp[(3) - (3)]) = r; (*(yyvsp[(1) - (3)]))->next = NULL; @@ -1822,7 +1845,9 @@ yyreduce: break; case 41: -#line 224 "scripts/genksyms/parse.y" + +/* Line 1455 of yacc.c */ +#line 225 "scripts/genksyms/parse.y" { struct string_list *s = *(yyvsp[(3) - (3)]), *i = *(yyvsp[(2) - (3)]), *r; r = copy_node(i); r->tag = SYM_UNION; r->next = (*(yyvsp[(1) - (3)]))->next; *(yyvsp[(3) - (3)]) = r; (*(yyvsp[(1) - (3)]))->next = NULL; @@ -1832,7 +1857,9 @@ yyreduce: break; case 42: -#line 231 "scripts/genksyms/parse.y" + +/* Line 1455 of yacc.c */ +#line 232 "scripts/genksyms/parse.y" { struct string_list *s = *(yyvsp[(3) - (3)]), *i = *(yyvsp[(2) - (3)]), *r; r = copy_node(i); r->tag = SYM_ENUM; r->next = (*(yyvsp[(1) - (3)]))->next; *(yyvsp[(3) - (3)]) = r; (*(yyvsp[(1) - (3)]))->next = NULL; @@ -1842,42 +1869,58 @@ yyreduce: break; case 43: -#line 239 "scripts/genksyms/parse.y" - { (yyval) = (yyvsp[(2) - (2)]); ;} + +/* Line 1455 of yacc.c */ +#line 242 "scripts/genksyms/parse.y" + { add_symbol(NULL, SYM_ENUM, NULL, 0); (yyval) = (yyvsp[(2) - (2)]); ;} break; case 44: -#line 240 "scripts/genksyms/parse.y" + +/* Line 1455 of yacc.c */ +#line 244 "scripts/genksyms/parse.y" { (yyval) = (yyvsp[(2) - (2)]); ;} break; case 45: -#line 241 "scripts/genksyms/parse.y" + +/* Line 1455 of yacc.c */ +#line 245 "scripts/genksyms/parse.y" { (yyval) = (yyvsp[(2) - (2)]); ;} break; case 56: -#line 255 "scripts/genksyms/parse.y" + +/* Line 1455 of yacc.c */ +#line 259 "scripts/genksyms/parse.y" { (*(yyvsp[(1) - (1)]))->tag = SYM_TYPEDEF; (yyval) = (yyvsp[(1) - (1)]); ;} break; case 57: -#line 260 "scripts/genksyms/parse.y" + +/* Line 1455 of yacc.c */ +#line 264 "scripts/genksyms/parse.y" { (yyval) = (yyvsp[(2) - (2)]) ? (yyvsp[(2) - (2)]) : (yyvsp[(1) - (2)]); ;} break; case 58: -#line 264 "scripts/genksyms/parse.y" + +/* Line 1455 of yacc.c */ +#line 268 "scripts/genksyms/parse.y" { (yyval) = NULL; ;} break; case 61: -#line 270 "scripts/genksyms/parse.y" + +/* Line 1455 of yacc.c */ +#line 274 "scripts/genksyms/parse.y" { (yyval) = (yyvsp[(2) - (2)]); ;} break; case 65: -#line 276 "scripts/genksyms/parse.y" + +/* Line 1455 of yacc.c */ +#line 280 "scripts/genksyms/parse.y" { /* restrict has no effect in prototypes so ignore it */ remove_node((yyvsp[(1) - (1)])); (yyval) = (yyvsp[(1) - (1)]); @@ -1885,12 +1928,16 @@ yyreduce: break; case 66: -#line 283 "scripts/genksyms/parse.y" + +/* Line 1455 of yacc.c */ +#line 287 "scripts/genksyms/parse.y" { (yyval) = (yyvsp[(2) - (2)]); ;} break; case 68: -#line 289 "scripts/genksyms/parse.y" + +/* Line 1455 of yacc.c */ +#line 293 "scripts/genksyms/parse.y" { if (current_name != NULL) { error_with_pos("unexpected second declaration name"); YYERROR; @@ -1902,97 +1949,135 @@ yyreduce: break; case 69: -#line 298 "scripts/genksyms/parse.y" + +/* Line 1455 of yacc.c */ +#line 302 "scripts/genksyms/parse.y" { (yyval) = (yyvsp[(4) - (4)]); ;} break; case 70: -#line 300 "scripts/genksyms/parse.y" + +/* Line 1455 of yacc.c */ +#line 304 "scripts/genksyms/parse.y" { (yyval) = (yyvsp[(4) - (4)]); ;} break; case 71: -#line 302 "scripts/genksyms/parse.y" + +/* Line 1455 of yacc.c */ +#line 306 "scripts/genksyms/parse.y" { (yyval) = (yyvsp[(2) - (2)]); ;} break; case 72: -#line 304 "scripts/genksyms/parse.y" + +/* Line 1455 of yacc.c */ +#line 308 "scripts/genksyms/parse.y" { (yyval) = (yyvsp[(3) - (3)]); ;} break; case 73: -#line 306 "scripts/genksyms/parse.y" + +/* Line 1455 of yacc.c */ +#line 310 "scripts/genksyms/parse.y" { (yyval) = (yyvsp[(3) - (3)]); ;} break; case 74: -#line 312 "scripts/genksyms/parse.y" + +/* Line 1455 of yacc.c */ +#line 316 "scripts/genksyms/parse.y" { (yyval) = (yyvsp[(2) - (2)]); ;} break; case 78: -#line 320 "scripts/genksyms/parse.y" + +/* Line 1455 of yacc.c */ +#line 324 "scripts/genksyms/parse.y" { (yyval) = (yyvsp[(4) - (4)]); ;} break; case 79: -#line 322 "scripts/genksyms/parse.y" + +/* Line 1455 of yacc.c */ +#line 326 "scripts/genksyms/parse.y" { (yyval) = (yyvsp[(4) - (4)]); ;} break; case 80: -#line 324 "scripts/genksyms/parse.y" + +/* Line 1455 of yacc.c */ +#line 328 "scripts/genksyms/parse.y" { (yyval) = (yyvsp[(2) - (2)]); ;} break; case 81: -#line 326 "scripts/genksyms/parse.y" + +/* Line 1455 of yacc.c */ +#line 330 "scripts/genksyms/parse.y" { (yyval) = (yyvsp[(3) - (3)]); ;} break; case 82: -#line 328 "scripts/genksyms/parse.y" + +/* Line 1455 of yacc.c */ +#line 332 "scripts/genksyms/parse.y" { (yyval) = (yyvsp[(3) - (3)]); ;} break; case 83: -#line 332 "scripts/genksyms/parse.y" + +/* Line 1455 of yacc.c */ +#line 336 "scripts/genksyms/parse.y" { (yyval) = (yyvsp[(2) - (2)]); ;} break; case 85: -#line 334 "scripts/genksyms/parse.y" + +/* Line 1455 of yacc.c */ +#line 338 "scripts/genksyms/parse.y" { (yyval) = (yyvsp[(3) - (3)]); ;} break; case 86: -#line 338 "scripts/genksyms/parse.y" + +/* Line 1455 of yacc.c */ +#line 342 "scripts/genksyms/parse.y" { (yyval) = NULL; ;} break; case 89: -#line 345 "scripts/genksyms/parse.y" + +/* Line 1455 of yacc.c */ +#line 349 "scripts/genksyms/parse.y" { (yyval) = (yyvsp[(3) - (3)]); ;} break; case 90: -#line 350 "scripts/genksyms/parse.y" + +/* Line 1455 of yacc.c */ +#line 354 "scripts/genksyms/parse.y" { (yyval) = (yyvsp[(2) - (2)]) ? (yyvsp[(2) - (2)]) : (yyvsp[(1) - (2)]); ;} break; case 91: -#line 355 "scripts/genksyms/parse.y" + +/* Line 1455 of yacc.c */ +#line 359 "scripts/genksyms/parse.y" { (yyval) = (yyvsp[(2) - (2)]) ? (yyvsp[(2) - (2)]) : (yyvsp[(1) - (2)]); ;} break; case 93: -#line 360 "scripts/genksyms/parse.y" + +/* Line 1455 of yacc.c */ +#line 364 "scripts/genksyms/parse.y" { (yyval) = NULL; ;} break; case 94: -#line 362 "scripts/genksyms/parse.y" + +/* Line 1455 of yacc.c */ +#line 366 "scripts/genksyms/parse.y" { /* For version 2 checksums, we don't want to remember private parameter names. */ remove_node((yyvsp[(1) - (1)])); @@ -2001,39 +2086,53 @@ yyreduce: break; case 95: -#line 370 "scripts/genksyms/parse.y" + +/* Line 1455 of yacc.c */ +#line 374 "scripts/genksyms/parse.y" { remove_node((yyvsp[(1) - (1)])); (yyval) = (yyvsp[(1) - (1)]); ;} break; case 96: -#line 374 "scripts/genksyms/parse.y" + +/* Line 1455 of yacc.c */ +#line 378 "scripts/genksyms/parse.y" { (yyval) = (yyvsp[(4) - (4)]); ;} break; case 97: -#line 376 "scripts/genksyms/parse.y" + +/* Line 1455 of yacc.c */ +#line 380 "scripts/genksyms/parse.y" { (yyval) = (yyvsp[(4) - (4)]); ;} break; case 98: -#line 378 "scripts/genksyms/parse.y" + +/* Line 1455 of yacc.c */ +#line 382 "scripts/genksyms/parse.y" { (yyval) = (yyvsp[(2) - (2)]); ;} break; case 99: -#line 380 "scripts/genksyms/parse.y" + +/* Line 1455 of yacc.c */ +#line 384 "scripts/genksyms/parse.y" { (yyval) = (yyvsp[(3) - (3)]); ;} break; case 100: -#line 382 "scripts/genksyms/parse.y" + +/* Line 1455 of yacc.c */ +#line 386 "scripts/genksyms/parse.y" { (yyval) = (yyvsp[(3) - (3)]); ;} break; case 101: -#line 387 "scripts/genksyms/parse.y" + +/* Line 1455 of yacc.c */ +#line 391 "scripts/genksyms/parse.y" { struct string_list *decl = *(yyvsp[(2) - (3)]); *(yyvsp[(2) - (3)]) = NULL; add_symbol(current_name, SYM_NORMAL, decl, is_extern); @@ -2042,93 +2141,163 @@ yyreduce: break; case 102: -#line 395 "scripts/genksyms/parse.y" + +/* Line 1455 of yacc.c */ +#line 399 "scripts/genksyms/parse.y" { (yyval) = NULL; ;} break; case 104: -#line 402 "scripts/genksyms/parse.y" + +/* Line 1455 of yacc.c */ +#line 406 "scripts/genksyms/parse.y" { remove_list((yyvsp[(2) - (2)]), &(*(yyvsp[(1) - (2)]))->next); (yyval) = (yyvsp[(2) - (2)]); ;} break; case 105: -#line 406 "scripts/genksyms/parse.y" + +/* Line 1455 of yacc.c */ +#line 410 "scripts/genksyms/parse.y" { (yyval) = (yyvsp[(3) - (3)]); ;} break; case 106: -#line 407 "scripts/genksyms/parse.y" + +/* Line 1455 of yacc.c */ +#line 411 "scripts/genksyms/parse.y" { (yyval) = (yyvsp[(3) - (3)]); ;} break; case 107: -#line 411 "scripts/genksyms/parse.y" + +/* Line 1455 of yacc.c */ +#line 415 "scripts/genksyms/parse.y" { (yyval) = NULL; ;} break; case 110: -#line 417 "scripts/genksyms/parse.y" + +/* Line 1455 of yacc.c */ +#line 421 "scripts/genksyms/parse.y" { (yyval) = (yyvsp[(2) - (2)]); ;} break; case 111: -#line 422 "scripts/genksyms/parse.y" + +/* Line 1455 of yacc.c */ +#line 426 "scripts/genksyms/parse.y" { (yyval) = (yyvsp[(3) - (3)]); ;} break; case 112: -#line 424 "scripts/genksyms/parse.y" + +/* Line 1455 of yacc.c */ +#line 428 "scripts/genksyms/parse.y" { (yyval) = (yyvsp[(2) - (2)]); ;} break; case 113: -#line 428 "scripts/genksyms/parse.y" + +/* Line 1455 of yacc.c */ +#line 432 "scripts/genksyms/parse.y" { (yyval) = NULL; ;} break; case 116: -#line 434 "scripts/genksyms/parse.y" + +/* Line 1455 of yacc.c */ +#line 438 "scripts/genksyms/parse.y" { (yyval) = (yyvsp[(3) - (3)]); ;} break; case 117: -#line 438 "scripts/genksyms/parse.y" + +/* Line 1455 of yacc.c */ +#line 442 "scripts/genksyms/parse.y" { (yyval) = (yyvsp[(2) - (2)]) ? (yyvsp[(2) - (2)]) : (yyvsp[(1) - (2)]); ;} break; case 118: -#line 439 "scripts/genksyms/parse.y" + +/* Line 1455 of yacc.c */ +#line 443 "scripts/genksyms/parse.y" { (yyval) = (yyvsp[(2) - (2)]); ;} break; case 120: -#line 444 "scripts/genksyms/parse.y" + +/* Line 1455 of yacc.c */ +#line 448 "scripts/genksyms/parse.y" { (yyval) = (yyvsp[(2) - (2)]); ;} break; case 121: -#line 448 "scripts/genksyms/parse.y" + +/* Line 1455 of yacc.c */ +#line 452 "scripts/genksyms/parse.y" { (yyval) = NULL; ;} break; case 123: -#line 453 "scripts/genksyms/parse.y" - { (yyval) = (yyvsp[(2) - (2)]); ;} + +/* Line 1455 of yacc.c */ +#line 457 "scripts/genksyms/parse.y" + { (yyval) = (yyvsp[(3) - (3)]); ;} break; case 124: -#line 457 "scripts/genksyms/parse.y" + +/* Line 1455 of yacc.c */ +#line 458 "scripts/genksyms/parse.y" + { (yyval) = (yyvsp[(4) - (4)]); ;} + break; + + case 127: + +/* Line 1455 of yacc.c */ +#line 467 "scripts/genksyms/parse.y" + { + const char *name = strdup((*(yyvsp[(1) - (1)]))->string); + add_symbol(name, SYM_ENUM_CONST, NULL, 0); + ;} + break; + + case 128: + +/* Line 1455 of yacc.c */ +#line 472 "scripts/genksyms/parse.y" + { + const char *name = strdup((*(yyvsp[(1) - (3)]))->string); + struct string_list *expr = copy_list_range(*(yyvsp[(3) - (3)]), *(yyvsp[(2) - (3)])); + add_symbol(name, SYM_ENUM_CONST, expr, 0); + ;} + break; + + case 129: + +/* Line 1455 of yacc.c */ +#line 479 "scripts/genksyms/parse.y" + { (yyval) = (yyvsp[(2) - (2)]); ;} + break; + + case 130: + +/* Line 1455 of yacc.c */ +#line 483 "scripts/genksyms/parse.y" { (yyval) = NULL; ;} break; - case 126: -#line 463 "scripts/genksyms/parse.y" + case 132: + +/* Line 1455 of yacc.c */ +#line 489 "scripts/genksyms/parse.y" { export_symbol((*(yyvsp[(3) - (5)]))->string); (yyval) = (yyvsp[(5) - (5)]); ;} break; -/* Line 1267 of yacc.c. */ -#line 2132 "scripts/genksyms/parse.c" + +/* Line 1455 of yacc.c */ +#line 2301 "scripts/genksyms/parse.c" default: break; } YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc); @@ -2139,7 +2308,6 @@ yyreduce: *++yyvsp = yyval; - /* Now `shift' the result of the reduction. Determine what state that goes to, based on the state we popped back to and the rule number reduced by. */ @@ -2204,7 +2372,7 @@ yyerrlab: if (yyerrstatus == 3) { - /* If just tried and failed to reuse look-ahead token after an + /* If just tried and failed to reuse lookahead token after an error, discard it. */ if (yychar <= YYEOF) @@ -2221,7 +2389,7 @@ yyerrlab: } } - /* Else will try to reuse look-ahead token after shifting the error + /* Else will try to reuse lookahead token after shifting the error token. */ goto yyerrlab1; @@ -2278,9 +2446,6 @@ yyerrlab1: YY_STACK_PRINT (yyss, yyssp); } - if (yyn == YYFINAL) - YYACCEPT; - *++yyvsp = yylval; @@ -2305,7 +2470,7 @@ yyabortlab: yyresult = 1; goto yyreturn; -#ifndef yyoverflow +#if !defined(yyoverflow) || YYERROR_VERBOSE /*-------------------------------------------------. | yyexhaustedlab -- memory exhaustion comes here. | `-------------------------------------------------*/ @@ -2316,7 +2481,7 @@ yyexhaustedlab: #endif yyreturn: - if (yychar != YYEOF && yychar != YYEMPTY) + if (yychar != YYEMPTY) yydestruct ("Cleanup: discarding lookahead", yytoken, &yylval); /* Do not reclaim the symbols of the rule which action triggered @@ -2342,7 +2507,9 @@ yyreturn: } -#line 467 "scripts/genksyms/parse.y" + +/* Line 1675 of yacc.c */ +#line 493 "scripts/genksyms/parse.y" static void diff --git a/scripts/genksyms/parse.h_shipped b/scripts/genksyms/parse.h_shipped index c4eeec652b799..517523669251b 100644 --- a/scripts/genksyms/parse.h_shipped +++ b/scripts/genksyms/parse.h_shipped @@ -1,24 +1,23 @@ -/* A Bison parser, made by GNU Bison 2.3. */ -/* Skeleton interface for Bison's Yacc-like parsers in C +/* A Bison parser, made by GNU Bison 2.4.1. */ - Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006 +/* Skeleton interface for Bison's Yacc-like parsers in C + + Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify + + This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2, or (at your option) - any later version. - + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. */ + along with this program. If not, see . */ /* As a special exception, you may create a larger work that contains part or all of the Bison parser skeleton and distribute that work @@ -29,10 +28,11 @@ special exception, which will cause the skeleton and the resulting Bison output files to be licensed under the GNU General Public License without this special exception. - + This special exception was added by the Free Software Foundation in version 2.2 of Bison. */ + /* Tokens. */ #ifndef YYTOKENTYPE # define YYTOKENTYPE @@ -82,58 +82,16 @@ FILENAME = 298 }; #endif -/* Tokens. */ -#define ASM_KEYW 258 -#define ATTRIBUTE_KEYW 259 -#define AUTO_KEYW 260 -#define BOOL_KEYW 261 -#define CHAR_KEYW 262 -#define CONST_KEYW 263 -#define DOUBLE_KEYW 264 -#define ENUM_KEYW 265 -#define EXTERN_KEYW 266 -#define EXTENSION_KEYW 267 -#define FLOAT_KEYW 268 -#define INLINE_KEYW 269 -#define INT_KEYW 270 -#define LONG_KEYW 271 -#define REGISTER_KEYW 272 -#define RESTRICT_KEYW 273 -#define SHORT_KEYW 274 -#define SIGNED_KEYW 275 -#define STATIC_KEYW 276 -#define STRUCT_KEYW 277 -#define TYPEDEF_KEYW 278 -#define UNION_KEYW 279 -#define UNSIGNED_KEYW 280 -#define VOID_KEYW 281 -#define VOLATILE_KEYW 282 -#define TYPEOF_KEYW 283 -#define EXPORT_SYMBOL_KEYW 284 -#define ASM_PHRASE 285 -#define ATTRIBUTE_PHRASE 286 -#define BRACE_PHRASE 287 -#define BRACKET_PHRASE 288 -#define EXPRESSION_PHRASE 289 -#define CHAR 290 -#define DOTS 291 -#define IDENT 292 -#define INT 293 -#define REAL 294 -#define STRING 295 -#define TYPE 296 -#define OTHER 297 -#define FILENAME 298 - #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED typedef int YYSTYPE; +# define YYSTYPE_IS_TRIVIAL 1 # define yystype YYSTYPE /* obsolescent; will be withdrawn */ # define YYSTYPE_IS_DECLARED 1 -# define YYSTYPE_IS_TRIVIAL 1 #endif extern YYSTYPE yylval; + -- GitLab From 8184f93eced1e304721c2a55c00d87d5a14f8907 Mon Sep 17 00:00:00 2001 From: Justin TerAvest Date: Thu, 17 Mar 2011 16:12:36 +0100 Subject: [PATCH 0807/2822] cfq-iosched: Don't update group weights when on service tree Version 3 is updated to apply to for-2.6.39/core. For version 2, I took Vivek's advice and made sure we update the group weight from cfq_group_service_tree_add(). If a weight was updated while a group is on the service tree, the calculation for the total weight of the service tree can be adjusted improperly, which either leads to bad service tree weights, or potentially crashes (if total_weight becomes 0). This patch defers updates to the weight until a group is off the service tree. Signed-off-by: Justin TerAvest Acked-by: Vivek Goyal Signed-off-by: Jens Axboe --- block/cfq-iosched.c | 53 +++++++++++++++++++++++++++++++++++---------- 1 file changed, 41 insertions(+), 12 deletions(-) diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c index 89e0d1cc14bab..12e380b2c4e47 100644 --- a/block/cfq-iosched.c +++ b/block/cfq-iosched.c @@ -178,6 +178,8 @@ struct cfq_group { /* group service_tree key */ u64 vdisktime; unsigned int weight; + unsigned int new_weight; + bool needs_update; /* number of cfqq currently on this group */ int nr_cfqq; @@ -853,7 +855,27 @@ __cfq_group_service_tree_add(struct cfq_rb_root *st, struct cfq_group *cfqg) } static void -cfq_group_service_tree_add(struct cfq_data *cfqd, struct cfq_group *cfqg) +cfq_update_group_weight(struct cfq_group *cfqg) +{ + BUG_ON(!RB_EMPTY_NODE(&cfqg->rb_node)); + if (cfqg->needs_update) { + cfqg->weight = cfqg->new_weight; + cfqg->needs_update = false; + } +} + +static void +cfq_group_service_tree_add(struct cfq_rb_root *st, struct cfq_group *cfqg) +{ + BUG_ON(!RB_EMPTY_NODE(&cfqg->rb_node)); + + cfq_update_group_weight(cfqg); + __cfq_group_service_tree_add(st, cfqg); + st->total_weight += cfqg->weight; +} + +static void +cfq_group_notify_queue_add(struct cfq_data *cfqd, struct cfq_group *cfqg) { struct cfq_rb_root *st = &cfqd->grp_service_tree; struct cfq_group *__cfqg; @@ -874,13 +896,19 @@ cfq_group_service_tree_add(struct cfq_data *cfqd, struct cfq_group *cfqg) cfqg->vdisktime = __cfqg->vdisktime + CFQ_IDLE_DELAY; } else cfqg->vdisktime = st->min_vdisktime; + cfq_group_service_tree_add(st, cfqg); +} - __cfq_group_service_tree_add(st, cfqg); - st->total_weight += cfqg->weight; +static void +cfq_group_service_tree_del(struct cfq_rb_root *st, struct cfq_group *cfqg) +{ + st->total_weight -= cfqg->weight; + if (!RB_EMPTY_NODE(&cfqg->rb_node)) + cfq_rb_erase(&cfqg->rb_node, st); } static void -cfq_group_service_tree_del(struct cfq_data *cfqd, struct cfq_group *cfqg) +cfq_group_notify_queue_del(struct cfq_data *cfqd, struct cfq_group *cfqg) { struct cfq_rb_root *st = &cfqd->grp_service_tree; @@ -892,9 +920,7 @@ cfq_group_service_tree_del(struct cfq_data *cfqd, struct cfq_group *cfqg) return; cfq_log_cfqg(cfqd, cfqg, "del_from_rr group"); - st->total_weight -= cfqg->weight; - if (!RB_EMPTY_NODE(&cfqg->rb_node)) - cfq_rb_erase(&cfqg->rb_node, st); + cfq_group_service_tree_del(st, cfqg); cfqg->saved_workload_slice = 0; cfq_blkiocg_update_dequeue_stats(&cfqg->blkg, 1); } @@ -948,9 +974,10 @@ static void cfq_group_served(struct cfq_data *cfqd, struct cfq_group *cfqg, charge = cfqq->allocated_slice; /* Can't update vdisktime while group is on service tree */ - cfq_rb_erase(&cfqg->rb_node, st); + cfq_group_service_tree_del(st, cfqg); cfqg->vdisktime += cfq_scale_slice(charge, cfqg); - __cfq_group_service_tree_add(st, cfqg); + /* If a new weight was requested, update now, off tree */ + cfq_group_service_tree_add(st, cfqg); /* This group is being expired. Save the context */ if (time_after(cfqd->workload_expires, jiffies)) { @@ -982,7 +1009,9 @@ static inline struct cfq_group *cfqg_of_blkg(struct blkio_group *blkg) void cfq_update_blkio_group_weight(void *key, struct blkio_group *blkg, unsigned int weight) { - cfqg_of_blkg(blkg)->weight = weight; + struct cfq_group *cfqg = cfqg_of_blkg(blkg); + cfqg->new_weight = weight; + cfqg->needs_update = true; } static struct cfq_group * @@ -1255,7 +1284,7 @@ static void cfq_service_tree_add(struct cfq_data *cfqd, struct cfq_queue *cfqq, service_tree->count++; if ((add_front || !new_cfqq) && !group_changed) return; - cfq_group_service_tree_add(cfqd, cfqq->cfqg); + cfq_group_notify_queue_add(cfqd, cfqq->cfqg); } static struct cfq_queue * @@ -1368,7 +1397,7 @@ static void cfq_del_cfqq_rr(struct cfq_data *cfqd, struct cfq_queue *cfqq) cfqq->p_root = NULL; } - cfq_group_service_tree_del(cfqd, cfqq->cfqg); + cfq_group_notify_queue_del(cfqd, cfqq->cfqg); BUG_ON(!cfqd->busy_queues); cfqd->busy_queues--; if (cfq_cfqq_sync(cfqq)) -- GitLab From 9ae78bcc000168251f893b1bf92a848308187695 Mon Sep 17 00:00:00 2001 From: "J. Bruce Fields" Date: Thu, 17 Mar 2011 12:52:33 -0400 Subject: [PATCH 0808/2822] nfsd4: fix comment and remove unused nfsd4_file fields A couple fields here were left over from a previous version of a patch, and are no longer used. Signed-off-by: J. Bruce Fields --- fs/nfsd/state.h | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/fs/nfsd/state.h b/fs/nfsd/state.h index 2d31224b07bfa..6bd2f3c21f2b7 100644 --- a/fs/nfsd/state.h +++ b/fs/nfsd/state.h @@ -367,16 +367,12 @@ struct nfs4_file { struct list_head fi_delegations; /* One each for O_RDONLY, O_WRONLY, O_RDWR: */ struct file * fi_fds[3]; - /* One each for O_RDONLY, O_WRONLY: */ - atomic_t fi_access[2]; /* - * Each open stateid contributes 1 to either fi_readers or - * fi_writers, or both, depending on the open mode. A - * delegation also takes an fi_readers reference. Lock - * stateid's take none. + * Each open or lock stateid contributes 1 to either + * fi_access[O_RDONLY], fi_access[O_WRONLY], or both, depending + * on open or lock mode: */ - atomic_t fi_readers; - atomic_t fi_writers; + atomic_t fi_access[2]; struct file *fi_deleg_file; struct file_lock *fi_lease; atomic_t fi_delegees; -- GitLab From 5a02ab7c3c4580f94d13c683721039855b67cda6 Mon Sep 17 00:00:00 2001 From: Mi Jinlong Date: Fri, 11 Mar 2011 12:13:55 +0800 Subject: [PATCH 0809/2822] nfsd: wrong index used in inner loop We must not use dummy for index. After the first index, READ32(dummy) will change dummy!!!! Signed-off-by: Mi Jinlong [bfields@redhat.com: Trond points out READ_BUF alone is sufficient.] Cc: stable@kernel.org Signed-off-by: J. Bruce Fields --- fs/nfsd/nfs4xdr.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c index 615f0a9f06008..c6766af00d983 100644 --- a/fs/nfsd/nfs4xdr.c +++ b/fs/nfsd/nfs4xdr.c @@ -1142,7 +1142,7 @@ nfsd4_decode_create_session(struct nfsd4_compoundargs *argp, u32 dummy; char *machine_name; - int i, j; + int i; int nr_secflavs; READ_BUF(16); @@ -1215,8 +1215,6 @@ nfsd4_decode_create_session(struct nfsd4_compoundargs *argp, READ_BUF(4); READ32(dummy); READ_BUF(dummy * 4); - for (j = 0; j < dummy; ++j) - READ32(dummy); break; case RPC_AUTH_GSS: dprintk("RPC_AUTH_GSS callback secflavor " @@ -1232,7 +1230,6 @@ nfsd4_decode_create_session(struct nfsd4_compoundargs *argp, READ_BUF(4); READ32(dummy); READ_BUF(dummy); - p += XDR_QUADLEN(dummy); break; default: dprintk("Illegal callback secflavor\n"); -- GitLab From 9f570b8d48b6677b5557d86fb3ca148215e295f2 Mon Sep 17 00:00:00 2001 From: Josef Bacik Date: Tue, 25 Jan 2011 12:42:37 -0500 Subject: [PATCH 0810/2822] Btrfs: fix formatting in file.c Sorry, but these were bugging me. Just cleanup some of the formatting in file.c. Signed-off-by: Josef Bacik --- fs/btrfs/file.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c index f447b783bb84c..4d49755926688 100644 --- a/fs/btrfs/file.c +++ b/fs/btrfs/file.c @@ -88,9 +88,8 @@ static noinline int btrfs_copy_from_user(loff_t pos, int num_pages, total_copied += copied; /* Return to btrfs_file_aio_write to fault page */ - if (unlikely(copied == 0)) { + if (unlikely(copied == 0)) break; - } if (unlikely(copied < PAGE_CACHE_SIZE - offset)) { offset += copied; @@ -162,13 +161,14 @@ static noinline int dirty_and_release_pages(struct btrfs_trans_handle *trans, ClearPageChecked(p); set_page_dirty(p); } - if (end_pos > isize) { + + /* + * we've only changed i_size in ram, and we haven't updated + * the disk i_size. There is no need to log the inode + * at this time. + */ + if (end_pos > isize) i_size_write(inode, end_pos); - /* we've only changed i_size in ram, and we haven't updated - * the disk i_size. There is no need to log the inode - * at this time. - */ - } return 0; } -- GitLab From d0215f3e5ebb5803cd6ec067b10c5e00a3ad7cfc Mon Sep 17 00:00:00 2001 From: Josef Bacik Date: Tue, 25 Jan 2011 14:57:24 -0500 Subject: [PATCH 0811/2822] Btrfs: simplify our write path Our aio_write function is huge and kind of hard to follow at times. So this patch fixes this by breaking out the buffered and direct write paths out into seperate functions so it's a little clearer what's going on. I've also fixed some wrong typing that we had and added the ability to handle getting an error back from btrfs_set_extent_delalloc. Tested this with xfstests and everything came out fine. Thanks, Signed-off-by: Josef Bacik --- fs/btrfs/file.c | 355 ++++++++++++++++++++++++------------------------ 1 file changed, 180 insertions(+), 175 deletions(-) diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c index 4d49755926688..f2a80e570a6c2 100644 --- a/fs/btrfs/file.c +++ b/fs/btrfs/file.c @@ -45,14 +45,14 @@ * and be replaced with calls into generic code. */ static noinline int btrfs_copy_from_user(loff_t pos, int num_pages, - int write_bytes, + size_t write_bytes, struct page **prepared_pages, struct iov_iter *i) { size_t copied = 0; + size_t total_copied = 0; int pg = 0; int offset = pos & (PAGE_CACHE_SIZE - 1); - int total_copied = 0; while (write_bytes > 0) { size_t count = min_t(size_t, @@ -129,13 +129,12 @@ static noinline void btrfs_drop_pages(struct page **pages, size_t num_pages) * this also makes the decision about creating an inline extent vs * doing real data extents, marking pages dirty and delalloc as required. */ -static noinline int dirty_and_release_pages(struct btrfs_trans_handle *trans, - struct btrfs_root *root, - struct file *file, - struct page **pages, - size_t num_pages, - loff_t pos, - size_t write_bytes) +static noinline int dirty_and_release_pages(struct btrfs_root *root, + struct file *file, + struct page **pages, + size_t num_pages, + loff_t pos, + size_t write_bytes) { int err = 0; int i; @@ -153,7 +152,8 @@ static noinline int dirty_and_release_pages(struct btrfs_trans_handle *trans, end_of_last_block = start_pos + num_bytes - 1; err = btrfs_set_extent_delalloc(inode, start_pos, end_of_last_block, NULL); - BUG_ON(err); + if (err) + return err; for (i = 0; i < num_pages; i++) { struct page *p = pages[i]; @@ -896,127 +896,38 @@ fail: } -static ssize_t btrfs_file_aio_write(struct kiocb *iocb, - const struct iovec *iov, - unsigned long nr_segs, loff_t pos) +static noinline ssize_t __btrfs_buffered_write(struct file *file, + struct iov_iter *i, + loff_t pos) { - struct file *file = iocb->ki_filp; struct inode *inode = fdentry(file)->d_inode; struct btrfs_root *root = BTRFS_I(inode)->root; struct page **pages = NULL; - struct iov_iter i; - loff_t *ppos = &iocb->ki_pos; - loff_t start_pos; - ssize_t num_written = 0; - ssize_t err = 0; - size_t count; - size_t ocount; - int ret = 0; - int nrptrs; unsigned long first_index; unsigned long last_index; - int will_write; - int buffered = 0; - int copied = 0; - int dirty_pages = 0; - - will_write = ((file->f_flags & O_DSYNC) || IS_SYNC(inode) || - (file->f_flags & O_DIRECT)); - - start_pos = pos; - - vfs_check_frozen(inode->i_sb, SB_FREEZE_WRITE); - - mutex_lock(&inode->i_mutex); - - err = generic_segment_checks(iov, &nr_segs, &ocount, VERIFY_READ); - if (err) - goto out; - count = ocount; - - current->backing_dev_info = inode->i_mapping->backing_dev_info; - err = generic_write_checks(file, &pos, &count, S_ISBLK(inode->i_mode)); - if (err) - goto out; - - if (count == 0) - goto out; - - err = file_remove_suid(file); - if (err) - goto out; - - /* - * If BTRFS flips readonly due to some impossible error - * (fs_info->fs_state now has BTRFS_SUPER_FLAG_ERROR), - * although we have opened a file as writable, we have - * to stop this write operation to ensure FS consistency. - */ - if (root->fs_info->fs_state & BTRFS_SUPER_FLAG_ERROR) { - err = -EROFS; - goto out; - } - - file_update_time(file); - BTRFS_I(inode)->sequence++; - - if (unlikely(file->f_flags & O_DIRECT)) { - num_written = generic_file_direct_write(iocb, iov, &nr_segs, - pos, ppos, count, - ocount); - /* - * the generic O_DIRECT will update in-memory i_size after the - * DIOs are done. But our endio handlers that update the on - * disk i_size never update past the in memory i_size. So we - * need one more update here to catch any additions to the - * file - */ - if (inode->i_size != BTRFS_I(inode)->disk_i_size) { - btrfs_ordered_update_i_size(inode, inode->i_size, NULL); - mark_inode_dirty(inode); - } - - if (num_written < 0) { - ret = num_written; - num_written = 0; - goto out; - } else if (num_written == count) { - /* pick up pos changes done by the generic code */ - pos = *ppos; - goto out; - } - /* - * We are going to do buffered for the rest of the range, so we - * need to make sure to invalidate the buffered pages when we're - * done. - */ - buffered = 1; - pos += num_written; - } + size_t num_written = 0; + int nrptrs; + int ret; - iov_iter_init(&i, iov, nr_segs, count, num_written); - nrptrs = min((iov_iter_count(&i) + PAGE_CACHE_SIZE - 1) / + nrptrs = min((iov_iter_count(i) + PAGE_CACHE_SIZE - 1) / PAGE_CACHE_SIZE, PAGE_CACHE_SIZE / (sizeof(struct page *))); pages = kmalloc(nrptrs * sizeof(struct page *), GFP_KERNEL); - if (!pages) { - ret = -ENOMEM; - goto out; - } - - /* generic_write_checks can change our pos */ - start_pos = pos; + if (!pages) + return -ENOMEM; first_index = pos >> PAGE_CACHE_SHIFT; - last_index = (pos + iov_iter_count(&i)) >> PAGE_CACHE_SHIFT; + last_index = (pos + iov_iter_count(i)) >> PAGE_CACHE_SHIFT; - while (iov_iter_count(&i) > 0) { + while (iov_iter_count(i) > 0) { size_t offset = pos & (PAGE_CACHE_SIZE - 1); - size_t write_bytes = min(iov_iter_count(&i), + size_t write_bytes = min(iov_iter_count(i), nrptrs * (size_t)PAGE_CACHE_SIZE - offset); size_t num_pages = (write_bytes + offset + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT; + size_t dirty_pages; + size_t copied; WARN_ON(num_pages > nrptrs); memset(pages, 0, sizeof(struct page *) * nrptrs); @@ -1025,15 +936,15 @@ static ssize_t btrfs_file_aio_write(struct kiocb *iocb, * Fault pages before locking them in prepare_pages * to avoid recursive lock */ - if (unlikely(iov_iter_fault_in_readable(&i, write_bytes))) { + if (unlikely(iov_iter_fault_in_readable(i, write_bytes))) { ret = -EFAULT; - goto out; + break; } ret = btrfs_delalloc_reserve_space(inode, num_pages << PAGE_CACHE_SHIFT); if (ret) - goto out; + break; ret = prepare_pages(root, file, pages, num_pages, pos, first_index, last_index, @@ -1041,11 +952,11 @@ static ssize_t btrfs_file_aio_write(struct kiocb *iocb, if (ret) { btrfs_delalloc_release_space(inode, num_pages << PAGE_CACHE_SHIFT); - goto out; + break; } copied = btrfs_copy_from_user(pos, num_pages, - write_bytes, pages, &i); + write_bytes, pages, i); /* * if we have trouble faulting in the pages, fall @@ -1061,6 +972,13 @@ static ssize_t btrfs_file_aio_write(struct kiocb *iocb, PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT; + /* + * If we had a short copy we need to release the excess delaloc + * bytes we reserved. We need to increment outstanding_extents + * because btrfs_delalloc_release_space will decrement it, but + * we still have an outstanding extent for the chunk we actually + * managed to copy. + */ if (num_pages > dirty_pages) { if (copied > 0) atomic_inc( @@ -1071,39 +989,157 @@ static ssize_t btrfs_file_aio_write(struct kiocb *iocb, } if (copied > 0) { - dirty_and_release_pages(NULL, root, file, pages, - dirty_pages, pos, copied); + ret = dirty_and_release_pages(root, file, pages, + dirty_pages, pos, + copied); + if (ret) { + btrfs_delalloc_release_space(inode, + dirty_pages << PAGE_CACHE_SHIFT); + btrfs_drop_pages(pages, num_pages); + break; + } } btrfs_drop_pages(pages, num_pages); - if (copied > 0) { - if (will_write) { - filemap_fdatawrite_range(inode->i_mapping, pos, - pos + copied - 1); - } else { - balance_dirty_pages_ratelimited_nr( - inode->i_mapping, - dirty_pages); - if (dirty_pages < - (root->leafsize >> PAGE_CACHE_SHIFT) + 1) - btrfs_btree_balance_dirty(root, 1); - btrfs_throttle(root); - } - } + cond_resched(); + + balance_dirty_pages_ratelimited_nr(inode->i_mapping, + dirty_pages); + if (dirty_pages < (root->leafsize >> PAGE_CACHE_SHIFT) + 1) + btrfs_btree_balance_dirty(root, 1); + btrfs_throttle(root); pos += copied; num_written += copied; + } - cond_resched(); + kfree(pages); + + return num_written ? num_written : ret; +} + +static ssize_t __btrfs_direct_write(struct kiocb *iocb, + const struct iovec *iov, + unsigned long nr_segs, loff_t pos, + loff_t *ppos, size_t count, size_t ocount) +{ + struct file *file = iocb->ki_filp; + struct inode *inode = fdentry(file)->d_inode; + struct iov_iter i; + ssize_t written; + ssize_t written_buffered; + loff_t endbyte; + int err; + + written = generic_file_direct_write(iocb, iov, &nr_segs, pos, ppos, + count, ocount); + + /* + * the generic O_DIRECT will update in-memory i_size after the + * DIOs are done. But our endio handlers that update the on + * disk i_size never update past the in memory i_size. So we + * need one more update here to catch any additions to the + * file + */ + if (inode->i_size != BTRFS_I(inode)->disk_i_size) { + btrfs_ordered_update_i_size(inode, inode->i_size, NULL); + mark_inode_dirty(inode); } + + if (written < 0 || written == count) + return written; + + pos += written; + count -= written; + iov_iter_init(&i, iov, nr_segs, count, written); + written_buffered = __btrfs_buffered_write(file, &i, pos); + if (written_buffered < 0) { + err = written_buffered; + goto out; + } + endbyte = pos + written_buffered - 1; + err = filemap_write_and_wait_range(file->f_mapping, pos, endbyte); + if (err) + goto out; + written += written_buffered; + *ppos = pos + written_buffered; + invalidate_mapping_pages(file->f_mapping, pos >> PAGE_CACHE_SHIFT, + endbyte >> PAGE_CACHE_SHIFT); out: - mutex_unlock(&inode->i_mutex); - if (ret) - err = ret; + return written ? written : err; +} - kfree(pages); - *ppos = pos; +static ssize_t btrfs_file_aio_write(struct kiocb *iocb, + const struct iovec *iov, + unsigned long nr_segs, loff_t pos) +{ + struct file *file = iocb->ki_filp; + struct inode *inode = fdentry(file)->d_inode; + struct btrfs_root *root = BTRFS_I(inode)->root; + loff_t *ppos = &iocb->ki_pos; + ssize_t num_written = 0; + ssize_t err = 0; + size_t count, ocount; + + vfs_check_frozen(inode->i_sb, SB_FREEZE_WRITE); + + mutex_lock(&inode->i_mutex); + + err = generic_segment_checks(iov, &nr_segs, &ocount, VERIFY_READ); + if (err) { + mutex_unlock(&inode->i_mutex); + goto out; + } + count = ocount; + + current->backing_dev_info = inode->i_mapping->backing_dev_info; + err = generic_write_checks(file, &pos, &count, S_ISBLK(inode->i_mode)); + if (err) { + mutex_unlock(&inode->i_mutex); + goto out; + } + + if (count == 0) { + mutex_unlock(&inode->i_mutex); + goto out; + } + + err = file_remove_suid(file); + if (err) { + mutex_unlock(&inode->i_mutex); + goto out; + } + + /* + * If BTRFS flips readonly due to some impossible error + * (fs_info->fs_state now has BTRFS_SUPER_FLAG_ERROR), + * although we have opened a file as writable, we have + * to stop this write operation to ensure FS consistency. + */ + if (root->fs_info->fs_state & BTRFS_SUPER_FLAG_ERROR) { + mutex_unlock(&inode->i_mutex); + err = -EROFS; + goto out; + } + + file_update_time(file); + BTRFS_I(inode)->sequence++; + + if (unlikely(file->f_flags & O_DIRECT)) { + num_written = __btrfs_direct_write(iocb, iov, nr_segs, + pos, ppos, count, ocount); + } else { + struct iov_iter i; + + iov_iter_init(&i, iov, nr_segs, count, num_written); + + num_written = __btrfs_buffered_write(file, &i, pos); + if (num_written > 0) + *ppos = pos + num_written; + } + + mutex_unlock(&inode->i_mutex); /* * we want to make sure fsync finds this change @@ -1118,43 +1154,12 @@ out: * one running right now. */ BTRFS_I(inode)->last_trans = root->fs_info->generation + 1; - - if (num_written > 0 && will_write) { - struct btrfs_trans_handle *trans; - - err = btrfs_wait_ordered_range(inode, start_pos, num_written); - if (err) + if (num_written > 0 || num_written == -EIOCBQUEUED) { + err = generic_write_sync(file, pos, num_written); + if (err < 0 && num_written > 0) num_written = err; - - if ((file->f_flags & O_DSYNC) || IS_SYNC(inode)) { - trans = btrfs_start_transaction(root, 0); - if (IS_ERR(trans)) { - num_written = PTR_ERR(trans); - goto done; - } - mutex_lock(&inode->i_mutex); - ret = btrfs_log_dentry_safe(trans, root, - file->f_dentry); - mutex_unlock(&inode->i_mutex); - if (ret == 0) { - ret = btrfs_sync_log(trans, root); - if (ret == 0) - btrfs_end_transaction(trans, root); - else - btrfs_commit_transaction(trans, root); - } else if (ret != BTRFS_NO_LOG_SYNC) { - btrfs_commit_transaction(trans, root); - } else { - btrfs_end_transaction(trans, root); - } - } - if (file->f_flags & O_DIRECT && buffered) { - invalidate_mapping_pages(inode->i_mapping, - start_pos >> PAGE_CACHE_SHIFT, - (start_pos + num_written - 1) >> PAGE_CACHE_SHIFT); - } } -done: +out: current->backing_dev_info = NULL; return num_written ? num_written : err; } -- GitLab From 4a64001f0047956e283f7ada9843dfc3f3b5d8c8 Mon Sep 17 00:00:00 2001 From: Josef Bacik Date: Tue, 25 Jan 2011 15:10:08 -0500 Subject: [PATCH 0812/2822] Btrfs: fix how we deal with the pages array in the write path Really we don't need to memset the pages array at all, since we know how many pages we're going to use in the array and pass that around. So don't memset, just trust we're not idiots and we pass num_pages around properly. Signed-off-by: Josef Bacik --- fs/btrfs/file.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c index f2a80e570a6c2..24a19c2743ca7 100644 --- a/fs/btrfs/file.c +++ b/fs/btrfs/file.c @@ -108,8 +108,6 @@ static noinline void btrfs_drop_pages(struct page **pages, size_t num_pages) { size_t i; for (i = 0; i < num_pages; i++) { - if (!pages[i]) - break; /* page checked is some magic around finding pages that * have been modified without going through btrfs_set_page_dirty * clear it here @@ -824,7 +822,6 @@ static noinline int prepare_pages(struct btrfs_root *root, struct file *file, return err; } - memset(pages, 0, num_pages * sizeof(struct page *)); again: for (i = 0; i < num_pages; i++) { pages[i] = grab_cache_page(inode->i_mapping, index + i); @@ -930,7 +927,6 @@ static noinline ssize_t __btrfs_buffered_write(struct file *file, size_t copied; WARN_ON(num_pages > nrptrs); - memset(pages, 0, sizeof(struct page *) * nrptrs); /* * Fault pages before locking them in prepare_pages @@ -946,6 +942,11 @@ static noinline ssize_t __btrfs_buffered_write(struct file *file, if (ret) break; + /* + * This is going to setup the pages array with the number of + * pages we want, so we don't really need to worry about the + * contents of pages from loop to loop + */ ret = prepare_pages(root, file, pages, num_pages, pos, first_index, last_index, write_bytes); -- GitLab From 57a45ced94fe48a701361d64230fc16eefa189dd Mon Sep 17 00:00:00 2001 From: Josef Bacik Date: Tue, 25 Jan 2011 16:30:38 -0500 Subject: [PATCH 0813/2822] Btrfs: change reserved_extents to an atomic_t We track delayed allocation per inodes via 2 counters, one is outstanding_extents and reserved_extents. Outstanding_extents is already an atomic_t, but reserved_extents is not and is protected by a spinlock. So convert this to an atomic_t and instead of using a spinlock, use atomic_cmpxchg when releasing delalloc bytes. This makes our inode 72 bytes smaller, and reduces locking overhead (albiet it was minimal to begin with). Thanks, Signed-off-by: Josef Bacik --- fs/btrfs/btrfs_inode.h | 3 +-- fs/btrfs/extent-tree.c | 42 ++++++++++++++++++++++++++---------------- fs/btrfs/inode.c | 5 ++--- 3 files changed, 29 insertions(+), 21 deletions(-) diff --git a/fs/btrfs/btrfs_inode.h b/fs/btrfs/btrfs_inode.h index ccc991c542df3..57c3bb2884cea 100644 --- a/fs/btrfs/btrfs_inode.h +++ b/fs/btrfs/btrfs_inode.h @@ -136,9 +136,8 @@ struct btrfs_inode { * items we think we'll end up using, and reserved_extents is the number * of extent items we've reserved metadata for. */ - spinlock_t accounting_lock; atomic_t outstanding_extents; - int reserved_extents; + atomic_t reserved_extents; /* * ordered_data_close is set by truncate when a file that used diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index 7b3089b5c2df8..27376c97d85f9 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c @@ -3996,6 +3996,7 @@ int btrfs_delalloc_reserve_metadata(struct inode *inode, u64 num_bytes) struct btrfs_block_rsv *block_rsv = &root->fs_info->delalloc_block_rsv; u64 to_reserve; int nr_extents; + int reserved_extents; int ret; if (btrfs_transaction_in_commit(root->fs_info)) @@ -4003,25 +4004,24 @@ int btrfs_delalloc_reserve_metadata(struct inode *inode, u64 num_bytes) num_bytes = ALIGN(num_bytes, root->sectorsize); - spin_lock(&BTRFS_I(inode)->accounting_lock); nr_extents = atomic_read(&BTRFS_I(inode)->outstanding_extents) + 1; - if (nr_extents > BTRFS_I(inode)->reserved_extents) { - nr_extents -= BTRFS_I(inode)->reserved_extents; + reserved_extents = atomic_read(&BTRFS_I(inode)->reserved_extents); + + if (nr_extents > reserved_extents) { + nr_extents -= reserved_extents; to_reserve = calc_trans_metadata_size(root, nr_extents); } else { nr_extents = 0; to_reserve = 0; } - spin_unlock(&BTRFS_I(inode)->accounting_lock); + to_reserve += calc_csum_metadata_size(inode, num_bytes); ret = reserve_metadata_bytes(NULL, root, block_rsv, to_reserve, 1); if (ret) return ret; - spin_lock(&BTRFS_I(inode)->accounting_lock); - BTRFS_I(inode)->reserved_extents += nr_extents; + atomic_add(nr_extents, &BTRFS_I(inode)->reserved_extents); atomic_inc(&BTRFS_I(inode)->outstanding_extents); - spin_unlock(&BTRFS_I(inode)->accounting_lock); block_rsv_add_bytes(block_rsv, to_reserve, 1); @@ -4036,20 +4036,30 @@ void btrfs_delalloc_release_metadata(struct inode *inode, u64 num_bytes) struct btrfs_root *root = BTRFS_I(inode)->root; u64 to_free; int nr_extents; + int reserved_extents; num_bytes = ALIGN(num_bytes, root->sectorsize); atomic_dec(&BTRFS_I(inode)->outstanding_extents); WARN_ON(atomic_read(&BTRFS_I(inode)->outstanding_extents) < 0); - spin_lock(&BTRFS_I(inode)->accounting_lock); - nr_extents = atomic_read(&BTRFS_I(inode)->outstanding_extents); - if (nr_extents < BTRFS_I(inode)->reserved_extents) { - nr_extents = BTRFS_I(inode)->reserved_extents - nr_extents; - BTRFS_I(inode)->reserved_extents -= nr_extents; - } else { - nr_extents = 0; - } - spin_unlock(&BTRFS_I(inode)->accounting_lock); + reserved_extents = atomic_read(&BTRFS_I(inode)->reserved_extents); + do { + int old, new; + + nr_extents = atomic_read(&BTRFS_I(inode)->outstanding_extents); + if (nr_extents >= reserved_extents) { + nr_extents = 0; + break; + } + old = reserved_extents; + nr_extents = reserved_extents - nr_extents; + new = reserved_extents - nr_extents; + old = atomic_cmpxchg(&BTRFS_I(inode)->reserved_extents, + reserved_extents, new); + if (likely(old == reserved_extents)) + break; + reserved_extents = old; + } while (1); to_free = calc_csum_metadata_size(inode, num_bytes); if (nr_extents > 0) diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 9007bbd01dbf6..d97b69afbbfb4 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -6632,9 +6632,8 @@ struct inode *btrfs_alloc_inode(struct super_block *sb) ei->index_cnt = (u64)-1; ei->last_unlink_trans = 0; - spin_lock_init(&ei->accounting_lock); atomic_set(&ei->outstanding_extents, 0); - ei->reserved_extents = 0; + atomic_set(&ei->reserved_extents, 0); ei->ordered_data_close = 0; ei->orphan_meta_reserved = 0; @@ -6670,7 +6669,7 @@ void btrfs_destroy_inode(struct inode *inode) WARN_ON(!list_empty(&inode->i_dentry)); WARN_ON(inode->i_data.nrpages); WARN_ON(atomic_read(&BTRFS_I(inode)->outstanding_extents)); - WARN_ON(BTRFS_I(inode)->reserved_extents); + WARN_ON(atomic_read(&BTRFS_I(inode)->reserved_extents)); /* * This can happen where we create an inode, but somebody else also -- GitLab From dc89e9824464e91fa0b06267864ceabe3186fd8b Mon Sep 17 00:00:00 2001 From: Josef Bacik Date: Fri, 28 Jan 2011 17:05:48 -0500 Subject: [PATCH 0814/2822] Btrfs: use a slab for the free space entries Since we alloc/free free space entries a whole lot, lets use a slab to keep track of them. This makes some of my tests slightly faster. Thanks, Signed-off-by: Josef Bacik --- fs/btrfs/ctree.h | 1 + fs/btrfs/free-space-cache.c | 34 ++++++++++++++++++---------------- fs/btrfs/inode.c | 10 ++++++++++ 3 files changed, 29 insertions(+), 16 deletions(-) diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index 7f78cc78fdd0a..2c98d209e6acb 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h @@ -40,6 +40,7 @@ extern struct kmem_cache *btrfs_trans_handle_cachep; extern struct kmem_cache *btrfs_transaction_cachep; extern struct kmem_cache *btrfs_bit_radix_cachep; extern struct kmem_cache *btrfs_path_cachep; +extern struct kmem_cache *btrfs_free_space_cachep; struct btrfs_ordered_sum; #define BTRFS_MAGIC "_BHRfS_M" diff --git a/fs/btrfs/free-space-cache.c b/fs/btrfs/free-space-cache.c index a0390657451b9..0282033041e13 100644 --- a/fs/btrfs/free-space-cache.c +++ b/fs/btrfs/free-space-cache.c @@ -393,7 +393,8 @@ int load_free_space_cache(struct btrfs_fs_info *fs_info, break; need_loop = 1; - e = kzalloc(sizeof(struct btrfs_free_space), GFP_NOFS); + e = kmem_cache_zalloc(btrfs_free_space_cachep, + GFP_NOFS); if (!e) { kunmap(page); unlock_page(page); @@ -405,7 +406,7 @@ int load_free_space_cache(struct btrfs_fs_info *fs_info, e->bytes = le64_to_cpu(entry->bytes); if (!e->bytes) { kunmap(page); - kfree(e); + kmem_cache_free(btrfs_free_space_cachep, e); unlock_page(page); page_cache_release(page); goto free_cache; @@ -420,7 +421,8 @@ int load_free_space_cache(struct btrfs_fs_info *fs_info, e->bitmap = kzalloc(PAGE_CACHE_SIZE, GFP_NOFS); if (!e->bitmap) { kunmap(page); - kfree(e); + kmem_cache_free( + btrfs_free_space_cachep, e); unlock_page(page); page_cache_release(page); goto free_cache; @@ -1187,7 +1189,7 @@ static void free_bitmap(struct btrfs_block_group_cache *block_group, { unlink_free_space(block_group, bitmap_info); kfree(bitmap_info->bitmap); - kfree(bitmap_info); + kmem_cache_free(btrfs_free_space_cachep, bitmap_info); block_group->total_bitmaps--; recalculate_thresholds(block_group); } @@ -1342,8 +1344,8 @@ new_bitmap: /* no pre-allocated info, allocate a new one */ if (!info) { - info = kzalloc(sizeof(struct btrfs_free_space), - GFP_NOFS); + info = kmem_cache_zalloc(btrfs_free_space_cachep, + GFP_NOFS); if (!info) { spin_lock(&block_group->tree_lock); ret = -ENOMEM; @@ -1365,7 +1367,7 @@ out: if (info) { if (info->bitmap) kfree(info->bitmap); - kfree(info); + kmem_cache_free(btrfs_free_space_cachep, info); } return ret; @@ -1398,7 +1400,7 @@ bool try_merge_free_space(struct btrfs_block_group_cache *block_group, else __unlink_free_space(block_group, right_info); info->bytes += right_info->bytes; - kfree(right_info); + kmem_cache_free(btrfs_free_space_cachep, right_info); merged = true; } @@ -1410,7 +1412,7 @@ bool try_merge_free_space(struct btrfs_block_group_cache *block_group, __unlink_free_space(block_group, left_info); info->offset = left_info->offset; info->bytes += left_info->bytes; - kfree(left_info); + kmem_cache_free(btrfs_free_space_cachep, left_info); merged = true; } @@ -1423,7 +1425,7 @@ int btrfs_add_free_space(struct btrfs_block_group_cache *block_group, struct btrfs_free_space *info; int ret = 0; - info = kzalloc(sizeof(struct btrfs_free_space), GFP_NOFS); + info = kmem_cache_zalloc(btrfs_free_space_cachep, GFP_NOFS); if (!info) return -ENOMEM; @@ -1450,7 +1452,7 @@ int btrfs_add_free_space(struct btrfs_block_group_cache *block_group, link: ret = link_free_space(block_group, info); if (ret) - kfree(info); + kmem_cache_free(btrfs_free_space_cachep, info); out: spin_unlock(&block_group->tree_lock); @@ -1520,7 +1522,7 @@ again: kfree(info->bitmap); block_group->total_bitmaps--; } - kfree(info); + kmem_cache_free(btrfs_free_space_cachep, info); goto out_lock; } @@ -1556,7 +1558,7 @@ again: /* the hole we're creating ends at the end * of the info struct, just free the info */ - kfree(info); + kmem_cache_free(btrfs_free_space_cachep, info); } spin_unlock(&block_group->tree_lock); @@ -1689,7 +1691,7 @@ void btrfs_remove_free_space_cache(struct btrfs_block_group_cache *block_group) unlink_free_space(block_group, info); if (info->bitmap) kfree(info->bitmap); - kfree(info); + kmem_cache_free(btrfs_free_space_cachep, info); if (need_resched()) { spin_unlock(&block_group->tree_lock); cond_resched(); @@ -1722,7 +1724,7 @@ u64 btrfs_find_space_for_alloc(struct btrfs_block_group_cache *block_group, entry->offset += bytes; entry->bytes -= bytes; if (!entry->bytes) - kfree(entry); + kmem_cache_free(btrfs_free_space_cachep, entry); else link_free_space(block_group, entry); } @@ -1884,7 +1886,7 @@ out: block_group->free_space -= bytes; if (entry->bytes == 0) { block_group->free_extents--; - kfree(entry); + kmem_cache_free(btrfs_free_space_cachep, entry); } spin_unlock(&block_group->tree_lock); diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index d97b69afbbfb4..2d2e079713d73 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -50,6 +50,7 @@ #include "tree-log.h" #include "compression.h" #include "locking.h" +#include "free-space-cache.h" struct btrfs_iget_args { u64 ino; @@ -70,6 +71,7 @@ static struct kmem_cache *btrfs_inode_cachep; struct kmem_cache *btrfs_trans_handle_cachep; struct kmem_cache *btrfs_transaction_cachep; struct kmem_cache *btrfs_path_cachep; +struct kmem_cache *btrfs_free_space_cachep; #define S_SHIFT 12 static unsigned char btrfs_type_by_mode[S_IFMT >> S_SHIFT] = { @@ -6761,6 +6763,8 @@ void btrfs_destroy_cachep(void) kmem_cache_destroy(btrfs_transaction_cachep); if (btrfs_path_cachep) kmem_cache_destroy(btrfs_path_cachep); + if (btrfs_free_space_cachep) + kmem_cache_destroy(btrfs_free_space_cachep); } int btrfs_init_cachep(void) @@ -6789,6 +6793,12 @@ int btrfs_init_cachep(void) if (!btrfs_path_cachep) goto fail; + btrfs_free_space_cachep = kmem_cache_create("btrfs_free_space_cache", + sizeof(struct btrfs_free_space), 0, + SLAB_RECLAIM_ACCOUNT | SLAB_MEM_SPREAD, NULL); + if (!btrfs_free_space_cachep) + goto fail; + return 0; fail: btrfs_destroy_cachep(); -- GitLab From a41ad394a03b802497958d7c98a9dcf607266645 Mon Sep 17 00:00:00 2001 From: Josef Bacik Date: Mon, 31 Jan 2011 15:30:16 -0500 Subject: [PATCH 0815/2822] Btrfs: convert to the new truncate sequence ->truncate() is going away, instead all of the work needs to be done in ->setattr(). So this converts us over to do this. It's fairly straightforward, just get rid of our .truncate inode operation and call btrfs_truncate() directly from btrfs_setsize. This works out better for us since truncate can technically return ENOSPC, and before we had no way of letting anybody know. Thanks, Signed-off-by: Josef Bacik --- fs/btrfs/ctree.h | 2 +- fs/btrfs/file.c | 5 +-- fs/btrfs/inode.c | 80 ++++++++++++++++++++++-------------------------- 3 files changed, 40 insertions(+), 47 deletions(-) diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index 2c98d209e6acb..34142d5647df0 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h @@ -2537,7 +2537,7 @@ void btrfs_orphan_post_snapshot(struct btrfs_trans_handle *trans, struct btrfs_pending_snapshot *pending); void btrfs_orphan_commit_root(struct btrfs_trans_handle *trans, struct btrfs_root *root); -int btrfs_cont_expand(struct inode *inode, loff_t size); +int btrfs_cont_expand(struct inode *inode, loff_t oldsize, loff_t size); int btrfs_invalidate_inodes(struct btrfs_root *root); void btrfs_add_delayed_iput(struct inode *inode); void btrfs_run_delayed_iputs(struct btrfs_root *root); diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c index 24a19c2743ca7..3786eca2a905f 100644 --- a/fs/btrfs/file.c +++ b/fs/btrfs/file.c @@ -817,7 +817,7 @@ static noinline int prepare_pages(struct btrfs_root *root, struct file *file, last_pos = ((u64)index + num_pages) << PAGE_CACHE_SHIFT; if (start_pos > inode->i_size) { - err = btrfs_cont_expand(inode, start_pos); + err = btrfs_cont_expand(inode, i_size_read(inode), start_pos); if (err) return err; } @@ -1330,7 +1330,8 @@ static long btrfs_fallocate(struct file *file, int mode, goto out; if (alloc_start > inode->i_size) { - ret = btrfs_cont_expand(inode, alloc_start); + ret = btrfs_cont_expand(inode, i_size_read(inode), + alloc_start); if (ret) goto out; } diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 2d2e079713d73..3662ffec17d98 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -84,7 +84,8 @@ static unsigned char btrfs_type_by_mode[S_IFMT >> S_SHIFT] = { [S_IFLNK >> S_SHIFT] = BTRFS_FT_SYMLINK, }; -static void btrfs_truncate(struct inode *inode); +static int btrfs_setsize(struct inode *inode, loff_t newsize); +static int btrfs_truncate(struct inode *inode); static int btrfs_finish_ordered_io(struct inode *inode, u64 start, u64 end); static noinline int cow_file_range(struct inode *inode, struct page *locked_page, @@ -2371,6 +2372,11 @@ void btrfs_orphan_cleanup(struct btrfs_root *root) /* if we have links, this was a truncate, lets do that */ if (inode->i_nlink) { + if (!S_ISREG(inode->i_mode)) { + WARN_ON(1); + iput(inode); + continue; + } nr_truncate++; btrfs_truncate(inode); } else { @@ -3538,7 +3544,7 @@ out: return ret; } -int btrfs_cont_expand(struct inode *inode, loff_t size) +int btrfs_cont_expand(struct inode *inode, loff_t oldsize, loff_t size) { struct btrfs_trans_handle *trans; struct btrfs_root *root = BTRFS_I(inode)->root; @@ -3546,7 +3552,7 @@ int btrfs_cont_expand(struct inode *inode, loff_t size) struct extent_map *em = NULL; struct extent_state *cached_state = NULL; u64 mask = root->sectorsize - 1; - u64 hole_start = (inode->i_size + mask) & ~mask; + u64 hole_start = (oldsize + mask) & ~mask; u64 block_end = (size + mask) & ~mask; u64 last_byte; u64 cur_offset; @@ -3617,27 +3623,17 @@ int btrfs_cont_expand(struct inode *inode, loff_t size) return err; } -static int btrfs_setattr_size(struct inode *inode, struct iattr *attr) +static int btrfs_setsize(struct inode *inode, loff_t newsize) { struct btrfs_root *root = BTRFS_I(inode)->root; struct btrfs_trans_handle *trans; + loff_t oldsize = i_size_read(inode); unsigned long nr; int ret; - if (attr->ia_size == inode->i_size) + if (newsize == oldsize) return 0; - if (attr->ia_size > inode->i_size) { - unsigned long limit; - limit = current->signal->rlim[RLIMIT_FSIZE].rlim_cur; - if (attr->ia_size > inode->i_sb->s_maxbytes) - return -EFBIG; - if (limit != RLIM_INFINITY && attr->ia_size > limit) { - send_sig(SIGXFSZ, current, 0); - return -EFBIG; - } - } - trans = btrfs_start_transaction(root, 5); if (IS_ERR(trans)) return PTR_ERR(trans); @@ -3651,16 +3647,16 @@ static int btrfs_setattr_size(struct inode *inode, struct iattr *attr) btrfs_end_transaction(trans, root); btrfs_btree_balance_dirty(root, nr); - if (attr->ia_size > inode->i_size) { - ret = btrfs_cont_expand(inode, attr->ia_size); + if (newsize > oldsize) { + i_size_write(inode, newsize); + btrfs_ordered_update_i_size(inode, i_size_read(inode), NULL); + truncate_pagecache(inode, oldsize, newsize); + ret = btrfs_cont_expand(inode, oldsize, newsize); if (ret) { - btrfs_truncate(inode); + btrfs_setsize(inode, oldsize); return ret; } - i_size_write(inode, attr->ia_size); - btrfs_ordered_update_i_size(inode, inode->i_size, NULL); - trans = btrfs_start_transaction(root, 0); BUG_ON(IS_ERR(trans)); btrfs_set_trans_block_group(trans, inode); @@ -3676,22 +3672,22 @@ static int btrfs_setattr_size(struct inode *inode, struct iattr *attr) nr = trans->blocks_used; btrfs_end_transaction(trans, root); btrfs_btree_balance_dirty(root, nr); - return 0; - } + } else { - /* - * We're truncating a file that used to have good data down to - * zero. Make sure it gets into the ordered flush list so that - * any new writes get down to disk quickly. - */ - if (attr->ia_size == 0) - BTRFS_I(inode)->ordered_data_close = 1; + /* + * We're truncating a file that used to have good data down to + * zero. Make sure it gets into the ordered flush list so that + * any new writes get down to disk quickly. + */ + if (newsize == 0) + BTRFS_I(inode)->ordered_data_close = 1; - /* we don't support swapfiles, so vmtruncate shouldn't fail */ - ret = vmtruncate(inode, attr->ia_size); - BUG_ON(ret); + /* we don't support swapfiles, so vmtruncate shouldn't fail */ + truncate_setsize(inode, newsize); + ret = btrfs_truncate(inode); + } - return 0; + return ret; } static int btrfs_setattr(struct dentry *dentry, struct iattr *attr) @@ -3708,7 +3704,7 @@ static int btrfs_setattr(struct dentry *dentry, struct iattr *attr) return err; if (S_ISREG(inode->i_mode) && (attr->ia_valid & ATTR_SIZE)) { - err = btrfs_setattr_size(inode, attr); + err = btrfs_setsize(inode, attr->ia_size); if (err) return err; } @@ -6478,7 +6474,7 @@ out: return ret; } -static void btrfs_truncate(struct inode *inode) +static int btrfs_truncate(struct inode *inode) { struct btrfs_root *root = BTRFS_I(inode)->root; int ret; @@ -6486,14 +6482,9 @@ static void btrfs_truncate(struct inode *inode) unsigned long nr; u64 mask = root->sectorsize - 1; - if (!S_ISREG(inode->i_mode)) { - WARN_ON(1); - return; - } - ret = btrfs_truncate_page(inode->i_mapping, inode->i_size); if (ret) - return; + return ret; btrfs_wait_ordered_range(inode, inode->i_size & (~mask), (u64)-1); btrfs_ordered_update_i_size(inode, inode->i_size, NULL); @@ -6568,6 +6559,8 @@ static void btrfs_truncate(struct inode *inode) ret = btrfs_end_transaction_throttle(trans, root); BUG_ON(ret); btrfs_btree_balance_dirty(root, nr); + + return ret; } /* @@ -7367,7 +7360,6 @@ static const struct address_space_operations btrfs_symlink_aops = { }; static const struct inode_operations btrfs_file_inode_operations = { - .truncate = btrfs_truncate, .getattr = btrfs_getattr, .setattr = btrfs_setattr, .setxattr = btrfs_setxattr, -- GitLab From 3893e33b0bebee2f67d96b6c15259dc884523c20 Mon Sep 17 00:00:00 2001 From: Josef Bacik Date: Mon, 31 Jan 2011 16:03:11 -0500 Subject: [PATCH 0816/2822] Btrfs: cleanup error handling in the truncate path Now that we can handle having errors in the truncate path lets make sure we return errors instead of doing BUG_ON() and such. Thanks, Signed-off-by: Josef Bacik --- fs/btrfs/inode.c | 64 ++++++++++++++++++++++++++++++++++-------------- 1 file changed, 45 insertions(+), 19 deletions(-) diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 3662ffec17d98..d83025063ee76 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -3597,13 +3597,15 @@ int btrfs_cont_expand(struct inode *inode, loff_t oldsize, loff_t size) err = btrfs_drop_extents(trans, inode, cur_offset, cur_offset + hole_size, &hint_byte, 1); - BUG_ON(err); + if (err) + break; err = btrfs_insert_file_extent(trans, root, inode->i_ino, cur_offset, 0, 0, hole_size, 0, hole_size, 0, 0, 0); - BUG_ON(err); + if (err) + break; btrfs_drop_extent_cache(inode, hole_start, last_byte - 1, 0); @@ -3641,7 +3643,10 @@ static int btrfs_setsize(struct inode *inode, loff_t newsize) btrfs_set_trans_block_group(trans, inode); ret = btrfs_orphan_add(trans, inode); - BUG_ON(ret); + if (ret) { + btrfs_end_transaction(trans, root); + return ret; + } nr = trans->blocks_used; btrfs_end_transaction(trans, root); @@ -3658,17 +3663,24 @@ static int btrfs_setsize(struct inode *inode, loff_t newsize) } trans = btrfs_start_transaction(root, 0); - BUG_ON(IS_ERR(trans)); + if (IS_ERR(trans)) + return PTR_ERR(trans); + btrfs_set_trans_block_group(trans, inode); trans->block_rsv = root->orphan_block_rsv; BUG_ON(!trans->block_rsv); + /* + * If this fails just leave the orphan item so that it can get + * cleaned up next time we mount. + */ ret = btrfs_update_inode(trans, root, inode); - BUG_ON(ret); - if (inode->i_nlink > 0) { - ret = btrfs_orphan_del(trans, inode); - BUG_ON(ret); + if (ret) { + btrfs_end_transaction(trans, root); + return ret; } + if (inode->i_nlink > 0) + ret = btrfs_orphan_del(trans, inode); nr = trans->blocks_used; btrfs_end_transaction(trans, root); btrfs_btree_balance_dirty(root, nr); @@ -6478,6 +6490,7 @@ static int btrfs_truncate(struct inode *inode) { struct btrfs_root *root = BTRFS_I(inode)->root; int ret; + int err = 0; struct btrfs_trans_handle *trans; unsigned long nr; u64 mask = root->sectorsize - 1; @@ -6490,7 +6503,8 @@ static int btrfs_truncate(struct inode *inode) btrfs_ordered_update_i_size(inode, inode->i_size, NULL); trans = btrfs_start_transaction(root, 0); - BUG_ON(IS_ERR(trans)); + if (IS_ERR(trans)) + return PTR_ERR(trans); btrfs_set_trans_block_group(trans, inode); trans->block_rsv = root->orphan_block_rsv; @@ -6517,29 +6531,38 @@ static int btrfs_truncate(struct inode *inode) while (1) { if (!trans) { trans = btrfs_start_transaction(root, 0); - BUG_ON(IS_ERR(trans)); + if (IS_ERR(trans)) + return PTR_ERR(trans); btrfs_set_trans_block_group(trans, inode); trans->block_rsv = root->orphan_block_rsv; } ret = btrfs_block_rsv_check(trans, root, root->orphan_block_rsv, 0, 5); - if (ret) { - BUG_ON(ret != -EAGAIN); + if (ret == -EAGAIN) { ret = btrfs_commit_transaction(trans, root); - BUG_ON(ret); + if (ret) + return ret; trans = NULL; continue; + } else if (ret) { + err = ret; + break; } ret = btrfs_truncate_inode_items(trans, root, inode, inode->i_size, BTRFS_EXTENT_DATA_KEY); - if (ret != -EAGAIN) + if (ret != -EAGAIN) { + err = ret; break; + } ret = btrfs_update_inode(trans, root, inode); - BUG_ON(ret); + if (ret) { + err = ret; + break; + } nr = trans->blocks_used; btrfs_end_transaction(trans, root); @@ -6549,18 +6572,21 @@ static int btrfs_truncate(struct inode *inode) if (ret == 0 && inode->i_nlink > 0) { ret = btrfs_orphan_del(trans, inode); - BUG_ON(ret); + if (ret) + err = ret; } ret = btrfs_update_inode(trans, root, inode); - BUG_ON(ret); + if (ret && !err) + err = ret; nr = trans->blocks_used; ret = btrfs_end_transaction_throttle(trans, root); - BUG_ON(ret); + if (ret && !err) + err = ret; btrfs_btree_balance_dirty(root, nr); - return ret; + return err; } /* -- GitLab From 66b4ffd110f9b48b8d8c1319ee446b53b8d073bf Mon Sep 17 00:00:00 2001 From: Josef Bacik Date: Mon, 31 Jan 2011 16:22:42 -0500 Subject: [PATCH 0817/2822] Btrfs: handle errors in btrfs_orphan_cleanup If we cannot truncate an inode for some reason we will never delete the orphan item associated with that inode, which means that we will loop forever in btrfs_orphan_cleanup. Instead of doing this just return error so we fail to mount. It sucks, but hey it's better than hanging. Thanks, Signed-off-by: Josef Bacik --- fs/btrfs/ctree.h | 2 +- fs/btrfs/disk-io.c | 15 +++++++++++--- fs/btrfs/extent-tree.c | 3 ++- fs/btrfs/inode.c | 47 ++++++++++++++++++++++++++++-------------- fs/btrfs/ioctl.c | 4 +++- fs/btrfs/relocation.c | 2 +- 6 files changed, 50 insertions(+), 23 deletions(-) diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index 34142d5647df0..841330f3d68d3 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h @@ -2529,7 +2529,7 @@ int btrfs_update_inode(struct btrfs_trans_handle *trans, struct inode *inode); int btrfs_orphan_add(struct btrfs_trans_handle *trans, struct inode *inode); int btrfs_orphan_del(struct btrfs_trans_handle *trans, struct inode *inode); -void btrfs_orphan_cleanup(struct btrfs_root *root); +int btrfs_orphan_cleanup(struct btrfs_root *root); void btrfs_orphan_pre_snapshot(struct btrfs_trans_handle *trans, struct btrfs_pending_snapshot *pending, u64 *bytes_to_reserve); diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index e1aa8d607bc7d..495b1ac45f8c1 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c @@ -2058,9 +2058,14 @@ struct btrfs_root *open_ctree(struct super_block *sb, if (!(sb->s_flags & MS_RDONLY)) { down_read(&fs_info->cleanup_work_sem); - btrfs_orphan_cleanup(fs_info->fs_root); - btrfs_orphan_cleanup(fs_info->tree_root); + err = btrfs_orphan_cleanup(fs_info->fs_root); + if (!err) + err = btrfs_orphan_cleanup(fs_info->tree_root); up_read(&fs_info->cleanup_work_sem); + if (err) { + close_ctree(tree_root); + return ERR_PTR(err); + } } return tree_root; @@ -2435,8 +2440,12 @@ int btrfs_cleanup_fs_roots(struct btrfs_fs_info *fs_info) root_objectid = gang[ret - 1]->root_key.objectid + 1; for (i = 0; i < ret; i++) { + int err; + root_objectid = gang[i]->root_key.objectid; - btrfs_orphan_cleanup(gang[i]); + err = btrfs_orphan_cleanup(gang[i]); + if (err) + return err; } root_objectid++; } diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index 27376c97d85f9..a8f4e8d2ba606 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c @@ -7619,7 +7619,8 @@ int btrfs_cleanup_reloc_trees(struct btrfs_root *root) reloc_root = btrfs_read_fs_root_no_name(root->fs_info, &location); BUG_ON(!reloc_root); - btrfs_orphan_cleanup(reloc_root); + ret = btrfs_orphan_cleanup(reloc_root); + BUG_ON(ret); return 0; } diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index d83025063ee76..0600265cb9b06 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -2284,7 +2284,7 @@ int btrfs_orphan_del(struct btrfs_trans_handle *trans, struct inode *inode) * this cleans up any orphans that may be left on the list from the last use * of this root. */ -void btrfs_orphan_cleanup(struct btrfs_root *root) +int btrfs_orphan_cleanup(struct btrfs_root *root) { struct btrfs_path *path; struct extent_buffer *leaf; @@ -2294,10 +2294,13 @@ void btrfs_orphan_cleanup(struct btrfs_root *root) int ret = 0, nr_unlink = 0, nr_truncate = 0; if (cmpxchg(&root->orphan_cleanup_state, 0, ORPHAN_CLEANUP_STARTED)) - return; + return 0; path = btrfs_alloc_path(); - BUG_ON(!path); + if (!path) { + ret = -ENOMEM; + goto out; + } path->reada = -1; key.objectid = BTRFS_ORPHAN_OBJECTID; @@ -2306,11 +2309,8 @@ void btrfs_orphan_cleanup(struct btrfs_root *root) while (1) { ret = btrfs_search_slot(NULL, root, &key, path, 0, 0); - if (ret < 0) { - printk(KERN_ERR "Error searching slot for orphan: %d" - "\n", ret); - break; - } + if (ret < 0) + goto out; /* * if ret == 0 means we found what we were searching for, which @@ -2318,6 +2318,7 @@ void btrfs_orphan_cleanup(struct btrfs_root *root) * find the key and see if we have stuff that matches */ if (ret > 0) { + ret = 0; if (path->slots[0] == 0) break; path->slots[0]--; @@ -2345,7 +2346,10 @@ void btrfs_orphan_cleanup(struct btrfs_root *root) found_key.type = BTRFS_INODE_ITEM_KEY; found_key.offset = 0; inode = btrfs_iget(root->fs_info->sb, &found_key, root, NULL); - BUG_ON(IS_ERR(inode)); + if (IS_ERR(inode)) { + ret = PTR_ERR(inode); + goto out; + } /* * add this inode to the orphan list so btrfs_orphan_del does @@ -2363,7 +2367,10 @@ void btrfs_orphan_cleanup(struct btrfs_root *root) */ if (is_bad_inode(inode)) { trans = btrfs_start_transaction(root, 0); - BUG_ON(IS_ERR(trans)); + if (IS_ERR(trans)) { + ret = PTR_ERR(trans); + goto out; + } btrfs_orphan_del(trans, inode); btrfs_end_transaction(trans, root); iput(inode); @@ -2378,16 +2385,16 @@ void btrfs_orphan_cleanup(struct btrfs_root *root) continue; } nr_truncate++; - btrfs_truncate(inode); + ret = btrfs_truncate(inode); } else { nr_unlink++; } /* this will do delete_inode and everything for us */ iput(inode); + if (ret) + goto out; } - btrfs_free_path(path); - root->orphan_cleanup_state = ORPHAN_CLEANUP_DONE; if (root->orphan_block_rsv) @@ -2396,14 +2403,20 @@ void btrfs_orphan_cleanup(struct btrfs_root *root) if (root->orphan_block_rsv || root->orphan_item_inserted) { trans = btrfs_join_transaction(root, 1); - BUG_ON(IS_ERR(trans)); - btrfs_end_transaction(trans, root); + if (!IS_ERR(trans)) + btrfs_end_transaction(trans, root); } if (nr_unlink) printk(KERN_INFO "btrfs: unlinked %d orphans\n", nr_unlink); if (nr_truncate) printk(KERN_INFO "btrfs: truncated %d orphans\n", nr_truncate); + +out: + if (ret) + printk(KERN_CRIT "btrfs: could not do orphan cleanup %d\n", ret); + btrfs_free_path(path); + return ret; } /* @@ -4156,8 +4169,10 @@ struct inode *btrfs_lookup_dentry(struct inode *dir, struct dentry *dentry) if (!IS_ERR(inode) && root != sub_root) { down_read(&root->fs_info->cleanup_work_sem); if (!(inode->i_sb->s_flags & MS_RDONLY)) - btrfs_orphan_cleanup(sub_root); + ret = btrfs_orphan_cleanup(sub_root); up_read(&root->fs_info->cleanup_work_sem); + if (ret) + inode = ERR_PTR(ret); } return inode; diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index 5fdb2abc4fa78..ad9b8c0e930b4 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c @@ -409,7 +409,9 @@ static int create_snapshot(struct btrfs_root *root, struct dentry *dentry, if (ret) goto fail; - btrfs_orphan_cleanup(pending_snapshot->snap); + ret = btrfs_orphan_cleanup(pending_snapshot->snap); + if (ret) + goto fail; parent = dget_parent(dentry); inode = btrfs_lookup_dentry(parent->d_inode, dentry); diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c index 31ade5802ae8a..c863c84470152 100644 --- a/fs/btrfs/relocation.c +++ b/fs/btrfs/relocation.c @@ -4209,7 +4209,7 @@ out: if (IS_ERR(fs_root)) err = PTR_ERR(fs_root); else - btrfs_orphan_cleanup(fs_root); + err = btrfs_orphan_cleanup(fs_root); } return err; } -- GitLab From ded5db9de78f963979e1605f859de67626f54693 Mon Sep 17 00:00:00 2001 From: Josef Bacik Date: Fri, 4 Mar 2011 14:09:46 -0500 Subject: [PATCH 0818/2822] Btrfs: make sure to remove the orphan item from the in-memory list This fixes a problem where if truncate fails the inode will still be on the in memory orphan list. This is will make us complain when the inode gets destroyed because it's still on the orphan list. So if we fail just remove us from the in memory list and carry on. Signed-off-by: Josef Bacik --- fs/btrfs/inode.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 0600265cb9b06..3bd0ff63bf30a 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -6589,6 +6589,12 @@ static int btrfs_truncate(struct inode *inode) ret = btrfs_orphan_del(trans, inode); if (ret) err = ret; + } else if (ret && inode->i_nlink > 0) { + /* + * Failed to do the truncate, remove us from the in memory + * orphan list. + */ + ret = btrfs_orphan_del(NULL, inode); } ret = btrfs_update_inode(trans, root, inode); -- GitLab From f0cd846e9221811d87047f1428cf5226e7236efe Mon Sep 17 00:00:00 2001 From: Josef Bacik Date: Fri, 4 Mar 2011 14:37:08 -0500 Subject: [PATCH 0819/2822] Btrfs: only add orphan items when truncating We don't need an orphan item when expanding files, we just need them for truncating them, so only add the orphan item in btrfs_truncate instead of in btrfs_setsize. Thanks, Signed-off-by: Josef Bacik --- fs/btrfs/inode.c | 45 ++++++++++++++++++--------------------------- 1 file changed, 18 insertions(+), 27 deletions(-) diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 3bd0ff63bf30a..206b60362cece 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -3649,22 +3649,6 @@ static int btrfs_setsize(struct inode *inode, loff_t newsize) if (newsize == oldsize) return 0; - trans = btrfs_start_transaction(root, 5); - if (IS_ERR(trans)) - return PTR_ERR(trans); - - btrfs_set_trans_block_group(trans, inode); - - ret = btrfs_orphan_add(trans, inode); - if (ret) { - btrfs_end_transaction(trans, root); - return ret; - } - - nr = trans->blocks_used; - btrfs_end_transaction(trans, root); - btrfs_btree_balance_dirty(root, nr); - if (newsize > oldsize) { i_size_write(inode, newsize); btrfs_ordered_update_i_size(inode, i_size_read(inode), NULL); @@ -3675,25 +3659,15 @@ static int btrfs_setsize(struct inode *inode, loff_t newsize) return ret; } - trans = btrfs_start_transaction(root, 0); + trans = btrfs_start_transaction(root, 1); if (IS_ERR(trans)) return PTR_ERR(trans); - btrfs_set_trans_block_group(trans, inode); - trans->block_rsv = root->orphan_block_rsv; - BUG_ON(!trans->block_rsv); - - /* - * If this fails just leave the orphan item so that it can get - * cleaned up next time we mount. - */ ret = btrfs_update_inode(trans, root, inode); if (ret) { btrfs_end_transaction(trans, root); return ret; } - if (inode->i_nlink > 0) - ret = btrfs_orphan_del(trans, inode); nr = trans->blocks_used; btrfs_end_transaction(trans, root); btrfs_btree_balance_dirty(root, nr); @@ -6517,6 +6491,23 @@ static int btrfs_truncate(struct inode *inode) btrfs_wait_ordered_range(inode, inode->i_size & (~mask), (u64)-1); btrfs_ordered_update_i_size(inode, inode->i_size, NULL); + trans = btrfs_start_transaction(root, 5); + if (IS_ERR(trans)) + return PTR_ERR(trans); + + btrfs_set_trans_block_group(trans, inode); + + ret = btrfs_orphan_add(trans, inode); + if (ret) { + btrfs_end_transaction(trans, root); + return ret; + } + + nr = trans->blocks_used; + btrfs_end_transaction(trans, root); + btrfs_btree_balance_dirty(root, nr); + + /* Now start a transaction for the truncate */ trans = btrfs_start_transaction(root, 0); if (IS_ERR(trans)) return PTR_ERR(trans); -- GitLab From 930f028abe39dfd0849b53131d19c4b67aacbe67 Mon Sep 17 00:00:00 2001 From: Josef Bacik Date: Fri, 4 Mar 2011 14:41:41 -0500 Subject: [PATCH 0820/2822] Btrfs: use mark_inode_dirty when expanding the file Mark_inode_dirty will call btrfs_dirty_inode which will take care of updating the inode. This makes setsize a little cleaner since we don't have to start a transaction and update the inode in there, we can just call mark_inode_dirty. Thanks, Signed-off-by: Josef Bacik --- fs/btrfs/inode.c | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 206b60362cece..64d57e032b4e5 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -3640,10 +3640,7 @@ int btrfs_cont_expand(struct inode *inode, loff_t oldsize, loff_t size) static int btrfs_setsize(struct inode *inode, loff_t newsize) { - struct btrfs_root *root = BTRFS_I(inode)->root; - struct btrfs_trans_handle *trans; loff_t oldsize = i_size_read(inode); - unsigned long nr; int ret; if (newsize == oldsize) @@ -3659,18 +3656,7 @@ static int btrfs_setsize(struct inode *inode, loff_t newsize) return ret; } - trans = btrfs_start_transaction(root, 1); - if (IS_ERR(trans)) - return PTR_ERR(trans); - - ret = btrfs_update_inode(trans, root, inode); - if (ret) { - btrfs_end_transaction(trans, root); - return ret; - } - nr = trans->blocks_used; - btrfs_end_transaction(trans, root); - btrfs_btree_balance_dirty(root, nr); + mark_inode_dirty(inode); } else { /* -- GitLab From 695a0d0da09e75c4475bbb303def159023ef72ca Mon Sep 17 00:00:00 2001 From: Josef Bacik Date: Fri, 4 Mar 2011 15:46:53 -0500 Subject: [PATCH 0821/2822] Btrfs: add a comment explaining what btrfs_cont_expand does Everytime I have to deal with btrfs_cont_expand I stare at it for 20 minutes trying to remember what exactly it does and why the hell we need it. So add a comment to save future-Josef some time. Thanks, Signed-off-by: Josef Bacik --- fs/btrfs/inode.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 64d57e032b4e5..888dbdb3b128b 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -3557,6 +3557,12 @@ out: return ret; } +/* + * This function puts in dummy file extents for the area we're creating a hole + * for. So if we are truncating this file to a larger size we need to insert + * these file extents so that btrfs_get_extent will return a EXTENT_MAP_HOLE for + * the range between oldsize and size + */ int btrfs_cont_expand(struct inode *inode, loff_t oldsize, loff_t size) { struct btrfs_trans_handle *trans; -- GitLab From 850265335f792f5d39ab24e5fb7160bac28d77e5 Mon Sep 17 00:00:00 2001 From: Josef Bacik Date: Tue, 15 Mar 2011 14:52:12 -0400 Subject: [PATCH 0822/2822] Btrfs: return error if the range we want to map is bogus Currently if we have corrupt metadata map_extent_buffer will complain about it, but not return an error so the caller has no idea a problem was hit. Fix this. Thanks, Signed-off-by: Josef Bacik --- fs/btrfs/extent_io.c | 1 + 1 file changed, 1 insertion(+) diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c index 714adc4ac4c24..1bbd26b4fc5cf 100644 --- a/fs/btrfs/extent_io.c +++ b/fs/btrfs/extent_io.c @@ -3690,6 +3690,7 @@ int map_private_extent_buffer(struct extent_buffer *eb, unsigned long start, "wanted %lu %lu\n", (unsigned long long)eb->start, eb->len, start, min_len); WARN_ON(1); + return -EINVAL; } p = extent_buffer_page(eb, i); -- GitLab From a826d6dcb32d811b4c81df57a5ef1367516586b0 Mon Sep 17 00:00:00 2001 From: Josef Bacik Date: Wed, 16 Mar 2011 13:42:43 -0400 Subject: [PATCH 0823/2822] Btrfs: check items for correctness as we search Currently if we have corrupted items things will blow up in spectacular ways. So as we read in blocks and they are leaves, check the entire leaf to make sure all of the items are correct and point to valid parts in the leaf for the item data the are responsible for. If the item is corrupt we will kick back EIO and not read any of the copies since they are likely to not be correct either. This will catch generic corruptions, it will be up to the individual callers of btrfs_search_slot to make sure their items are right. Thanks, Signed-off-by: Josef Bacik --- fs/btrfs/ctree.c | 123 ----------------------------------------- fs/btrfs/disk-io.c | 90 +++++++++++++++++++++++++++++- fs/btrfs/extent-tree.c | 5 ++ fs/btrfs/extent_io.h | 1 + 4 files changed, 95 insertions(+), 124 deletions(-) diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c index b5baff0dccfec..73e53009e126d 100644 --- a/fs/btrfs/ctree.c +++ b/fs/btrfs/ctree.c @@ -732,122 +732,6 @@ static inline unsigned int leaf_data_end(struct btrfs_root *root, return btrfs_item_offset_nr(leaf, nr - 1); } -/* - * extra debugging checks to make sure all the items in a key are - * well formed and in the proper order - */ -static int check_node(struct btrfs_root *root, struct btrfs_path *path, - int level) -{ - struct extent_buffer *parent = NULL; - struct extent_buffer *node = path->nodes[level]; - struct btrfs_disk_key parent_key; - struct btrfs_disk_key node_key; - int parent_slot; - int slot; - struct btrfs_key cpukey; - u32 nritems = btrfs_header_nritems(node); - - if (path->nodes[level + 1]) - parent = path->nodes[level + 1]; - - slot = path->slots[level]; - BUG_ON(nritems == 0); - if (parent) { - parent_slot = path->slots[level + 1]; - btrfs_node_key(parent, &parent_key, parent_slot); - btrfs_node_key(node, &node_key, 0); - BUG_ON(memcmp(&parent_key, &node_key, - sizeof(struct btrfs_disk_key))); - BUG_ON(btrfs_node_blockptr(parent, parent_slot) != - btrfs_header_bytenr(node)); - } - BUG_ON(nritems > BTRFS_NODEPTRS_PER_BLOCK(root)); - if (slot != 0) { - btrfs_node_key_to_cpu(node, &cpukey, slot - 1); - btrfs_node_key(node, &node_key, slot); - BUG_ON(comp_keys(&node_key, &cpukey) <= 0); - } - if (slot < nritems - 1) { - btrfs_node_key_to_cpu(node, &cpukey, slot + 1); - btrfs_node_key(node, &node_key, slot); - BUG_ON(comp_keys(&node_key, &cpukey) >= 0); - } - return 0; -} - -/* - * extra checking to make sure all the items in a leaf are - * well formed and in the proper order - */ -static int check_leaf(struct btrfs_root *root, struct btrfs_path *path, - int level) -{ - struct extent_buffer *leaf = path->nodes[level]; - struct extent_buffer *parent = NULL; - int parent_slot; - struct btrfs_key cpukey; - struct btrfs_disk_key parent_key; - struct btrfs_disk_key leaf_key; - int slot = path->slots[0]; - - u32 nritems = btrfs_header_nritems(leaf); - - if (path->nodes[level + 1]) - parent = path->nodes[level + 1]; - - if (nritems == 0) - return 0; - - if (parent) { - parent_slot = path->slots[level + 1]; - btrfs_node_key(parent, &parent_key, parent_slot); - btrfs_item_key(leaf, &leaf_key, 0); - - BUG_ON(memcmp(&parent_key, &leaf_key, - sizeof(struct btrfs_disk_key))); - BUG_ON(btrfs_node_blockptr(parent, parent_slot) != - btrfs_header_bytenr(leaf)); - } - if (slot != 0 && slot < nritems - 1) { - btrfs_item_key(leaf, &leaf_key, slot); - btrfs_item_key_to_cpu(leaf, &cpukey, slot - 1); - if (comp_keys(&leaf_key, &cpukey) <= 0) { - btrfs_print_leaf(root, leaf); - printk(KERN_CRIT "slot %d offset bad key\n", slot); - BUG_ON(1); - } - if (btrfs_item_offset_nr(leaf, slot - 1) != - btrfs_item_end_nr(leaf, slot)) { - btrfs_print_leaf(root, leaf); - printk(KERN_CRIT "slot %d offset bad\n", slot); - BUG_ON(1); - } - } - if (slot < nritems - 1) { - btrfs_item_key(leaf, &leaf_key, slot); - btrfs_item_key_to_cpu(leaf, &cpukey, slot + 1); - BUG_ON(comp_keys(&leaf_key, &cpukey) >= 0); - if (btrfs_item_offset_nr(leaf, slot) != - btrfs_item_end_nr(leaf, slot + 1)) { - btrfs_print_leaf(root, leaf); - printk(KERN_CRIT "slot %d offset bad\n", slot); - BUG_ON(1); - } - } - BUG_ON(btrfs_item_offset_nr(leaf, 0) + - btrfs_item_size_nr(leaf, 0) != BTRFS_LEAF_DATA_SIZE(root)); - return 0; -} - -static noinline int check_block(struct btrfs_root *root, - struct btrfs_path *path, int level) -{ - return 0; - if (level == 0) - return check_leaf(root, path, level); - return check_node(root, path, level); -} /* * search for key in the extent_buffer. The items start at offset p, @@ -1188,7 +1072,6 @@ static noinline int balance_level(struct btrfs_trans_handle *trans, } } /* double check we haven't messed things up */ - check_block(root, path, level); if (orig_ptr != btrfs_node_blockptr(path->nodes[level], path->slots[level])) BUG(); @@ -1798,12 +1681,6 @@ cow_done: if (!cow) btrfs_unlock_up_safe(p, level + 1); - ret = check_block(root, p, level); - if (ret) { - ret = -1; - goto done; - } - ret = bin_search(b, key, level, &slot); if (level != 0) { diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 495b1ac45f8c1..9f31e110b4814 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c @@ -323,6 +323,7 @@ static int btree_read_extent_buffer_pages(struct btrfs_root *root, int num_copies = 0; int mirror_num = 0; + clear_bit(EXTENT_BUFFER_CORRUPT, &eb->bflags); io_tree = &BTRFS_I(root->fs_info->btree_inode)->io_tree; while (1) { ret = read_extent_buffer_pages(io_tree, eb, start, 1, @@ -331,6 +332,14 @@ static int btree_read_extent_buffer_pages(struct btrfs_root *root, !verify_parent_transid(io_tree, eb, parent_transid)) return ret; + /* + * This buffer's crc is fine, but its contents are corrupted, so + * there is no reason to read the other copies, they won't be + * any less wrong. + */ + if (test_bit(EXTENT_BUFFER_CORRUPT, &eb->bflags)) + return ret; + num_copies = btrfs_num_copies(&root->fs_info->mapping_tree, eb->start, eb->len); if (num_copies == 1) @@ -419,6 +428,73 @@ static int check_tree_block_fsid(struct btrfs_root *root, return ret; } +#define CORRUPT(reason, eb, root, slot) \ + printk(KERN_CRIT "btrfs: corrupt leaf, %s: block=%llu," \ + "root=%llu, slot=%d\n", reason, \ + (unsigned long long)btrfs_header_bytenr(eb), \ + (unsigned long long)root->objectid, slot) + +static noinline int check_leaf(struct btrfs_root *root, + struct extent_buffer *leaf) +{ + struct btrfs_key key; + struct btrfs_key leaf_key; + u32 nritems = btrfs_header_nritems(leaf); + int slot; + + if (nritems == 0) + return 0; + + /* Check the 0 item */ + if (btrfs_item_offset_nr(leaf, 0) + btrfs_item_size_nr(leaf, 0) != + BTRFS_LEAF_DATA_SIZE(root)) { + CORRUPT("invalid item offset size pair", leaf, root, 0); + return -EIO; + } + + /* + * Check to make sure each items keys are in the correct order and their + * offsets make sense. We only have to loop through nritems-1 because + * we check the current slot against the next slot, which verifies the + * next slot's offset+size makes sense and that the current's slot + * offset is correct. + */ + for (slot = 0; slot < nritems - 1; slot++) { + btrfs_item_key_to_cpu(leaf, &leaf_key, slot); + btrfs_item_key_to_cpu(leaf, &key, slot + 1); + + /* Make sure the keys are in the right order */ + if (btrfs_comp_cpu_keys(&leaf_key, &key) >= 0) { + CORRUPT("bad key order", leaf, root, slot); + return -EIO; + } + + /* + * Make sure the offset and ends are right, remember that the + * item data starts at the end of the leaf and grows towards the + * front. + */ + if (btrfs_item_offset_nr(leaf, slot) != + btrfs_item_end_nr(leaf, slot + 1)) { + CORRUPT("slot offset bad", leaf, root, slot); + return -EIO; + } + + /* + * Check to make sure that we don't point outside of the leaf, + * just incase all the items are consistent to eachother, but + * all point outside of the leaf. + */ + if (btrfs_item_end_nr(leaf, slot) > + BTRFS_LEAF_DATA_SIZE(root)) { + CORRUPT("slot end outside of leaf", leaf, root, slot); + return -EIO; + } + } + + return 0; +} + #ifdef CONFIG_DEBUG_LOCK_ALLOC void btrfs_set_buffer_lockdep_class(struct extent_buffer *eb, int level) { @@ -485,8 +561,20 @@ static int btree_readpage_end_io_hook(struct page *page, u64 start, u64 end, btrfs_set_buffer_lockdep_class(eb, found_level); ret = csum_tree_block(root, eb, 1); - if (ret) + if (ret) { ret = -EIO; + goto err; + } + + /* + * If this is a leaf block and it is corrupt, set the corrupt bit so + * that we don't try and read the other copies of this block, just + * return -EIO. + */ + if (found_level == 0 && check_leaf(root, eb)) { + set_bit(EXTENT_BUFFER_CORRUPT, &eb->bflags); + ret = -EIO; + } end = min_t(u64, eb->len, PAGE_CACHE_SIZE); end = eb->start + end - 1; diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index a8f4e8d2ba606..cd794c35a6363 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c @@ -4754,6 +4754,11 @@ pin: } } out: + /* + * Deleting the buffer, clear the corrupt flag since it doesn't matter + * anymore. + */ + clear_bit(EXTENT_BUFFER_CORRUPT, &buf->bflags); btrfs_put_block_group(cache); } diff --git a/fs/btrfs/extent_io.h b/fs/btrfs/extent_io.h index 9318dfefd59c5..f62c5442835d1 100644 --- a/fs/btrfs/extent_io.h +++ b/fs/btrfs/extent_io.h @@ -31,6 +31,7 @@ #define EXTENT_BUFFER_UPTODATE 0 #define EXTENT_BUFFER_BLOCKING 1 #define EXTENT_BUFFER_DIRTY 2 +#define EXTENT_BUFFER_CORRUPT 3 /* these are flags for extent_clear_unlock_delalloc */ #define EXTENT_CLEAR_UNLOCK_PAGE 0x1 -- GitLab From 41415730a1050499fbd63b3f7dd59b3a4c3bb91a Mon Sep 17 00:00:00 2001 From: Josef Bacik Date: Wed, 16 Mar 2011 13:59:32 -0400 Subject: [PATCH 0824/2822] Btrfs: check return value of btrfs_search_slot properly Doing an audit of where we use btrfs_search_slot only showed one place where we don't check the return value of btrfs_search_slot properly. Just fix mark_extent_written to see if btrfs_search_slot failed and act accordingly. Thanks, Signed-off-by: Josef Bacik --- fs/btrfs/file.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c index 3786eca2a905f..a85b044cf39e7 100644 --- a/fs/btrfs/file.c +++ b/fs/btrfs/file.c @@ -608,6 +608,8 @@ again: key.offset = split; ret = btrfs_search_slot(trans, root, &key, path, -1, 1); + if (ret < 0) + goto out; if (ret > 0 && path->slots[0] > 0) path->slots[0]--; -- GitLab From 22a94d44bd6876a90630338229da6c0436d46593 Mon Sep 17 00:00:00 2001 From: Josef Bacik Date: Wed, 16 Mar 2011 16:47:17 -0400 Subject: [PATCH 0825/2822] Btrfs: add checks to verify dir items are correct We need to make sure the dir items we get are valid dir items. So any time we try and read one check it with verify_dir_item, which will do various sanity checks to make sure it looks sane. Thanks, Signed-off-by: Josef Bacik --- fs/btrfs/ctree.h | 3 +++ fs/btrfs/dir-item.c | 35 +++++++++++++++++++++++++++++++++++ fs/btrfs/inode.c | 3 +++ fs/btrfs/tree-log.c | 7 +++++++ fs/btrfs/xattr.c | 2 ++ 5 files changed, 50 insertions(+) diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index 841330f3d68d3..6036fdb88c53a 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h @@ -2393,6 +2393,9 @@ struct btrfs_dir_item *btrfs_lookup_xattr(struct btrfs_trans_handle *trans, struct btrfs_path *path, u64 dir, const char *name, u16 name_len, int mod); +int verify_dir_item(struct btrfs_root *root, + struct extent_buffer *leaf, + struct btrfs_dir_item *dir_item); /* orphan.c */ int btrfs_insert_orphan_item(struct btrfs_trans_handle *trans, diff --git a/fs/btrfs/dir-item.c b/fs/btrfs/dir-item.c index f0cad5ae5be75..02c97ad61b6dd 100644 --- a/fs/btrfs/dir-item.c +++ b/fs/btrfs/dir-item.c @@ -377,6 +377,9 @@ struct btrfs_dir_item *btrfs_match_dir_item_name(struct btrfs_root *root, leaf = path->nodes[0]; dir_item = btrfs_item_ptr(leaf, path->slots[0], struct btrfs_dir_item); + if (verify_dir_item(root, leaf, dir_item)) + return NULL; + total_len = btrfs_item_size_nr(leaf, path->slots[0]); while (cur < total_len) { this_len = sizeof(*dir_item) + @@ -429,3 +432,35 @@ int btrfs_delete_one_dir_name(struct btrfs_trans_handle *trans, } return ret; } + +int verify_dir_item(struct btrfs_root *root, + struct extent_buffer *leaf, + struct btrfs_dir_item *dir_item) +{ + u16 namelen = BTRFS_NAME_LEN; + u8 type = btrfs_dir_type(leaf, dir_item); + + if (type >= BTRFS_FT_MAX) { + printk(KERN_CRIT "btrfs: invalid dir item type: %d\n", + (int)type); + return 1; + } + + if (type == BTRFS_FT_XATTR) + namelen = XATTR_NAME_MAX; + + if (btrfs_dir_name_len(leaf, dir_item) > namelen) { + printk(KERN_CRIT "btrfS: invalid dir item name len: %u\n", + (unsigned)btrfs_dir_data_len(leaf, dir_item)); + return 1; + } + + /* BTRFS_MAX_XATTR_SIZE is the same for all dir items */ + if (btrfs_dir_data_len(leaf, dir_item) > BTRFS_MAX_XATTR_SIZE(root)) { + printk(KERN_CRIT "btrfs: invalid dir item data len: %u\n", + (unsigned)btrfs_dir_data_len(leaf, dir_item)); + return 1; + } + + return 0; +} diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 888dbdb3b128b..e010000d4bc9b 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -4272,6 +4272,9 @@ static int btrfs_real_readdir(struct file *filp, void *dirent, while (di_cur < di_total) { struct btrfs_key location; + if (verify_dir_item(root, leaf, di)) + break; + name_len = btrfs_dir_name_len(leaf, di); if (name_len <= sizeof(tmp_name)) { name_ptr = tmp_name; diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c index a4bbb854dfd21..429cfcfadf909 100644 --- a/fs/btrfs/tree-log.c +++ b/fs/btrfs/tree-log.c @@ -1286,6 +1286,8 @@ static noinline int replay_one_dir_item(struct btrfs_trans_handle *trans, ptr_end = ptr + item_size; while (ptr < ptr_end) { di = (struct btrfs_dir_item *)ptr; + if (verify_dir_item(root, eb, di)) + return -EIO; name_len = btrfs_dir_name_len(eb, di); ret = replay_one_name(trans, root, path, eb, di, key); BUG_ON(ret); @@ -1412,6 +1414,11 @@ again: ptr_end = ptr + item_size; while (ptr < ptr_end) { di = (struct btrfs_dir_item *)ptr; + if (verify_dir_item(root, eb, di)) { + ret = -EIO; + goto out; + } + name_len = btrfs_dir_name_len(eb, di); name = kmalloc(name_len, GFP_NOFS); if (!name) { diff --git a/fs/btrfs/xattr.c b/fs/btrfs/xattr.c index a5776531dc2ba..e5d22f280956c 100644 --- a/fs/btrfs/xattr.c +++ b/fs/btrfs/xattr.c @@ -242,6 +242,8 @@ ssize_t btrfs_listxattr(struct dentry *dentry, char *buffer, size_t size) break; di = btrfs_item_ptr(leaf, slot, struct btrfs_dir_item); + if (verify_dir_item(root, leaf, di)) + continue; name_len = btrfs_dir_name_len(leaf, di); total_size += name_len + 1; -- GitLab From 4be34b9d69c97211ff4eb00d79078f3c1593804d Mon Sep 17 00:00:00 2001 From: Jesper Juhl Date: Sat, 22 Jan 2011 22:40:20 +0100 Subject: [PATCH 0826/2822] SUNRPC: Remove resource leak in svc_rdma_send_error() We leak the memory allocated to 'ctxt' when we return after 'ib_dma_mapping_error()' returns !=0. Signed-off-by: Jesper Juhl Signed-off-by: J. Bruce Fields --- net/sunrpc/xprtrdma/svc_rdma_transport.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/sunrpc/xprtrdma/svc_rdma_transport.c b/net/sunrpc/xprtrdma/svc_rdma_transport.c index 9df1eadc912a8..1a10dcd999ea9 100644 --- a/net/sunrpc/xprtrdma/svc_rdma_transport.c +++ b/net/sunrpc/xprtrdma/svc_rdma_transport.c @@ -1335,6 +1335,7 @@ void svc_rdma_send_error(struct svcxprt_rdma *xprt, struct rpcrdma_msg *rmsgp, p, 0, length, DMA_FROM_DEVICE); if (ib_dma_mapping_error(xprt->sc_cm_id->device, ctxt->sge[0].addr)) { put_page(p); + svc_rdma_put_context(ctxt, 1); return; } atomic_inc(&xprt->sc_dma_used); -- GitLab From dffc55adfa2676a02a838d56a0cc4edd3809510c Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Wed, 16 Feb 2011 23:28:53 +0100 Subject: [PATCH 0827/2822] mmc: msm_sdcc: remove needless cache flush after dma_unmap_sg() dma_unmap_sg() already flushes the cache, I don't get what this code is doing here. Signed-off-by: Linus Walleij Signed-off-by: Chris Ball --- drivers/mmc/host/msm_sdcc.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/drivers/mmc/host/msm_sdcc.c b/drivers/mmc/host/msm_sdcc.c index 153ab977a0136..67b08819556de 100644 --- a/drivers/mmc/host/msm_sdcc.c +++ b/drivers/mmc/host/msm_sdcc.c @@ -266,14 +266,6 @@ msmsdcc_dma_complete_tlet(unsigned long data) dma_unmap_sg(mmc_dev(host->mmc), host->dma.sg, host->dma.num_ents, host->dma.dir); - if (host->curr.user_pages) { - struct scatterlist *sg = host->dma.sg; - int i; - - for (i = 0; i < host->dma.num_ents; i++) - flush_dcache_page(sg_page(sg++)); - } - host->dma.sg = NULL; host->dma.busy = 0; -- GitLab From 0c6d49ce53bc18c0ac637fb137f1e01ee9082201 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Sat, 26 Feb 2011 14:44:39 +0100 Subject: [PATCH 0828/2822] mmc: sdhci-esdhc-imx: add write protect on custom GPIO on mx25/35 Signed-off-by: Wolfram Sang Tested-by: Marc Reilly Tested-by: Eric Benard Signed-off-by: Chris Ball --- arch/arm/plat-mxc/include/mach/esdhc.h | 10 ++++- drivers/mmc/host/sdhci-esdhc-imx.c | 52 ++++++++++++++++++++------ 2 files changed, 50 insertions(+), 12 deletions(-) diff --git a/arch/arm/plat-mxc/include/mach/esdhc.h b/arch/arm/plat-mxc/include/mach/esdhc.h index a48a9aaa56b1d..47da109ce09b0 100644 --- a/arch/arm/plat-mxc/include/mach/esdhc.h +++ b/arch/arm/plat-mxc/include/mach/esdhc.h @@ -10,7 +10,15 @@ #ifndef __ASM_ARCH_IMX_ESDHC_H #define __ASM_ARCH_IMX_ESDHC_H +/** + * struct esdhc_platform_data - optional platform data for esdhc on i.MX + * + * strongly recommended for i.MX25/35, not needed for other variants + * + * @wp_gpio: gpio for write_protect (-EINVAL if unused) + */ + struct esdhc_platform_data { - unsigned int wp_gpio; /* write protect pin */ + unsigned int wp_gpio; }; #endif /* __ASM_ARCH_IMX_ESDHC_H */ diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c index 9b82910b9dbb3..65df00bb00dd0 100644 --- a/drivers/mmc/host/sdhci-esdhc-imx.c +++ b/drivers/mmc/host/sdhci-esdhc-imx.c @@ -15,9 +15,11 @@ #include #include #include +#include #include #include #include +#include #include "sdhci.h" #include "sdhci-pltfm.h" #include "sdhci-esdhc.h" @@ -100,10 +102,31 @@ static unsigned int esdhc_pltfm_get_min_clock(struct sdhci_host *host) return clk_get_rate(pltfm_host->clk) / 256 / 16; } +static unsigned int esdhc_pltfm_get_ro(struct sdhci_host *host) +{ + struct esdhc_platform_data *boarddata = host->mmc->parent->platform_data; + + if (boarddata && gpio_is_valid(boarddata->wp_gpio)) + return gpio_get_value(boarddata->wp_gpio); + else + return -ENOSYS; +} + +static struct sdhci_ops sdhci_esdhc_ops = { + .read_w = esdhc_readw_le, + .write_w = esdhc_writew_le, + .write_b = esdhc_writeb_le, + .set_clock = esdhc_set_clock, + .get_max_clock = esdhc_pltfm_get_max_clock, + .get_min_clock = esdhc_pltfm_get_min_clock, +}; + static int esdhc_pltfm_init(struct sdhci_host *host, struct sdhci_pltfm_data *pdata) { struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); + struct esdhc_platform_data *boarddata = host->mmc->parent->platform_data; struct clk *clk; + int err; clk = clk_get(mmc_dev(host->mmc), NULL); if (IS_ERR(clk)) { @@ -116,9 +139,21 @@ static int esdhc_pltfm_init(struct sdhci_host *host, struct sdhci_pltfm_data *pd if (cpu_is_mx35() || cpu_is_mx51()) host->quirks |= SDHCI_QUIRK_BROKEN_TIMEOUT_VAL; - /* Fix errata ENGcm07207 which is present on i.MX25 and i.MX35 */ - if (cpu_is_mx25() || cpu_is_mx35()) + if (cpu_is_mx25() || cpu_is_mx35()) { + /* Fix errata ENGcm07207 present on i.MX25 and i.MX35 */ host->quirks |= SDHCI_QUIRK_NO_MULTIBLOCK; + /* write_protect can't be routed to controller, use gpio */ + sdhci_esdhc_ops.get_ro = esdhc_pltfm_get_ro; + } + + if (boarddata) { + err = gpio_request_one(boarddata->wp_gpio, GPIOF_IN, "ESDHC_WP"); + if (err) { + dev_warn(mmc_dev(host->mmc), + "no write-protect pin available!\n"); + boarddata->wp_gpio = err; + } + } return 0; } @@ -126,20 +161,15 @@ static int esdhc_pltfm_init(struct sdhci_host *host, struct sdhci_pltfm_data *pd static void esdhc_pltfm_exit(struct sdhci_host *host) { struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); + struct esdhc_platform_data *boarddata = host->mmc->parent->platform_data; + + if (boarddata && gpio_is_valid(boarddata->wp_gpio)) + gpio_free(boarddata->wp_gpio); clk_disable(pltfm_host->clk); clk_put(pltfm_host->clk); } -static struct sdhci_ops sdhci_esdhc_ops = { - .read_w = esdhc_readw_le, - .write_w = esdhc_writew_le, - .write_b = esdhc_writeb_le, - .set_clock = esdhc_set_clock, - .get_max_clock = esdhc_pltfm_get_max_clock, - .get_min_clock = esdhc_pltfm_get_min_clock, -}; - struct sdhci_pltfm_data sdhci_esdhc_imx_pdata = { .quirks = ESDHC_DEFAULT_QUIRKS | SDHCI_QUIRK_BROKEN_ADMA, /* ADMA has issues. Might be fixable */ -- GitLab From 3bb2a9f6a7c0887a7f79b59c5b9bff349a03247e Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Sat, 26 Feb 2011 14:44:40 +0100 Subject: [PATCH 0829/2822] mmc: sdhci-esdhc: broken card detection is not a default quirk It can be worked around using a GPIO which will be done for i.MX later. Signed-off-by: Wolfram Sang Acked-by: Anton Vorontsov Tested-by: Marc Reilly Tested-by: Eric Benard Signed-off-by: Chris Ball --- drivers/mmc/host/sdhci-esdhc-imx.c | 3 ++- drivers/mmc/host/sdhci-esdhc.h | 1 - drivers/mmc/host/sdhci-of-esdhc.c | 3 ++- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c index 65df00bb00dd0..49c9801ef1226 100644 --- a/drivers/mmc/host/sdhci-esdhc-imx.c +++ b/drivers/mmc/host/sdhci-esdhc-imx.c @@ -171,7 +171,8 @@ static void esdhc_pltfm_exit(struct sdhci_host *host) } struct sdhci_pltfm_data sdhci_esdhc_imx_pdata = { - .quirks = ESDHC_DEFAULT_QUIRKS | SDHCI_QUIRK_BROKEN_ADMA, + .quirks = ESDHC_DEFAULT_QUIRKS | SDHCI_QUIRK_BROKEN_ADMA + | SDHCI_QUIRK_BROKEN_CARD_DETECTION, /* ADMA has issues. Might be fixable */ .ops = &sdhci_esdhc_ops, .init = esdhc_pltfm_init, diff --git a/drivers/mmc/host/sdhci-esdhc.h b/drivers/mmc/host/sdhci-esdhc.h index afaf1bc4913a3..c55aae828aac1 100644 --- a/drivers/mmc/host/sdhci-esdhc.h +++ b/drivers/mmc/host/sdhci-esdhc.h @@ -19,7 +19,6 @@ */ #define ESDHC_DEFAULT_QUIRKS (SDHCI_QUIRK_FORCE_BLK_SZ_2048 | \ - SDHCI_QUIRK_BROKEN_CARD_DETECTION | \ SDHCI_QUIRK_NO_BUSY_IRQ | \ SDHCI_QUIRK_NONSTANDARD_CLOCK | \ SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK | \ diff --git a/drivers/mmc/host/sdhci-of-esdhc.c b/drivers/mmc/host/sdhci-of-esdhc.c index fcd0e1fcba446..08161f690ae87 100644 --- a/drivers/mmc/host/sdhci-of-esdhc.c +++ b/drivers/mmc/host/sdhci-of-esdhc.c @@ -73,7 +73,8 @@ static unsigned int esdhc_of_get_min_clock(struct sdhci_host *host) } struct sdhci_of_data sdhci_esdhc = { - .quirks = ESDHC_DEFAULT_QUIRKS, + /* card detection could be handled via GPIO */ + .quirks = ESDHC_DEFAULT_QUIRKS | SDHCI_QUIRK_BROKEN_CARD_DETECTION, .ops = { .read_l = sdhci_be32bs_readl, .read_w = esdhc_readw, -- GitLab From 7e29c3060369c2cd003b8069972b8535944310e4 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Sat, 26 Feb 2011 14:44:41 +0100 Subject: [PATCH 0830/2822] mmc: sdhci-esdhc-imx: add card detect on custom GPIO for mx25/35 Signed-off-by: Wolfram Sang Tested-by: Marc Reilly Tested-by: Eric Benard Signed-off-by: Chris Ball --- arch/arm/plat-mxc/include/mach/esdhc.h | 2 + drivers/mmc/host/sdhci-esdhc-imx.c | 79 ++++++++++++++++++++++++++ 2 files changed, 81 insertions(+) diff --git a/arch/arm/plat-mxc/include/mach/esdhc.h b/arch/arm/plat-mxc/include/mach/esdhc.h index 47da109ce09b0..86003f411755f 100644 --- a/arch/arm/plat-mxc/include/mach/esdhc.h +++ b/arch/arm/plat-mxc/include/mach/esdhc.h @@ -16,9 +16,11 @@ * strongly recommended for i.MX25/35, not needed for other variants * * @wp_gpio: gpio for write_protect (-EINVAL if unused) + * @cd_gpio: gpio for card_detect interrupt (-EINVAL if unused) */ struct esdhc_platform_data { unsigned int wp_gpio; + unsigned int cd_gpio; }; #endif /* __ASM_ARCH_IMX_ESDHC_H */ diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c index 49c9801ef1226..3b5248567973d 100644 --- a/drivers/mmc/host/sdhci-esdhc-imx.c +++ b/drivers/mmc/host/sdhci-esdhc-imx.c @@ -32,6 +32,39 @@ static inline void esdhc_clrset_le(struct sdhci_host *host, u32 mask, u32 val, i writel(((readl(base) & ~(mask << shift)) | (val << shift)), base); } +static u32 esdhc_readl_le(struct sdhci_host *host, int reg) +{ + /* fake CARD_PRESENT flag on mx25/35 */ + u32 val = readl(host->ioaddr + reg); + + if (unlikely(reg == SDHCI_PRESENT_STATE)) { + struct esdhc_platform_data *boarddata = + host->mmc->parent->platform_data; + + if (boarddata && gpio_is_valid(boarddata->cd_gpio) + && gpio_get_value(boarddata->cd_gpio)) + /* no card, if a valid gpio says so... */ + val &= SDHCI_CARD_PRESENT; + else + /* ... in all other cases assume card is present */ + val |= SDHCI_CARD_PRESENT; + } + + return val; +} + +static void esdhc_writel_le(struct sdhci_host *host, u32 val, int reg) +{ + if (unlikely(reg == SDHCI_INT_ENABLE || reg == SDHCI_SIGNAL_ENABLE)) + /* + * these interrupts won't work with a custom card_detect gpio + * (only applied to mx25/35) + */ + val &= ~(SDHCI_INT_CARD_REMOVE | SDHCI_INT_CARD_INSERT); + + writel(val, host->ioaddr + reg); +} + static u16 esdhc_readw_le(struct sdhci_host *host, int reg) { if (unlikely(reg == SDHCI_HOST_VERSION)) @@ -121,6 +154,14 @@ static struct sdhci_ops sdhci_esdhc_ops = { .get_min_clock = esdhc_pltfm_get_min_clock, }; +static irqreturn_t cd_irq(int irq, void *data) +{ + struct sdhci_host *sdhost = (struct sdhci_host *)data; + + tasklet_schedule(&sdhost->card_tasklet); + return IRQ_HANDLED; +}; + static int esdhc_pltfm_init(struct sdhci_host *host, struct sdhci_pltfm_data *pdata) { struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); @@ -153,9 +194,40 @@ static int esdhc_pltfm_init(struct sdhci_host *host, struct sdhci_pltfm_data *pd "no write-protect pin available!\n"); boarddata->wp_gpio = err; } + + err = gpio_request_one(boarddata->cd_gpio, GPIOF_IN, "ESDHC_CD"); + if (err) { + dev_warn(mmc_dev(host->mmc), + "no card-detect pin available!\n"); + goto no_card_detect_pin; + } + + /* i.MX5x has issues to be researched */ + if (!cpu_is_mx25() && !cpu_is_mx35()) + goto not_supported; + + err = request_irq(gpio_to_irq(boarddata->cd_gpio), cd_irq, + IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING, + mmc_hostname(host->mmc), host); + if (err) { + dev_warn(mmc_dev(host->mmc), "request irq error\n"); + goto no_card_detect_irq; + } + + sdhci_esdhc_ops.write_l = esdhc_writel_le; + sdhci_esdhc_ops.read_l = esdhc_readl_le; + /* Now we have a working card_detect again */ + host->quirks &= ~SDHCI_QUIRK_BROKEN_CARD_DETECTION; } return 0; + + no_card_detect_irq: + gpio_free(boarddata->cd_gpio); + no_card_detect_pin: + boarddata->cd_gpio = err; + not_supported: + return 0; } static void esdhc_pltfm_exit(struct sdhci_host *host) @@ -166,6 +238,13 @@ static void esdhc_pltfm_exit(struct sdhci_host *host) if (boarddata && gpio_is_valid(boarddata->wp_gpio)) gpio_free(boarddata->wp_gpio); + if (boarddata && gpio_is_valid(boarddata->cd_gpio)) { + gpio_free(boarddata->cd_gpio); + + if (!(host->quirks & SDHCI_QUIRK_BROKEN_CARD_DETECTION)) + free_irq(gpio_to_irq(boarddata->cd_gpio), host); + } + clk_disable(pltfm_host->clk); clk_put(pltfm_host->clk); } -- GitLab From ba6a902d9d89b976bf64a435ec97a490cd160dec Mon Sep 17 00:00:00 2001 From: Chris Ball Date: Mon, 28 Feb 2011 16:45:10 -0500 Subject: [PATCH 0831/2822] mmc: dw_mmc: Remove set-but-unused variable. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit count is only ever used by assigning to old_len if count == 0, and then old_len isn't ever used at all. So, both are redundant. Fixes: drivers/mmc/host/dw_mmc.c: In function ‘dw_mci_read_data_pio’: drivers/mmc/host/dw_mmc.c:1034:32: warning: variable ‘old_len’ set but not used [-Wunused-but-set-variable] Signed-off-by: Chris Ball Acked-by: Will Newton --- drivers/mmc/host/dw_mmc.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c index 58476c1bb0562..299c1d61b6b3e 100644 --- a/drivers/mmc/host/dw_mmc.c +++ b/drivers/mmc/host/dw_mmc.c @@ -1031,13 +1031,10 @@ static void dw_mci_read_data_pio(struct dw_mci *host) struct mmc_data *data = host->data; int shift = host->data_shift; u32 status; - unsigned int nbytes = 0, len, old_len, count = 0; + unsigned int nbytes = 0, len; do { len = SDMMC_GET_FCNT(mci_readl(host, STATUS)) << shift; - if (count == 0) - old_len = len; - if (offset + len <= sg->length) { host->pull_data(host, (void *)(buf + offset), len); @@ -1082,7 +1079,6 @@ static void dw_mci_read_data_pio(struct dw_mci *host) tasklet_schedule(&host->tasklet); return; } - count++; } while (status & SDMMC_INT_RXDR); /*if the RXDR is ready read again*/ len = SDMMC_GET_FCNT(mci_readl(host, STATUS)); host->pio_offset = offset; -- GitLab From 0aab3995485b8a994bf29a995a008c9ea4a28054 Mon Sep 17 00:00:00 2001 From: Stefan Nilsson XK Date: Tue, 1 Mar 2011 14:41:04 +0100 Subject: [PATCH 0832/2822] mmc: sdio: remember new card RCA when redetecting card During redetection of a SDIO card, a request for a new card RCA was submitted to the card, but was then overwritten by the old RCA. This caused the card to be deselected instead of selected when using the incorrect RCA. This bug's been present since the "oldcard" handling was introduced in 2.6.32. Signed-off-by: Stefan Nilsson XK Reviewed-by: Ulf Hansson Reviewed-by: Pawel Wieczorkiewicz Signed-off-by: Linus Walleij Cc: Signed-off-by: Chris Ball --- drivers/mmc/core/sdio.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/mmc/core/sdio.c b/drivers/mmc/core/sdio.c index c9fbb777440df..db0f0b44d6846 100644 --- a/drivers/mmc/core/sdio.c +++ b/drivers/mmc/core/sdio.c @@ -395,6 +395,14 @@ static int mmc_sdio_init_card(struct mmc_host *host, u32 ocr, if (err) goto remove; + /* + * Update oldcard with the new RCA received from the SDIO + * device -- we're doing this so that it's updated in the + * "card" struct when oldcard overwrites that later. + */ + if (oldcard) + oldcard->rca = card->rca; + mmc_set_bus_mode(host, MMC_BUSMODE_PUSHPULL); } -- GitLab From ab1efd271704416c9e6e9cb4e5f58e7e4c4260e6 Mon Sep 17 00:00:00 2001 From: Ulf Hansson Date: Wed, 9 Mar 2011 09:11:02 +0100 Subject: [PATCH 0833/2822] mmc: core: export function mmc_do_release_host() When using mmc_try_claim_host the corresponding release function is mmc_do_release_host, which then also must be exported. Reviewed-by: Jonas Aberg Reviewed-by: Sebastian Rasmussen Signed-off-by: Ulf Hansson Signed-off-by: Linus Walleij Signed-off-by: Chris Ball --- drivers/mmc/core/core.c | 10 +++++++++- include/linux/mmc/core.h | 1 + 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index c47e13b79eeec..4956da133be46 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c @@ -527,7 +527,14 @@ int mmc_try_claim_host(struct mmc_host *host) } EXPORT_SYMBOL(mmc_try_claim_host); -static void mmc_do_release_host(struct mmc_host *host) +/** + * mmc_do_release_host - release a claimed host + * @host: mmc host to release + * + * If you successfully claimed a host, this function will + * release it again. + */ +void mmc_do_release_host(struct mmc_host *host) { unsigned long flags; @@ -542,6 +549,7 @@ static void mmc_do_release_host(struct mmc_host *host) wake_up(&host->wq); } } +EXPORT_SYMBOL(mmc_do_release_host); void mmc_host_deeper_disable(struct work_struct *work) { diff --git a/include/linux/mmc/core.h b/include/linux/mmc/core.h index 64e013f1cfb82..07f27af4dba52 100644 --- a/include/linux/mmc/core.h +++ b/include/linux/mmc/core.h @@ -160,6 +160,7 @@ extern unsigned int mmc_align_data_size(struct mmc_card *, unsigned int); extern int __mmc_claim_host(struct mmc_host *host, atomic_t *abort); extern void mmc_release_host(struct mmc_host *host); +extern void mmc_do_release_host(struct mmc_host *host); extern int mmc_try_claim_host(struct mmc_host *host); /** -- GitLab From b33d46c398fd071dccd0815f33620924684860cd Mon Sep 17 00:00:00 2001 From: Ulf Hansson Date: Sat, 5 Mar 2011 14:36:24 +0100 Subject: [PATCH 0834/2822] mmc: core: reset card voltage after power off At power off, reset OCR mask to be the highest possible voltage supported for the current mmc host. This solves the re-initialization during the power up sequence. The voltage may have been decreased due to the card accepts a lower voltage than the voltage used during the initialization sequence. We need to reset the voltage to by the host highest possible value since according to specification the initialization must always be done at high voltage. Reviewed-by: Jonas Aberg Signed-off-by: Ulf Hansson Signed-off-by: Linus Walleij Signed-off-by: Chris Ball --- drivers/mmc/core/core.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index 4956da133be46..1f453acc8682b 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c @@ -1009,6 +1009,13 @@ static void mmc_power_off(struct mmc_host *host) { host->ios.clock = 0; host->ios.vdd = 0; + + /* + * Reset ocr mask to be the highest possible voltage supported for + * this mmc host. This value will be used at next power up. + */ + host->ocr = 1 << (fls(host->ocr_avail) - 1); + if (!mmc_host_is_spi(host)) { host->ios.bus_mode = MMC_BUSMODE_OPENDRAIN; host->ios.chip_select = MMC_CS_DONTCARE; -- GitLab From 860cfe796c793bfad1e666de9600852f2d653c57 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Fri, 11 Mar 2011 08:30:14 +0100 Subject: [PATCH 0835/2822] mmc: tmio: fix address in kunmap_atomic() calls Currently kunmap_atomic() doesn't take into account the offset, used with kmap_atomic(). On platforms, where kunmap_atomic() is not a NOP, this will lead to problems, when offset != 0. Signed-off-by: Guennadi Liakhovetski Signed-off-by: Chris Ball --- drivers/mmc/host/tmio_mmc.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/mmc/host/tmio_mmc.c b/drivers/mmc/host/tmio_mmc.c index 0e4998fa6fc5f..ac52eb65395ef 100644 --- a/drivers/mmc/host/tmio_mmc.c +++ b/drivers/mmc/host/tmio_mmc.c @@ -219,9 +219,9 @@ static char *tmio_mmc_kmap_atomic(struct scatterlist *sg, unsigned long *flags) return kmap_atomic(sg_page(sg), KM_BIO_SRC_IRQ) + sg->offset; } -static void tmio_mmc_kunmap_atomic(void *virt, unsigned long *flags) +static void tmio_mmc_kunmap_atomic(struct scatterlist *sg, unsigned long *flags, void *virt) { - kunmap_atomic(virt, KM_BIO_SRC_IRQ); + kunmap_atomic(virt - sg->offset, KM_BIO_SRC_IRQ); local_irq_restore(*flags); } @@ -510,7 +510,7 @@ static void tmio_mmc_pio_irq(struct tmio_mmc_host *host) host->sg_off += count; - tmio_mmc_kunmap_atomic(sg_virt, &flags); + tmio_mmc_kunmap_atomic(host->sg_ptr, &flags, sg_virt); if (host->sg_off == host->sg_ptr->length) tmio_mmc_next_sg(host); @@ -770,7 +770,7 @@ static void tmio_check_bounce_buffer(struct tmio_mmc_host *host) unsigned long flags; void *sg_vaddr = tmio_mmc_kmap_atomic(host->sg_orig, &flags); memcpy(sg_vaddr, host->bounce_buf, host->bounce_sg.length); - tmio_mmc_kunmap_atomic(sg_vaddr, &flags); + tmio_mmc_kunmap_atomic(host->sg_orig, &flags, sg_vaddr); } } @@ -897,7 +897,7 @@ static void tmio_mmc_start_dma_tx(struct tmio_mmc_host *host) void *sg_vaddr = tmio_mmc_kmap_atomic(sg, &flags); sg_init_one(&host->bounce_sg, host->bounce_buf, sg->length); memcpy(host->bounce_buf, sg_vaddr, host->bounce_sg.length); - tmio_mmc_kunmap_atomic(sg_vaddr, &flags); + tmio_mmc_kunmap_atomic(sg, &flags, sg_vaddr); host->sg_ptr = &host->bounce_sg; sg = host->sg_ptr; } -- GitLab From fc3d7720541d4b70cbae25ac121d7e6343125090 Mon Sep 17 00:00:00 2001 From: Jaehoon Chung Date: Fri, 25 Feb 2011 11:08:15 +0900 Subject: [PATCH 0836/2822] mmc: dw_mmc: add quirks for unreliable card detect, and capabilities This patch adds quirks and capabilities to platdata. Some cards don't use the CDn pin; in that case, we assume the card's inserted. Some boards need other capabilities. So, we add capabilities in the board's platdata. Signed-off-by: Jaehoon Chung Signed-off-by: Kyungmin Park Acked-by: Will Newton Signed-off-by: Chris Ball --- drivers/mmc/host/dw_mmc.c | 10 ++++++++-- include/linux/mmc/dw_mmc.h | 10 +++++++--- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c index 299c1d61b6b3e..94ec6502bdde1 100644 --- a/drivers/mmc/host/dw_mmc.c +++ b/drivers/mmc/host/dw_mmc.c @@ -729,7 +729,9 @@ static int dw_mci_get_cd(struct mmc_host *mmc) struct dw_mci_board *brd = slot->host->pdata; /* Use platform get_cd function, else try onboard card detect */ - if (brd->get_cd) + if (brd->quirks & DW_MCI_QUIRK_BROKEN_CARD_DETECTION) + present = 1; + else if (brd->get_cd) present = !brd->get_cd(slot->id); else present = (mci_readl(slot->host, CDETECT) & (1 << slot->id)) @@ -1403,7 +1405,11 @@ static int __init dw_mci_init_slot(struct dw_mci *host, unsigned int id) if (host->pdata->setpower) host->pdata->setpower(id, 0); - mmc->caps = 0; + if (host->pdata->caps) + mmc->caps = host->pdata->caps; + else + mmc->caps = 0; + if (host->pdata->get_bus_wd) if (host->pdata->get_bus_wd(slot->id) >= 4) mmc->caps |= MMC_CAP_4_BIT_DATA; diff --git a/include/linux/mmc/dw_mmc.h b/include/linux/mmc/dw_mmc.h index 3f22c201ee3a0..f081631988774 100644 --- a/include/linux/mmc/dw_mmc.h +++ b/include/linux/mmc/dw_mmc.h @@ -166,11 +166,13 @@ struct dw_mci_dma_ops { /* IP Quirks/flags. */ /* DTO fix for command transmission with IDMAC configured */ -#define DW_MCI_QUIRK_IDMAC_DTO BIT(0) +#define DW_MCI_QUIRK_IDMAC_DTO BIT(0) /* delay needed between retries on some 2.11a implementations */ -#define DW_MCI_QUIRK_RETRY_DELAY BIT(1) +#define DW_MCI_QUIRK_RETRY_DELAY BIT(1) /* High Speed Capable - Supports HS cards (upto 50MHz) */ -#define DW_MCI_QUIRK_HIGHSPEED BIT(2) +#define DW_MCI_QUIRK_HIGHSPEED BIT(2) +/* Unreliable card detection */ +#define DW_MCI_QUIRK_BROKEN_CARD_DETECTION BIT(3) struct dma_pdata; @@ -190,6 +192,8 @@ struct dw_mci_board { u32 quirks; /* Workaround / Quirk flags */ unsigned int bus_hz; /* Bus speed */ + unsigned int caps; /* Capabilities */ + /* delay in mS before detecting cards after interrupt */ u32 detect_delay_ms; -- GitLab From e61cf1184d72e574460492fd6c6b6d8a3ace2089 Mon Sep 17 00:00:00 2001 From: Jaehoon Chung Date: Thu, 17 Mar 2011 20:32:33 +0900 Subject: [PATCH 0837/2822] mmc: dw_mmc: fix suspend/resume operation This patch is related to re-init processing on suspend/resume. When card is resuming, some register is reset. If card is removable, maybe controller should be rescan for card. But if assume card is non-removable, need to restore the old value at registers. We store the value of FIFOTH at probe time and then restore it in dw_mci_resume(). Signed-off-by: Jaehoon Chung Signed-off-by: Kyungmin Park Acked-by: Will Newton Signed-off-by: Chris Ball --- drivers/mmc/host/dw_mmc.c | 22 ++++++++++++++++++++-- include/linux/mmc/dw_mmc.h | 1 + 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c index 94ec6502bdde1..51ee2f5909d45 100644 --- a/drivers/mmc/host/dw_mmc.c +++ b/drivers/mmc/host/dw_mmc.c @@ -1639,8 +1639,9 @@ static int dw_mci_probe(struct platform_device *pdev) */ fifo_size = mci_readl(host, FIFOTH); fifo_size = (fifo_size >> 16) & 0x7ff; - mci_writel(host, FIFOTH, ((0x2 << 28) | ((fifo_size/2 - 1) << 16) | - ((fifo_size/2) << 0))); + host->fifoth_val = ((0x2 << 28) | ((fifo_size/2 - 1) << 16) | + ((fifo_size/2) << 0)); + mci_writel(host, FIFOTH, host->fifoth_val); /* disable clock to CIU */ mci_writel(host, CLKENA, 0); @@ -1772,6 +1773,23 @@ static int dw_mci_resume(struct platform_device *pdev) int i, ret; struct dw_mci *host = platform_get_drvdata(pdev); + if (host->dma_ops->init) + host->dma_ops->init(host); + + if (!mci_wait_reset(&pdev->dev, host)) { + ret = -ENODEV; + return ret; + } + + /* Restore the old value at FIFOTH register */ + mci_writel(host, FIFOTH, host->fifoth_val); + + mci_writel(host, RINTSTS, 0xFFFFFFFF); + mci_writel(host, INTMASK, SDMMC_INT_CMD_DONE | SDMMC_INT_DATA_OVER | + SDMMC_INT_TXDR | SDMMC_INT_RXDR | + DW_MCI_ERROR_FLAGS | SDMMC_INT_CD); + mci_writel(host, CTRL, SDMMC_CTRL_INT_ENABLE); + for (i = 0; i < host->num_slots; i++) { struct dw_mci_slot *slot = host->slot[i]; if (!slot) diff --git a/include/linux/mmc/dw_mmc.h b/include/linux/mmc/dw_mmc.h index f081631988774..6c324de20de2c 100644 --- a/include/linux/mmc/dw_mmc.h +++ b/include/linux/mmc/dw_mmc.h @@ -140,6 +140,7 @@ struct dw_mci { u32 bus_hz; u32 current_speed; u32 num_slots; + u32 fifoth_val; struct platform_device *pdev; struct dw_mci_board *pdata; struct dw_mci_slot *slot[MAX_MCI_SLOTS]; -- GitLab From c07946a3350244d7c3d9bc1032325e04dd11575b Mon Sep 17 00:00:00 2001 From: Jaehoon Chung Date: Fri, 25 Feb 2011 11:08:14 +0900 Subject: [PATCH 0838/2822] mmc: dw_mmc: support mmc power control with regulator This patch adds support for power regulators. Signed-off-by: Jaehoon Chung Signed-off-by: kyungmin Park Acked-by: Will Newton Signed-off-by: Chris Ball --- drivers/mmc/host/dw_mmc.c | 25 +++++++++++++++++++++++++ include/linux/mmc/dw_mmc.h | 2 ++ 2 files changed, 27 insertions(+) diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c index 51ee2f5909d45..5a614069cb00b 100644 --- a/drivers/mmc/host/dw_mmc.c +++ b/drivers/mmc/host/dw_mmc.c @@ -32,6 +32,7 @@ #include #include #include +#include #include "dw_mmc.h" @@ -1440,6 +1441,13 @@ static int __init dw_mci_init_slot(struct dw_mci *host, unsigned int id) } #endif /* CONFIG_MMC_DW_IDMAC */ + host->vmmc = regulator_get(mmc_dev(mmc), "vmmc"); + if (IS_ERR(host->vmmc)) { + printk(KERN_INFO "%s: no vmmc regulator found\n", mmc_hostname(mmc)); + host->vmmc = NULL; + } else + regulator_enable(host->vmmc); + if (dw_mci_get_cd(mmc)) set_bit(DW_MMC_CARD_PRESENT, &slot->flags); else @@ -1704,6 +1712,12 @@ err_dmaunmap: host->sg_cpu, host->sg_dma); iounmap(host->regs); + if (host->vmmc) { + regulator_disable(host->vmmc); + regulator_put(host->vmmc); + } + + err_freehost: kfree(host); return ret; @@ -1735,6 +1749,11 @@ static int __exit dw_mci_remove(struct platform_device *pdev) if (host->use_dma && host->dma_ops->exit) host->dma_ops->exit(host); + if (host->vmmc) { + regulator_disable(host->vmmc); + regulator_put(host->vmmc); + } + iounmap(host->regs); kfree(host); @@ -1750,6 +1769,9 @@ static int dw_mci_suspend(struct platform_device *pdev, pm_message_t mesg) int i, ret; struct dw_mci *host = platform_get_drvdata(pdev); + if (host->vmmc) + regulator_enable(host->vmmc); + for (i = 0; i < host->num_slots; i++) { struct dw_mci_slot *slot = host->slot[i]; if (!slot) @@ -1765,6 +1787,9 @@ static int dw_mci_suspend(struct platform_device *pdev, pm_message_t mesg) } } + if (host->vmmc) + regulator_disable(host->vmmc); + return 0; } diff --git a/include/linux/mmc/dw_mmc.h b/include/linux/mmc/dw_mmc.h index 6c324de20de2c..c0207a770476f 100644 --- a/include/linux/mmc/dw_mmc.h +++ b/include/linux/mmc/dw_mmc.h @@ -152,6 +152,8 @@ struct dw_mci { /* Workaround flags */ u32 quirks; + + struct regulator *vmmc; /* Power regulator */ }; /* DMA ops for Internal/External DMAC interface */ -- GitLab From 1bdd6384c2b43cac9be8d6f2c298bcf39f50cd07 Mon Sep 17 00:00:00 2001 From: Sean Hefty Date: Thu, 17 Mar 2011 23:35:39 +0000 Subject: [PATCH 0839/2822] RDMA/addr: Fix return of uninitialized ret value Commit b23dd4fe42b4 ("ipv4: Make output route lookup return rtable directly") resulted in leaving ret uninitialized, where it may later be returned. Signed-off-by: Sean Hefty Signed-off-by: Roland Dreier --- drivers/infiniband/core/addr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/infiniband/core/addr.c b/drivers/infiniband/core/addr.c index e0ef5fdc361e6..4ffc224faa7fa 100644 --- a/drivers/infiniband/core/addr.c +++ b/drivers/infiniband/core/addr.c @@ -204,7 +204,7 @@ static int addr4_resolve(struct sockaddr_in *src_in, /* If the device does ARP internally, return 'done' */ if (rt->dst.dev->flags & IFF_NOARP) { - rdma_copy_addr(addr, rt->dst.dev, NULL); + ret = rdma_copy_addr(addr, rt->dst.dev, NULL); goto put; } -- GitLab From 0acf659f1469725fb6e39d53af970f36c5f69a41 Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Mon, 14 Mar 2011 07:28:57 -0500 Subject: [PATCH 0840/2822] OMAP: DSS2: Clean up for dpll4_m4_ck handling OMAP2 does not have dpll4_m4_ck source clock for dss functional clock, but later OMAPs do. Currently we check for cpu type in multiple places to find out if dpll4_m4_ck is available. This patch cleans up dss.c by using the fact that dss.dpll4_m4_ck pointer is NULL on OMAP2. This allows us to remove many of the cpu checks. Signed-off-by: Tomi Valkeinen --- drivers/video/omap2/dss/dss.c | 93 ++++++++++++++++++++++------------- 1 file changed, 59 insertions(+), 34 deletions(-) diff --git a/drivers/video/omap2/dss/dss.c b/drivers/video/omap2/dss/dss.c index f1628bd850d1a..9d2390299df70 100644 --- a/drivers/video/omap2/dss/dss.c +++ b/drivers/video/omap2/dss/dss.c @@ -239,30 +239,40 @@ void dss_dump_clocks(struct seq_file *s) { unsigned long dpll4_ck_rate; unsigned long dpll4_m4_ck_rate; + const char *fclk_name, *fclk_real_name; + unsigned long fclk_rate; dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK); - dpll4_ck_rate = clk_get_rate(clk_get_parent(dss.dpll4_m4_ck)); - dpll4_m4_ck_rate = clk_get_rate(dss.dpll4_m4_ck); - seq_printf(s, "- DSS -\n"); - seq_printf(s, "dpll4_ck %lu\n", dpll4_ck_rate); + fclk_name = dss_get_generic_clk_source_name(DSS_CLK_SRC_FCK); + fclk_real_name = dss_feat_get_clk_source_name(DSS_CLK_SRC_FCK); + fclk_rate = dss_clk_get_rate(DSS_CLK_FCK); - if (cpu_is_omap3630()) - seq_printf(s, "%s (%s) = %lu / %lu = %lu\n", - dss_get_generic_clk_source_name(DSS_CLK_SRC_FCK), - dss_feat_get_clk_source_name(DSS_CLK_SRC_FCK), - dpll4_ck_rate, - dpll4_ck_rate / dpll4_m4_ck_rate, - dss_clk_get_rate(DSS_CLK_FCK)); - else - seq_printf(s, "%s (%s) = %lu / %lu * 2 = %lu\n", - dss_get_generic_clk_source_name(DSS_CLK_SRC_FCK), - dss_feat_get_clk_source_name(DSS_CLK_SRC_FCK), - dpll4_ck_rate, - dpll4_ck_rate / dpll4_m4_ck_rate, - dss_clk_get_rate(DSS_CLK_FCK)); + if (dss.dpll4_m4_ck) { + dpll4_ck_rate = clk_get_rate(clk_get_parent(dss.dpll4_m4_ck)); + dpll4_m4_ck_rate = clk_get_rate(dss.dpll4_m4_ck); + + seq_printf(s, "dpll4_ck %lu\n", dpll4_ck_rate); + + if (cpu_is_omap3630()) + seq_printf(s, "%s (%s) = %lu / %lu = %lu\n", + fclk_name, fclk_real_name, + dpll4_ck_rate, + dpll4_ck_rate / dpll4_m4_ck_rate, + fclk_rate); + else + seq_printf(s, "%s (%s) = %lu / %lu * 2 = %lu\n", + fclk_name, fclk_real_name, + dpll4_ck_rate, + dpll4_ck_rate / dpll4_m4_ck_rate, + fclk_rate); + } else { + seq_printf(s, "%s (%s) = %lu\n", + fclk_name, fclk_real_name, + fclk_rate); + } dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK); } @@ -382,31 +392,40 @@ enum dss_clk_source dss_get_lcd_clk_source(enum omap_channel channel) /* calculate clock rates using dividers in cinfo */ int dss_calc_clock_rates(struct dss_clock_info *cinfo) { - unsigned long prate; + if (dss.dpll4_m4_ck) { + unsigned long prate; - if (cinfo->fck_div > (cpu_is_omap3630() ? 32 : 16) || - cinfo->fck_div == 0) - return -EINVAL; + if (cinfo->fck_div > (cpu_is_omap3630() ? 32 : 16) || + cinfo->fck_div == 0) + return -EINVAL; - prate = clk_get_rate(clk_get_parent(dss.dpll4_m4_ck)); + prate = clk_get_rate(clk_get_parent(dss.dpll4_m4_ck)); - cinfo->fck = prate / cinfo->fck_div; + cinfo->fck = prate / cinfo->fck_div; + } else { + if (cinfo->fck_div != 0) + return -EINVAL; + cinfo->fck = dss_clk_get_rate(DSS_CLK_FCK); + } return 0; } int dss_set_clock_div(struct dss_clock_info *cinfo) { - unsigned long prate; - int r; + if (dss.dpll4_m4_ck) { + unsigned long prate; + int r; - if (cpu_is_omap34xx()) { prate = clk_get_rate(clk_get_parent(dss.dpll4_m4_ck)); DSSDBG("dpll4_m4 = %ld\n", prate); r = clk_set_rate(dss.dpll4_m4_ck, prate / cinfo->fck_div); if (r) return r; + } else { + if (cinfo->fck_div != 0) + return -EINVAL; } DSSDBG("fck = %ld (%d)\n", cinfo->fck, cinfo->fck_div); @@ -418,9 +437,11 @@ int dss_get_clock_div(struct dss_clock_info *cinfo) { cinfo->fck = dss_clk_get_rate(DSS_CLK_FCK); - if (cpu_is_omap34xx()) { + if (dss.dpll4_m4_ck) { unsigned long prate; + prate = clk_get_rate(clk_get_parent(dss.dpll4_m4_ck)); + if (cpu_is_omap3630()) cinfo->fck_div = prate / (cinfo->fck); else @@ -434,7 +455,7 @@ int dss_get_clock_div(struct dss_clock_info *cinfo) unsigned long dss_get_dpll4_rate(void) { - if (cpu_is_omap34xx()) + if (dss.dpll4_m4_ck) return clk_get_rate(clk_get_parent(dss.dpll4_m4_ck)); else return 0; @@ -615,6 +636,7 @@ static int dss_init(void) int r; u32 rev; struct resource *dss_mem; + struct clk *dpll4_m4_ck; dss_mem = platform_get_resource(dss.pdev, IORESOURCE_MEM, 0); if (!dss_mem) { @@ -655,16 +677,19 @@ static int dss_init(void) REG_FLD_MOD(DSS_CONTROL, 1, 3, 3); /* venc clock 4x enable */ REG_FLD_MOD(DSS_CONTROL, 0, 2, 2); /* venc clock mode = normal */ #endif - if (cpu_is_omap34xx()) { - dss.dpll4_m4_ck = clk_get(NULL, "dpll4_m4_ck"); - if (IS_ERR(dss.dpll4_m4_ck)) { + dpll4_m4_ck = clk_get(NULL, "dpll4_m4_ck"); + if (IS_ERR(dpll4_m4_ck)) { DSSERR("Failed to get dpll4_m4_ck\n"); - r = PTR_ERR(dss.dpll4_m4_ck); + r = PTR_ERR(dpll4_m4_ck); goto fail1; } + } else { /* omap24xx */ + dpll4_m4_ck = NULL; } + dss.dpll4_m4_ck = dpll4_m4_ck; + dss.dsi_clk_source = DSS_CLK_SRC_FCK; dss.dispc_clk_source = DSS_CLK_SRC_FCK; dss.lcd_clk_source[0] = DSS_CLK_SRC_FCK; @@ -686,7 +711,7 @@ fail0: static void dss_exit(void) { - if (cpu_is_omap34xx()) + if (dss.dpll4_m4_ck) clk_put(dss.dpll4_m4_ck); iounmap(dss.base); -- GitLab From 2de110868f455b74e91111801ce63a3c9d06f091 Mon Sep 17 00:00:00 2001 From: "Murthy, Raghuveer" Date: Mon, 14 Mar 2011 07:28:58 -0500 Subject: [PATCH 0841/2822] OMAP: DSS2: Implement OMAP4 DSS fclk support Add dss.dpll4_m4_ck (DSS FCLK) initialization for OMAP4. This is used to compute the pixel clock for DPI interface and also to reconfigure the DSS FCLK to the desired rate, corresponding to the rate computed for pixel clock. Adding these cpu_is_44xx() checks are meant to be temporary, until a cleaner implementation to manage these checks are added. Currently this is needed to get DVI display running on OMAP4 PandaBoard Signed-off-by: Raghuveer Murthy [tomi.valkeinen@ti.com: minor changes due to conflicts] Signed-off-by: Tomi Valkeinen --- drivers/video/omap2/dss/dss.c | 34 ++++++++++++++++++++++------------ 1 file changed, 22 insertions(+), 12 deletions(-) diff --git a/drivers/video/omap2/dss/dss.c b/drivers/video/omap2/dss/dss.c index 9d2390299df70..3f1fee63c6783 100644 --- a/drivers/video/omap2/dss/dss.c +++ b/drivers/video/omap2/dss/dss.c @@ -256,7 +256,7 @@ void dss_dump_clocks(struct seq_file *s) seq_printf(s, "dpll4_ck %lu\n", dpll4_ck_rate); - if (cpu_is_omap3630()) + if (cpu_is_omap3630() || cpu_is_omap44xx()) seq_printf(s, "%s (%s) = %lu / %lu = %lu\n", fclk_name, fclk_real_name, dpll4_ck_rate, @@ -394,9 +394,12 @@ int dss_calc_clock_rates(struct dss_clock_info *cinfo) { if (dss.dpll4_m4_ck) { unsigned long prate; + u16 fck_div_max = 16; - if (cinfo->fck_div > (cpu_is_omap3630() ? 32 : 16) || - cinfo->fck_div == 0) + if (cpu_is_omap3630() || cpu_is_omap44xx()) + fck_div_max = 32; + + if (cinfo->fck_div > fck_div_max || cinfo->fck_div == 0) return -EINVAL; prate = clk_get_rate(clk_get_parent(dss.dpll4_m4_ck)); @@ -442,7 +445,7 @@ int dss_get_clock_div(struct dss_clock_info *cinfo) prate = clk_get_rate(clk_get_parent(dss.dpll4_m4_ck)); - if (cpu_is_omap3630()) + if (cpu_is_omap3630() || cpu_is_omap44xx()) cinfo->fck_div = prate / (cinfo->fck); else cinfo->fck_div = prate / (cinfo->fck / 2); @@ -471,7 +474,7 @@ int dss_calc_clock_div(bool is_tft, unsigned long req_pck, unsigned long fck, max_dss_fck; - u16 fck_div; + u16 fck_div, fck_div_max = 16; int match = 0; int min_fck_per_pck; @@ -504,7 +507,7 @@ retry: memset(&best_dss, 0, sizeof(best_dss)); memset(&best_dispc, 0, sizeof(best_dispc)); - if (cpu_is_omap24xx()) { + if (dss.dpll4_m4_ck == NULL) { struct dispc_clock_info cur_dispc; /* XXX can we change the clock on omap2? */ fck = dss_clk_get_rate(DSS_CLK_FCK); @@ -519,12 +522,14 @@ retry: best_dispc = cur_dispc; goto found; - } else if (cpu_is_omap34xx()) { - for (fck_div = (cpu_is_omap3630() ? 32 : 16); - fck_div > 0; --fck_div) { + } else { + if (cpu_is_omap3630() || cpu_is_omap44xx()) + fck_div_max = 32; + + for (fck_div = fck_div_max; fck_div > 0; --fck_div) { struct dispc_clock_info cur_dispc; - if (cpu_is_omap3630()) + if (fck_div_max == 32) fck = prate / fck_div; else fck = prate / fck_div * 2; @@ -552,8 +557,6 @@ retry: goto found; } } - } else { - BUG(); } found: @@ -684,6 +687,13 @@ static int dss_init(void) r = PTR_ERR(dpll4_m4_ck); goto fail1; } + } else if (cpu_is_omap44xx()) { + dpll4_m4_ck = clk_get(NULL, "dpll_per_m5x2_ck"); + if (IS_ERR(dpll4_m4_ck)) { + DSSERR("Failed to get dpll4_m4_ck\n"); + r = PTR_ERR(dpll4_m4_ck); + goto fail1; + } } else { /* omap24xx */ dpll4_m4_ck = NULL; } -- GitLab From b295d6e593e02168fdafc5db11464b6d51cf239d Mon Sep 17 00:00:00 2001 From: "Murthy, Raghuveer" Date: Mon, 14 Mar 2011 07:52:25 -0500 Subject: [PATCH 0842/2822] OMAP4: PandaBoard: Adding DVI support Adding DVI support to OMAP4 PandaBoard. PandaBoard uses TFP410 DVI Framer chip http://focus.ti.com/lit/ds/symlink/tfp410.pdf The TFP410 gets its power enable and display data over GPIO lines muxed in from OMAP4430. PandaBoard supports other LCD displays through expansion connectors, following board rework. This will disable the DVI interface. However, the existing mux settings remain the same PandaBoard additionally supports display over HDMI interface. It is mutually exclusive to display over DVI. Hence the mux settings need to be configured seperately, as and when HDMI is enabled Also, I2C3 bus used for reading EDID data from DVI Monitors is registered here. Since the design is similar to BeagleBoard, the code for the same is taken from the kernel.org commit e3333f48dd5cb21 (omap: Adding beagle i2c eeprom driver to read EDID) Reviewed-by: Manjunath G Kondaiah Reviewed-by: Anand Gadiyar Reviewed-by: Nishanth Menon Reviewed-by: Sumit Semwal Signed-off-by: Raghuveer Murthy [tomi.valkeinen@ti.com: fixed conflicts with HDMI] Signed-off-by: Tomi Valkeinen --- arch/arm/mach-omap2/board-omap4panda.c | 131 ++++++++++++++++++++++++- 1 file changed, 129 insertions(+), 2 deletions(-) diff --git a/arch/arm/mach-omap2/board-omap4panda.c b/arch/arm/mach-omap2/board-omap4panda.c index 795ffc4615221..e2b912f376cce 100644 --- a/arch/arm/mach-omap2/board-omap4panda.c +++ b/arch/arm/mach-omap2/board-omap4panda.c @@ -40,6 +40,7 @@ #include #include #include +#include #include "timer-gp.h" #include "hsmmc.h" @@ -435,6 +436,17 @@ static struct i2c_board_info __initdata omap4_panda_i2c_boardinfo[] = { .platform_data = &omap4_panda_twldata, }, }; + +/* + * Display monitor features are burnt in their EEPROM as EDID data. The EEPROM + * is connected as I2C slave device, and can be accessed at address 0x50 + */ +static struct i2c_board_info __initdata panda_i2c_eeprom[] = { + { + I2C_BOARD_INFO("eeprom", 0x50), + }, +}; + static int __init omap4_panda_i2c_init(void) { /* @@ -444,7 +456,12 @@ static int __init omap4_panda_i2c_init(void) omap_register_i2c_bus(1, 400, omap4_panda_i2c_boardinfo, ARRAY_SIZE(omap4_panda_i2c_boardinfo)); omap_register_i2c_bus(2, 400, NULL, 0); - omap_register_i2c_bus(3, 400, NULL, 0); + /* + * Bus 3 is attached to the DVI port where devices like the pico DLP + * projector don't work reliably with 400kHz + */ + omap_register_i2c_bus(3, 100, panda_i2c_eeprom, + ARRAY_SIZE(panda_i2c_eeprom)); omap_register_i2c_bus(4, 400, NULL, 0); return 0; } @@ -464,12 +481,115 @@ static struct omap_board_mux board_mux[] __initdata = { OMAP4_MUX(SDMMC5_DAT1, OMAP_MUX_MODE0 | OMAP_PIN_INPUT_PULLUP), OMAP4_MUX(SDMMC5_DAT2, OMAP_MUX_MODE0 | OMAP_PIN_INPUT_PULLUP), OMAP4_MUX(SDMMC5_DAT3, OMAP_MUX_MODE0 | OMAP_PIN_INPUT_PULLUP), + /* gpio 0 - TFP410 PD */ + OMAP4_MUX(KPD_COL1, OMAP_PIN_OUTPUT | OMAP_MUX_MODE3), + /* dispc2_data23 */ + OMAP4_MUX(USBB2_ULPITLL_STP, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5), + /* dispc2_data22 */ + OMAP4_MUX(USBB2_ULPITLL_DIR, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5), + /* dispc2_data21 */ + OMAP4_MUX(USBB2_ULPITLL_NXT, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5), + /* dispc2_data20 */ + OMAP4_MUX(USBB2_ULPITLL_DAT0, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5), + /* dispc2_data19 */ + OMAP4_MUX(USBB2_ULPITLL_DAT1, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5), + /* dispc2_data18 */ + OMAP4_MUX(USBB2_ULPITLL_DAT2, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5), + /* dispc2_data15 */ + OMAP4_MUX(USBB2_ULPITLL_DAT3, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5), + /* dispc2_data14 */ + OMAP4_MUX(USBB2_ULPITLL_DAT4, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5), + /* dispc2_data13 */ + OMAP4_MUX(USBB2_ULPITLL_DAT5, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5), + /* dispc2_data12 */ + OMAP4_MUX(USBB2_ULPITLL_DAT6, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5), + /* dispc2_data11 */ + OMAP4_MUX(USBB2_ULPITLL_DAT7, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5), + /* dispc2_data10 */ + OMAP4_MUX(DPM_EMU3, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5), + /* dispc2_data9 */ + OMAP4_MUX(DPM_EMU4, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5), + /* dispc2_data16 */ + OMAP4_MUX(DPM_EMU5, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5), + /* dispc2_data17 */ + OMAP4_MUX(DPM_EMU6, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5), + /* dispc2_hsync */ + OMAP4_MUX(DPM_EMU7, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5), + /* dispc2_pclk */ + OMAP4_MUX(DPM_EMU8, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5), + /* dispc2_vsync */ + OMAP4_MUX(DPM_EMU9, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5), + /* dispc2_de */ + OMAP4_MUX(DPM_EMU10, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5), + /* dispc2_data8 */ + OMAP4_MUX(DPM_EMU11, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5), + /* dispc2_data7 */ + OMAP4_MUX(DPM_EMU12, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5), + /* dispc2_data6 */ + OMAP4_MUX(DPM_EMU13, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5), + /* dispc2_data5 */ + OMAP4_MUX(DPM_EMU14, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5), + /* dispc2_data4 */ + OMAP4_MUX(DPM_EMU15, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5), + /* dispc2_data3 */ + OMAP4_MUX(DPM_EMU16, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5), + /* dispc2_data2 */ + OMAP4_MUX(DPM_EMU17, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5), + /* dispc2_data1 */ + OMAP4_MUX(DPM_EMU18, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5), + /* dispc2_data0 */ + OMAP4_MUX(DPM_EMU19, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5), { .reg_offset = OMAP_MUX_TERMINATOR }, }; #else #define board_mux NULL #endif +/* Display DVI */ +#define PANDA_DVI_TFP410_POWER_DOWN_GPIO 0 + +static int omap4_panda_enable_dvi(struct omap_dss_device *dssdev) +{ + gpio_set_value(dssdev->reset_gpio, 1); + return 0; +} + +static void omap4_panda_disable_dvi(struct omap_dss_device *dssdev) +{ + gpio_set_value(dssdev->reset_gpio, 0); +} + +/* Using generic display panel */ +static struct panel_generic_dpi_data omap4_dvi_panel = { + .name = "generic", + .platform_enable = omap4_panda_enable_dvi, + .platform_disable = omap4_panda_disable_dvi, +}; + +struct omap_dss_device omap4_panda_dvi_device = { + .type = OMAP_DISPLAY_TYPE_DPI, + .name = "dvi", + .driver_name = "generic_dpi_panel", + .data = &omap4_dvi_panel, + .phy.dpi.data_lines = 24, + .reset_gpio = PANDA_DVI_TFP410_POWER_DOWN_GPIO, + .channel = OMAP_DSS_CHANNEL_LCD2, +}; + +int __init omap4_panda_dvi_init(void) +{ + int r; + + /* Requesting TFP410 DVI GPIO and disabling it, at bootup */ + r = gpio_request_one(omap4_panda_dvi_device.reset_gpio, + GPIOF_OUT_INIT_LOW, "DVI PD"); + if (r) + pr_err("Failed to get DVI powerdown GPIO\n"); + + return r; +} + + static void omap4_panda_hdmi_mux_init(void) { /* PAD0_HDMI_HPD_PAD1_HDMI_CEC */ @@ -525,17 +645,24 @@ static struct omap_dss_device omap4_panda_hdmi_device = { }; static struct omap_dss_device *omap4_panda_dss_devices[] = { + &omap4_panda_dvi_device, &omap4_panda_hdmi_device, }; static struct omap_dss_board_info omap4_panda_dss_data = { .num_devices = ARRAY_SIZE(omap4_panda_dss_devices), .devices = omap4_panda_dss_devices, - .default_device = &omap4_panda_hdmi_device, + .default_device = &omap4_panda_dvi_device, }; void omap4_panda_display_init(void) { + int r; + + r = omap4_panda_dvi_init(); + if (r) + pr_err("error initializing panda DVI\n"); + omap4_panda_hdmi_mux_init(); omap_display_init(&omap4_panda_dss_data); } -- GitLab From 6ce0466d631d40662e2ab9ec5a05019482bd1074 Mon Sep 17 00:00:00 2001 From: Sonic Zhang Date: Tue, 6 Apr 2010 09:11:59 +0000 Subject: [PATCH 0843/2822] Blackfin: SMP: avoid section mismatch warnings Since coreb_trampoline_start() calls coreb_start(), they need to be in the same section. Signed-off-by: Sonic Zhang Signed-off-by: Mike Frysinger --- arch/blackfin/mach-bf561/secondary.S | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/blackfin/mach-bf561/secondary.S b/arch/blackfin/mach-bf561/secondary.S index 4624eebbf9c4c..ef9acf21eb8e5 100644 --- a/arch/blackfin/mach-bf561/secondary.S +++ b/arch/blackfin/mach-bf561/secondary.S @@ -196,7 +196,7 @@ ENTRY(_coreb_sleep) jump (p0); ENDPROC(_coreb_sleep) -__CPUINIT +__INIT ENTRY(_coreb_start) [--sp] = reti; -- GitLab From 55835175a03392d2e4d9bff9d482312d118f304e Mon Sep 17 00:00:00 2001 From: steven miao Date: Fri, 22 Oct 2010 08:48:41 +0000 Subject: [PATCH 0844/2822] Blackfin: bf54x: add kconfig for UART2/3 DMA channel assignments The BF54x lacks dedicated DMA channels for the UART peripherals and need to be muxed between others. So add a kconfig option so people can select which channels the UARTs will use so they can pick between SPORTs and the less commonly used EPPI/PIXC peripherals. Signed-off-by: steven miao Signed-off-by: Mike Frysinger --- arch/blackfin/kernel/bfin_dma_5xx.c | 32 ++++++----- arch/blackfin/mach-bf548/Kconfig | 59 +++++++++++++++++++++ arch/blackfin/mach-bf548/include/mach/dma.h | 28 ++++++++-- arch/blackfin/mach-bf548/include/mach/irq.h | 4 -- 4 files changed, 102 insertions(+), 21 deletions(-) diff --git a/arch/blackfin/kernel/bfin_dma_5xx.c b/arch/blackfin/kernel/bfin_dma_5xx.c index 1e485dfdc9f21..6ce8dce753c9a 100644 --- a/arch/blackfin/kernel/bfin_dma_5xx.c +++ b/arch/blackfin/kernel/bfin_dma_5xx.c @@ -84,6 +84,24 @@ static int __init proc_dma_init(void) late_initcall(proc_dma_init); #endif +static void set_dma_peripheral_map(unsigned int channel, const char *device_id) +{ +#ifdef CONFIG_BF54x + unsigned int per_map; + + switch (channel) { + case CH_UART2_RX: per_map = 0xC << 12; break; + case CH_UART2_TX: per_map = 0xD << 12; break; + case CH_UART3_RX: per_map = 0xE << 12; break; + case CH_UART3_TX: per_map = 0xF << 12; break; + default: return; + } + + if (strncmp(device_id, "BFIN_UART", 9) == 0) + dma_ch[channel].regs->peripheral_map = per_map; +#endif +} + /** * request_dma - request a DMA channel * @@ -111,19 +129,7 @@ int request_dma(unsigned int channel, const char *device_id) return -EBUSY; } -#ifdef CONFIG_BF54x - if (channel >= CH_UART2_RX && channel <= CH_UART3_TX) { - unsigned int per_map; - per_map = dma_ch[channel].regs->peripheral_map & 0xFFF; - if (strncmp(device_id, "BFIN_UART", 9) == 0) - dma_ch[channel].regs->peripheral_map = per_map | - ((channel - CH_UART2_RX + 0xC)<<12); - else - dma_ch[channel].regs->peripheral_map = per_map | - ((channel - CH_UART2_RX + 0x6)<<12); - } -#endif - + set_dma_peripheral_map(channel, device_id); dma_ch[channel].device_id = device_id; dma_ch[channel].irq = 0; diff --git a/arch/blackfin/mach-bf548/Kconfig b/arch/blackfin/mach-bf548/Kconfig index 70189a0d1a190..94acb586832e6 100644 --- a/arch/blackfin/mach-bf548/Kconfig +++ b/arch/blackfin/mach-bf548/Kconfig @@ -42,6 +42,65 @@ config BF548_ATAPI_ALTERNATIVE_PORT async address or GPIO port F and G. Select y to route it to GPIO. +choice + prompt "UART2 DMA channel selection" + depends on SERIAL_BFIN_UART2 + default UART2_DMA_RX_ON_DMA18 + help + UART2 DMA channel selection + RX -> DMA18 + TX -> DMA19 + or + RX -> DMA13 + TX -> DMA14 + +config UART2_DMA_RX_ON_DMA18 + bool "UART2 DMA RX -> DMA18 TX -> DMA19" + help + UART2 DMA channel assignment + RX -> DMA18 + TX -> DMA19 + use SPORT2 default DMA channel + +config UART2_DMA_RX_ON_DMA13 + bool "UART2 DMA RX -> DMA13 TX -> DMA14" + help + UART2 DMA channel assignment + RX -> DMA13 + TX -> DMA14 + use EPPI1 EPPI2 default DMA channel +endchoice + +choice + prompt "UART3 DMA channel selection" + depends on SERIAL_BFIN_UART3 + default UART3_DMA_RX_ON_DMA20 + help + UART3 DMA channel selection + RX -> DMA20 + TX -> DMA21 + or + RX -> DMA15 + TX -> DMA16 + +config UART3_DMA_RX_ON_DMA20 + bool "UART3 DMA RX -> DMA20 TX -> DMA21" + help + UART3 DMA channel assignment + RX -> DMA20 + TX -> DMA21 + use SPORT3 default DMA channel + +config UART3_DMA_RX_ON_DMA15 + bool "UART3 DMA RX -> DMA15 TX -> DMA16" + help + UART3 DMA channel assignment + RX -> DMA15 + TX -> DMA16 + use PIXC default DMA channel + +endchoice + comment "Interrupt Priority Assignment" menu "Priority" diff --git a/arch/blackfin/mach-bf548/include/mach/dma.h b/arch/blackfin/mach-bf548/include/mach/dma.h index a30d242c7398d..1a1091b071fd5 100644 --- a/arch/blackfin/mach-bf548/include/mach/dma.h +++ b/arch/blackfin/mach-bf548/include/mach/dma.h @@ -27,17 +27,37 @@ #define CH_PIXC_OVERLAY 16 #define CH_PIXC_OUTPUT 17 #define CH_SPORT2_RX 18 -#define CH_UART2_RX 18 #define CH_SPORT2_TX 19 -#define CH_UART2_TX 19 #define CH_SPORT3_RX 20 -#define CH_UART3_RX 20 #define CH_SPORT3_TX 21 -#define CH_UART3_TX 21 #define CH_SDH 22 #define CH_NFC 22 #define CH_SPI2 23 +#if defined(CONFIG_UART2_DMA_RX_ON_DMA13) +#define CH_UART2_RX 13 +#define IRQ_UART2_RX BFIN_IRQ(37) /* UART2 RX USE EPP1 (DMA13) Interrupt */ +#define CH_UART2_TX 14 +#define IRQ_UART2_TX BFIN_IRQ(38) /* UART2 RX USE EPP1 (DMA14) Interrupt */ +#else /* Default USE SPORT2's DMA Channel */ +#define CH_UART2_RX 18 +#define IRQ_UART2_RX BFIN_IRQ(33) /* UART2 RX (DMA18) Interrupt */ +#define CH_UART2_TX 19 +#define IRQ_UART2_TX BFIN_IRQ(34) /* UART2 TX (DMA19) Interrupt */ +#endif + +#if defined(CONFIG_UART3_DMA_RX_ON_DMA15) +#define CH_UART3_RX 15 +#define IRQ_UART3_RX BFIN_IRQ(64) /* UART3 RX USE PIXC IN0 (DMA15) Interrupt */ +#define CH_UART3_TX 16 +#define IRQ_UART3_TX BFIN_IRQ(65) /* UART3 TX USE PIXC IN1 (DMA16) Interrupt */ +#else /* Default USE SPORT3's DMA Channel */ +#define CH_UART3_RX 20 +#define IRQ_UART3_RX BFIN_IRQ(35) /* UART3 RX (DMA20) Interrupt */ +#define CH_UART3_TX 21 +#define IRQ_UART3_TX BFIN_IRQ(36) /* UART3 TX (DMA21) Interrupt */ +#endif + #define CH_MEM_STREAM0_DEST 24 #define CH_MEM_STREAM0_SRC 25 #define CH_MEM_STREAM1_DEST 26 diff --git a/arch/blackfin/mach-bf548/include/mach/irq.h b/arch/blackfin/mach-bf548/include/mach/irq.h index 99fd1b2c53d8c..7f87787e77382 100644 --- a/arch/blackfin/mach-bf548/include/mach/irq.h +++ b/arch/blackfin/mach-bf548/include/mach/irq.h @@ -74,13 +74,9 @@ Events (highest priority) EMU 0 #define IRQ_UART2_ERROR BFIN_IRQ(31) /* UART2 Status (Error) Interrupt */ #define IRQ_CAN0_ERROR BFIN_IRQ(32) /* CAN0 Status (Error) Interrupt */ #define IRQ_SPORT2_RX BFIN_IRQ(33) /* SPORT2 RX (DMA18) Interrupt */ -#define IRQ_UART2_RX BFIN_IRQ(33) /* UART2 RX (DMA18) Interrupt */ #define IRQ_SPORT2_TX BFIN_IRQ(34) /* SPORT2 TX (DMA19) Interrupt */ -#define IRQ_UART2_TX BFIN_IRQ(34) /* UART2 TX (DMA19) Interrupt */ #define IRQ_SPORT3_RX BFIN_IRQ(35) /* SPORT3 RX (DMA20) Interrupt */ -#define IRQ_UART3_RX BFIN_IRQ(35) /* UART3 RX (DMA20) Interrupt */ #define IRQ_SPORT3_TX BFIN_IRQ(36) /* SPORT3 TX (DMA21) Interrupt */ -#define IRQ_UART3_TX BFIN_IRQ(36) /* UART3 TX (DMA21) Interrupt */ #define IRQ_EPPI1 BFIN_IRQ(37) /* EPP1 (DMA13) Interrupt */ #define IRQ_EPPI2 BFIN_IRQ(38) /* EPP2 (DMA14) Interrupt */ #define IRQ_SPI1 BFIN_IRQ(39) /* SPI1 (DMA5) Interrupt */ -- GitLab From 4c131c8c23eeb90d0fe93bd490ffd63ff0f97d10 Mon Sep 17 00:00:00 2001 From: Aaron Wu Date: Wed, 22 Dec 2010 06:21:03 +0000 Subject: [PATCH 0845/2822] Blackfin: bf548-ezkit: add CAN1 support Signed-off-by: Aaron Wu Signed-off-by: Mike Frysinger --- arch/blackfin/mach-bf548/boards/ezkit.c | 55 +++++++++++++++++++++---- 1 file changed, 48 insertions(+), 7 deletions(-) diff --git a/arch/blackfin/mach-bf548/boards/ezkit.c b/arch/blackfin/mach-bf548/boards/ezkit.c index ce5a2bb147dc2..93e19a54a8803 100644 --- a/arch/blackfin/mach-bf548/boards/ezkit.c +++ b/arch/blackfin/mach-bf548/boards/ezkit.c @@ -778,11 +778,12 @@ static struct platform_device bfin_sport3_uart_device = { #endif #if defined(CONFIG_CAN_BFIN) || defined(CONFIG_CAN_BFIN_MODULE) -static unsigned short bfin_can_peripherals[] = { + +static unsigned short bfin_can0_peripherals[] = { P_CAN0_RX, P_CAN0_TX, 0 }; -static struct resource bfin_can_resources[] = { +static struct resource bfin_can0_resources[] = { { .start = 0xFFC02A00, .end = 0xFFC02FFF, @@ -805,14 +806,53 @@ static struct resource bfin_can_resources[] = { }, }; -static struct platform_device bfin_can_device = { +static struct platform_device bfin_can0_device = { .name = "bfin_can", - .num_resources = ARRAY_SIZE(bfin_can_resources), - .resource = bfin_can_resources, + .id = 0, + .num_resources = ARRAY_SIZE(bfin_can0_resources), + .resource = bfin_can0_resources, .dev = { - .platform_data = &bfin_can_peripherals, /* Passed to driver */ + .platform_data = &bfin_can0_peripherals, /* Passed to driver */ }, }; + +static unsigned short bfin_can1_peripherals[] = { + P_CAN1_RX, P_CAN1_TX, 0 +}; + +static struct resource bfin_can1_resources[] = { + { + .start = 0xFFC03200, + .end = 0xFFC037FF, + .flags = IORESOURCE_MEM, + }, + { + .start = IRQ_CAN1_RX, + .end = IRQ_CAN1_RX, + .flags = IORESOURCE_IRQ, + }, + { + .start = IRQ_CAN1_TX, + .end = IRQ_CAN1_TX, + .flags = IORESOURCE_IRQ, + }, + { + .start = IRQ_CAN1_ERROR, + .end = IRQ_CAN1_ERROR, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device bfin_can1_device = { + .name = "bfin_can", + .id = 1, + .num_resources = ARRAY_SIZE(bfin_can1_resources), + .resource = bfin_can1_resources, + .dev = { + .platform_data = &bfin_can1_peripherals, /* Passed to driver */ + }, +}; + #endif #if defined(CONFIG_PATA_BF54X) || defined(CONFIG_PATA_BF54X_MODULE) @@ -1366,7 +1406,8 @@ static struct platform_device *ezkit_devices[] __initdata = { #endif #if defined(CONFIG_CAN_BFIN) || defined(CONFIG_CAN_BFIN_MODULE) - &bfin_can_device, + &bfin_can0_device, + &bfin_can1_device, #endif #if defined(CONFIG_PATA_BF54X) || defined(CONFIG_PATA_BF54X_MODULE) -- GitLab From b5fc12df9039a9e6a2c5ae1fc0cee244b6aca8e2 Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Tue, 11 Jan 2011 16:33:15 +0000 Subject: [PATCH 0846/2822] Blackfin: add bfin_write_{or,and} helpers Signed-off-by: Mike Frysinger --- arch/blackfin/include/asm/def_LPBlackfin.h | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/arch/blackfin/include/asm/def_LPBlackfin.h b/arch/blackfin/include/asm/def_LPBlackfin.h index e3f0f4c49819e..7600fe0696af1 100644 --- a/arch/blackfin/include/asm/def_LPBlackfin.h +++ b/arch/blackfin/include/asm/def_LPBlackfin.h @@ -58,14 +58,26 @@ ({ BUG(); 0; }); \ }) #define bfin_write(addr, val) \ -({ \ +do { \ switch (sizeof(*(addr))) { \ case 1: bfin_write8(addr, val); break; \ case 2: bfin_write16(addr, val); break; \ case 4: bfin_write32(addr, val); break; \ default: BUG(); \ } \ -}) +} while (0) + +#define bfin_write_or(addr, bits) \ +do { \ + void *__addr = (void *)(addr); \ + bfin_write(__addr, bfin_read(__addr) | (bits)); \ +} while (0) + +#define bfin_write_and(addr, bits) \ +do { \ + void *__addr = (void *)(addr); \ + bfin_write(__addr, bfin_read(__addr) & (bits)); \ +} while (0) #endif /* __ASSEMBLY__ */ -- GitLab From adfe6a4882ec8324d7f5be8cca8d8e59b8a8dfa0 Mon Sep 17 00:00:00 2001 From: Andreas Schallenberg Date: Tue, 18 Jan 2011 19:43:27 +0000 Subject: [PATCH 0847/2822] Blackfin: dnp5370: drop MMC card detect support The board doesn't actually have a pin hooked up to do card detection, so punt the code for it. Signed-off-by: Andreas Schallenberg Signed-off-by: Mike Frysinger --- arch/blackfin/mach-bf537/boards/dnp5370.c | 20 -------------------- 1 file changed, 20 deletions(-) diff --git a/arch/blackfin/mach-bf537/boards/dnp5370.c b/arch/blackfin/mach-bf537/boards/dnp5370.c index e1e9ea02ad898..6b4ff4605bffd 100644 --- a/arch/blackfin/mach-bf537/boards/dnp5370.c +++ b/arch/blackfin/mach-bf537/boards/dnp5370.c @@ -128,30 +128,11 @@ static struct platform_device asmb_flash_device = { #if defined(CONFIG_MMC_SPI) || defined(CONFIG_MMC_SPI_MODULE) -#define MMC_SPI_CARD_DETECT_INT IRQ_PF5 - -static int bfin_mmc_spi_init(struct device *dev, - irqreturn_t (*detect_int)(int, void *), void *data) -{ - return request_irq(MMC_SPI_CARD_DETECT_INT, detect_int, - IRQF_TRIGGER_FALLING, "mmc-spi-detect", data); -} - -static void bfin_mmc_spi_exit(struct device *dev, void *data) -{ - free_irq(MMC_SPI_CARD_DETECT_INT, data); -} - static struct bfin5xx_spi_chip mmc_spi_chip_info = { .enable_dma = 0, /* use no dma transfer with this chip*/ .bits_per_word = 8, }; -static struct mmc_spi_platform_data bfin_mmc_spi_pdata = { - .init = bfin_mmc_spi_init, - .exit = bfin_mmc_spi_exit, - .detect_delay = 100, /* msecs */ -}; #endif #if defined(CONFIG_MTD_DATAFLASH) || defined(CONFIG_MTD_DATAFLASH_MODULE) @@ -192,7 +173,6 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = { .max_speed_hz = 20000000, .bus_num = 0, .chip_select = 1, - .platform_data = &bfin_mmc_spi_pdata, .controller_data = &mmc_spi_chip_info, .mode = SPI_MODE_3, }, -- GitLab From cdb92f6794fb28c8f6c3bf85024bff8b438a7333 Mon Sep 17 00:00:00 2001 From: Sonic Zhang Date: Fri, 28 Jan 2011 10:58:59 +0000 Subject: [PATCH 0848/2822] Blackfin: kgdb: drop dead KGDB_THR_PROC_SWAP for SMP systems Common code no longer defines this, so stop using it. Signed-off-by: Sonic Zhang Signed-off-by: Mike Frysinger --- arch/blackfin/kernel/kgdb.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/arch/blackfin/kernel/kgdb.c b/arch/blackfin/kernel/kgdb.c index eb92592fd80cc..b8cfe34989e4e 100644 --- a/arch/blackfin/kernel/kgdb.c +++ b/arch/blackfin/kernel/kgdb.c @@ -422,11 +422,7 @@ int kgdb_arch_handle_exception(int vector, int signo, struct kgdb_arch arch_kgdb_ops = { .gdb_bpt_instr = {0xa1}, -#ifdef CONFIG_SMP - .flags = KGDB_HW_BREAKPOINT|KGDB_THR_PROC_SWAP, -#else .flags = KGDB_HW_BREAKPOINT, -#endif .set_hw_breakpoint = bfin_set_hw_break, .remove_hw_breakpoint = bfin_remove_hw_break, .disable_hw_break = bfin_disable_hw_debug, -- GitLab From d6b435be4b3277b341ad1a77392d2e58b3d7b36d Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Sun, 30 Jan 2011 07:26:26 +0000 Subject: [PATCH 0849/2822] Blackfin: ADI boards: enable pseudo debug insns support We use these insns when testing, so enable them by default for all of our development boards. Signed-off-by: Mike Frysinger --- arch/blackfin/configs/BF518F-EZBRD_defconfig | 1 + arch/blackfin/configs/BF526-EZBRD_defconfig | 1 + arch/blackfin/configs/BF527-EZKIT-V2_defconfig | 1 + arch/blackfin/configs/BF527-EZKIT_defconfig | 1 + arch/blackfin/configs/BF533-EZKIT_defconfig | 1 + arch/blackfin/configs/BF533-STAMP_defconfig | 1 + arch/blackfin/configs/BF537-STAMP_defconfig | 1 + arch/blackfin/configs/BF538-EZKIT_defconfig | 1 + arch/blackfin/configs/BF548-EZKIT_defconfig | 1 + arch/blackfin/configs/BF561-EZKIT-SMP_defconfig | 1 + arch/blackfin/configs/BF561-EZKIT_defconfig | 1 + 11 files changed, 11 insertions(+) diff --git a/arch/blackfin/configs/BF518F-EZBRD_defconfig b/arch/blackfin/configs/BF518F-EZBRD_defconfig index db8d38a12a9ae..5edcb58d6f737 100644 --- a/arch/blackfin/configs/BF518F-EZBRD_defconfig +++ b/arch/blackfin/configs/BF518F-EZBRD_defconfig @@ -115,6 +115,7 @@ CONFIG_DEBUG_DOUBLEFAULT=y CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_ONE=y CONFIG_EARLY_PRINTK=y CONFIG_CPLB_INFO=y +CONFIG_BFIN_PSEUDODBG_INSNS=y CONFIG_CRYPTO=y # CONFIG_CRYPTO_ANSI_CPRNG is not set CONFIG_CRC_CCITT=m diff --git a/arch/blackfin/configs/BF526-EZBRD_defconfig b/arch/blackfin/configs/BF526-EZBRD_defconfig index 3e50d7857c272..2e549572d4f59 100644 --- a/arch/blackfin/configs/BF526-EZBRD_defconfig +++ b/arch/blackfin/configs/BF526-EZBRD_defconfig @@ -153,6 +153,7 @@ CONFIG_DEBUG_DOUBLEFAULT=y CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_ONE=y CONFIG_EARLY_PRINTK=y CONFIG_CPLB_INFO=y +CONFIG_BFIN_PSEUDODBG_INSNS=y CONFIG_CRYPTO=y # CONFIG_CRYPTO_ANSI_CPRNG is not set CONFIG_CRC_CCITT=m diff --git a/arch/blackfin/configs/BF527-EZKIT-V2_defconfig b/arch/blackfin/configs/BF527-EZKIT-V2_defconfig index 023ff0df2692c..95cf2ba9de17b 100644 --- a/arch/blackfin/configs/BF527-EZKIT-V2_defconfig +++ b/arch/blackfin/configs/BF527-EZKIT-V2_defconfig @@ -183,5 +183,6 @@ CONFIG_DEBUG_DOUBLEFAULT=y CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_ONE=y CONFIG_EARLY_PRINTK=y CONFIG_CPLB_INFO=y +CONFIG_BFIN_PSEUDODBG_INSNS=y CONFIG_CRYPTO=y # CONFIG_CRYPTO_ANSI_CPRNG is not set diff --git a/arch/blackfin/configs/BF527-EZKIT_defconfig b/arch/blackfin/configs/BF527-EZKIT_defconfig index 4e5a121b3c563..8be8e33fac526 100644 --- a/arch/blackfin/configs/BF527-EZKIT_defconfig +++ b/arch/blackfin/configs/BF527-EZKIT_defconfig @@ -175,5 +175,6 @@ CONFIG_DEBUG_DOUBLEFAULT=y CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_ONE=y CONFIG_EARLY_PRINTK=y CONFIG_CPLB_INFO=y +CONFIG_BFIN_PSEUDODBG_INSNS=y CONFIG_CRYPTO=y # CONFIG_CRYPTO_ANSI_CPRNG is not set diff --git a/arch/blackfin/configs/BF533-EZKIT_defconfig b/arch/blackfin/configs/BF533-EZKIT_defconfig index 9f8fc84e4ac94..a7eb54bf30899 100644 --- a/arch/blackfin/configs/BF533-EZKIT_defconfig +++ b/arch/blackfin/configs/BF533-EZKIT_defconfig @@ -108,5 +108,6 @@ CONFIG_DEBUG_DOUBLEFAULT=y CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_ONE=y CONFIG_EARLY_PRINTK=y CONFIG_CPLB_INFO=y +CONFIG_BFIN_PSEUDODBG_INSNS=y CONFIG_CRYPTO=y # CONFIG_CRYPTO_ANSI_CPRNG is not set diff --git a/arch/blackfin/configs/BF533-STAMP_defconfig b/arch/blackfin/configs/BF533-STAMP_defconfig index ccc432b722a07..0aafde6c8c2d0 100644 --- a/arch/blackfin/configs/BF533-STAMP_defconfig +++ b/arch/blackfin/configs/BF533-STAMP_defconfig @@ -122,5 +122,6 @@ CONFIG_DEBUG_DOUBLEFAULT=y CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_ONE=y CONFIG_EARLY_PRINTK=y CONFIG_CPLB_INFO=y +CONFIG_BFIN_PSEUDODBG_INSNS=y CONFIG_CRYPTO=y # CONFIG_CRYPTO_ANSI_CPRNG is not set diff --git a/arch/blackfin/configs/BF537-STAMP_defconfig b/arch/blackfin/configs/BF537-STAMP_defconfig index 566695472a848..c9077fb581354 100644 --- a/arch/blackfin/configs/BF537-STAMP_defconfig +++ b/arch/blackfin/configs/BF537-STAMP_defconfig @@ -133,5 +133,6 @@ CONFIG_DEBUG_DOUBLEFAULT=y CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_ONE=y CONFIG_EARLY_PRINTK=y CONFIG_CPLB_INFO=y +CONFIG_BFIN_PSEUDODBG_INSNS=y CONFIG_CRYPTO=y # CONFIG_CRYPTO_ANSI_CPRNG is not set diff --git a/arch/blackfin/configs/BF538-EZKIT_defconfig b/arch/blackfin/configs/BF538-EZKIT_defconfig index ac22124ccb6cc..6883803e6ca89 100644 --- a/arch/blackfin/configs/BF538-EZKIT_defconfig +++ b/arch/blackfin/configs/BF538-EZKIT_defconfig @@ -131,5 +131,6 @@ CONFIG_DEBUG_DOUBLEFAULT=y CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_ONE=y CONFIG_EARLY_PRINTK=y CONFIG_CPLB_INFO=y +CONFIG_BFIN_PSEUDODBG_INSNS=y CONFIG_CRYPTO=y # CONFIG_CRYPTO_ANSI_CPRNG is not set diff --git a/arch/blackfin/configs/BF548-EZKIT_defconfig b/arch/blackfin/configs/BF548-EZKIT_defconfig index 944404b6ff08a..56151b5dbc444 100644 --- a/arch/blackfin/configs/BF548-EZKIT_defconfig +++ b/arch/blackfin/configs/BF548-EZKIT_defconfig @@ -205,5 +205,6 @@ CONFIG_DEBUG_DOUBLEFAULT=y CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_ONE=y CONFIG_EARLY_PRINTK=y CONFIG_CPLB_INFO=y +CONFIG_BFIN_PSEUDODBG_INSNS=y CONFIG_CRYPTO=y # CONFIG_CRYPTO_ANSI_CPRNG is not set diff --git a/arch/blackfin/configs/BF561-EZKIT-SMP_defconfig b/arch/blackfin/configs/BF561-EZKIT-SMP_defconfig index 7e67ba31e9919..f5ed34e12e0ca 100644 --- a/arch/blackfin/configs/BF561-EZKIT-SMP_defconfig +++ b/arch/blackfin/configs/BF561-EZKIT-SMP_defconfig @@ -109,5 +109,6 @@ CONFIG_DEBUG_DOUBLEFAULT=y CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_ONE=y CONFIG_EARLY_PRINTK=y CONFIG_CPLB_INFO=y +CONFIG_BFIN_PSEUDODBG_INSNS=y CONFIG_CRYPTO=y # CONFIG_CRYPTO_ANSI_CPRNG is not set diff --git a/arch/blackfin/configs/BF561-EZKIT_defconfig b/arch/blackfin/configs/BF561-EZKIT_defconfig index 141e5933e1aaf..1c0a82a105919 100644 --- a/arch/blackfin/configs/BF561-EZKIT_defconfig +++ b/arch/blackfin/configs/BF561-EZKIT_defconfig @@ -111,5 +111,6 @@ CONFIG_DEBUG_DOUBLEFAULT=y CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_ONE=y CONFIG_EARLY_PRINTK=y CONFIG_CPLB_INFO=y +CONFIG_BFIN_PSEUDODBG_INSNS=y CONFIG_CRYPTO=y # CONFIG_CRYPTO_ANSI_CPRNG is not set -- GitLab From ef9d8c251ac84e2c471768bb57298b177f8d6ab5 Mon Sep 17 00:00:00 2001 From: steven miao Date: Mon, 31 Jan 2011 10:10:54 +0000 Subject: [PATCH 0850/2822] Blackfin: SMP: PERCPU section should be PAGE aligned Common code checks the alignment of some of the variables and calls BUG() if they aren't page aligned. Signed-off-by: steven miao Signed-off-by: Mike Frysinger --- arch/blackfin/kernel/vmlinux.lds.S | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/blackfin/kernel/vmlinux.lds.S b/arch/blackfin/kernel/vmlinux.lds.S index c40d07f708e8d..f5fd234e57732 100644 --- a/arch/blackfin/kernel/vmlinux.lds.S +++ b/arch/blackfin/kernel/vmlinux.lds.S @@ -136,7 +136,7 @@ SECTIONS . = ALIGN(16); INIT_DATA_SECTION(16) - PERCPU(32, 4) + PERCPU(32, PAGE_SIZE) .exit.data : { -- GitLab From 5f362c91d09370cf8a3c5fbe349218377ad64e4a Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Wed, 2 Feb 2011 01:55:01 +0000 Subject: [PATCH 0851/2822] Blackfin: SMP: use standard cache functions Signed-off-by: Mike Frysinger --- arch/blackfin/mach-common/smp.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/blackfin/mach-common/smp.c b/arch/blackfin/mach-common/smp.c index 9f251406a76ac..d3f597a92053a 100644 --- a/arch/blackfin/mach-common/smp.c +++ b/arch/blackfin/mach-common/smp.c @@ -105,10 +105,10 @@ static void ipi_flush_icache(void *info) struct blackfin_flush_data *fdata = info; /* Invalidate the memory holding the bounds of the flushed region. */ - blackfin_dcache_invalidate_range((unsigned long)fdata, - (unsigned long)fdata + sizeof(*fdata)); + invalidate_dcache_range((unsigned long)fdata, + (unsigned long)fdata + sizeof(*fdata)); - blackfin_icache_flush_range(fdata->start, fdata->end); + flush_icache_range(fdata->start, fdata->end); } static void ipi_call_function(unsigned int cpu, struct ipi_message *msg) -- GitLab From ab61d2ac5c9d7c9232b8455c8d889216ca9d4814 Mon Sep 17 00:00:00 2001 From: steven miao Date: Tue, 7 Sep 2010 10:08:36 +0000 Subject: [PATCH 0852/2822] Blackfin: SMP: delay enabling caches until CPU is initialized Defer bfin_setup_caches(cpu) to avoid unexpected faults due to the cpu state not yet being fully initialized. Signed-off-by: steven miao Signed-off-by: Mike Frysinger --- arch/blackfin/mach-common/smp.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/blackfin/mach-common/smp.c b/arch/blackfin/mach-common/smp.c index d3f597a92053a..40e6cbc363f5f 100644 --- a/arch/blackfin/mach-common/smp.c +++ b/arch/blackfin/mach-common/smp.c @@ -361,8 +361,6 @@ void __cpuinit secondary_start_kernel(void) */ init_exception_vectors(); - bfin_setup_caches(cpu); - local_irq_disable(); /* Attach the new idle task to the global mm. */ @@ -381,6 +379,8 @@ void __cpuinit secondary_start_kernel(void) local_irq_enable(); + bfin_setup_caches(cpu); + /* * Calibrate loops per jiffy value. * IRQs need to be enabled here - D-cache can be invalidated -- GitLab From 567ebfc99d7546913408b560ad443a5315bf8a53 Mon Sep 17 00:00:00 2001 From: Sonic Zhang Date: Fri, 25 Jun 2010 05:55:16 +0000 Subject: [PATCH 0853/2822] Blackfin: SMP: disable preempt with smp_processor_id to send messages The smp_processor_id() API requires that preempt be disabled when calling it, so make sure it is when we go to send messages to other processors. Signed-off-by: Sonic Zhang Signed-off-by: Mike Frysinger --- arch/blackfin/mach-common/smp.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/arch/blackfin/mach-common/smp.c b/arch/blackfin/mach-common/smp.c index 40e6cbc363f5f..5f7617d669055 100644 --- a/arch/blackfin/mach-common/smp.c +++ b/arch/blackfin/mach-common/smp.c @@ -244,12 +244,13 @@ int smp_call_function(void (*func)(void *info), void *info, int wait) { cpumask_t callmap; + preempt_disable(); callmap = cpu_online_map; cpu_clear(smp_processor_id(), callmap); - if (cpus_empty(callmap)) - return 0; + if (!cpus_empty(callmap)) + smp_send_message(callmap, BFIN_IPI_CALL_FUNC, func, info, wait); - smp_send_message(callmap, BFIN_IPI_CALL_FUNC, func, info, wait); + preempt_enable(); return 0; } @@ -286,12 +287,13 @@ void smp_send_stop(void) { cpumask_t callmap; + preempt_disable(); callmap = cpu_online_map; cpu_clear(smp_processor_id(), callmap); - if (cpus_empty(callmap)) - return; + if (!cpus_empty(callmap)) + smp_send_message(callmap, BFIN_IPI_CPU_STOP, NULL, NULL, 0); - smp_send_message(callmap, BFIN_IPI_CPU_STOP, NULL, NULL, 0); + preempt_enable(); return; } -- GitLab From 820b127dae869cbbd2133f066e8b8f32a90d46e5 Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Wed, 2 Feb 2011 22:31:42 -0500 Subject: [PATCH 0854/2822] Blackfin: split optimization settings more We need to place icache flush funcs into L1 inst sram to work around a hardware anomaly. But this currently breaks SMP support as the L1 inst sram is per-core and cannot be called directly. So in preparation for making that work, split the two options. Further, split out the SMP depend so that we can allow some for SMP. Signed-off-by: Mike Frysinger --- arch/blackfin/Kconfig | 42 ++++++++++++++++++++----- arch/blackfin/mach-common/arch_checks.c | 2 +- arch/blackfin/mach-common/cache.S | 18 +++++++---- 3 files changed, 47 insertions(+), 15 deletions(-) diff --git a/arch/blackfin/Kconfig b/arch/blackfin/Kconfig index c09577ddc3c5b..0f34ec58bac3f 100644 --- a/arch/blackfin/Kconfig +++ b/arch/blackfin/Kconfig @@ -690,13 +690,13 @@ endmenu menu "Blackfin Kernel Optimizations" - depends on !SMP comment "Memory Optimizations" config I_ENTRY_L1 bool "Locate interrupt entry code in L1 Memory" default y + depends on !SMP help If enabled, interrupt entry code (STORE/RESTORE CONTEXT) is linked into L1 instruction memory. (less latency) @@ -704,6 +704,7 @@ config I_ENTRY_L1 config EXCPT_IRQ_SYSC_L1 bool "Locate entire ASM lowlevel exception / interrupt - Syscall and CPLB handler code in L1 Memory" default y + depends on !SMP help If enabled, the entire ASM lowlevel exception and interrupt entry code (STORE/RESTORE CONTEXT) is linked into L1 instruction memory. @@ -712,6 +713,7 @@ config EXCPT_IRQ_SYSC_L1 config DO_IRQ_L1 bool "Locate frequently called do_irq dispatcher function in L1 Memory" default y + depends on !SMP help If enabled, the frequently called do_irq dispatcher function is linked into L1 instruction memory. (less latency) @@ -719,6 +721,7 @@ config DO_IRQ_L1 config CORE_TIMER_IRQ_L1 bool "Locate frequently called timer_interrupt() function in L1 Memory" default y + depends on !SMP help If enabled, the frequently called timer_interrupt() function is linked into L1 instruction memory. (less latency) @@ -726,6 +729,7 @@ config CORE_TIMER_IRQ_L1 config IDLE_L1 bool "Locate frequently idle function in L1 Memory" default y + depends on !SMP help If enabled, the frequently called idle function is linked into L1 instruction memory. (less latency) @@ -733,6 +737,7 @@ config IDLE_L1 config SCHEDULE_L1 bool "Locate kernel schedule function in L1 Memory" default y + depends on !SMP help If enabled, the frequently called kernel schedule is linked into L1 instruction memory. (less latency) @@ -740,6 +745,7 @@ config SCHEDULE_L1 config ARITHMETIC_OPS_L1 bool "Locate kernel owned arithmetic functions in L1 Memory" default y + depends on !SMP help If enabled, arithmetic functions are linked into L1 instruction memory. (less latency) @@ -747,6 +753,7 @@ config ARITHMETIC_OPS_L1 config ACCESS_OK_L1 bool "Locate access_ok function in L1 Memory" default y + depends on !SMP help If enabled, the access_ok function is linked into L1 instruction memory. (less latency) @@ -754,6 +761,7 @@ config ACCESS_OK_L1 config MEMSET_L1 bool "Locate memset function in L1 Memory" default y + depends on !SMP help If enabled, the memset function is linked into L1 instruction memory. (less latency) @@ -761,6 +769,7 @@ config MEMSET_L1 config MEMCPY_L1 bool "Locate memcpy function in L1 Memory" default y + depends on !SMP help If enabled, the memcpy function is linked into L1 instruction memory. (less latency) @@ -768,6 +777,7 @@ config MEMCPY_L1 config STRCMP_L1 bool "locate strcmp function in L1 Memory" default y + depends on !SMP help If enabled, the strcmp function is linked into L1 instruction memory (less latency). @@ -775,6 +785,7 @@ config STRCMP_L1 config STRNCMP_L1 bool "locate strncmp function in L1 Memory" default y + depends on !SMP help If enabled, the strncmp function is linked into L1 instruction memory (less latency). @@ -782,6 +793,7 @@ config STRNCMP_L1 config STRCPY_L1 bool "locate strcpy function in L1 Memory" default y + depends on !SMP help If enabled, the strcpy function is linked into L1 instruction memory (less latency). @@ -789,6 +801,7 @@ config STRCPY_L1 config STRNCPY_L1 bool "locate strncpy function in L1 Memory" default y + depends on !SMP help If enabled, the strncpy function is linked into L1 instruction memory (less latency). @@ -796,6 +809,7 @@ config STRNCPY_L1 config SYS_BFIN_SPINLOCK_L1 bool "Locate sys_bfin_spinlock function in L1 Memory" default y + depends on !SMP help If enabled, sys_bfin_spinlock function is linked into L1 instruction memory. (less latency) @@ -803,6 +817,7 @@ config SYS_BFIN_SPINLOCK_L1 config IP_CHECKSUM_L1 bool "Locate IP Checksum function in L1 Memory" default n + depends on !SMP help If enabled, the IP Checksum function is linked into L1 instruction memory. (less latency) @@ -811,7 +826,7 @@ config CACHELINE_ALIGNED_L1 bool "Locate cacheline_aligned data to L1 Data Memory" default y if !BF54x default n if BF54x - depends on !BF531 + depends on !SMP && !BF531 help If enabled, cacheline_aligned data is linked into L1 data memory. (less latency) @@ -819,7 +834,7 @@ config CACHELINE_ALIGNED_L1 config SYSCALL_TAB_L1 bool "Locate Syscall Table L1 Data Memory" default n - depends on !BF531 + depends on !SMP && !BF531 help If enabled, the Syscall LUT is linked into L1 data memory. (less latency) @@ -827,16 +842,17 @@ config SYSCALL_TAB_L1 config CPLB_SWITCH_TAB_L1 bool "Locate CPLB Switch Tables L1 Data Memory" default n - depends on !BF531 + depends on !SMP && !BF531 help If enabled, the CPLB Switch Tables are linked into L1 data memory. (less latency) -config CACHE_FLUSH_L1 - bool "Locate cache flush funcs in L1 Inst Memory" +config ICACHE_FLUSH_L1 + bool "Locate icache flush funcs in L1 Inst Memory" default y + depends on !SMP help - If enabled, the Blackfin cache flushing functions are linked + If enabled, the Blackfin icache flushing functions are linked into L1 instruction memory. Note that this might be required to address anomalies, but @@ -844,9 +860,18 @@ config CACHE_FLUSH_L1 If you are using a processor affected by an anomaly, the build system will double check for you and prevent it. +config DCACHE_FLUSH_L1 + bool "Locate dcache flush funcs in L1 Inst Memory" + default y + depends on !SMP + help + If enabled, the Blackfin dcache flushing functions are linked + into L1 instruction memory. + config APP_STACK_L1 bool "Support locating application stack in L1 Scratch Memory" default y + depends on !SMP help If enabled the application stack can be located in L1 scratch memory (less latency). @@ -856,7 +881,7 @@ config APP_STACK_L1 config EXCEPTION_L1_SCRATCH bool "Locate exception stack in L1 Scratch Memory" default n - depends on !APP_STACK_L1 + depends on !SMP && !APP_STACK_L1 help Whenever an exception occurs, use the L1 Scratch memory for stack storage. You cannot place the stacks of FLAT binaries @@ -868,6 +893,7 @@ comment "Speed Optimizations" config BFIN_INS_LOWOVERHEAD bool "ins[bwl] low overhead, higher interrupt latency" default y + depends on !SMP help Reads on the Blackfin are speculative. In Blackfin terms, this means they can be interrupted at any time (even after they have been issued diff --git a/arch/blackfin/mach-common/arch_checks.c b/arch/blackfin/mach-common/arch_checks.c index bceb98126c21e..d8643fdd0fcf1 100644 --- a/arch/blackfin/mach-common/arch_checks.c +++ b/arch/blackfin/mach-common/arch_checks.c @@ -61,6 +61,6 @@ # error "Anomaly 05000220 does not allow you to use Write Back cache with L2 or External Memory" #endif -#if ANOMALY_05000491 && !defined(CONFIG_CACHE_FLUSH_L1) +#if ANOMALY_05000491 && !defined(CONFIG_ICACHE_FLUSH_L1) # error You need IFLUSH in L1 inst while Anomaly 05000491 applies #endif diff --git a/arch/blackfin/mach-common/cache.S b/arch/blackfin/mach-common/cache.S index ab4a925a443e4..85aadeb766585 100644 --- a/arch/blackfin/mach-common/cache.S +++ b/arch/blackfin/mach-common/cache.S @@ -11,12 +11,6 @@ #include #include -#ifdef CONFIG_CACHE_FLUSH_L1 -.section .l1.text -#else -.text -#endif - /* 05000443 - IFLUSH cannot be last instruction in hardware loop */ #if ANOMALY_05000443 # define BROK_FLUSH_INST "IFLUSH" @@ -68,11 +62,23 @@ RTS; .endm +#ifdef CONFIG_ICACHE_FLUSH_L1 +.section .l1.text +#else +.text +#endif + /* Invalidate all instruction cache lines assocoiated with this memory area */ ENTRY(_blackfin_icache_flush_range) do_flush IFLUSH ENDPROC(_blackfin_icache_flush_range) +#ifdef CONFIG_DCACHE_FLUSH_L1 +.section .l1.text +#else +.text +#endif + /* Throw away all D-cached data in specified region without any obligation to * write them back. Since the Blackfin ISA does not have an "invalidate" * instruction, we use flush/invalidate. Perhaps as a speed optimization we -- GitLab From 6f546bc3ac9eedbf770bf3bcbc45ce2ea32c94ad Mon Sep 17 00:00:00 2001 From: Graf Yang Date: Thu, 28 Jan 2010 10:46:55 +0000 Subject: [PATCH 0855/2822] Blackfin: SMP: implement cpu_freq support Re-use some of the existing cpu hotplugging code in the process. Signed-off-by: Graf Yang Signed-off-by: Mike Frysinger --- arch/blackfin/include/asm/dpmc.h | 3 ++ arch/blackfin/include/asm/smp.h | 2 +- arch/blackfin/mach-bf561/hotplug.c | 21 +++++------- arch/blackfin/mach-bf561/secondary.S | 26 +++++---------- arch/blackfin/mach-common/cpufreq.c | 2 -- arch/blackfin/mach-common/dpmc.c | 50 ++++++++++++++++++++++++++-- 6 files changed, 70 insertions(+), 34 deletions(-) diff --git a/arch/blackfin/include/asm/dpmc.h b/arch/blackfin/include/asm/dpmc.h index 3047120cfcff4..edf2a2ad51831 100644 --- a/arch/blackfin/include/asm/dpmc.h +++ b/arch/blackfin/include/asm/dpmc.h @@ -125,6 +125,9 @@ void unset_dram_srfs(void); #define VRPAIR(vlev, freq) (((vlev) << 16) | ((freq) >> 16)) +#ifdef CONFIG_CPU_FREQ +#define CPUFREQ_CPU 0 +#endif struct bfin_dpmc_platform_data { const unsigned int *tuple_tab; unsigned short tabsize; diff --git a/arch/blackfin/include/asm/smp.h b/arch/blackfin/include/asm/smp.h index f5b537967116d..9dd4873752479 100644 --- a/arch/blackfin/include/asm/smp.h +++ b/arch/blackfin/include/asm/smp.h @@ -34,7 +34,7 @@ extern unsigned long dcache_invld_count[NR_CPUS]; void smp_icache_flush_range_others(unsigned long start, unsigned long end); #ifdef CONFIG_HOTPLUG_CPU -void coreb_sleep(u32 sic_iwr0, u32 sic_iwr1, u32 sic_iwr2); +void coreb_die(void); void cpu_die(void); void platform_cpu_die(void); int __cpu_disable(void); diff --git a/arch/blackfin/mach-bf561/hotplug.c b/arch/blackfin/mach-bf561/hotplug.c index 4cd3b28cd046d..42fc085629c76 100644 --- a/arch/blackfin/mach-bf561/hotplug.c +++ b/arch/blackfin/mach-bf561/hotplug.c @@ -5,30 +5,27 @@ * Licensed under the GPL-2 or later. */ +#include #include -#include -#include - -#define SIC_SYSIRQ(irq) (irq - (IRQ_CORETMR + 1)) +#include int hotplug_coreb; void platform_cpu_die(void) { - unsigned long iwr[2] = {0, 0}; - unsigned long bank = SIC_SYSIRQ(IRQ_SUPPLE_0) / 32; - unsigned long bit = 1 << (SIC_SYSIRQ(IRQ_SUPPLE_0) % 32); - + unsigned long iwr; hotplug_coreb = 1; - iwr[bank] = bit; - /* disable core timer */ bfin_write_TCNTL(0); - /* clear ipi interrupt IRQ_SUPPLE_0 */ + /* clear ipi interrupt IRQ_SUPPLE_0 of CoreB */ bfin_write_SICB_SYSCR(bfin_read_SICB_SYSCR() | (1 << (10 + 1))); SSYNC(); - coreb_sleep(iwr[0], iwr[1], 0); + /* set CoreB wakeup by ipi0, iwr will be discarded */ + bfin_iwr_set_sup0(&iwr, &iwr, &iwr); + SSYNC(); + + coreb_die(); } diff --git a/arch/blackfin/mach-bf561/secondary.S b/arch/blackfin/mach-bf561/secondary.S index ef9acf21eb8e5..148e50764555f 100644 --- a/arch/blackfin/mach-bf561/secondary.S +++ b/arch/blackfin/mach-bf561/secondary.S @@ -162,39 +162,31 @@ ENTRY(_coreb_trampoline_start) ENDPROC(_coreb_trampoline_start) ENTRY(_coreb_trampoline_end) +#ifdef CONFIG_HOTPLUG_CPU .section ".text" -ENTRY(_set_sicb_iwr) - P0.H = hi(SICB_IWR0); - P0.L = lo(SICB_IWR0); - P1.H = hi(SICB_IWR1); - P1.L = lo(SICB_IWR1); - [P0] = R0; - [P1] = R1; - SSYNC; - RTS; -ENDPROC(_set_sicb_iwr) - -ENTRY(_coreb_sleep) +ENTRY(_coreb_die) sp.l = lo(INITIAL_STACK); sp.h = hi(INITIAL_STACK); fp = sp; usp = sp; - call _set_sicb_iwr; - CLI R2; SSYNC; IDLE; STI R2; R0 = IWR_DISABLE_ALL; - R1 = IWR_DISABLE_ALL; - call _set_sicb_iwr; + P0.H = hi(SYSMMR_BASE); + P0.L = lo(SYSMMR_BASE); + [P0 + (SICB_IWR0 - SYSMMR_BASE)] = R0; + [P0 + (SICB_IWR1 - SYSMMR_BASE)] = R0; + SSYNC; p0.h = hi(COREB_L1_CODE_START); p0.l = lo(COREB_L1_CODE_START); jump (p0); -ENDPROC(_coreb_sleep) +ENDPROC(_coreb_die) +#endif __INIT ENTRY(_coreb_start) diff --git a/arch/blackfin/mach-common/cpufreq.c b/arch/blackfin/mach-common/cpufreq.c index f4cf11d362e1d..c33fb61b50822 100644 --- a/arch/blackfin/mach-common/cpufreq.c +++ b/arch/blackfin/mach-common/cpufreq.c @@ -16,8 +16,6 @@ #include #include -#define CPUFREQ_CPU 0 - /* this is the table of CCLK frequencies, in Hz */ /* .index is the entry in the auxillary dpm_state_table[] */ static struct cpufreq_frequency_table bfin_freq_table[] = { diff --git a/arch/blackfin/mach-common/dpmc.c b/arch/blackfin/mach-common/dpmc.c index 02c7efd1bcf48..382099fd55619 100644 --- a/arch/blackfin/mach-common/dpmc.c +++ b/arch/blackfin/mach-common/dpmc.c @@ -61,17 +61,63 @@ err_out: } #ifdef CONFIG_CPU_FREQ +# ifdef CONFIG_SMP +static void bfin_idle_this_cpu(void *info) +{ + unsigned long flags = 0; + unsigned long iwr0, iwr1, iwr2; + unsigned int cpu = smp_processor_id(); + + local_irq_save_hw(flags); + bfin_iwr_set_sup0(&iwr0, &iwr1, &iwr2); + + platform_clear_ipi(cpu, IRQ_SUPPLE_0); + SSYNC(); + asm("IDLE;"); + bfin_iwr_restore(iwr0, iwr1, iwr2); + + local_irq_restore_hw(flags); +} + +static void bfin_idle_cpu(void) +{ + smp_call_function(bfin_idle_this_cpu, NULL, 0); +} + +static void bfin_wakeup_cpu(void) +{ + unsigned int cpu; + unsigned int this_cpu = smp_processor_id(); + cpumask_t mask = cpu_online_map; + + cpu_clear(this_cpu, mask); + for_each_cpu_mask(cpu, mask) + platform_send_ipi_cpu(cpu, IRQ_SUPPLE_0); +} + +# else +static void bfin_idle_cpu(void) {} +static void bfin_wakeup_cpu(void) {} +# endif + static int vreg_cpufreq_notifier(struct notifier_block *nb, unsigned long val, void *data) { struct cpufreq_freqs *freq = data; + if (freq->cpu != CPUFREQ_CPU) + return 0; + if (val == CPUFREQ_PRECHANGE && freq->old < freq->new) { + bfin_idle_cpu(); bfin_set_vlev(bfin_get_vlev(freq->new)); udelay(pdata->vr_settling_time); /* Wait until Volatge settled */ - - } else if (val == CPUFREQ_POSTCHANGE && freq->old > freq->new) + bfin_wakeup_cpu(); + } else if (val == CPUFREQ_POSTCHANGE && freq->old > freq->new) { + bfin_idle_cpu(); bfin_set_vlev(bfin_get_vlev(freq->new)); + bfin_wakeup_cpu(); + } return 0; } -- GitLab From c6345ab1a3d17f4b6c80ac79d7fb0f006b32fdaa Mon Sep 17 00:00:00 2001 From: Sonic Zhang Date: Thu, 5 Aug 2010 07:49:26 +0000 Subject: [PATCH 0856/2822] Blackfin: SMP: work around anomaly 05000491 In order to safely work around anomaly 05000491, we have to execute IFLUSH from L1 instruction sram. The trouble with multi-core systems is that all L1 sram is visible only to the active core. So we can't just place the functions into L1 and call it directly. We need to setup a jump table and place the entry point in external memory. This will call the right func based on the active core. In the process, convert from the manual relocation of a small bit of code into Core B's L1 to the more general framework we already have in place for loading arbitrary pieces of code into L1. Signed-off-by: Sonic Zhang Signed-off-by: Mike Frysinger --- arch/blackfin/Kconfig | 1 - arch/blackfin/include/asm/smp.h | 7 +++++- arch/blackfin/kernel/setup.c | 37 ++++++++++++++++++++++++++++ arch/blackfin/kernel/vmlinux.lds.S | 1 + arch/blackfin/mach-bf561/secondary.S | 7 ++++-- arch/blackfin/mach-bf561/smp.c | 9 +------ arch/blackfin/mach-common/cache.S | 20 +++++++++++++++ arch/blackfin/mach-common/smp.c | 4 +++ 8 files changed, 74 insertions(+), 12 deletions(-) diff --git a/arch/blackfin/Kconfig b/arch/blackfin/Kconfig index 0f34ec58bac3f..c4cda6f52b61e 100644 --- a/arch/blackfin/Kconfig +++ b/arch/blackfin/Kconfig @@ -850,7 +850,6 @@ config CPLB_SWITCH_TAB_L1 config ICACHE_FLUSH_L1 bool "Locate icache flush funcs in L1 Inst Memory" default y - depends on !SMP help If enabled, the Blackfin icache flushing functions are linked into L1 instruction memory. diff --git a/arch/blackfin/include/asm/smp.h b/arch/blackfin/include/asm/smp.h index 9dd4873752479..af6c0aa79bae9 100644 --- a/arch/blackfin/include/asm/smp.h +++ b/arch/blackfin/include/asm/smp.h @@ -17,7 +17,12 @@ #define raw_smp_processor_id() blackfin_core_id() -extern char coreb_trampoline_start, coreb_trampoline_end; +extern void bfin_relocate_coreb_l1_mem(void); + +#if defined(CONFIG_SMP) && defined(CONFIG_ICACHE_FLUSH_L1) +asmlinkage void blackfin_icache_flush_range_l1(unsigned long *ptr); +extern unsigned long blackfin_iflush_l1_entry[NR_CPUS]; +#endif struct corelock_slot { int lock; diff --git a/arch/blackfin/kernel/setup.c b/arch/blackfin/kernel/setup.c index ac71dc15cbdb5..805c6132c7796 100644 --- a/arch/blackfin/kernel/setup.c +++ b/arch/blackfin/kernel/setup.c @@ -215,11 +215,48 @@ void __init bfin_relocate_l1_mem(void) early_dma_memcpy_done(); +#if defined(CONFIG_SMP) && defined(CONFIG_ICACHE_FLUSH_L1) + blackfin_iflush_l1_entry[0] = (unsigned long)blackfin_icache_flush_range_l1; +#endif + /* if necessary, copy L2 text/data to L2 SRAM */ if (L2_LENGTH && l2_len) memcpy(_stext_l2, _l2_lma, l2_len); } +#ifdef CONFIG_SMP +void __init bfin_relocate_coreb_l1_mem(void) +{ + unsigned long text_l1_len = (unsigned long)_text_l1_len; + unsigned long data_l1_len = (unsigned long)_data_l1_len; + unsigned long data_b_l1_len = (unsigned long)_data_b_l1_len; + + blackfin_dma_early_init(); + + /* if necessary, copy L1 text to L1 instruction SRAM */ + if (L1_CODE_LENGTH && text_l1_len) + early_dma_memcpy((void *)COREB_L1_CODE_START, _text_l1_lma, + text_l1_len); + + /* if necessary, copy L1 data to L1 data bank A SRAM */ + if (L1_DATA_A_LENGTH && data_l1_len) + early_dma_memcpy((void *)COREB_L1_DATA_A_START, _data_l1_lma, + data_l1_len); + + /* if necessary, copy L1 data B to L1 data bank B SRAM */ + if (L1_DATA_B_LENGTH && data_b_l1_len) + early_dma_memcpy((void *)COREB_L1_DATA_B_START, _data_b_l1_lma, + data_b_l1_len); + + early_dma_memcpy_done(); + +#ifdef CONFIG_ICACHE_FLUSH_L1 + blackfin_iflush_l1_entry[1] = (unsigned long)blackfin_icache_flush_range_l1 - + (unsigned long)_stext_l1 + COREB_L1_CODE_START; +#endif +} +#endif + #ifdef CONFIG_ROMKERNEL void __init bfin_relocate_xip_data(void) { diff --git a/arch/blackfin/kernel/vmlinux.lds.S b/arch/blackfin/kernel/vmlinux.lds.S index f5fd234e57732..854fa49f1c3ec 100644 --- a/arch/blackfin/kernel/vmlinux.lds.S +++ b/arch/blackfin/kernel/vmlinux.lds.S @@ -176,6 +176,7 @@ SECTIONS { . = ALIGN(4); __stext_l1 = .; + *(.l1.text.head) *(.l1.text) #ifdef CONFIG_SCHEDULE_L1 SCHED_TEXT diff --git a/arch/blackfin/mach-bf561/secondary.S b/arch/blackfin/mach-bf561/secondary.S index 148e50764555f..4c462838f4e1f 100644 --- a/arch/blackfin/mach-bf561/secondary.S +++ b/arch/blackfin/mach-bf561/secondary.S @@ -13,7 +13,11 @@ #include #include -__INIT +/* + * This code must come first as CoreB is hardcoded (in hardware) + * to start at the beginning of its L1 instruction memory. + */ +.section .l1.text.head /* Lay the initial stack into the L1 scratch area of Core B */ #define INITIAL_STACK (COREB_L1_SCRATCH_START + L1_SCRATCH_LENGTH - 12) @@ -160,7 +164,6 @@ ENTRY(_coreb_trampoline_start) .LWAIT_HERE: jump .LWAIT_HERE; ENDPROC(_coreb_trampoline_start) -ENTRY(_coreb_trampoline_end) #ifdef CONFIG_HOTPLUG_CPU .section ".text" diff --git a/arch/blackfin/mach-bf561/smp.c b/arch/blackfin/mach-bf561/smp.c index 1074a7ef81c7e..82b94e1378860 100644 --- a/arch/blackfin/mach-bf561/smp.c +++ b/arch/blackfin/mach-bf561/smp.c @@ -30,18 +30,11 @@ void __init platform_init_cpus(void) void __init platform_prepare_cpus(unsigned int max_cpus) { - int len; - - len = &coreb_trampoline_end - &coreb_trampoline_start + 1; - BUG_ON(len > L1_CODE_LENGTH); - - dma_memcpy((void *)COREB_L1_CODE_START, &coreb_trampoline_start, len); + bfin_relocate_coreb_l1_mem(); /* Both cores ought to be present on a bf561! */ cpu_set(0, cpu_present_map); /* CoreA */ cpu_set(1, cpu_present_map); /* CoreB */ - - printk(KERN_INFO "CoreB bootstrap code to SRAM %p via DMA.\n", (void *)COREB_L1_CODE_START); } int __init setup_profiling_timer(unsigned int multiplier) /* not supported */ diff --git a/arch/blackfin/mach-common/cache.S b/arch/blackfin/mach-common/cache.S index 85aadeb766585..9f4dd35bfd743 100644 --- a/arch/blackfin/mach-common/cache.S +++ b/arch/blackfin/mach-common/cache.S @@ -69,10 +69,30 @@ #endif /* Invalidate all instruction cache lines assocoiated with this memory area */ +#ifdef CONFIG_SMP +# define _blackfin_icache_flush_range _blackfin_icache_flush_range_l1 +#endif ENTRY(_blackfin_icache_flush_range) do_flush IFLUSH ENDPROC(_blackfin_icache_flush_range) +#ifdef CONFIG_SMP +.text +# undef _blackfin_icache_flush_range +ENTRY(_blackfin_icache_flush_range) + p0.L = LO(DSPID); + p0.H = HI(DSPID); + r3 = [p0]; + r3 = r3.b (z); + p2 = r3; + p0.L = _blackfin_iflush_l1_entry; + p0.H = _blackfin_iflush_l1_entry; + p0 = p0 + (p2 << 2); + p1 = [p0]; + jump (p1); +ENDPROC(_blackfin_icache_flush_range) +#endif + #ifdef CONFIG_DCACHE_FLUSH_L1 .section .l1.text #else diff --git a/arch/blackfin/mach-common/smp.c b/arch/blackfin/mach-common/smp.c index 5f7617d669055..6e17a265c4d31 100644 --- a/arch/blackfin/mach-common/smp.c +++ b/arch/blackfin/mach-common/smp.c @@ -40,6 +40,10 @@ */ struct corelock_slot corelock __attribute__ ((__section__(".l2.bss"))); +#ifdef CONFIG_ICACHE_FLUSH_L1 +unsigned long blackfin_iflush_l1_entry[NR_CPUS]; +#endif + void __cpuinitdata *init_retx_coreb, *init_saved_retx_coreb, *init_saved_seqstat_coreb, *init_saved_icplb_fault_addr_coreb, *init_saved_dcplb_fault_addr_coreb; -- GitLab From 511cdcc50031eacd88cc70351da54beebff515e2 Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Thu, 3 Feb 2011 02:16:44 +0000 Subject: [PATCH 0857/2822] Blackfin: optimize startup code Take advantage of more Blackfin-specific insns, and only initialize registers required by the ABI. Signed-off-by: Mike Frysinger --- arch/blackfin/mach-common/head.S | 110 ++++++++++++------------------- 1 file changed, 41 insertions(+), 69 deletions(-) diff --git a/arch/blackfin/mach-common/head.S b/arch/blackfin/mach-common/head.S index 4391621d90488..581e2b0a71ace 100644 --- a/arch/blackfin/mach-common/head.S +++ b/arch/blackfin/mach-common/head.S @@ -31,6 +31,7 @@ ENDPROC(__init_clear_bss) ENTRY(__start) /* R0: argument of command line string, passed from uboot, save it */ R7 = R0; + /* Enable Cycle Counter and Nesting Of Interrupts */ #ifdef CONFIG_BFIN_SCRATCH_REG_CYCLES R0 = SYSCFG_SNEN; @@ -38,76 +39,49 @@ ENTRY(__start) R0 = SYSCFG_SNEN | SYSCFG_CCEN; #endif SYSCFG = R0; - R0 = 0; - - /* Clear Out All the data and pointer Registers */ - R1 = R0; - R2 = R0; - R3 = R0; - R4 = R0; - R5 = R0; - R6 = R0; - - P0 = R0; - P1 = R0; - P2 = R0; - P3 = R0; - P4 = R0; - P5 = R0; - - LC0 = r0; - LC1 = r0; - L0 = r0; - L1 = r0; - L2 = r0; - L3 = r0; - - /* Clear Out All the DAG Registers */ - B0 = r0; - B1 = r0; - B2 = r0; - B3 = r0; - - I0 = r0; - I1 = r0; - I2 = r0; - I3 = r0; - - M0 = r0; - M1 = r0; - M2 = r0; - M3 = r0; + + /* Optimization register tricks: keep a base value in the + * reserved P registers so we use the load/store with an + * offset syntax. R0 = [P5 + ]; + * P5 - core MMR base + * R6 - 0 + */ + r6 = 0; + p5.l = 0; + p5.h = hi(COREMMR_BASE); + + /* Zero out registers required by Blackfin ABI */ + + /* Disable circular buffers */ + L0 = r6; + L1 = r6; + L2 = r6; + L3 = r6; + + /* Disable hardware loops in case we were started by 'go' */ + LC0 = r6; + LC1 = r6; /* * Clear ITEST_COMMAND and DTEST_COMMAND registers, * Leaving these as non-zero can confuse the emulator */ - p0.L = LO(DTEST_COMMAND); - p0.H = HI(DTEST_COMMAND); - [p0] = R0; - [p0 + (ITEST_COMMAND - DTEST_COMMAND)] = R0; + [p5 + (DTEST_COMMAND - COREMMR_BASE)] = r6; + [p5 + (ITEST_COMMAND - COREMMR_BASE)] = r6; CSYNC; trace_buffer_init(p0,r0); - P0 = R1; - R0 = R1; /* Turn off the icache */ - p0.l = LO(IMEM_CONTROL); - p0.h = HI(IMEM_CONTROL); - R1 = [p0]; - R0 = ~ENICPLB; - R0 = R0 & R1; - [p0] = R0; + r1 = [p5 + (IMEM_CONTROL - COREMMR_BASE)]; + BITCLR (r1, ENICPLB_P); + [p5 + (IMEM_CONTROL - COREMMR_BASE)] = r1; SSYNC; /* Turn off the dcache */ - p0.l = LO(DMEM_CONTROL); - p0.h = HI(DMEM_CONTROL); - R1 = [p0]; - R0 = ~ENDCPLB; - R0 = R0 & R1; - [p0] = R0; + r1 = [p5 + (DMEM_CONTROL - COREMMR_BASE)]; + BITCLR (r1, ENDCPLB_P); + [p5 + (DMEM_CONTROL - COREMMR_BASE)] = r1; SSYNC; /* in case of double faults, save a few things */ @@ -122,25 +96,25 @@ ENTRY(__start) * below */ GET_PDA(p0, r0); - r6 = [p0 + PDA_DF_RETX]; + r5 = [p0 + PDA_DF_RETX]; p1.l = _init_saved_retx; p1.h = _init_saved_retx; - [p1] = r6; + [p1] = r5; - r6 = [p0 + PDA_DF_DCPLB]; + r5 = [p0 + PDA_DF_DCPLB]; p1.l = _init_saved_dcplb_fault_addr; p1.h = _init_saved_dcplb_fault_addr; - [p1] = r6; + [p1] = r5; - r6 = [p0 + PDA_DF_ICPLB]; + r5 = [p0 + PDA_DF_ICPLB]; p1.l = _init_saved_icplb_fault_addr; p1.h = _init_saved_icplb_fault_addr; - [p1] = r6; + [p1] = r5; - r6 = [p0 + PDA_DF_SEQSTAT]; + r5 = [p0 + PDA_DF_SEQSTAT]; p1.l = _init_saved_seqstat; p1.h = _init_saved_seqstat; - [p1] = r6; + [p1] = r5; #endif /* Initialize stack pointer */ @@ -155,7 +129,7 @@ ENTRY(__start) sti r0; #endif - r0 = 0 (x); + r0 = r6; /* Zero out all of the fun bss regions */ #if L1_DATA_A_LENGTH > 0 r1.l = __sbss_l1; @@ -210,11 +184,9 @@ ENTRY(__start) /* EVT15 = _real_start */ - p0.l = lo(EVT15); - p0.h = hi(EVT15); p1.l = _real_start; p1.h = _real_start; - [p0] = p1; + [p5 + (EVT15 - COREMMR_BASE)] = p1; csync; #ifdef CONFIG_EARLY_PRINTK -- GitLab From b10bbbbce77ed45a3f5cb7e2bd1d3d5dbee20666 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Sun, 6 Feb 2011 18:23:25 +0000 Subject: [PATCH 0858/2822] Blackfin: use proper wrappers for irq_desc Fixup the open coded access to irq_desc and use the proper wrappers. Signed-off-by: Thomas Gleixner Signed-off-by: Mike Frysinger --- arch/blackfin/mach-common/ints-priority.c | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/arch/blackfin/mach-common/ints-priority.c b/arch/blackfin/mach-common/ints-priority.c index a604f19d8dc31..6e7db990bfae2 100644 --- a/arch/blackfin/mach-common/ints-priority.c +++ b/arch/blackfin/mach-common/ints-priority.c @@ -312,8 +312,7 @@ static void bfin_handle_irq(unsigned irq) __ipipe_handle_irq(irq, ®s); ipipe_trace_irq_exit(irq); #else /* !CONFIG_IPIPE */ - struct irq_desc *desc = irq_desc + irq; - desc->handle_irq(irq, desc); + generic_handle_irq(irq); #endif /* !CONFIG_IPIPE */ } @@ -540,10 +539,7 @@ static inline void bfin_set_irq_handler(unsigned irq, irq_flow_handler_t handle) #ifdef CONFIG_IPIPE _set_irq_handler(irq, handle_level_irq); #else - struct irq_desc *desc = irq_desc + irq; - /* May not call generic set_irq_handler() due to spinlock - recursion. */ - desc->handle_irq = handle; + __set_irq_handler_unlocked(irq, handle); #endif } @@ -562,7 +558,7 @@ static void bfin_gpio_ack_irq(unsigned int irq) static void bfin_gpio_mask_ack_irq(unsigned int irq) { - struct irq_desc *desc = irq_desc + irq; + struct irq_desc *desc = irq_to_desc(irq); u32 gpionr = irq_to_gpio(irq); if (desc->handle_irq == handle_edge_irq) @@ -820,7 +816,7 @@ void init_pint_lut(void) static void bfin_gpio_ack_irq(unsigned int irq) { - struct irq_desc *desc = irq_desc + irq; + struct irq_desc *desc = irq_to_desc(irq); u32 pint_val = irq2pint_lut[irq - SYS_IRQS]; u32 pintbit = PINT_BIT(pint_val); u32 bank = PINT_2_BANK(pint_val); @@ -837,7 +833,7 @@ static void bfin_gpio_ack_irq(unsigned int irq) static void bfin_gpio_mask_ack_irq(unsigned int irq) { - struct irq_desc *desc = irq_desc + irq; + struct irq_desc *desc = irq_to_desc(irq); u32 pint_val = irq2pint_lut[irq - SYS_IRQS]; u32 pintbit = PINT_BIT(pint_val); u32 bank = PINT_2_BANK(pint_val); -- GitLab From 4f19ea4978cd0803e7a70558f9f3a2f5d7c51640 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Sun, 6 Feb 2011 18:23:27 +0000 Subject: [PATCH 0859/2822] Blackfin: convert core irq_chip to new functions Signed-off-by: Thomas Gleixner Signed-off-by: Mike Frysinger --- arch/blackfin/mach-common/ints-priority.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/arch/blackfin/mach-common/ints-priority.c b/arch/blackfin/mach-common/ints-priority.c index 6e7db990bfae2..c00915156f0c5 100644 --- a/arch/blackfin/mach-common/ints-priority.c +++ b/arch/blackfin/mach-common/ints-priority.c @@ -124,21 +124,21 @@ static void __init search_IAR(void) * This is for core internal IRQs */ -static void bfin_ack_noop(unsigned int irq) +static void bfin_ack_noop(struct irq_data *d) { /* Dummy function. */ } -static void bfin_core_mask_irq(unsigned int irq) +static void bfin_core_mask_irq(struct irq_data *d) { - bfin_irq_flags &= ~(1 << irq); + bfin_irq_flags &= ~(1 << d->irq); if (!hard_irqs_disabled()) hard_local_irq_enable(); } -static void bfin_core_unmask_irq(unsigned int irq) +static void bfin_core_unmask_irq(struct irq_data *d) { - bfin_irq_flags |= 1 << irq; + bfin_irq_flags |= 1 << d->irq; /* * If interrupts are enabled, IMASK must contain the same value * as bfin_irq_flags. Make sure that invariant holds. If interrupts @@ -283,14 +283,14 @@ int bfin_internal_set_wake(unsigned int irq, unsigned int state) static struct irq_chip bfin_core_irqchip = { .name = "CORE", - .ack = bfin_ack_noop, - .mask = bfin_core_mask_irq, - .unmask = bfin_core_unmask_irq, + .irq_ack = bfin_ack_noop, + .irq_mask = bfin_core_mask_irq, + .irq_unmask = bfin_core_unmask_irq, }; static struct irq_chip bfin_internal_irqchip = { .name = "INTN", - .ack = bfin_ack_noop, + .irq_ack = bfin_ack_noop, .mask = bfin_internal_mask_irq, .unmask = bfin_internal_unmask_irq, .mask_ack = bfin_internal_mask_irq, @@ -334,7 +334,7 @@ static void bfin_generic_error_unmask_irq(unsigned int irq) static struct irq_chip bfin_generic_error_irqchip = { .name = "ERROR", - .ack = bfin_ack_noop, + .irq_ack = bfin_ack_noop, .mask_ack = bfin_generic_error_mask_irq, .mask = bfin_generic_error_mask_irq, .unmask = bfin_generic_error_unmask_irq, @@ -495,7 +495,7 @@ int bfin_mac_status_set_wake(unsigned int irq, unsigned int state) static struct irq_chip bfin_mac_status_irqchip = { .name = "MACST", - .ack = bfin_ack_noop, + .irq_ack = bfin_ack_noop, .mask_ack = bfin_mac_status_mask_irq, .mask = bfin_mac_status_mask_irq, .unmask = bfin_mac_status_unmask_irq, -- GitLab From ff43a67f67b47fc7e4e108ab1966072dc36b65c0 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Sun, 6 Feb 2011 18:23:29 +0000 Subject: [PATCH 0860/2822] Blackfin: convert internal irq_chip to new functions Signed-off-by: Thomas Gleixner Signed-off-by: Mike Frysinger --- arch/blackfin/mach-common/ints-priority.c | 41 ++++++++++++++++------- 1 file changed, 28 insertions(+), 13 deletions(-) diff --git a/arch/blackfin/mach-common/ints-priority.c b/arch/blackfin/mach-common/ints-priority.c index c00915156f0c5..a233c3ec88248 100644 --- a/arch/blackfin/mach-common/ints-priority.c +++ b/arch/blackfin/mach-common/ints-priority.c @@ -176,6 +176,11 @@ static void bfin_internal_mask_irq(unsigned int irq) hard_local_irq_restore(flags); } +static void bfin_internal_mask_irq_chip(struct irq_data *d) +{ + bfin_internal_mask_irq(d->irq); +} + #ifdef CONFIG_SMP static void bfin_internal_unmask_irq_affinity(unsigned int irq, const struct cpumask *affinity) @@ -211,19 +216,24 @@ static void bfin_internal_unmask_irq(unsigned int irq) } #ifdef CONFIG_SMP -static void bfin_internal_unmask_irq(unsigned int irq) +static void bfin_internal_unmask_irq_chip(struct irq_data *d) { - struct irq_desc *desc = irq_to_desc(irq); - bfin_internal_unmask_irq_affinity(irq, desc->affinity); + bfin_internal_unmask_irq_affinity(d->irq, d->affinity); } -static int bfin_internal_set_affinity(unsigned int irq, const struct cpumask *mask) +static int bfin_internal_set_affinity(struct irq_data *d, + const struct cpumask *mask, bool force) { - bfin_internal_mask_irq(irq); - bfin_internal_unmask_irq_affinity(irq, mask); + bfin_internal_mask_irq(d->irq); + bfin_internal_unmask_irq_affinity(d->irq, mask); return 0; } +#else +static void bfin_internal_unmask_irq_chip(struct irq_data *d) +{ + bfin_internal_unmask_irq(d->irq); +} #endif #ifdef CONFIG_PM @@ -279,6 +289,11 @@ int bfin_internal_set_wake(unsigned int irq, unsigned int state) return 0; } + +static int bfin_internal_set_wake_chip(struct irq_data *d, unsigned int state) +{ + return bfin_internal_set_wake(d->irq, state); +} #endif static struct irq_chip bfin_core_irqchip = { @@ -291,16 +306,16 @@ static struct irq_chip bfin_core_irqchip = { static struct irq_chip bfin_internal_irqchip = { .name = "INTN", .irq_ack = bfin_ack_noop, - .mask = bfin_internal_mask_irq, - .unmask = bfin_internal_unmask_irq, - .mask_ack = bfin_internal_mask_irq, - .disable = bfin_internal_mask_irq, - .enable = bfin_internal_unmask_irq, + .irq_mask = bfin_internal_mask_irq_chip, + .irq_unmask = bfin_internal_unmask_irq_chip, + .irq_mask_ack = bfin_internal_mask_irq_chip, + .irq_disable = bfin_internal_mask_irq_chip, + .irq_enable = bfin_internal_unmask_irq_chip, #ifdef CONFIG_SMP - .set_affinity = bfin_internal_set_affinity, + .irq_set_affinity = bfin_internal_set_affinity, #endif #ifdef CONFIG_PM - .set_wake = bfin_internal_set_wake, + .irq_set_wake = bfin_internal_set_wake_chip, #endif }; -- GitLab From dabf64bcc58cc182f389a9ca602f2c5cb9ba8aef Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Sun, 6 Feb 2011 18:23:31 +0000 Subject: [PATCH 0861/2822] Blackfin: convert error irq_chip to new functions Signed-off-by: Thomas Gleixner Signed-off-by: Mike Frysinger --- arch/blackfin/mach-common/ints-priority.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/arch/blackfin/mach-common/ints-priority.c b/arch/blackfin/mach-common/ints-priority.c index a233c3ec88248..79ee08d898151 100644 --- a/arch/blackfin/mach-common/ints-priority.c +++ b/arch/blackfin/mach-common/ints-priority.c @@ -334,25 +334,25 @@ static void bfin_handle_irq(unsigned irq) #ifdef BF537_GENERIC_ERROR_INT_DEMUX static int error_int_mask; -static void bfin_generic_error_mask_irq(unsigned int irq) +static void bfin_generic_error_mask_irq(struct irq_data *d) { - error_int_mask &= ~(1L << (irq - IRQ_PPI_ERROR)); + error_int_mask &= ~(1L << (d->irq - IRQ_PPI_ERROR)); if (!error_int_mask) bfin_internal_mask_irq(IRQ_GENERIC_ERROR); } -static void bfin_generic_error_unmask_irq(unsigned int irq) +static void bfin_generic_error_unmask_irq(struct irq_data *d) { bfin_internal_unmask_irq(IRQ_GENERIC_ERROR); - error_int_mask |= 1L << (irq - IRQ_PPI_ERROR); + error_int_mask |= 1L << (d->irq - IRQ_PPI_ERROR); } static struct irq_chip bfin_generic_error_irqchip = { .name = "ERROR", .irq_ack = bfin_ack_noop, - .mask_ack = bfin_generic_error_mask_irq, - .mask = bfin_generic_error_mask_irq, - .unmask = bfin_generic_error_unmask_irq, + .irq_mask_ack = bfin_generic_error_mask_irq, + .irq_mask = bfin_generic_error_mask_irq, + .irq_unmask = bfin_generic_error_unmask_irq, }; static void bfin_demux_error_irq(unsigned int int_err_irq, -- GitLab From 172d2d1d8414f6d8d4ae97557e102463b064aff0 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Sun, 6 Feb 2011 18:23:34 +0000 Subject: [PATCH 0862/2822] Blackfin: convert mac irq_chip to new functions Signed-off-by: Thomas Gleixner Signed-off-by: Mike Frysinger --- arch/blackfin/mach-common/ints-priority.c | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/arch/blackfin/mach-common/ints-priority.c b/arch/blackfin/mach-common/ints-priority.c index 79ee08d898151..2d9720ca916c2 100644 --- a/arch/blackfin/mach-common/ints-priority.c +++ b/arch/blackfin/mach-common/ints-priority.c @@ -462,8 +462,10 @@ static void bfin_mac_status_ack_irq(unsigned int irq) } } -static void bfin_mac_status_mask_irq(unsigned int irq) +static void bfin_mac_status_mask_irq(struct irq_data *d) { + unsigned int irq = d->irq; + mac_stat_int_mask &= ~(1L << (irq - IRQ_MAC_PHYINT)); #ifdef BF537_GENERIC_ERROR_INT_DEMUX switch (irq) { @@ -480,8 +482,10 @@ static void bfin_mac_status_mask_irq(unsigned int irq) bfin_mac_status_ack_irq(irq); } -static void bfin_mac_status_unmask_irq(unsigned int irq) +static void bfin_mac_status_unmask_irq(struct irq_data *d) { + unsigned int irq = d->irq; + #ifdef BF537_GENERIC_ERROR_INT_DEMUX switch (irq) { case IRQ_MAC_PHYINT: @@ -498,7 +502,7 @@ static void bfin_mac_status_unmask_irq(unsigned int irq) } #ifdef CONFIG_PM -int bfin_mac_status_set_wake(unsigned int irq, unsigned int state) +int bfin_mac_status_set_wake(struct irq_data *d, unsigned int state) { #ifdef BF537_GENERIC_ERROR_INT_DEMUX return bfin_internal_set_wake(IRQ_GENERIC_ERROR, state); @@ -511,11 +515,11 @@ int bfin_mac_status_set_wake(unsigned int irq, unsigned int state) static struct irq_chip bfin_mac_status_irqchip = { .name = "MACST", .irq_ack = bfin_ack_noop, - .mask_ack = bfin_mac_status_mask_irq, - .mask = bfin_mac_status_mask_irq, - .unmask = bfin_mac_status_unmask_irq, + .irq_mask_ack = bfin_mac_status_mask_irq, + .irq_mask = bfin_mac_status_mask_irq, + .irq_unmask = bfin_mac_status_unmask_irq, #ifdef CONFIG_PM - .set_wake = bfin_mac_status_set_wake, + .irq_set_wake = bfin_mac_status_set_wake, #endif }; -- GitLab From e9502850b9a861f4e6adc379e35bba019bfa987f Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Sun, 6 Feb 2011 18:23:36 +0000 Subject: [PATCH 0863/2822] Blackfin: convert gpio irq_chip to new functions Signed-off-by: Thomas Gleixner Signed-off-by: Mike Frysinger --- arch/blackfin/mach-common/ints-priority.c | 92 ++++++++++++----------- 1 file changed, 48 insertions(+), 44 deletions(-) diff --git a/arch/blackfin/mach-common/ints-priority.c b/arch/blackfin/mach-common/ints-priority.c index 2d9720ca916c2..8e9d3cc308850 100644 --- a/arch/blackfin/mach-common/ints-priority.c +++ b/arch/blackfin/mach-common/ints-priority.c @@ -567,16 +567,17 @@ extern void bfin_gpio_irq_prepare(unsigned gpio); #if !defined(CONFIG_BF54x) -static void bfin_gpio_ack_irq(unsigned int irq) +static void bfin_gpio_ack_irq(struct irq_data *d) { /* AFAIK ack_irq in case mask_ack is provided * get's only called for edge sense irqs */ - set_gpio_data(irq_to_gpio(irq), 0); + set_gpio_data(irq_to_gpio(d->irq), 0); } -static void bfin_gpio_mask_ack_irq(unsigned int irq) +static void bfin_gpio_mask_ack_irq(struct irq_data *d) { + unsigned int irq = d->irq; struct irq_desc *desc = irq_to_desc(irq); u32 gpionr = irq_to_gpio(irq); @@ -586,39 +587,40 @@ static void bfin_gpio_mask_ack_irq(unsigned int irq) set_gpio_maska(gpionr, 0); } -static void bfin_gpio_mask_irq(unsigned int irq) +static void bfin_gpio_mask_irq(struct irq_data *d) { - set_gpio_maska(irq_to_gpio(irq), 0); + set_gpio_maska(irq_to_gpio(d->irq), 0); } -static void bfin_gpio_unmask_irq(unsigned int irq) +static void bfin_gpio_unmask_irq(struct irq_data *d) { - set_gpio_maska(irq_to_gpio(irq), 1); + set_gpio_maska(irq_to_gpio(d->irq), 1); } -static unsigned int bfin_gpio_irq_startup(unsigned int irq) +static unsigned int bfin_gpio_irq_startup(struct irq_data *d) { - u32 gpionr = irq_to_gpio(irq); + u32 gpionr = irq_to_gpio(d->irq); if (__test_and_set_bit(gpionr, gpio_enabled)) bfin_gpio_irq_prepare(gpionr); - bfin_gpio_unmask_irq(irq); + bfin_gpio_unmask_irq(d); return 0; } -static void bfin_gpio_irq_shutdown(unsigned int irq) +static void bfin_gpio_irq_shutdown(struct irq_data *d) { - u32 gpionr = irq_to_gpio(irq); + u32 gpionr = irq_to_gpio(d->irq); - bfin_gpio_mask_irq(irq); + bfin_gpio_mask_irq(d); __clear_bit(gpionr, gpio_enabled); bfin_gpio_irq_free(gpionr); } -static int bfin_gpio_irq_type(unsigned int irq, unsigned int type) +static int bfin_gpio_irq_type(struct irq_data *d, unsigned int type) { + unsigned int irq = d->irq; int ret; char buf[16]; u32 gpionr = irq_to_gpio(irq); @@ -679,9 +681,9 @@ static int bfin_gpio_irq_type(unsigned int irq, unsigned int type) } #ifdef CONFIG_PM -int bfin_gpio_set_wake(unsigned int irq, unsigned int state) +int bfin_gpio_set_wake(struct irq_data *d, unsigned int state) { - return gpio_pm_wakeup_ctrl(irq_to_gpio(irq), state); + return gpio_pm_wakeup_ctrl(irq_to_gpio(d->irq), state); } #endif @@ -833,10 +835,10 @@ void init_pint_lut(void) } } -static void bfin_gpio_ack_irq(unsigned int irq) +static void bfin_gpio_ack_irq(struct irq_data *d) { - struct irq_desc *desc = irq_to_desc(irq); - u32 pint_val = irq2pint_lut[irq - SYS_IRQS]; + struct irq_desc *desc = irq_to_desc(d->irq); + u32 pint_val = irq2pint_lut[d->irq - SYS_IRQS]; u32 pintbit = PINT_BIT(pint_val); u32 bank = PINT_2_BANK(pint_val); @@ -850,10 +852,10 @@ static void bfin_gpio_ack_irq(unsigned int irq) } -static void bfin_gpio_mask_ack_irq(unsigned int irq) +static void bfin_gpio_mask_ack_irq(struct irq_data *d) { - struct irq_desc *desc = irq_to_desc(irq); - u32 pint_val = irq2pint_lut[irq - SYS_IRQS]; + struct irq_desc *desc = irq_to_desc(d->irq); + u32 pint_val = irq2pint_lut[d->irq - SYS_IRQS]; u32 pintbit = PINT_BIT(pint_val); u32 bank = PINT_2_BANK(pint_val); @@ -868,24 +870,25 @@ static void bfin_gpio_mask_ack_irq(unsigned int irq) pint[bank]->mask_clear = pintbit; } -static void bfin_gpio_mask_irq(unsigned int irq) +static void bfin_gpio_mask_irq(struct irq_data *d) { - u32 pint_val = irq2pint_lut[irq - SYS_IRQS]; + u32 pint_val = irq2pint_lut[d->irq - SYS_IRQS]; pint[PINT_2_BANK(pint_val)]->mask_clear = PINT_BIT(pint_val); } -static void bfin_gpio_unmask_irq(unsigned int irq) +static void bfin_gpio_unmask_irq(struct irq_data *d) { - u32 pint_val = irq2pint_lut[irq - SYS_IRQS]; + u32 pint_val = irq2pint_lut[d->irq - SYS_IRQS]; u32 pintbit = PINT_BIT(pint_val); u32 bank = PINT_2_BANK(pint_val); pint[bank]->mask_set = pintbit; } -static unsigned int bfin_gpio_irq_startup(unsigned int irq) +static unsigned int bfin_gpio_irq_startup(struct irq_data *d) { + unsigned int irq = d->irq; u32 gpionr = irq_to_gpio(irq); u32 pint_val = irq2pint_lut[irq - SYS_IRQS]; @@ -899,22 +902,23 @@ static unsigned int bfin_gpio_irq_startup(unsigned int irq) if (__test_and_set_bit(gpionr, gpio_enabled)) bfin_gpio_irq_prepare(gpionr); - bfin_gpio_unmask_irq(irq); + bfin_gpio_unmask_irq(d); return 0; } -static void bfin_gpio_irq_shutdown(unsigned int irq) +static void bfin_gpio_irq_shutdown(struct irq_data *d) { - u32 gpionr = irq_to_gpio(irq); + u32 gpionr = irq_to_gpio(d->irq); - bfin_gpio_mask_irq(irq); + bfin_gpio_mask_irq(d); __clear_bit(gpionr, gpio_enabled); bfin_gpio_irq_free(gpionr); } -static int bfin_gpio_irq_type(unsigned int irq, unsigned int type) +static int bfin_gpio_irq_type(struct irq_data *d, unsigned int type) { + unsigned int irq = d->irq; int ret; char buf[16]; u32 gpionr = irq_to_gpio(irq); @@ -976,10 +980,10 @@ static int bfin_gpio_irq_type(unsigned int irq, unsigned int type) u32 pint_saved_masks[NR_PINT_SYS_IRQS]; u32 pint_wakeup_masks[NR_PINT_SYS_IRQS]; -int bfin_gpio_set_wake(unsigned int irq, unsigned int state) +int bfin_gpio_set_wake(struct irq_data *d, unsigned int state) { u32 pint_irq; - u32 pint_val = irq2pint_lut[irq - SYS_IRQS]; + u32 pint_val = irq2pint_lut[d->irq - SYS_IRQS]; u32 bank = PINT_2_BANK(pint_val); u32 pintbit = PINT_BIT(pint_val); @@ -1081,17 +1085,17 @@ static void bfin_demux_gpio_irq(unsigned int inta_irq, static struct irq_chip bfin_gpio_irqchip = { .name = "GPIO", - .ack = bfin_gpio_ack_irq, - .mask = bfin_gpio_mask_irq, - .mask_ack = bfin_gpio_mask_ack_irq, - .unmask = bfin_gpio_unmask_irq, - .disable = bfin_gpio_mask_irq, - .enable = bfin_gpio_unmask_irq, - .set_type = bfin_gpio_irq_type, - .startup = bfin_gpio_irq_startup, - .shutdown = bfin_gpio_irq_shutdown, + .irq_ack = bfin_gpio_ack_irq, + .irq_mask = bfin_gpio_mask_irq, + .irq_mask_ack = bfin_gpio_mask_ack_irq, + .irq_unmask = bfin_gpio_unmask_irq, + .irq_disable = bfin_gpio_mask_irq, + .irq_enable = bfin_gpio_unmask_irq, + .irq_set_type = bfin_gpio_irq_type, + .irq_startup = bfin_gpio_irq_startup, + .irq_shutdown = bfin_gpio_irq_shutdown, #ifdef CONFIG_PM - .set_wake = bfin_gpio_set_wake, + .irq_set_wake = bfin_gpio_set_wake, #endif }; -- GitLab From bc2f6bd8027a88da69102a8aed65dcbd1e895119 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Sun, 6 Feb 2011 18:23:38 +0000 Subject: [PATCH 0864/2822] Blackfin: use proper wrapper functions for modifying irq status Signed-off-by: Thomas Gleixner Signed-off-by: Mike Frysinger --- arch/blackfin/mach-bf537/boards/cm_bf537e.c | 2 +- arch/blackfin/mach-bf537/boards/cm_bf537u.c | 2 +- arch/blackfin/mach-bf537/boards/tcm_bf537.c | 2 +- arch/blackfin/mach-bf561/boards/cm_bf561.c | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/blackfin/mach-bf537/boards/cm_bf537e.c b/arch/blackfin/mach-bf537/boards/cm_bf537e.c index 2c776e188a944..d582b810e7a74 100644 --- a/arch/blackfin/mach-bf537/boards/cm_bf537e.c +++ b/arch/blackfin/mach-bf537/boards/cm_bf537e.c @@ -775,7 +775,7 @@ static int __init cm_bf537e_init(void) #endif #if defined(CONFIG_PATA_PLATFORM) || defined(CONFIG_PATA_PLATFORM_MODULE) - irq_desc[PATA_INT].status |= IRQ_NOAUTOEN; + irq_set_status_flags(PATA_INT, IRQ_NOAUTOEN); #endif return 0; } diff --git a/arch/blackfin/mach-bf537/boards/cm_bf537u.c b/arch/blackfin/mach-bf537/boards/cm_bf537u.c index 085661175ec7b..cbb8098604c56 100644 --- a/arch/blackfin/mach-bf537/boards/cm_bf537u.c +++ b/arch/blackfin/mach-bf537/boards/cm_bf537u.c @@ -740,7 +740,7 @@ static int __init cm_bf537u_init(void) #endif #if defined(CONFIG_PATA_PLATFORM) || defined(CONFIG_PATA_PLATFORM_MODULE) - irq_desc[PATA_INT].status |= IRQ_NOAUTOEN; + irq_set_status_flags(PATA_INT, IRQ_NOAUTOEN); #endif return 0; } diff --git a/arch/blackfin/mach-bf537/boards/tcm_bf537.c b/arch/blackfin/mach-bf537/boards/tcm_bf537.c index 0761b201abcab..164a7e02c022c 100644 --- a/arch/blackfin/mach-bf537/boards/tcm_bf537.c +++ b/arch/blackfin/mach-bf537/boards/tcm_bf537.c @@ -742,7 +742,7 @@ static int __init tcm_bf537_init(void) #endif #if defined(CONFIG_PATA_PLATFORM) || defined(CONFIG_PATA_PLATFORM_MODULE) - irq_desc[PATA_INT].status |= IRQ_NOAUTOEN; + irq_set_status_flags(PATA_INT, IRQ_NOAUTOEN); #endif return 0; } diff --git a/arch/blackfin/mach-bf561/boards/cm_bf561.c b/arch/blackfin/mach-bf561/boards/cm_bf561.c index 3b67929d4c0a5..87595cd38afe1 100644 --- a/arch/blackfin/mach-bf561/boards/cm_bf561.c +++ b/arch/blackfin/mach-bf561/boards/cm_bf561.c @@ -541,7 +541,7 @@ static int __init cm_bf561_init(void) #endif #if defined(CONFIG_PATA_PLATFORM) || defined(CONFIG_PATA_PLATFORM_MODULE) - irq_desc[PATA_INT].status |= IRQ_NOAUTOEN; + irq_set_status_flags(PATA_INT, IRQ_NOAUTOEN); #endif return 0; } -- GitLab From 9f51a874ced2106947e391d85abdf1f22c94f018 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Mon, 7 Feb 2011 12:01:59 +0100 Subject: [PATCH 0865/2822] Blackfin: use accessor functions in show_interrupts() Signed-off-by: Thomas Gleixner Signed-off-by: Mike Frysinger --- arch/blackfin/kernel/irqchip.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/arch/blackfin/kernel/irqchip.c b/arch/blackfin/kernel/irqchip.c index 64cff54a8a58c..8f079392aff07 100644 --- a/arch/blackfin/kernel/irqchip.c +++ b/arch/blackfin/kernel/irqchip.c @@ -39,21 +39,23 @@ int show_interrupts(struct seq_file *p, void *v) unsigned long flags; if (i < NR_IRQS) { - raw_spin_lock_irqsave(&irq_desc[i].lock, flags); - action = irq_desc[i].action; + struct irq_desc *desc = irq_to_desc(i); + + raw_spin_lock_irqsave(&desc->lock, flags); + action = desc->action; if (!action) goto skip; seq_printf(p, "%3d: ", i); for_each_online_cpu(j) seq_printf(p, "%10u ", kstat_irqs_cpu(i, j)); - seq_printf(p, " %8s", irq_desc[i].chip->name); + seq_printf(p, " %8s", get_irq_desc_chip(desc)->name); seq_printf(p, " %s", action->name); for (action = action->next; action; action = action->next) seq_printf(p, " %s", action->name); seq_putc(p, '\n'); skip: - raw_spin_unlock_irqrestore(&irq_desc[i].lock, flags); + raw_spin_unlock_irqrestore(&desc->lock, flags); } else if (i == NR_IRQS) { seq_printf(p, "NMI: "); for_each_online_cpu(j) -- GitLab From 91796c235dcefefde38732e1a969afc5c3d63ae6 Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Fri, 18 Mar 2011 03:03:23 -0400 Subject: [PATCH 0866/2822] Blackfin: SMP: convert to irq chip functions Signed-off-by: Mike Frysinger --- arch/blackfin/mach-bf561/smp.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/arch/blackfin/mach-bf561/smp.c b/arch/blackfin/mach-bf561/smp.c index 82b94e1378860..5d68bf613b0b9 100644 --- a/arch/blackfin/mach-bf561/smp.c +++ b/arch/blackfin/mach-bf561/smp.c @@ -154,9 +154,13 @@ void platform_clear_ipi(unsigned int cpu, int irq) void __cpuinit bfin_local_timer_setup(void) { #if defined(CONFIG_TICKSOURCE_CORETMR) + struct irq_chip *chip = get_irq_chip(IRQ_CORETMR); + struct irq_desc *desc = irq_to_desc(IRQ_CORETMR); + bfin_coretmr_init(); bfin_coretmr_clockevent_init(); - get_irq_chip(IRQ_CORETMR)->unmask(IRQ_CORETMR); + + chip->irq_unmask(&desc->irq_data); #else /* Power down the core timer, just to play safe. */ bfin_write_TCNTL(0); -- GitLab From 1eb5efa0e442710f35ed41ba09510e777b5cc409 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Sun, 6 Feb 2011 18:23:41 +0000 Subject: [PATCH 0867/2822] Blackfin: enable GENERIC_HARDIRQS_NO_DEPRECATED All chips converted. Signed-off-by: Thomas Gleixner Signed-off-by: Mike Frysinger --- arch/blackfin/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/blackfin/Kconfig b/arch/blackfin/Kconfig index c4cda6f52b61e..01615d4f57d6f 100644 --- a/arch/blackfin/Kconfig +++ b/arch/blackfin/Kconfig @@ -33,6 +33,7 @@ config BLACKFIN select HAVE_GENERIC_HARDIRQS select GENERIC_IRQ_PROBE select IRQ_PER_CPU if SMP + select GENERIC_HARDIRQS_NO_DEPRECATED config GENERIC_CSUM def_bool y -- GitLab From 8944b5a258d73abd1f86bb360c27bb8c3bed5daa Mon Sep 17 00:00:00 2001 From: Michael Hennerich Date: Mon, 28 Feb 2011 21:23:36 +0000 Subject: [PATCH 0868/2822] Blackfin: cpufreq: fix typos No functional changes here. Signed-off-by: Michael Hennerich Signed-off-by: Mike Frysinger --- arch/blackfin/mach-common/cpufreq.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/blackfin/mach-common/cpufreq.c b/arch/blackfin/mach-common/cpufreq.c index c33fb61b50822..85dc6d69f9c02 100644 --- a/arch/blackfin/mach-common/cpufreq.c +++ b/arch/blackfin/mach-common/cpufreq.c @@ -1,7 +1,7 @@ /* * Blackfin core clock scaling * - * Copyright 2008-2009 Analog Devices Inc. + * Copyright 2008-2011 Analog Devices Inc. * * Licensed under the GPL-2 or later. */ @@ -17,7 +17,7 @@ #include /* this is the table of CCLK frequencies, in Hz */ -/* .index is the entry in the auxillary dpm_state_table[] */ +/* .index is the entry in the auxiliary dpm_state_table[] */ static struct cpufreq_frequency_table bfin_freq_table[] = { { .frequency = CPUFREQ_TABLE_END, @@ -44,7 +44,7 @@ static struct bfin_dpm_state { #if defined(CONFIG_CYCLES_CLOCKSOURCE) /* - * normalized to maximum frequncy offset for CYCLES, + * normalized to maximum frequency offset for CYCLES, * used in time-ts cycles clock source, but could be used * somewhere also. */ -- GitLab From 5b5da4c4b843e0d84244472b72fe1e7500f5681f Mon Sep 17 00:00:00 2001 From: Philippe Gerum Date: Thu, 17 Mar 2011 02:12:48 -0400 Subject: [PATCH 0869/2822] Blackfin/ipipe: upgrade to I-pipe mainline This patch introduces Blackfin-specific bits to support the current tip of the interrupt pipeline development, mainly: - 2/3-level interrupt maps (sparse IRQs) - generic virq handling - sysinfo v2 format for ipipe_get_sysinfo() Signed-off-by: Philippe Gerum Signed-off-by: Mike Frysinger --- arch/blackfin/include/asm/ipipe.h | 95 ++++++++--------------- arch/blackfin/include/asm/ipipe_base.h | 11 ++- arch/blackfin/kernel/ipipe.c | 84 ++++++++++---------- arch/blackfin/mach-common/ints-priority.c | 41 +++++++++- 4 files changed, 117 insertions(+), 114 deletions(-) diff --git a/arch/blackfin/include/asm/ipipe.h b/arch/blackfin/include/asm/ipipe.h index 40f94a704c020..9e0cc0e2534f6 100644 --- a/arch/blackfin/include/asm/ipipe.h +++ b/arch/blackfin/include/asm/ipipe.h @@ -34,11 +34,12 @@ #include #include #include +#include -#define IPIPE_ARCH_STRING "1.12-00" +#define IPIPE_ARCH_STRING "1.16-01" #define IPIPE_MAJOR_NUMBER 1 -#define IPIPE_MINOR_NUMBER 12 -#define IPIPE_PATCH_NUMBER 0 +#define IPIPE_MINOR_NUMBER 16 +#define IPIPE_PATCH_NUMBER 1 #ifdef CONFIG_SMP #error "I-pipe/blackfin: SMP not implemented" @@ -55,25 +56,19 @@ do { \ #define task_hijacked(p) \ ({ \ int __x__ = __ipipe_root_domain_p; \ - __clear_bit(IPIPE_SYNC_FLAG, &ipipe_root_cpudom_var(status)); \ if (__x__) \ - hard_local_irq_enable(); \ + hard_local_irq_enable(); \ !__x__; \ }) struct ipipe_domain; struct ipipe_sysinfo { - - int ncpus; /* Number of CPUs on board */ - u64 cpufreq; /* CPU frequency (in Hz) */ - - /* Arch-dependent block */ - - struct { - unsigned tmirq; /* Timer tick IRQ */ - u64 tmfreq; /* Timer frequency */ - } archdep; + int sys_nr_cpus; /* Number of CPUs on board */ + int sys_hrtimer_irq; /* hrtimer device IRQ */ + u64 sys_hrtimer_freq; /* hrtimer device frequency */ + u64 sys_hrclock_freq; /* hrclock device frequency */ + u64 sys_cpu_freq; /* CPU frequency (Hz) */ }; #define ipipe_read_tsc(t) \ @@ -115,9 +110,19 @@ void __ipipe_enable_irqdesc(struct ipipe_domain *ipd, void __ipipe_disable_irqdesc(struct ipipe_domain *ipd, unsigned irq); -#define __ipipe_enable_irq(irq) (irq_desc[irq].chip->unmask(irq)) +#define __ipipe_enable_irq(irq) \ + do { \ + struct irq_desc *desc = irq_to_desc(irq); \ + struct irq_chip *chip = get_irq_desc_chip(desc); \ + chip->irq_unmask(&desc->irq_data); \ + } while (0) -#define __ipipe_disable_irq(irq) (irq_desc[irq].chip->mask(irq)) +#define __ipipe_disable_irq(irq) \ + do { \ + struct irq_desc *desc = irq_to_desc(irq); \ + struct irq_chip *chip = get_irq_desc_chip(desc); \ + chip->irq_mask(&desc->irq_data); \ + } while (0) static inline int __ipipe_check_tickdev(const char *devname) { @@ -128,12 +133,11 @@ void __ipipe_enable_pipeline(void); #define __ipipe_hook_critical_ipi(ipd) do { } while (0) -#define __ipipe_sync_pipeline ___ipipe_sync_pipeline -void ___ipipe_sync_pipeline(unsigned long syncmask); +void ___ipipe_sync_pipeline(void); void __ipipe_handle_irq(unsigned irq, struct pt_regs *regs); -int __ipipe_get_irq_priority(unsigned irq); +int __ipipe_get_irq_priority(unsigned int irq); void __ipipe_serial_debug(const char *fmt, ...); @@ -152,7 +156,10 @@ static inline unsigned long __ipipe_ffnz(unsigned long ul) return ffs(ul) - 1; } -#define __ipipe_run_irqtail() /* Must be a macro */ \ +#define __ipipe_do_root_xirq(ipd, irq) \ + ((ipd)->irqs[irq].handler(irq, &__raw_get_cpu_var(__ipipe_tick_regs))) + +#define __ipipe_run_irqtail(irq) /* Must be a macro */ \ do { \ unsigned long __pending; \ CSYNC(); \ @@ -164,42 +171,8 @@ static inline unsigned long __ipipe_ffnz(unsigned long ul) } \ } while (0) -#define __ipipe_run_isr(ipd, irq) \ - do { \ - if (!__ipipe_pipeline_head_p(ipd)) \ - hard_local_irq_enable(); \ - if (ipd == ipipe_root_domain) { \ - if (unlikely(ipipe_virtual_irq_p(irq))) { \ - irq_enter(); \ - ipd->irqs[irq].handler(irq, ipd->irqs[irq].cookie); \ - irq_exit(); \ - } else \ - ipd->irqs[irq].handler(irq, &__raw_get_cpu_var(__ipipe_tick_regs)); \ - } else { \ - __clear_bit(IPIPE_SYNC_FLAG, &ipipe_cpudom_var(ipd, status)); \ - ipd->irqs[irq].handler(irq, ipd->irqs[irq].cookie); \ - /* Attempt to exit the outer interrupt level before \ - * starting the deferred IRQ processing. */ \ - __ipipe_run_irqtail(); \ - __set_bit(IPIPE_SYNC_FLAG, &ipipe_cpudom_var(ipd, status)); \ - } \ - hard_local_irq_disable(); \ - } while (0) - #define __ipipe_syscall_watched_p(p, sc) \ - (((p)->flags & PF_EVNOTIFY) || (unsigned long)sc >= NR_syscalls) - -void ipipe_init_irq_threads(void); - -int ipipe_start_irq_thread(unsigned irq, struct irq_desc *desc); - -#ifdef CONFIG_TICKSOURCE_CORETMR -#define IRQ_SYSTMR IRQ_CORETMR -#define IRQ_PRIOTMR IRQ_CORETMR -#else -#define IRQ_SYSTMR IRQ_TIMER0 -#define IRQ_PRIOTMR CONFIG_IRQ_TIMER0 -#endif + (ipipe_notifier_enabled_p(p) || (unsigned long)sc >= NR_syscalls) #ifdef CONFIG_BF561 #define bfin_write_TIMER_DISABLE(val) bfin_write_TMRS8_DISABLE(val) @@ -219,11 +192,11 @@ int ipipe_start_irq_thread(unsigned irq, struct irq_desc *desc); #define task_hijacked(p) 0 #define ipipe_trap_notify(t, r) 0 +#define __ipipe_root_tick_p(regs) 1 -#define ipipe_init_irq_threads() do { } while (0) -#define ipipe_start_irq_thread(irq, desc) 0 +#endif /* !CONFIG_IPIPE */ -#ifndef CONFIG_TICKSOURCE_GPTMR0 +#ifdef CONFIG_TICKSOURCE_CORETMR #define IRQ_SYSTMR IRQ_CORETMR #define IRQ_PRIOTMR IRQ_CORETMR #else @@ -231,10 +204,6 @@ int ipipe_start_irq_thread(unsigned irq, struct irq_desc *desc); #define IRQ_PRIOTMR CONFIG_IRQ_TIMER0 #endif -#define __ipipe_root_tick_p(regs) 1 - -#endif /* !CONFIG_IPIPE */ - #define ipipe_update_tick_evtdev(evtdev) do { } while (0) #endif /* !__ASM_BLACKFIN_IPIPE_H */ diff --git a/arch/blackfin/include/asm/ipipe_base.h b/arch/blackfin/include/asm/ipipe_base.h index 00409201d9edc..84a4ffd367475 100644 --- a/arch/blackfin/include/asm/ipipe_base.h +++ b/arch/blackfin/include/asm/ipipe_base.h @@ -24,8 +24,10 @@ #ifdef CONFIG_IPIPE +#include +#include + #define IPIPE_NR_XIRQS NR_IRQS -#define IPIPE_IRQ_ISHIFT 5 /* 2^5 for 32bits arch. */ /* Blackfin-specific, per-cpu pipeline status */ #define IPIPE_SYNCDEFER_FLAG 15 @@ -42,11 +44,14 @@ #define IPIPE_EVENT_INIT (IPIPE_FIRST_EVENT + 4) #define IPIPE_EVENT_EXIT (IPIPE_FIRST_EVENT + 5) #define IPIPE_EVENT_CLEANUP (IPIPE_FIRST_EVENT + 6) -#define IPIPE_LAST_EVENT IPIPE_EVENT_CLEANUP +#define IPIPE_EVENT_RETURN (IPIPE_FIRST_EVENT + 7) +#define IPIPE_LAST_EVENT IPIPE_EVENT_RETURN #define IPIPE_NR_EVENTS (IPIPE_LAST_EVENT + 1) #define IPIPE_TIMER_IRQ IRQ_CORETMR +#define __IPIPE_FEATURE_SYSINFO_V2 1 + #ifndef __ASSEMBLY__ extern unsigned long __ipipe_root_status; /* Alias to ipipe_root_cpudom_var(status) */ @@ -63,6 +68,8 @@ void __ipipe_unlock_root(void); #endif /* !__ASSEMBLY__ */ +#define __IPIPE_FEATURE_SYSINFO_V2 1 + #endif /* CONFIG_IPIPE */ #endif /* !__ASM_BLACKFIN_IPIPE_BASE_H */ diff --git a/arch/blackfin/kernel/ipipe.c b/arch/blackfin/kernel/ipipe.c index 3b1da4aff2a1e..f37019c847c9b 100644 --- a/arch/blackfin/kernel/ipipe.c +++ b/arch/blackfin/kernel/ipipe.c @@ -154,7 +154,7 @@ void __ipipe_handle_irq(unsigned irq, struct pt_regs *regs) * pending for it. */ if (test_bit(IPIPE_AHEAD_FLAG, &this_domain->flags) && - ipipe_head_cpudom_var(irqpend_himask) == 0) + !__ipipe_ipending_p(ipipe_head_cpudom_ptr())) goto out; __ipipe_walk_pipeline(head); @@ -185,25 +185,21 @@ void __ipipe_disable_irqdesc(struct ipipe_domain *ipd, unsigned irq) } EXPORT_SYMBOL(__ipipe_disable_irqdesc); -int __ipipe_syscall_root(struct pt_regs *regs) +asmlinkage int __ipipe_syscall_root(struct pt_regs *regs) { struct ipipe_percpu_domain_data *p; - unsigned long flags; + void (*hook)(void); int ret; + WARN_ON_ONCE(irqs_disabled_hw()); + /* - * We need to run the IRQ tail hook whenever we don't - * propagate a syscall to higher domains, because we know that - * important operations might be pending there (e.g. Xenomai - * deferred rescheduling). + * We need to run the IRQ tail hook each time we intercept a + * syscall, because we know that important operations might be + * pending there (e.g. Xenomai deferred rescheduling). */ - - if (regs->orig_p0 < NR_syscalls) { - void (*hook)(void) = (void (*)(void))__ipipe_irq_tail_hook; - hook(); - if ((current->flags & PF_EVNOTIFY) == 0) - return 0; - } + hook = (__typeof__(hook))__ipipe_irq_tail_hook; + hook(); /* * This routine either returns: @@ -214,51 +210,47 @@ int __ipipe_syscall_root(struct pt_regs *regs) * tail work has to be performed (for handling signals etc). */ - if (!__ipipe_event_monitored_p(IPIPE_EVENT_SYSCALL)) + if (!__ipipe_syscall_watched_p(current, regs->orig_p0) || + !__ipipe_event_monitored_p(IPIPE_EVENT_SYSCALL)) return 0; ret = __ipipe_dispatch_event(IPIPE_EVENT_SYSCALL, regs); - flags = hard_local_irq_save(); + hard_local_irq_disable(); - if (!__ipipe_root_domain_p) { - hard_local_irq_restore(flags); - return 1; + /* + * This is the end of the syscall path, so we may + * safely assume a valid Linux task stack here. + */ + if (current->ipipe_flags & PF_EVTRET) { + current->ipipe_flags &= ~PF_EVTRET; + __ipipe_dispatch_event(IPIPE_EVENT_RETURN, regs); } - p = ipipe_root_cpudom_ptr(); - if ((p->irqpend_himask & IPIPE_IRQMASK_VIRT) != 0) - __ipipe_sync_pipeline(IPIPE_IRQMASK_VIRT); + if (!__ipipe_root_domain_p) + ret = -1; + else { + p = ipipe_root_cpudom_ptr(); + if (__ipipe_ipending_p(p)) + __ipipe_sync_pipeline(); + } - hard_local_irq_restore(flags); + hard_local_irq_enable(); return -ret; } -unsigned long ipipe_critical_enter(void (*syncfn) (void)) -{ - unsigned long flags; - - flags = hard_local_irq_save(); - - return flags; -} - -void ipipe_critical_exit(unsigned long flags) -{ - hard_local_irq_restore(flags); -} - static void __ipipe_no_irqtail(void) { } int ipipe_get_sysinfo(struct ipipe_sysinfo *info) { - info->ncpus = num_online_cpus(); - info->cpufreq = ipipe_cpu_freq(); - info->archdep.tmirq = IPIPE_TIMER_IRQ; - info->archdep.tmfreq = info->cpufreq; + info->sys_nr_cpus = num_online_cpus(); + info->sys_cpu_freq = ipipe_cpu_freq(); + info->sys_hrtimer_irq = IPIPE_TIMER_IRQ; + info->sys_hrtimer_freq = __ipipe_core_clock; + info->sys_hrclock_freq = __ipipe_core_clock; return 0; } @@ -289,6 +281,7 @@ int ipipe_trigger_irq(unsigned irq) asmlinkage void __ipipe_sync_root(void) { void (*irq_tail_hook)(void) = (void (*)(void))__ipipe_irq_tail_hook; + struct ipipe_percpu_domain_data *p; unsigned long flags; BUG_ON(irqs_disabled()); @@ -300,19 +293,20 @@ asmlinkage void __ipipe_sync_root(void) clear_thread_flag(TIF_IRQ_SYNC); - if (ipipe_root_cpudom_var(irqpend_himask) != 0) - __ipipe_sync_pipeline(IPIPE_IRQMASK_ANY); + p = ipipe_root_cpudom_ptr(); + if (__ipipe_ipending_p(p)) + __ipipe_sync_pipeline(); hard_local_irq_restore(flags); } -void ___ipipe_sync_pipeline(unsigned long syncmask) +void ___ipipe_sync_pipeline(void) { if (__ipipe_root_domain_p && test_bit(IPIPE_SYNCDEFER_FLAG, &ipipe_root_cpudom_var(status))) return; - __ipipe_sync_stage(syncmask); + __ipipe_sync_stage(); } void __ipipe_disable_root_irqs_hw(void) diff --git a/arch/blackfin/mach-common/ints-priority.c b/arch/blackfin/mach-common/ints-priority.c index 8e9d3cc308850..6cd52395a9998 100644 --- a/arch/blackfin/mach-common/ints-priority.c +++ b/arch/blackfin/mach-common/ints-priority.c @@ -15,6 +15,7 @@ #include #include #include +#include #ifdef CONFIG_IPIPE #include #endif @@ -556,10 +557,9 @@ static void bfin_demux_mac_status_irq(unsigned int int_err_irq, static inline void bfin_set_irq_handler(unsigned irq, irq_flow_handler_t handle) { #ifdef CONFIG_IPIPE - _set_irq_handler(irq, handle_level_irq); -#else - __set_irq_handler_unlocked(irq, handle); + handle = handle_level_irq; #endif + __set_irq_handler_unlocked(irq, handle); } static DECLARE_BITMAP(gpio_enabled, MAX_BLACKFIN_GPIOS); @@ -1392,7 +1392,7 @@ asmlinkage int __ipipe_grab_irq(int vec, struct pt_regs *regs) struct ipipe_domain *this_domain = __ipipe_current_domain; struct ivgx *ivg_stop = ivg7_13[vec-IVG7].istop; struct ivgx *ivg = ivg7_13[vec-IVG7].ifirst; - int irq, s; + int irq, s = 0; if (likely(vec == EVT_IVTMR_P)) irq = IRQ_CORETMR; @@ -1442,6 +1442,21 @@ asmlinkage int __ipipe_grab_irq(int vec, struct pt_regs *regs) __raw_get_cpu_var(__ipipe_tick_regs).ipend |= 0x10; } + /* + * We don't want Linux interrupt handlers to run at the + * current core priority level (i.e. < EVT15), since this + * might delay other interrupts handled by a high priority + * domain. Here is what we do instead: + * + * - we raise the SYNCDEFER bit to prevent + * __ipipe_handle_irq() to sync the pipeline for the root + * stage for the incoming interrupt. Upon return, that IRQ is + * pending in the interrupt log. + * + * - we raise the TIF_IRQ_SYNC bit for the current thread, so + * that _schedule_and_signal_from_int will eventually sync the + * pipeline from EVT15. + */ if (this_domain == ipipe_root_domain) { s = __test_and_set_bit(IPIPE_SYNCDEFER_FLAG, &p->status); barrier(); @@ -1451,6 +1466,24 @@ asmlinkage int __ipipe_grab_irq(int vec, struct pt_regs *regs) __ipipe_handle_irq(irq, regs); ipipe_trace_irq_exit(irq); + if (user_mode(regs) && + !ipipe_test_foreign_stack() && + (current->ipipe_flags & PF_EVTRET) != 0) { + /* + * Testing for user_regs() does NOT fully eliminate + * foreign stack contexts, because of the forged + * interrupt returns we do through + * __ipipe_call_irqtail. In that case, we might have + * preempted a foreign stack context in a high + * priority domain, with a single interrupt level now + * pending after the irqtail unwinding is done. In + * which case user_mode() is now true, and the event + * gets dispatched spuriously. + */ + current->ipipe_flags &= ~PF_EVTRET; + __ipipe_dispatch_event(IPIPE_EVENT_RETURN, regs); + } + if (this_domain == ipipe_root_domain) { set_thread_flag(TIF_IRQ_SYNC); if (!s) { -- GitLab From 9169b51f8ce6cd11cd19913b54466ec11e6a12f9 Mon Sep 17 00:00:00 2001 From: Philippe Gerum Date: Thu, 17 Mar 2011 02:15:24 -0400 Subject: [PATCH 0870/2822] Blackfin/ipipe: fix deferred pipeline sync for the root stage This patch makes sure to sync the pipeline for the root stage only from the outer interrupt level, when resuming kernel code after an interrupt. This fixes a bug causing EVT15 to be spuriously popped off upon nested interrupts, which in turn would cause the preempted kernel code to resume without supervisor privileges. Signed-off-by: Philippe Gerum Signed-off-by: Mike Frysinger --- arch/blackfin/mach-common/entry.S | 11 +++++++++++ arch/blackfin/mach-common/interrupt.S | 6 +++--- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/arch/blackfin/mach-common/entry.S b/arch/blackfin/mach-common/entry.S index bc08c98d008d8..4845d51e88a62 100644 --- a/arch/blackfin/mach-common/entry.S +++ b/arch/blackfin/mach-common/entry.S @@ -952,8 +952,17 @@ ENDPROC(_evt_up_evt14) #ifdef CONFIG_IPIPE _resume_kernel_from_int: + r1 = LO(~0x8000) (Z); + r1 = r0 & r1; + r0 = 1; + r0 = r1 - r0; + r2 = r1 & r0; + cc = r2 == 0; + /* Sync the root stage only from the outer interrupt level. */ + if !cc jump .Lnosync; r0.l = ___ipipe_sync_root; r0.h = ___ipipe_sync_root; + [--sp] = reti; [--sp] = rets; [--sp] = ( r7:4, p5:3 ); SP += -12; @@ -961,6 +970,8 @@ _resume_kernel_from_int: SP += 12; ( r7:4, p5:3 ) = [sp++]; rets = [sp++]; + reti = [sp++]; +.Lnosync: rts #elif defined(CONFIG_PREEMPT) diff --git a/arch/blackfin/mach-common/interrupt.S b/arch/blackfin/mach-common/interrupt.S index 2df37db3b49b6..469ce7282dc8b 100644 --- a/arch/blackfin/mach-common/interrupt.S +++ b/arch/blackfin/mach-common/interrupt.S @@ -274,16 +274,16 @@ ENDPROC(_evt_system_call) * level to EVT14 to prepare the caller for a normal interrupt * return through RTI. * - * We currently use this facility in two occasions: + * We currently use this feature in two occasions: * - * - to branch to __ipipe_irq_tail_hook as requested by a high + * - before branching to __ipipe_irq_tail_hook as requested by a high * priority domain after the pipeline delivered an interrupt, * e.g. such as Xenomai, in order to start its rescheduling * procedure, since we may not switch tasks when IRQ levels are * nested on the Blackfin, so we have to fake an interrupt return * so that we may reschedule immediately. * - * - to branch to sync_root_irqs, in order to play any interrupt + * - before branching to __ipipe_sync_root(), in order to play any interrupt * pending for the root domain (i.e. the Linux kernel). This lowers * the core priority level enough so that Linux IRQ handlers may * never delay interrupts handled by high priority domains; we defer -- GitLab From 1353d050facf5efd8dc05ba6c4d7852fcb423b15 Mon Sep 17 00:00:00 2001 From: Philippe Gerum Date: Thu, 17 Mar 2011 02:16:16 -0400 Subject: [PATCH 0871/2822] Blackfin/ipipe: restore pipeline bits in irqflags This patch fixes the Blackfin irqflags to make them I-pipe aware anew, after the introduction of the hard_local_irq_*() API. Signed-off-by: Philippe Gerum Signed-off-by: Mike Frysinger --- arch/blackfin/include/asm/irqflags.h | 87 ++++++++++++++++++++++++---- 1 file changed, 77 insertions(+), 10 deletions(-) diff --git a/arch/blackfin/include/asm/irqflags.h b/arch/blackfin/include/asm/irqflags.h index 3365cb97f539a..b4bbb75a9e15a 100644 --- a/arch/blackfin/include/asm/irqflags.h +++ b/arch/blackfin/include/asm/irqflags.h @@ -89,15 +89,33 @@ static inline void __hard_local_irq_restore(unsigned long flags) #ifdef CONFIG_IPIPE #include -#include #include +/* + * Way too many inter-deps between low-level headers in this port, so + * we redeclare the required bits we cannot pick from + * to prevent circular dependencies. + */ +void __ipipe_stall_root(void); +void __ipipe_unstall_root(void); +unsigned long __ipipe_test_root(void); +unsigned long __ipipe_test_and_stall_root(void); +void __ipipe_restore_root(unsigned long flags); + +#ifdef CONFIG_IPIPE_DEBUG_CONTEXT +struct ipipe_domain; +extern struct ipipe_domain ipipe_root; +void ipipe_check_context(struct ipipe_domain *ipd); +#define __check_irqop_context(ipd) ipipe_check_context(&ipipe_root) +#else /* !CONFIG_IPIPE_DEBUG_CONTEXT */ +#define __check_irqop_context(ipd) do { } while (0) +#endif /* !CONFIG_IPIPE_DEBUG_CONTEXT */ /* * Interrupt pipe interface to linux/irqflags.h. */ static inline void arch_local_irq_disable(void) { - ipipe_check_context(ipipe_root_domain); + __check_irqop_context(); __ipipe_stall_root(); barrier(); } @@ -105,7 +123,7 @@ static inline void arch_local_irq_disable(void) static inline void arch_local_irq_enable(void) { barrier(); - ipipe_check_context(ipipe_root_domain); + __check_irqop_context(); __ipipe_unstall_root(); } @@ -119,16 +137,21 @@ static inline int arch_irqs_disabled_flags(unsigned long flags) return flags == bfin_no_irqs; } -static inline void arch_local_irq_save_ptr(unsigned long *_flags) +static inline unsigned long arch_local_irq_save(void) { - x = __ipipe_test_and_stall_root() ? bfin_no_irqs : bfin_irq_flags; + unsigned long flags; + + __check_irqop_context(); + flags = __ipipe_test_and_stall_root() ? bfin_no_irqs : bfin_irq_flags; barrier(); + + return flags; } -static inline unsigned long arch_local_irq_save(void) +static inline void arch_local_irq_restore(unsigned long flags) { - ipipe_check_context(ipipe_root_domain); - return __hard_local_irq_save(); + __check_irqop_context(); + __ipipe_restore_root(flags == bfin_no_irqs); } static inline unsigned long arch_mangle_irq_bits(int virt, unsigned long real) @@ -192,7 +215,10 @@ static inline void hard_local_irq_restore(unsigned long flags) # define hard_local_irq_restore(flags) __hard_local_irq_restore(flags) #endif /* !CONFIG_IPIPE_TRACE_IRQSOFF */ -#else /* CONFIG_IPIPE */ +#define hard_local_irq_save_cond() hard_local_irq_save() +#define hard_local_irq_restore_cond(flags) hard_local_irq_restore(flags) + +#else /* !CONFIG_IPIPE */ /* * Direct interface to linux/irqflags.h. @@ -212,7 +238,48 @@ static inline void hard_local_irq_restore(unsigned long flags) #define hard_local_irq_restore(flags) __hard_local_irq_restore(flags) #define hard_local_irq_enable() __hard_local_irq_enable() #define hard_local_irq_disable() __hard_local_irq_disable() - +#define hard_local_irq_save_cond() hard_local_save_flags() +#define hard_local_irq_restore_cond(flags) do { (void)(flags); } while (0) #endif /* !CONFIG_IPIPE */ + +#ifdef CONFIG_SMP +#define hard_local_irq_save_smp() hard_local_irq_save() +#define hard_local_irq_restore_smp(flags) hard_local_irq_restore(flags) +#else +#define hard_local_irq_save_smp() hard_local_save_flags() +#define hard_local_irq_restore_smp(flags) do { (void)(flags); } while (0) +#endif + +/* + * Remap the arch-neutral IRQ state manipulation macros to the + * blackfin-specific hard_local_irq_* API. + */ +#define local_irq_save_hw(flags) \ + do { \ + (flags) = hard_local_irq_save(); \ + } while (0) +#define local_irq_restore_hw(flags) \ + do { \ + hard_local_irq_restore(flags); \ + } while (0) +#define local_irq_disable_hw() \ + do { \ + hard_local_irq_disable(); \ + } while (0) +#define local_irq_enable_hw() \ + do { \ + hard_local_irq_enable(); \ + } while (0) +#define local_irq_save_hw_notrace(flags) \ + do { \ + (flags) = __hard_local_irq_save(); \ + } while (0) +#define local_irq_restore_hw_notrace(flags) \ + do { \ + __hard_local_irq_restore(flags); \ + } while (0) + +#define irqs_disabled_hw() hard_irqs_disabled() + #endif -- GitLab From a8d0142fb7e31a11919ef2d45d6f43e0f225f568 Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Fri, 18 Mar 2011 04:05:23 -0400 Subject: [PATCH 0872/2822] Blackfin: wire up new syscalls Hook up name_to_handle_at, open_by_handle_at, and clock_adjtime. Signed-off-by: Mike Frysinger --- arch/blackfin/include/asm/unistd.h | 5 ++++- arch/blackfin/mach-common/entry.S | 3 +++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/arch/blackfin/include/asm/unistd.h b/arch/blackfin/include/asm/unistd.h index 928ae975b87e2..c97497dd0d195 100644 --- a/arch/blackfin/include/asm/unistd.h +++ b/arch/blackfin/include/asm/unistd.h @@ -393,8 +393,11 @@ #define __NR_fanotify_mark 372 #define __NR_prlimit64 373 #define __NR_cacheflush 374 +#define __NR_name_to_handle_at 375 +#define __NR_open_by_handle_at 376 +#define __NR_clock_adjtime 377 -#define __NR_syscall 375 +#define __NR_syscall 378 #define NR_syscalls __NR_syscall /* Old optional stuff no one actually uses */ diff --git a/arch/blackfin/mach-common/entry.S b/arch/blackfin/mach-common/entry.S index 4845d51e88a62..757943f620e78 100644 --- a/arch/blackfin/mach-common/entry.S +++ b/arch/blackfin/mach-common/entry.S @@ -1749,6 +1749,9 @@ ENTRY(_sys_call_table) .long _sys_fanotify_mark .long _sys_prlimit64 .long _sys_cacheflush + .long _sys_name_to_handle_at /* 375 */ + .long _sys_open_by_handle_at + .long _sys_clock_adjtime .rept NR_syscalls-(.-_sys_call_table)/4 .long _sys_ni_syscall -- GitLab From 58ee0d3bb115da727ccffeaebce21274e03b5d2e Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Fri, 18 Mar 2011 04:17:40 -0400 Subject: [PATCH 0873/2822] Blackfin: punt unused HDMA masks No code uses these, and the short define names are polluting the global namespace where they collide with things like common irq files. So just punt the damned things. If in the future we need HDMA support, we can make a standalone header for these things. Signed-off-by: Mike Frysinger --- .../mach-bf518/include/mach/defBF512.h | 19 ------------------- .../mach-bf527/include/mach/defBF522.h | 19 ------------------- .../mach-bf537/include/mach/defBF534.h | 18 ------------------ .../mach-bf548/include/mach/defBF544.h | 18 ------------------ .../mach-bf548/include/mach/defBF547.h | 19 ------------------- 5 files changed, 93 deletions(-) diff --git a/arch/blackfin/mach-bf518/include/mach/defBF512.h b/arch/blackfin/mach-bf518/include/mach/defBF512.h index 27285823fb252..cb1172f507572 100644 --- a/arch/blackfin/mach-bf518/include/mach/defBF512.h +++ b/arch/blackfin/mach-bf518/include/mach/defBF512.h @@ -1201,25 +1201,6 @@ #define PGTE_PPI 0x0000 /* Enable PPI D15:13 */ #define PGTE_SPORT 0x0800 /* Enable DT1PRI/TFS1/TSCLK1 */ - -/* ****************** HANDSHAKE DMA (HDMA) MASKS *********************/ -/* HDMAx_CTL Masks */ -#define HMDMAEN 0x0001 /* Enable Handshake DMA 0/1 */ -#define REP 0x0002 /* HDMA Request Polarity */ -#define UTE 0x0004 /* Urgency Threshold Enable */ -#define OIE 0x0010 /* Overflow Interrupt Enable */ -#define BDIE 0x0020 /* Block Done Interrupt Enable */ -#define MBDI 0x0040 /* Mask Block Done IRQ If Pending ECNT */ -#define DRQ 0x0300 /* HDMA Request Type */ -#define DRQ_NONE 0x0000 /* No Request */ -#define DRQ_SINGLE 0x0100 /* Channels Request Single */ -#define DRQ_MULTI 0x0200 /* Channels Request Multi (Default) */ -#define DRQ_URGENT 0x0300 /* Channels Request Multi Urgent */ -#define RBC 0x1000 /* Reload BCNT With IBCNT */ -#define PS 0x2000 /* HDMA Pin Status */ -#define OI 0x4000 /* Overflow Interrupt Generated */ -#define BDI 0x8000 /* Block Done Interrupt Generated */ - /* entry addresses of the user-callable Boot ROM functions */ #define _BOOTROM_RESET 0xEF000000 diff --git a/arch/blackfin/mach-bf527/include/mach/defBF522.h b/arch/blackfin/mach-bf527/include/mach/defBF522.h index 89f5420ee6cd3..84ef11e52644c 100644 --- a/arch/blackfin/mach-bf527/include/mach/defBF522.h +++ b/arch/blackfin/mach-bf527/include/mach/defBF522.h @@ -1204,25 +1204,6 @@ #define PGTE_PPI 0x0000 /* Enable PPI D15:13 */ #define PGTE_SPORT 0x0800 /* Enable DT1PRI/TFS1/TSCLK1 */ - -/* ****************** HANDSHAKE DMA (HDMA) MASKS *********************/ -/* HDMAx_CTL Masks */ -#define HMDMAEN 0x0001 /* Enable Handshake DMA 0/1 */ -#define REP 0x0002 /* HDMA Request Polarity */ -#define UTE 0x0004 /* Urgency Threshold Enable */ -#define OIE 0x0010 /* Overflow Interrupt Enable */ -#define BDIE 0x0020 /* Block Done Interrupt Enable */ -#define MBDI 0x0040 /* Mask Block Done IRQ If Pending ECNT */ -#define DRQ 0x0300 /* HDMA Request Type */ -#define DRQ_NONE 0x0000 /* No Request */ -#define DRQ_SINGLE 0x0100 /* Channels Request Single */ -#define DRQ_MULTI 0x0200 /* Channels Request Multi (Default) */ -#define DRQ_URGENT 0x0300 /* Channels Request Multi Urgent */ -#define RBC 0x1000 /* Reload BCNT With IBCNT */ -#define PS 0x2000 /* HDMA Pin Status */ -#define OI 0x4000 /* Overflow Interrupt Generated */ -#define BDI 0x8000 /* Block Done Interrupt Generated */ - /* entry addresses of the user-callable Boot ROM functions */ #define _BOOTROM_RESET 0xEF000000 diff --git a/arch/blackfin/mach-bf537/include/mach/defBF534.h b/arch/blackfin/mach-bf537/include/mach/defBF534.h index 725bb35f3aaa0..4a031dde173fb 100644 --- a/arch/blackfin/mach-bf537/include/mach/defBF534.h +++ b/arch/blackfin/mach-bf537/include/mach/defBF534.h @@ -1520,24 +1520,6 @@ #define PGTE_PPI 0x0000 /* Enable PPI D15:13 */ #define PGTE_SPORT 0x0800 /* Enable DT1PRI/TFS1/TSCLK1 */ -/* ****************** HANDSHAKE DMA (HDMA) MASKS *********************/ -/* HDMAx_CTL Masks */ -#define HMDMAEN 0x0001 /* Enable Handshake DMA 0/1 */ -#define REP 0x0002 /* HDMA Request Polarity */ -#define UTE 0x0004 /* Urgency Threshold Enable */ -#define OIE 0x0010 /* Overflow Interrupt Enable */ -#define BDIE 0x0020 /* Block Done Interrupt Enable */ -#define MBDI 0x0040 /* Mask Block Done IRQ If Pending ECNT */ -#define DRQ 0x0300 /* HDMA Request Type */ -#define DRQ_NONE 0x0000 /* No Request */ -#define DRQ_SINGLE 0x0100 /* Channels Request Single */ -#define DRQ_MULTI 0x0200 /* Channels Request Multi (Default) */ -#define DRQ_URGENT 0x0300 /* Channels Request Multi Urgent */ -#define RBC 0x1000 /* Reload BCNT With IBCNT */ -#define PS 0x2000 /* HDMA Pin Status */ -#define OI 0x4000 /* Overflow Interrupt Generated */ -#define BDI 0x8000 /* Block Done Interrupt Generated */ - /* entry addresses of the user-callable Boot ROM functions */ #define _BOOTROM_RESET 0xEF000000 diff --git a/arch/blackfin/mach-bf548/include/mach/defBF544.h b/arch/blackfin/mach-bf548/include/mach/defBF544.h index 642468c1bcb1c..bcccab36629c3 100644 --- a/arch/blackfin/mach-bf548/include/mach/defBF544.h +++ b/arch/blackfin/mach-bf548/include/mach/defBF544.h @@ -657,22 +657,4 @@ /* Bit masks for EPPI0 are obtained from common base header for EPPIx (EPPI1 and EPPI2) */ -/* Bit masks for HMDMAx_CONTROL */ - -#define HMDMAEN 0x1 /* Handshake MDMA Enable */ -#define REP 0x2 /* Handshake MDMA Request Polarity */ -#define UTE 0x8 /* Urgency Threshold Enable */ -#define OIE 0x10 /* Overflow Interrupt Enable */ -#define BDIE 0x20 /* Block Done Interrupt Enable */ -#define MBDI 0x40 /* Mask Block Done Interrupt */ -#define DRQ 0x300 /* Handshake MDMA Request Type */ -#define RBC 0x1000 /* Force Reload of BCOUNT */ -#define PS 0x2000 /* Pin Status */ -#define OI 0x4000 /* Overflow Interrupt Generated */ -#define BDI 0x8000 /* Block Done Interrupt Generated */ - -/* ******************************************* */ -/* MULTI BIT MACRO ENUMERATIONS */ -/* ******************************************* */ - #endif /* _DEF_BF544_H */ diff --git a/arch/blackfin/mach-bf548/include/mach/defBF547.h b/arch/blackfin/mach-bf548/include/mach/defBF547.h index 2f3337cd311e8..1cbba115f96f3 100644 --- a/arch/blackfin/mach-bf548/include/mach/defBF547.h +++ b/arch/blackfin/mach-bf548/include/mach/defBF547.h @@ -1063,23 +1063,4 @@ #define DMA_COUNT_LOW 0xffff /* Lower 16-bits of byte count of DMA transfer for DMA master channel */ -/* Bit masks for HMDMAx_CONTROL */ - -#define HMDMAEN 0x1 /* Handshake MDMA Enable */ -#define REP 0x2 /* Handshake MDMA Request Polarity */ -#define UTE 0x8 /* Urgency Threshold Enable */ -#define OIE 0x10 /* Overflow Interrupt Enable */ -#define BDIE 0x20 /* Block Done Interrupt Enable */ -#define MBDI 0x40 /* Mask Block Done Interrupt */ -#define DRQ 0x300 /* Handshake MDMA Request Type */ -#define RBC 0x1000 /* Force Reload of BCOUNT */ -#define PS 0x2000 /* Pin Status */ -#define OI 0x4000 /* Overflow Interrupt Generated */ -#define BDI 0x8000 /* Block Done Interrupt Generated */ - -/* ******************************************* */ -/* MULTI BIT MACRO ENUMERATIONS */ -/* ******************************************* */ - - #endif /* _DEF_BF547_H */ -- GitLab From 0c082bd15828135d609a2f593b583de9eacece0f Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Fri, 18 Mar 2011 05:15:52 -0400 Subject: [PATCH 0874/2822] Blackfin: ip0x: fix unused variable warning The previous commit that changed this code to the common GPIO layers forgot to delete the local and now unused "i" variable. Signed-off-by: Mike Frysinger --- arch/blackfin/mach-bf533/boards/ip0x.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/arch/blackfin/mach-bf533/boards/ip0x.c b/arch/blackfin/mach-bf533/boards/ip0x.c index f869a3711480d..a377d8afea038 100644 --- a/arch/blackfin/mach-bf533/boards/ip0x.c +++ b/arch/blackfin/mach-bf533/boards/ip0x.c @@ -289,8 +289,6 @@ static struct platform_device *ip0x_devices[] __initdata = { static int __init ip0x_init(void) { - int i; - printk(KERN_INFO "%s(): registering device resources\n", __func__); platform_add_devices(ip0x_devices, ARRAY_SIZE(ip0x_devices)); -- GitLab From b1a56b331aec59be04f25ac99694d855d591c539 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 16 Mar 2011 18:18:53 +0000 Subject: [PATCH 0875/2822] ASoC: Remove bogus check for register validity in debugfs write Since not all registers need to be cached and the cache is entirely optional anyway we shouldn't be checking that a register is in the cached range. If the register is invalid then the actual I/O code can determine that and report an error. Similarly, the step size can and should be enforced by the lower level code if it's important. Signed-off-by: Mark Brown Acked-by: Liam Girdwood --- sound/soc/soc-core.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 17efacdb248a9..4dda58926bc52 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -259,8 +259,6 @@ static ssize_t codec_reg_write_file(struct file *file, while (*start == ' ') start++; reg = simple_strtoul(start, &start, 16); - if ((reg >= codec->driver->reg_cache_size) || (reg % step)) - return -EINVAL; while (*start == ' ') start++; if (strict_strtoul(start, 16, &value)) -- GitLab From 977a6ef3c0cb622b572fb8e2e5088dbe09521375 Mon Sep 17 00:00:00 2001 From: Xiaochen Wang Date: Fri, 18 Mar 2011 16:29:25 +0800 Subject: [PATCH 0876/2822] sound: read i_size with i_size_read() Convert direct read of inode->i_size to using i_size_read(). i_size_read is guaranteed to return a valid value and its caller does not need to use addtional locking. Signed-off-by: Xiaochen Wang Signed-off-by: Takashi Iwai --- sound/sound_firmware.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/sound_firmware.c b/sound/sound_firmware.c index 340a0bc5303e9..7e96249536b4e 100644 --- a/sound/sound_firmware.c +++ b/sound/sound_firmware.c @@ -19,7 +19,7 @@ static int do_mod_firmware_load(const char *fn, char **fp) printk(KERN_INFO "Unable to load '%s'.\n", fn); return 0; } - l = filp->f_path.dentry->d_inode->i_size; + l = i_size_read(filp->f_path.dentry->d_inode); if (l <= 0 || l > 131072) { printk(KERN_INFO "Invalid firmware '%s'\n", fn); -- GitLab From 748bfd9c1ded8419e7fdba4ca6f0c1dc1642df63 Mon Sep 17 00:00:00 2001 From: Roland Dreier Date: Fri, 18 Mar 2011 08:52:30 -0700 Subject: [PATCH 0877/2822] RDMA/nes: Don't print success message at level KERN_ERR There's no reason to print "NetEffect RNIC driver successfully loaded" at level KERN_ERR (where it will uglify the console on a quiet boot). Change it to KERN_INFO. Signed-off-by: Roland Dreier --- drivers/infiniband/hw/nes/nes.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/infiniband/hw/nes/nes.c b/drivers/infiniband/hw/nes/nes.c index 3d7f3664b67b9..13de1192927cc 100644 --- a/drivers/infiniband/hw/nes/nes.c +++ b/drivers/infiniband/hw/nes/nes.c @@ -694,7 +694,7 @@ static int __devinit nes_probe(struct pci_dev *pcidev, const struct pci_device_i nesdev->netdev_count++; nesdev->nesadapter->netdev_count++; - printk(KERN_ERR PFX "%s: NetEffect RNIC driver successfully loaded.\n", + printk(KERN_INFO PFX "%s: NetEffect RNIC driver successfully loaded.\n", pci_name(pcidev)); return 0; -- GitLab From 1eba843dd7678b9033a0d1ccff21c21b857de77b Mon Sep 17 00:00:00 2001 From: Michael Heinz Date: Fri, 11 Feb 2011 21:44:30 +0000 Subject: [PATCH 0878/2822] IB/mad: Improve an error message so error code is included Signed-off-by: Michael Heinz Signed-off-by: Roland Dreier --- drivers/infiniband/core/agent.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/infiniband/core/agent.c b/drivers/infiniband/core/agent.c index 91916a8d5de40..2bc7f5af64f42 100644 --- a/drivers/infiniband/core/agent.c +++ b/drivers/infiniband/core/agent.c @@ -101,7 +101,8 @@ void agent_send_response(struct ib_mad *mad, struct ib_grh *grh, agent = port_priv->agent[qpn]; ah = ib_create_ah_from_wc(agent->qp->pd, wc, grh, port_num); if (IS_ERR(ah)) { - printk(KERN_ERR SPFX "ib_create_ah_from_wc error\n"); + printk(KERN_ERR SPFX "ib_create_ah_from_wc error %ld\n", + PTR_ERR(ah)); return; } -- GitLab From 73a173a4117419892bd436e85a00a53aa22ad118 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Fri, 18 Mar 2011 16:42:06 +0000 Subject: [PATCH 0879/2822] MN10300: Remove stale code mn10300 implements clocksource and clockevents and selects them unconditionally in Kconfig. Remove the stale code which seems to be a leftover of the conversion. Cleanup the configuration switches as well. Signed-off-by: Thomas Gleixner Acked-by: John Stultz Cc: Koichi Yasutake Cc: Mark Salter Signed-off-by: David Howells --- arch/mn10300/Kconfig | 15 ----------- arch/mn10300/kernel/Makefile | 5 ++-- arch/mn10300/kernel/time.c | 49 ------------------------------------ 3 files changed, 2 insertions(+), 67 deletions(-) diff --git a/arch/mn10300/Kconfig b/arch/mn10300/Kconfig index 243bfa23fd586..8b979ff4373ec 100644 --- a/arch/mn10300/Kconfig +++ b/arch/mn10300/Kconfig @@ -53,21 +53,6 @@ config GENERIC_TIME config GENERIC_CLOCKEVENTS def_bool y -config GENERIC_CLOCKEVENTS_BUILD - def_bool y - depends on GENERIC_CLOCKEVENTS - -config GENERIC_CLOCKEVENTS_BROADCAST - bool - -config CEVT_MN10300 - def_bool y - depends on GENERIC_CLOCKEVENTS - -config CSRC_MN10300 - def_bool y - depends on GENERIC_TIME - config GENERIC_BUG def_bool y diff --git a/arch/mn10300/kernel/Makefile b/arch/mn10300/kernel/Makefile index 8f5f1e81baf5c..a06a2e10051d5 100644 --- a/arch/mn10300/kernel/Makefile +++ b/arch/mn10300/kernel/Makefile @@ -8,7 +8,8 @@ fpu-obj-$(CONFIG_FPU) := fpu.o fpu-low.o obj-y := process.o signal.o entry.o traps.o irq.o \ ptrace.o setup.o time.o sys_mn10300.o io.o kthread.o \ - switch_to.o mn10300_ksyms.o kernel_execve.o $(fpu-obj-y) + switch_to.o mn10300_ksyms.o kernel_execve.o $(fpu-obj-y) \ + csrc-mn10300.o cevt-mn10300.o obj-$(CONFIG_SMP) += smp.o smp-low.o @@ -28,5 +29,3 @@ obj-$(CONFIG_MN10300_RTC) += rtc.o obj-$(CONFIG_PROFILE) += profile.o profile-low.o obj-$(CONFIG_MODULES) += module.o obj-$(CONFIG_KPROBES) += kprobes.o -obj-$(CONFIG_CSRC_MN10300) += csrc-mn10300.o -obj-$(CONFIG_CEVT_MN10300) += cevt-mn10300.o diff --git a/arch/mn10300/kernel/time.c b/arch/mn10300/kernel/time.c index 5b955000626d9..611696df816fa 100644 --- a/arch/mn10300/kernel/time.c +++ b/arch/mn10300/kernel/time.c @@ -93,43 +93,6 @@ irqreturn_t local_timer_interrupt(void) return IRQ_HANDLED; } -#ifndef CONFIG_GENERIC_TIME -/* - * advance the kernel's time keeping clocks (xtime and jiffies) - * - we use Timer 0 & 1 cascaded as a clock to nudge us the next time - * there's a need to update - */ -static irqreturn_t timer_interrupt(int irq, void *dev_id) -{ - unsigned tsc, elapse; - irqreturn_t ret; - - while (tsc = get_cycles(), - elapse = tsc - mn10300_last_tsc, /* time elapsed since last - * tick */ - elapse > MN10300_TSC_PER_HZ - ) { - mn10300_last_tsc += MN10300_TSC_PER_HZ; - - /* advance the kernel's time tracking system */ - xtime_update(1); - } - - ret = local_timer_interrupt(); -#ifdef CONFIG_SMP - send_IPI_allbutself(LOCAL_TIMER_IPI); -#endif - return ret; -} - -static struct irqaction timer_irq = { - .handler = timer_interrupt, - .flags = IRQF_DISABLED | IRQF_SHARED | IRQF_TIMER, - .name = "timer", -}; -#endif /* CONFIG_GENERIC_TIME */ - -#ifdef CONFIG_CSRC_MN10300 void __init clocksource_set_clock(struct clocksource *cs, unsigned int clock) { u64 temp; @@ -145,9 +108,7 @@ void __init clocksource_set_clock(struct clocksource *cs, unsigned int clock) cs->shift = shift; cs->mult = (u32) temp; } -#endif -#if CONFIG_CEVT_MN10300 void __cpuinit clockevent_set_clock(struct clock_event_device *cd, unsigned int clock) { @@ -164,7 +125,6 @@ void __cpuinit clockevent_set_clock(struct clock_event_device *cd, cd->shift = shift; cd->mult = (u32) temp; } -#endif /* * initialise the various timers used by the main part of the kernel @@ -177,11 +137,7 @@ void __init time_init(void) */ TMPSCNT |= TMPSCNT_ENABLE; -#ifdef CONFIG_GENERIC_TIME init_clocksource(); -#else - startup_timestamp_counter(); -#endif printk(KERN_INFO "timestamp counter I/O clock running at %lu.%02lu" @@ -190,12 +146,7 @@ void __init time_init(void) mn10300_last_tsc = read_timestamp_counter(); -#ifdef CONFIG_GENERIC_CLOCKEVENTS init_clockevents(); -#else - reload_jiffies_counter(MN10300_JC_PER_HZ - 1); - setup_jiffies_interrupt(TMJCIRQ, &timer_irq, CONFIG_TIMER_IRQ_LEVEL); -#endif #ifdef CONFIG_MN10300_WD_TIMER /* start the watchdog timer */ -- GitLab From 817890ba15df44181bc9c2bf7527cb066ebae06f Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Fri, 18 Mar 2011 16:52:50 +0000 Subject: [PATCH 0880/2822] MN10300: Use clocksource_register_hz() clocksource_register_hz() calculates the shift/mult pair for the clocksource. Remove the mn10300 duplicate implementation. Signed-off-by: Thomas Gleixner Acked-by: John Stultz Cc: Koichi Yasutake Cc: Mark Salter Signed-off-by: David Howells --- arch/mn10300/kernel/csrc-mn10300.c | 3 +-- arch/mn10300/kernel/internal.h | 3 --- arch/mn10300/kernel/time.c | 16 ---------------- 3 files changed, 1 insertion(+), 21 deletions(-) diff --git a/arch/mn10300/kernel/csrc-mn10300.c b/arch/mn10300/kernel/csrc-mn10300.c index ba2f0c4d6e01c..45644cf18c412 100644 --- a/arch/mn10300/kernel/csrc-mn10300.c +++ b/arch/mn10300/kernel/csrc-mn10300.c @@ -29,7 +29,6 @@ static struct clocksource clocksource_mn10300 = { int __init init_clocksource(void) { startup_timestamp_counter(); - clocksource_set_clock(&clocksource_mn10300, MN10300_TSCCLK); - clocksource_register(&clocksource_mn10300); + clocksource_register_hz(&clocksource_mn10300, MN10300_TSCCLK); return 0; } diff --git a/arch/mn10300/kernel/internal.h b/arch/mn10300/kernel/internal.h index 6a064ab5af077..3d43d4dd02334 100644 --- a/arch/mn10300/kernel/internal.h +++ b/arch/mn10300/kernel/internal.h @@ -37,9 +37,6 @@ extern irqreturn_t local_timer_interrupt(void); /* * time.c */ -#ifdef CONFIG_CEVT_MN10300 -extern void clockevent_set_clock(struct clock_event_device *, unsigned int); -#endif #ifdef CONFIG_CSRC_MN10300 extern void clocksource_set_clock(struct clocksource *, unsigned int); #endif diff --git a/arch/mn10300/kernel/time.c b/arch/mn10300/kernel/time.c index 611696df816fa..78f72080ca171 100644 --- a/arch/mn10300/kernel/time.c +++ b/arch/mn10300/kernel/time.c @@ -93,22 +93,6 @@ irqreturn_t local_timer_interrupt(void) return IRQ_HANDLED; } -void __init clocksource_set_clock(struct clocksource *cs, unsigned int clock) -{ - u64 temp; - u32 shift; - - /* Find a shift value */ - for (shift = 32; shift > 0; shift--) { - temp = (u64) NSEC_PER_SEC << shift; - do_div(temp, clock); - if ((temp >> 32) == 0) - break; - } - cs->shift = shift; - cs->mult = (u32) temp; -} - void __cpuinit clockevent_set_clock(struct clock_event_device *cd, unsigned int clock) { -- GitLab From dc7daf33626d1f4afc97505516f824caf440d52c Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Fri, 18 Mar 2011 16:52:50 +0000 Subject: [PATCH 0881/2822] MN10300: Use clockevents_calc_mult_shift() Use clockevents_calc_mult_shift() instead of the homebrewn function in mn10300/kernel/time.c. Signed-off-by: Thomas Gleixner Acked-by: John Stultz Cc: Koichi Yasutake Cc: Mark Salter Signed-off-by: David Howells --- arch/mn10300/kernel/cevt-mn10300.c | 5 +++-- arch/mn10300/kernel/internal.h | 7 ------- arch/mn10300/kernel/time.c | 17 ----------------- 3 files changed, 3 insertions(+), 26 deletions(-) diff --git a/arch/mn10300/kernel/cevt-mn10300.c b/arch/mn10300/kernel/cevt-mn10300.c index d4cb535bf7863..9eb387adea7cc 100644 --- a/arch/mn10300/kernel/cevt-mn10300.c +++ b/arch/mn10300/kernel/cevt-mn10300.c @@ -89,9 +89,10 @@ int __init init_clockevents(void) cd->name = "Timestamp"; cd->features = CLOCK_EVT_FEAT_ONESHOT; - /* Calculate the min / max delta */ - clockevent_set_clock(cd, MN10300_JCCLK); + /* Calculate shift/mult. We want to spawn at least 1 second */ + clockevents_calc_mult_shift(cd, MN10300_JCCLK, 1); + /* Calculate the min / max delta */ cd->max_delta_ns = clockevent_delta2ns(TMJCBR_MAX, cd); cd->min_delta_ns = clockevent_delta2ns(100, cd); diff --git a/arch/mn10300/kernel/internal.h b/arch/mn10300/kernel/internal.h index 3d43d4dd02334..ea946613f46d1 100644 --- a/arch/mn10300/kernel/internal.h +++ b/arch/mn10300/kernel/internal.h @@ -33,10 +33,3 @@ extern void mn10300_low_ipi_handler(void); * time.c */ extern irqreturn_t local_timer_interrupt(void); - -/* - * time.c - */ -#ifdef CONFIG_CSRC_MN10300 -extern void clocksource_set_clock(struct clocksource *, unsigned int); -#endif diff --git a/arch/mn10300/kernel/time.c b/arch/mn10300/kernel/time.c index 78f72080ca171..67c6416a58f83 100644 --- a/arch/mn10300/kernel/time.c +++ b/arch/mn10300/kernel/time.c @@ -93,23 +93,6 @@ irqreturn_t local_timer_interrupt(void) return IRQ_HANDLED; } -void __cpuinit clockevent_set_clock(struct clock_event_device *cd, - unsigned int clock) -{ - u64 temp; - u32 shift; - - /* Find a shift value */ - for (shift = 32; shift > 0; shift--) { - temp = (u64) clock << shift; - do_div(temp, NSEC_PER_SEC); - if ((temp >> 32) == 0) - break; - } - cd->shift = shift; - cd->mult = (u32) temp; -} - /* * initialise the various timers used by the main part of the kernel */ -- GitLab From e61645a0aa9d96b1df36a1879f9b052ca71a5f22 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Fri, 18 Mar 2011 16:52:51 +0000 Subject: [PATCH 0882/2822] MN10300: Remove stale irq_chip.end - V2 irq_chip.end is obsolete with the removal of __do_IRQ(). Signed-off-by: Thomas Gleixner Signed-off-by: David Howells --- arch/mn10300/kernel/mn10300-serial.c | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/mn10300/kernel/mn10300-serial.c b/arch/mn10300/kernel/mn10300-serial.c index 996384dba45da..94f3b54c6eca5 100644 --- a/arch/mn10300/kernel/mn10300-serial.c +++ b/arch/mn10300/kernel/mn10300-serial.c @@ -394,7 +394,6 @@ static struct irq_chip mn10300_serial_pic = { .mask = mn10300_serial_mask_ack, .mask_ack = mn10300_serial_mask_ack, .unmask = mn10300_serial_nop, - .end = mn10300_serial_nop, }; -- GitLab From a494d3df1e482e3f5552268af5b4b122421b5ee6 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Fri, 18 Mar 2011 16:52:51 +0000 Subject: [PATCH 0883/2822] MN10300: Remove unused mn10300_intc_* functions No users. Signed-off-by: Thomas Gleixner Signed-off-by: David Howells --- arch/mn10300/include/asm/intctl-regs.h | 5 ----- arch/mn10300/kernel/irq.c | 25 ------------------------- 2 files changed, 30 deletions(-) diff --git a/arch/mn10300/include/asm/intctl-regs.h b/arch/mn10300/include/asm/intctl-regs.h index 585b708c2bc06..d65bbeebe50a6 100644 --- a/arch/mn10300/include/asm/intctl-regs.h +++ b/arch/mn10300/include/asm/intctl-regs.h @@ -60,11 +60,6 @@ #ifndef __ASSEMBLY__ extern void set_intr_level(int irq, u16 level); -extern void mn10300_intc_set_level(unsigned int irq, unsigned int level); -extern void mn10300_intc_clear(unsigned int irq); -extern void mn10300_intc_set(unsigned int irq); -extern void mn10300_intc_enable(unsigned int irq); -extern void mn10300_intc_disable(unsigned int irq); extern void mn10300_set_lateack_irq_type(int irq); #endif diff --git a/arch/mn10300/kernel/irq.c b/arch/mn10300/kernel/irq.c index ac11754ecec54..e19fe8124f4c0 100644 --- a/arch/mn10300/kernel/irq.c +++ b/arch/mn10300/kernel/irq.c @@ -252,31 +252,6 @@ void set_intr_level(int irq, u16 level) __mask_and_set_icr(irq, GxICR_ENABLE, level); } -void mn10300_intc_set_level(unsigned int irq, unsigned int level) -{ - set_intr_level(irq, NUM2GxICR_LEVEL(level) & GxICR_LEVEL); -} - -void mn10300_intc_clear(unsigned int irq) -{ - __mask_and_set_icr(irq, GxICR_LEVEL | GxICR_ENABLE, GxICR_DETECT); -} - -void mn10300_intc_set(unsigned int irq) -{ - __mask_and_set_icr(irq, 0, GxICR_REQUEST | GxICR_DETECT); -} - -void mn10300_intc_enable(unsigned int irq) -{ - mn10300_cpupic_unmask(irq); -} - -void mn10300_intc_disable(unsigned int irq) -{ - mn10300_cpupic_mask(irq); -} - /* * mark an interrupt to be ACK'd after interrupt handlers have been run rather * than before -- GitLab From 125bb1dbaded3f7d12ad39e5e26d5fa0aa9ca751 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Fri, 18 Mar 2011 16:52:51 +0000 Subject: [PATCH 0884/2822] MN10300: Convert cpu irq_chips to new functions Signed-off-by: Thomas Gleixner Signed-off-by: David Howells --- arch/mn10300/kernel/irq.c | 62 +++++++++++++++++++++------------------ 1 file changed, 33 insertions(+), 29 deletions(-) diff --git a/arch/mn10300/kernel/irq.c b/arch/mn10300/kernel/irq.c index e19fe8124f4c0..cd36a6c62770a 100644 --- a/arch/mn10300/kernel/irq.c +++ b/arch/mn10300/kernel/irq.c @@ -37,8 +37,9 @@ atomic_t irq_err_count; /* * MN10300 interrupt controller operations */ -static void mn10300_cpupic_ack(unsigned int irq) +static void mn10300_cpupic_ack(struct irq_data *d) { + unsigned int irq = d->irq; unsigned long flags; u16 tmp; @@ -61,13 +62,14 @@ static void __mask_and_set_icr(unsigned int irq, arch_local_irq_restore(flags); } -static void mn10300_cpupic_mask(unsigned int irq) +static void mn10300_cpupic_mask(struct irq_data *d) { - __mask_and_set_icr(irq, GxICR_LEVEL, 0); + __mask_and_set_icr(d->irq, GxICR_LEVEL, 0); } -static void mn10300_cpupic_mask_ack(unsigned int irq) +static void mn10300_cpupic_mask_ack(struct irq_data *d) { + unsigned int irq = d->irq; #ifdef CONFIG_SMP unsigned long flags; u16 tmp; @@ -85,7 +87,7 @@ static void mn10300_cpupic_mask_ack(unsigned int irq) tmp2 = GxICR(irq); irq_affinity_online[irq] = - any_online_cpu(*irq_desc[irq].affinity); + any_online_cpu(*d->affinity); CROSS_GxICR(irq, irq_affinity_online[irq]) = (tmp & (GxICR_LEVEL | GxICR_ENABLE)) | GxICR_DETECT; tmp = CROSS_GxICR(irq, irq_affinity_online[irq]); @@ -97,13 +99,14 @@ static void mn10300_cpupic_mask_ack(unsigned int irq) #endif /* CONFIG_SMP */ } -static void mn10300_cpupic_unmask(unsigned int irq) +static void mn10300_cpupic_unmask(struct irq_data *d) { - __mask_and_set_icr(irq, GxICR_LEVEL, GxICR_ENABLE); + __mask_and_set_icr(d->irq, GxICR_LEVEL, GxICR_ENABLE); } -static void mn10300_cpupic_unmask_clear(unsigned int irq) +static void mn10300_cpupic_unmask_clear(struct irq_data *d) { + unsigned int irq = d->irq; /* the MN10300 PIC latches its interrupt request bit, even after the * device has ceased to assert its interrupt line and the interrupt * channel has been disabled in the PIC, so for level-triggered @@ -121,7 +124,7 @@ static void mn10300_cpupic_unmask_clear(unsigned int irq) } else { tmp = GxICR(irq); - irq_affinity_online[irq] = any_online_cpu(*irq_desc[irq].affinity); + irq_affinity_online[irq] = any_online_cpu(*d->affinity); CROSS_GxICR(irq, irq_affinity_online[irq]) = (tmp & GxICR_LEVEL) | GxICR_ENABLE | GxICR_DETECT; tmp = CROSS_GxICR(irq, irq_affinity_online[irq]); } @@ -134,7 +137,8 @@ static void mn10300_cpupic_unmask_clear(unsigned int irq) #ifdef CONFIG_SMP static int -mn10300_cpupic_setaffinity(unsigned int irq, const struct cpumask *mask) +mn10300_cpupic_setaffinity(struct irq_data *d, const struct cpumask *mask, + bool force) { unsigned long flags; int err; @@ -142,7 +146,7 @@ mn10300_cpupic_setaffinity(unsigned int irq, const struct cpumask *mask) flags = arch_local_cli_save(); /* check irq no */ - switch (irq) { + switch (d->irq) { case TMJCIRQ: case RESCHEDULE_IPI: case CALL_FUNC_SINGLE_IPI: @@ -181,7 +185,7 @@ mn10300_cpupic_setaffinity(unsigned int irq, const struct cpumask *mask) break; default: - set_bit(irq, irq_affinity_request); + set_bit(d->irq, irq_affinity_request); err = 0; break; } @@ -202,15 +206,15 @@ mn10300_cpupic_setaffinity(unsigned int irq, const struct cpumask *mask) * mask_ack() is provided), and mask_ack() just masks. */ static struct irq_chip mn10300_cpu_pic_level = { - .name = "cpu_l", - .disable = mn10300_cpupic_mask, - .enable = mn10300_cpupic_unmask_clear, - .ack = NULL, - .mask = mn10300_cpupic_mask, - .mask_ack = mn10300_cpupic_mask, - .unmask = mn10300_cpupic_unmask_clear, + .name = "cpu_l", + .irq_disable = mn10300_cpupic_mask, + .irq_enable = mn10300_cpupic_unmask_clear, + .irq_ack = NULL, + .irq_mask = mn10300_cpupic_mask, + .irq_mask_ack = mn10300_cpupic_mask, + .irq_unmask = mn10300_cpupic_unmask_clear, #ifdef CONFIG_SMP - .set_affinity = mn10300_cpupic_setaffinity, + .irq_set_affinity = mn10300_cpupic_setaffinity, #endif }; @@ -220,15 +224,15 @@ static struct irq_chip mn10300_cpu_pic_level = { * We use the latch clearing function of the PIC as the 'ACK' function. */ static struct irq_chip mn10300_cpu_pic_edge = { - .name = "cpu_e", - .disable = mn10300_cpupic_mask, - .enable = mn10300_cpupic_unmask, - .ack = mn10300_cpupic_ack, - .mask = mn10300_cpupic_mask, - .mask_ack = mn10300_cpupic_mask_ack, - .unmask = mn10300_cpupic_unmask, + .name = "cpu_e", + .irq_disable = mn10300_cpupic_mask, + .irq_enable = mn10300_cpupic_unmask, + .irq_ack = mn10300_cpupic_ack, + .irq_mask = mn10300_cpupic_mask, + .irq_mask_ack = mn10300_cpupic_mask_ack, + .irq_unmask = mn10300_cpupic_unmask, #ifdef CONFIG_SMP - .set_affinity = mn10300_cpupic_setaffinity, + .irq_set_affinity = mn10300_cpupic_setaffinity, #endif }; @@ -271,7 +275,7 @@ void __init init_IRQ(void) int irq; for (irq = 0; irq < NR_IRQS; irq++) - if (irq_desc[irq].chip == &no_irq_chip) + if (get_irq_chip(irq) == &no_irq_chip) /* due to the PIC latching interrupt requests, even * when the IRQ is disabled, IRQ_PENDING is superfluous * and we can use handle_level_irq() for edge-triggered -- GitLab From b023ba598c86747ded27d549f0225cf384c2e132 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Fri, 18 Mar 2011 16:52:52 +0000 Subject: [PATCH 0885/2822] MN10300: Convert serial irq_chip to new functions Signed-off-by: Thomas Gleixner Signed-off-by: David Howells --- arch/mn10300/kernel/mn10300-serial.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/arch/mn10300/kernel/mn10300-serial.c b/arch/mn10300/kernel/mn10300-serial.c index 94f3b54c6eca5..93c53739cfc94 100644 --- a/arch/mn10300/kernel/mn10300-serial.c +++ b/arch/mn10300/kernel/mn10300-serial.c @@ -384,16 +384,21 @@ static void mn10300_serial_mask_ack(unsigned int irq) arch_local_irq_restore(flags); } -static void mn10300_serial_nop(unsigned int irq) +static void mn10300_serial_chip_mask_ack(struct irq_data *d) +{ + mn10300_serial_mask_ack(d->irq); +} + +static void mn10300_serial_nop(struct irq_data *d) { } static struct irq_chip mn10300_serial_pic = { .name = "mnserial", - .ack = mn10300_serial_mask_ack, - .mask = mn10300_serial_mask_ack, - .mask_ack = mn10300_serial_mask_ack, - .unmask = mn10300_serial_nop, + .irq_ack = mn10300_serial_chip_mask_ack, + .irq_mask = mn10300_serial_chip_mask_ack, + .irq_mask_ack = mn10300_serial_chip_mask_ack, + .irq_unmask = mn10300_serial_nop, }; -- GitLab From 3ba65467f046fb58ae6fd93793fbe21119a8d875 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Fri, 18 Mar 2011 16:52:52 +0000 Subject: [PATCH 0886/2822] MN10300: Convert ipi irq_chip to new functions Signed-off-by: Thomas Gleixner Signed-off-by: David Howells --- arch/mn10300/kernel/smp.c | 30 ++++++++++++++++++++++-------- 1 file changed, 22 insertions(+), 8 deletions(-) diff --git a/arch/mn10300/kernel/smp.c b/arch/mn10300/kernel/smp.c index 0dcd1c686ba8e..1ebb79f1650d7 100644 --- a/arch/mn10300/kernel/smp.c +++ b/arch/mn10300/kernel/smp.c @@ -113,15 +113,17 @@ static void init_ipi(void); */ static void mn10300_ipi_disable(unsigned int irq); static void mn10300_ipi_enable(unsigned int irq); -static void mn10300_ipi_ack(unsigned int irq); -static void mn10300_ipi_nop(unsigned int irq); +static void mn10300_ipi_chip_disable(struct irq_data *d); +static void mn10300_ipi_chip_enable(struct irq_data *d); +static void mn10300_ipi_ack(struct irq_data *d); +static void mn10300_ipi_nop(struct irq_data *d); static struct irq_chip mn10300_ipi_type = { .name = "cpu_ipi", - .disable = mn10300_ipi_disable, - .enable = mn10300_ipi_enable, - .ack = mn10300_ipi_ack, - .eoi = mn10300_ipi_nop + .irq_disable = mn10300_ipi_chip_disable, + .irq_enable = mn10300_ipi_chip_enable, + .irq_ack = mn10300_ipi_ack, + .irq_eoi = mn10300_ipi_nop }; static irqreturn_t smp_reschedule_interrupt(int irq, void *dev_id); @@ -236,6 +238,11 @@ static void mn10300_ipi_enable(unsigned int irq) arch_local_irq_restore(flags); } +static void mn10300_ipi_chip_enable(struct irq_data *d) +{ + mn10300_ipi_enable(d->irq); +} + /** * mn10300_ipi_disable - Disable an IPI * @irq: The IPI to be disabled. @@ -254,6 +261,12 @@ static void mn10300_ipi_disable(unsigned int irq) arch_local_irq_restore(flags); } +static void mn10300_ipi_chip_disable(struct irq_data *d) +{ + mn10300_ipi_disable(d->irq); +} + + /** * mn10300_ipi_ack - Acknowledge an IPI interrupt in the PIC * @irq: The IPI to be acknowledged. @@ -261,8 +274,9 @@ static void mn10300_ipi_disable(unsigned int irq) * Clear the interrupt detection flag for the IPI on the appropriate interrupt * channel in the PIC. */ -static void mn10300_ipi_ack(unsigned int irq) +static void mn10300_ipi_ack(struct irq_data *d) { + unsigned int irq = d->irq; unsigned long flags; u16 tmp; @@ -276,7 +290,7 @@ static void mn10300_ipi_ack(unsigned int irq) * mn10300_ipi_nop - Dummy IPI action * @irq: The IPI to be acted upon. */ -static void mn10300_ipi_nop(unsigned int irq) +static void mn10300_ipi_nop(struct irq_data *d) { } -- GitLab From 1ddc4a38ca008b3a399ff7a6643076a50f0a2d11 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Fri, 18 Mar 2011 16:52:52 +0000 Subject: [PATCH 0887/2822] MN10300: Convert ASB2364 FPGA irq_chip to new functions Signed-off-by: Thomas Gleixner Signed-off-by: David Howells --- arch/mn10300/unit-asb2364/irq-fpga.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/arch/mn10300/unit-asb2364/irq-fpga.c b/arch/mn10300/unit-asb2364/irq-fpga.c index fcf29754e4d17..4204a6c62a254 100644 --- a/arch/mn10300/unit-asb2364/irq-fpga.c +++ b/arch/mn10300/unit-asb2364/irq-fpga.c @@ -17,38 +17,38 @@ /* * FPGA PIC operations */ -static void asb2364_fpga_mask(unsigned int irq) +static void asb2364_fpga_mask(struct irq_data *d) { - ASB2364_FPGA_REG_MASK(irq - NR_CPU_IRQS) = 0x0001; + ASB2364_FPGA_REG_MASK(d->irq - NR_CPU_IRQS) = 0x0001; SyncExBus(); } -static void asb2364_fpga_ack(unsigned int irq) +static void asb2364_fpga_ack(struct irq_data *d) { - ASB2364_FPGA_REG_IRQ(irq - NR_CPU_IRQS) = 0x0001; + ASB2364_FPGA_REG_IRQ(d->irq - NR_CPU_IRQS) = 0x0001; SyncExBus(); } -static void asb2364_fpga_mask_ack(unsigned int irq) +static void asb2364_fpga_mask_ack(struct irq_data *d) { - ASB2364_FPGA_REG_MASK(irq - NR_CPU_IRQS) = 0x0001; + ASB2364_FPGA_REG_MASK(d->irq - NR_CPU_IRQS) = 0x0001; SyncExBus(); - ASB2364_FPGA_REG_IRQ(irq - NR_CPU_IRQS) = 0x0001; + ASB2364_FPGA_REG_IRQ(d->irq - NR_CPU_IRQS) = 0x0001; SyncExBus(); } -static void asb2364_fpga_unmask(unsigned int irq) +static void asb2364_fpga_unmask(struct irq_data *d) { - ASB2364_FPGA_REG_MASK(irq - NR_CPU_IRQS) = 0x0000; + ASB2364_FPGA_REG_MASK(d->irq - NR_CPU_IRQS) = 0x0000; SyncExBus(); } static struct irq_chip asb2364_fpga_pic = { .name = "fpga", - .ack = asb2364_fpga_ack, - .mask = asb2364_fpga_mask, - .mask_ack = asb2364_fpga_mask_ack, - .unmask = asb2364_fpga_unmask, + .irq_ack = asb2364_fpga_ack, + .irq_mask = asb2364_fpga_mask, + .irq_mask_ack = asb2364_fpga_mask_ack, + .irq_unmask = asb2364_fpga_unmask, }; /* -- GitLab From 4692edbd4c5ab58c4e17f8cba136d93104254a15 Mon Sep 17 00:00:00 2001 From: David Howells Date: Fri, 18 Mar 2011 16:52:53 +0000 Subject: [PATCH 0888/2822] MN10300: Select HAVE_GENERIC_HARDIRQS rather than GENERIC_HARDIRQS Select HAVE_GENERIC_HARDIRQS rather than GENERIC_HARDIRQS in MN10300's main Kconfig file to avoid this warning: warning: (MN10300) selects GENERIC_HARDIRQS which has unmet direct dependencies (HAVE_GENERIC_HARDIRQS) Signed-off-by: David Howells --- arch/mn10300/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/mn10300/Kconfig b/arch/mn10300/Kconfig index 8b979ff4373ec..e207701c25905 100644 --- a/arch/mn10300/Kconfig +++ b/arch/mn10300/Kconfig @@ -1,7 +1,7 @@ config MN10300 def_bool y select HAVE_OPROFILE - select GENERIC_HARDIRQS + select HAVE_GENERIC_HARDIRQS config AM33_2 def_bool n -- GitLab From df43b86b411dcc1e6ddbd9b7a44357c28d523bad Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Fri, 18 Mar 2011 16:52:53 +0000 Subject: [PATCH 0889/2822] MN10300: Select GENERIC_HARDIRQS_NO_DEPRECATED All chips converted. Signed-off-by: Thomas Gleixner Signed-off-by: David Howells --- arch/mn10300/Kconfig | 1 + arch/mn10300/kernel/cevt-mn10300.c | 6 +++--- arch/mn10300/kernel/irq.c | 4 ++-- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/arch/mn10300/Kconfig b/arch/mn10300/Kconfig index e207701c25905..10971be430615 100644 --- a/arch/mn10300/Kconfig +++ b/arch/mn10300/Kconfig @@ -2,6 +2,7 @@ config MN10300 def_bool y select HAVE_OPROFILE select HAVE_GENERIC_HARDIRQS + select GENERIC_HARDIRQS_NO_DEPRECATED config AM33_2 def_bool n diff --git a/arch/mn10300/kernel/cevt-mn10300.c b/arch/mn10300/kernel/cevt-mn10300.c index 9eb387adea7cc..69cae02607862 100644 --- a/arch/mn10300/kernel/cevt-mn10300.c +++ b/arch/mn10300/kernel/cevt-mn10300.c @@ -111,9 +111,9 @@ int __init init_clockevents(void) #if defined(CONFIG_SMP) && !defined(CONFIG_GENERIC_CLOCKEVENTS_BROADCAST) /* setup timer irq affinity so it only runs on this cpu */ { - struct irq_desc *desc; - desc = irq_to_desc(cd->irq); - cpumask_copy(desc->affinity, cpumask_of(cpu)); + struct irq_data *data; + data = irq_get_irq_data(cd->irq); + cpumask_copy(data->affinity, cpumask_of(cpu)); iact->flags |= IRQF_NOBALANCING; } #endif diff --git a/arch/mn10300/kernel/irq.c b/arch/mn10300/kernel/irq.c index cd36a6c62770a..f09fed5e6afc2 100644 --- a/arch/mn10300/kernel/irq.c +++ b/arch/mn10300/kernel/irq.c @@ -363,12 +363,12 @@ int show_interrupts(struct seq_file *p, void *v) if (i < NR_CPU_IRQS) seq_printf(p, " %14s.%u", - irq_desc[i].chip->name, + irq_desc[i].irq_data.chip->name, (GxICR(i) & GxICR_LEVEL) >> GxICR_LEVEL_SHIFT); else seq_printf(p, " %14s", - irq_desc[i].chip->name); + irq_desc[i].irq_data.chip->name); seq_printf(p, " %s", action->name); -- GitLab From 5f91a1affc4f94589e386f9a687d7c3ecb944df4 Mon Sep 17 00:00:00 2001 From: David Howells Date: Fri, 18 Mar 2011 16:52:53 +0000 Subject: [PATCH 0890/2822] MN10300: Fix ASB2364 FPGA register defs Fix the definition of the ASB2364 FPGA IRQ detect registers. They accidentally got defined to be the same as the mask registers when the patches were being ported to the upstream kernel. Signed-off-by: David Howells --- arch/mn10300/unit-asb2364/include/unit/fpga-regs.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/mn10300/unit-asb2364/include/unit/fpga-regs.h b/arch/mn10300/unit-asb2364/include/unit/fpga-regs.h index 7cf12054db65d..33f100f9b468e 100644 --- a/arch/mn10300/unit-asb2364/include/unit/fpga-regs.h +++ b/arch/mn10300/unit-asb2364/include/unit/fpga-regs.h @@ -14,7 +14,7 @@ #define ASB2364_FPGA_REG_RESET_USB __SYSREG(0xa900130c, u16) #define ASB2364_FPGA_REG_RESET_AV __SYSREG(0xa9001310, u16) -#define ASB2364_FPGA_REG_IRQ(X) __SYSREG(0xa9001590+((X)*4), u16) +#define ASB2364_FPGA_REG_IRQ(X) __SYSREG(0xa9001510+((X)*4), u16) #define ASB2364_FPGA_REG_IRQ_LAN ASB2364_FPGA_REG_IRQ(0) #define ASB2364_FPGA_REG_IRQ_UART ASB2364_FPGA_REG_IRQ(1) #define ASB2364_FPGA_REG_IRQ_I2C ASB2364_FPGA_REG_IRQ(2) -- GitLab From 02b2944cd70c3166984699dd623612e2f8a3eebf Mon Sep 17 00:00:00 2001 From: David Howells Date: Fri, 18 Mar 2011 16:52:54 +0000 Subject: [PATCH 0891/2822] MN10300: Fix the ASB2364 gdbport UART register defs Fix the ASB2364 gdbport UART register definitions. These registers are actually 2 bytes apart, not 4 (which the ASB2303 and ASB2305 are). Signed-off-by: David Howells --- .../unit-asb2364/include/unit/serial.h | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/arch/mn10300/unit-asb2364/include/unit/serial.h b/arch/mn10300/unit-asb2364/include/unit/serial.h index 7f048bbfdfd7f..92f224a97efcc 100644 --- a/arch/mn10300/unit-asb2364/include/unit/serial.h +++ b/arch/mn10300/unit-asb2364/include/unit/serial.h @@ -59,18 +59,18 @@ static inline void __debug_to_serial(const char *p, int n) #define SERIAL_PORT_DFNS /* stolen by gdb-stub */ #if defined(CONFIG_GDBSTUB_ON_TTYS0) -#define GDBPORT_SERIAL_RX __SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_RX * 4, u8) -#define GDBPORT_SERIAL_TX __SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_TX * 4, u8) -#define GDBPORT_SERIAL_DLL __SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_DLL * 4, u8) -#define GDBPORT_SERIAL_DLM __SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_DLM * 4, u8) -#define GDBPORT_SERIAL_IER __SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_IER * 4, u8) -#define GDBPORT_SERIAL_IIR __SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_IIR * 4, u8) -#define GDBPORT_SERIAL_FCR __SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_FCR * 4, u8) -#define GDBPORT_SERIAL_LCR __SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_LCR * 4, u8) -#define GDBPORT_SERIAL_MCR __SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_MCR * 4, u8) -#define GDBPORT_SERIAL_LSR __SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_LSR * 4, u8) -#define GDBPORT_SERIAL_MSR __SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_MSR * 4, u8) -#define GDBPORT_SERIAL_SCR __SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_SCR * 4, u8) +#define GDBPORT_SERIAL_RX __SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_RX * 2, u8) +#define GDBPORT_SERIAL_TX __SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_TX * 2, u8) +#define GDBPORT_SERIAL_DLL __SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_DLL * 2, u8) +#define GDBPORT_SERIAL_DLM __SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_DLM * 2, u8) +#define GDBPORT_SERIAL_IER __SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_IER * 2, u8) +#define GDBPORT_SERIAL_IIR __SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_IIR * 2, u8) +#define GDBPORT_SERIAL_FCR __SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_FCR * 2, u8) +#define GDBPORT_SERIAL_LCR __SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_LCR * 2, u8) +#define GDBPORT_SERIAL_MCR __SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_MCR * 2, u8) +#define GDBPORT_SERIAL_LSR __SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_LSR * 2, u8) +#define GDBPORT_SERIAL_MSR __SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_MSR * 2, u8) +#define GDBPORT_SERIAL_SCR __SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_SCR * 2, u8) #define GDBPORT_SERIAL_IRQ SERIAL_IRQ #elif defined(CONFIG_GDBSTUB_ON_TTYS1) -- GitLab From ddb7d1e975d224885397c002512ded987be3c3bc Mon Sep 17 00:00:00 2001 From: David Howells Date: Fri, 18 Mar 2011 16:52:54 +0000 Subject: [PATCH 0892/2822] MN10300: Clear ASB2364 peripheral interrupt masks before enabling interrupts Clear the interrupt mask registers of ASB2364 peripherals before enabling interrupts so that any peripherals that weren't dealt with by the bootloader after a reboot (if there was one) won't cause an interrupt storm when interrupts are first enabled before the drivers are initialised. Also, attempt to reset the peripherals attached to the FPGA. Signed-off-by: David Howells --- arch/mn10300/unit-asb2364/irq-fpga.c | 11 +++++++ arch/mn10300/unit-asb2364/unit-init.c | 44 +++++++++++++++++++++++++++ 2 files changed, 55 insertions(+) diff --git a/arch/mn10300/unit-asb2364/irq-fpga.c b/arch/mn10300/unit-asb2364/irq-fpga.c index 4204a6c62a254..ee84e62b16ede 100644 --- a/arch/mn10300/unit-asb2364/irq-fpga.c +++ b/arch/mn10300/unit-asb2364/irq-fpga.c @@ -88,6 +88,17 @@ void __init irq_fpga_init(void) { int irq; + ASB2364_FPGA_REG_MASK_LAN = 0x0001; + SyncExBus(); + ASB2364_FPGA_REG_MASK_UART = 0x0001; + SyncExBus(); + ASB2364_FPGA_REG_MASK_I2C = 0x0001; + SyncExBus(); + ASB2364_FPGA_REG_MASK_USB = 0x0001; + SyncExBus(); + ASB2364_FPGA_REG_MASK_FPGA = 0x0001; + SyncExBus(); + for (irq = NR_CPU_IRQS; irq < NR_IRQS; irq++) set_irq_chip_and_handler(irq, &asb2364_fpga_pic, handle_level_irq); diff --git a/arch/mn10300/unit-asb2364/unit-init.c b/arch/mn10300/unit-asb2364/unit-init.c index 11440803db10f..6359b41ce7e97 100644 --- a/arch/mn10300/unit-asb2364/unit-init.c +++ b/arch/mn10300/unit-asb2364/unit-init.c @@ -20,13 +20,41 @@ #include #include #include +#include #include +#include +#include + +#define TTYS0_SERIAL_IER __SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_IER * 2, u8) +#define LAN_IRQ_CFG __SYSREG(SMSC911X_BASE + 0x54, u32) +#define LAN_INT_EN __SYSREG(SMSC911X_BASE + 0x5c, u32) /* * initialise some of the unit hardware before gdbstub is set up */ asmlinkage void __init unit_init(void) { + /* Make sure we aren't going to get unexpected interrupts */ + TTYS0_SERIAL_IER = 0; + SC0RXICR = 0; + SC0TXICR = 0; + SC1RXICR = 0; + SC1TXICR = 0; + SC2RXICR = 0; + SC2TXICR = 0; + + /* Attempt to reset the FPGA attached peripherals */ + ASB2364_FPGA_REG_RESET_LAN = 0x0000; + SyncExBus(); + ASB2364_FPGA_REG_RESET_UART = 0x0000; + SyncExBus(); + ASB2364_FPGA_REG_RESET_I2C = 0x0000; + SyncExBus(); + ASB2364_FPGA_REG_RESET_USB = 0x0000; + SyncExBus(); + ASB2364_FPGA_REG_RESET_AV = 0x0000; + SyncExBus(); + /* set up the external interrupts */ /* XIRQ[0]: NAND RXBY */ @@ -56,7 +84,23 @@ asmlinkage void __init unit_init(void) */ asmlinkage void __init unit_setup(void) { + /* Release the reset on the SMSC911X so that it is ready by the time we + * need it */ + ASB2364_FPGA_REG_RESET_LAN = 0x0001; + SyncExBus(); + ASB2364_FPGA_REG_RESET_UART = 0x0001; + SyncExBus(); + ASB2364_FPGA_REG_RESET_I2C = 0x0001; + SyncExBus(); + ASB2364_FPGA_REG_RESET_USB = 0x0001; + SyncExBus(); + ASB2364_FPGA_REG_RESET_AV = 0x0001; + SyncExBus(); + /* Make sure the ethernet chipset isn't going to give us an interrupt + * storm from stuff it was doing pre-reset */ + LAN_IRQ_CFG = 0; + LAN_INT_EN = 0; } /* -- GitLab From 9ee21723ccc30070f47c411826d4ed013cd050c2 Mon Sep 17 00:00:00 2001 From: David Howells Date: Fri, 18 Mar 2011 16:54:29 +0000 Subject: [PATCH 0893/2822] MN10300: gdbstub: Restrict single-stepping to non-preemptable non-SMP configs Restrict single-stepping through the kernel using gdbstub to non-preemptable non-SMP configs as gdbstub has to do software single-stepping by means of temporary breakpoints. Hardware single-stepping is unavailable as Panasonic have not sufficiently documented the interface to it. Software single-stepping through preemptable or SMP kernels runs into problems as it makes it much more likely that the wrong thread will hit the temporary breakpoints. It seems impractical to work around the problem for the most part. It could be possible to make a UP preemptable kernel switch temporary breakpoints in and out in switch_to(). Signed-off-by: David Howells --- arch/mn10300/Kconfig.debug | 8 ++++++++ arch/mn10300/kernel/gdb-stub.c | 12 ++++++++++-- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/arch/mn10300/Kconfig.debug b/arch/mn10300/Kconfig.debug index ce83c74b3fd71..a1b8620f65ae4 100644 --- a/arch/mn10300/Kconfig.debug +++ b/arch/mn10300/Kconfig.debug @@ -54,6 +54,14 @@ config GDBSTUB_IMMEDIATE possible, leaving the program counter at the beginning of start_kernel() in init/main.c. +config GDBSTUB_ALLOW_SINGLE_STEP + bool "Allow software single-stepping in GDB stub" + depends on GDBSTUB && !SMP && !PREEMPT + help + Allow GDB stub to perform software single-stepping through the + kernel. This doesn't work very well on SMP or preemptible kernels as + it uses temporary breakpoints to emulate single-stepping. + config GDB_CONSOLE bool "Console output to GDB" depends on GDBSTUB diff --git a/arch/mn10300/kernel/gdb-stub.c b/arch/mn10300/kernel/gdb-stub.c index b169d99d9f20e..a9c1e916687ff 100644 --- a/arch/mn10300/kernel/gdb-stub.c +++ b/arch/mn10300/kernel/gdb-stub.c @@ -405,6 +405,7 @@ static int hexToInt(char **ptr, int *intValue) return (numChars); } +#ifdef CONFIG_GDBSTUB_ALLOW_SINGLE_STEP /* * We single-step by setting breakpoints. When an exception * is handled, we need to restore the instructions hoisted @@ -729,6 +730,7 @@ static int gdbstub_single_step(struct pt_regs *regs) __gdbstub_restore_bp(); return -EFAULT; } +#endif /* CONFIG_GDBSTUB_ALLOW_SINGLE_STEP */ #ifdef CONFIG_GDBSTUB_CONSOLE @@ -1208,11 +1210,13 @@ static int gdbstub(struct pt_regs *regs, enum exception_code excep) /* if we were single stepping, restore the opcodes hoisted for the * breakpoint[s] */ broke = 0; +#ifdef CONFIG_GDBSTUB_ALLOW_SINGLE_STEP if ((step_bp[0].addr && step_bp[0].addr == (u8 *) regs->pc) || (step_bp[1].addr && step_bp[1].addr == (u8 *) regs->pc)) broke = 1; __gdbstub_restore_bp(); +#endif if (gdbstub_rx_unget) { sigval = SIGINT; @@ -1548,17 +1552,21 @@ packet_waiting: * Step to next instruction */ case 's': - /* - * using the T flag doesn't seem to perform single + /* Using the T flag doesn't seem to perform single * stepping (it seems to wind up being caught by the * JTAG unit), so we have to use breakpoints and * continue instead. */ +#ifdef CONFIG_GDBSTUB_ALLOW_SINGLE_STEP if (gdbstub_single_step(regs) < 0) /* ignore any fault error for now */ gdbstub_printk("unable to set single-step" " bp\n"); goto done; +#else + gdbstub_strcpy(output_buffer, "E01"); + break; +#endif /* * Set baud rate (bBB) -- GitLab From b75bb2365d50f73c09e42cf2de07f5805a3988ea Mon Sep 17 00:00:00 2001 From: David Howells Date: Fri, 18 Mar 2011 16:54:29 +0000 Subject: [PATCH 0894/2822] MN10300: The icache invalidate functions should disable the icache first The icache invalidate functions should disable the icache on AM33 and wait for it to quiesce before attempting to invalidate it, and should then wait for it to quiesce again before reenabling it, but on AM34 they should invalidate directly. The same goes for the dcache invalidation, but this isn't used much. Whilst we're at it, this can be wrapped in assembler macros to remove duplicate code. The AM33 manual states that: An operation that invalidates the cache, switches the writing mode, or changes the way mode must be performed after disabling the cache, checking the busy bit, and confirming that the cache is not in operation. for the dcache [sec 2.8.3.2.1]. This is not stated so for the icache [sec 2.8.3.1.1] but the example code there suggests that it is. Whilst the AM34 manual states that the cache must be disabled for both the icache [sec 1.8.3.2.1] and the dcache [sec 1.8.3.2.1], the Panasonic hardware engineers say the manual is wrong and that disabling the caches for invalidation is wrong. Furthermore, they say that disabling the caches on the AM34 whilst running an SMP kernel can lead to incoherency between the various CPU caches and should thus be avoided. Signed-off-by: David Howells --- arch/mn10300/mm/cache-inv-by-reg.S | 13 +-- arch/mn10300/mm/cache-inv-by-tag.S | 77 +---------------- arch/mn10300/mm/cache.inc | 133 +++++++++++++++++++++++++++++ 3 files changed, 140 insertions(+), 83 deletions(-) create mode 100644 arch/mn10300/mm/cache.inc diff --git a/arch/mn10300/mm/cache-inv-by-reg.S b/arch/mn10300/mm/cache-inv-by-reg.S index c8950861ed779..d1f363a8d36b9 100644 --- a/arch/mn10300/mm/cache-inv-by-reg.S +++ b/arch/mn10300/mm/cache-inv-by-reg.S @@ -15,6 +15,7 @@ #include #include #include +#include "cache.inc" #define mn10300_local_dcache_inv_range_intr_interval \ +((1 << MN10300_DCACHE_INV_RANGE_INTR_LOG2_INTERVAL) - 1) @@ -62,10 +63,7 @@ mn10300_local_icache_inv: btst CHCTR_ICEN,d0 beq mn10300_local_icache_inv_end - # invalidate - or CHCTR_ICINV,d0 - movhu d0,(a0) - movhu (a0),d0 + invalidate_icache 1 mn10300_local_icache_inv_end: ret [],0 @@ -87,11 +85,8 @@ mn10300_local_dcache_inv: btst CHCTR_DCEN,d0 beq mn10300_local_dcache_inv_end - # invalidate - or CHCTR_DCINV,d0 - movhu d0,(a0) - movhu (a0),d0 - + invalidate_dcache 1 + mn10300_local_dcache_inv_end: ret [],0 .size mn10300_local_dcache_inv,.-mn10300_local_dcache_inv diff --git a/arch/mn10300/mm/cache-inv-by-tag.S b/arch/mn10300/mm/cache-inv-by-tag.S index e9713b40c0ff4..c5c80322eefb5 100644 --- a/arch/mn10300/mm/cache-inv-by-tag.S +++ b/arch/mn10300/mm/cache-inv-by-tag.S @@ -15,6 +15,7 @@ #include #include #include +#include "cache.inc" #define mn10300_local_dcache_inv_range_intr_interval \ +((1 << MN10300_DCACHE_INV_RANGE_INTR_LOG2_INTERVAL) - 1) @@ -70,43 +71,7 @@ mn10300_local_icache_inv: btst CHCTR_ICEN,d0 beq mn10300_local_icache_inv_end -#if defined(CONFIG_AM33_2) || defined(CONFIG_AM33_3) - LOCAL_CLI_SAVE(d1) - - # disable the icache - and ~CHCTR_ICEN,d0 - movhu d0,(a0) - - # and wait for it to calm down - setlb - movhu (a0),d0 - btst CHCTR_ICBUSY,d0 - lne - - # invalidate - or CHCTR_ICINV,d0 - movhu d0,(a0) - - # wait for the cache to finish - mov CHCTR,a0 - setlb - movhu (a0),d0 - btst CHCTR_ICBUSY,d0 - lne - - # and reenable it - and ~CHCTR_ICINV,d0 - or CHCTR_ICEN,d0 - movhu d0,(a0) - movhu (a0),d0 - - LOCAL_IRQ_RESTORE(d1) -#else /* CONFIG_AM33_2 || CONFIG_AM33_3 */ - # invalidate - or CHCTR_ICINV,d0 - movhu d0,(a0) - movhu (a0),d0 -#endif /* CONFIG_AM33_2 || CONFIG_AM33_3 */ + invalidate_icache 1 mn10300_local_icache_inv_end: ret [],0 @@ -128,43 +93,7 @@ mn10300_local_dcache_inv: btst CHCTR_DCEN,d0 beq mn10300_local_dcache_inv_end -#if defined(CONFIG_AM33_2) || defined(CONFIG_AM33_3) - LOCAL_CLI_SAVE(d1) - - # disable the dcache - and ~CHCTR_DCEN,d0 - movhu d0,(a0) - - # and wait for it to calm down - setlb - movhu (a0),d0 - btst CHCTR_DCBUSY,d0 - lne - - # invalidate - or CHCTR_DCINV,d0 - movhu d0,(a0) - - # wait for the cache to finish - mov CHCTR,a0 - setlb - movhu (a0),d0 - btst CHCTR_DCBUSY,d0 - lne - - # and reenable it - and ~CHCTR_DCINV,d0 - or CHCTR_DCEN,d0 - movhu d0,(a0) - movhu (a0),d0 - - LOCAL_IRQ_RESTORE(d1) -#else /* CONFIG_AM33_2 || CONFIG_AM33_3 */ - # invalidate - or CHCTR_DCINV,d0 - movhu d0,(a0) - movhu (a0),d0 -#endif /* CONFIG_AM33_2 || CONFIG_AM33_3 */ + invalidate_dcache 1 mn10300_local_dcache_inv_end: ret [],0 diff --git a/arch/mn10300/mm/cache.inc b/arch/mn10300/mm/cache.inc new file mode 100644 index 0000000000000..394a119b9c733 --- /dev/null +++ b/arch/mn10300/mm/cache.inc @@ -0,0 +1,133 @@ +/* MN10300 CPU core caching macros -*- asm -*- + * + * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public Licence + * as published by the Free Software Foundation; either version + * 2 of the Licence, or (at your option) any later version. + */ + + +############################################################################### +# +# Invalidate the instruction cache. +# A0: Should hold CHCTR +# D0: Should have been read from CHCTR +# D1: Will be clobbered +# +# On some cores it is necessary to disable the icache whilst we do this. +# +############################################################################### + .macro invalidate_icache,disable_irq + +#if defined(CONFIG_AM33_2) || defined(CONFIG_AM33_3) + .if \disable_irq + # don't want an interrupt routine seeing a disabled cache + mov epsw,d1 + and ~EPSW_IE,epsw + or EPSW_NMID,epsw + nop + nop + .endif + + # disable the icache + and ~CHCTR_ICEN,d0 + movhu d0,(a0) + + # and wait for it to calm down + setlb + movhu (a0),d0 + btst CHCTR_ICBUSY,d0 + lne + + # invalidate + or CHCTR_ICINV,d0 + movhu d0,(a0) + + # wait for the cache to finish + setlb + movhu (a0),d0 + btst CHCTR_ICBUSY,d0 + lne + + # and reenable it + or CHCTR_ICEN,d0 + movhu d0,(a0) + movhu (a0),d0 + + .if \disable_irq + LOCAL_IRQ_RESTORE(d1) + .endif + +#else /* CONFIG_AM33_2 || CONFIG_AM33_3 */ + + # invalidate + or CHCTR_ICINV,d0 + movhu d0,(a0) + movhu (a0),d0 + +#endif /* CONFIG_AM33_2 || CONFIG_AM33_3 */ + .endm + +############################################################################### +# +# Invalidate the data cache. +# A0: Should hold CHCTR +# D0: Should have been read from CHCTR +# D1: Will be clobbered +# +# On some cores it is necessary to disable the dcache whilst we do this. +# +############################################################################### + .macro invalidate_dcache,disable_irq + +#if defined(CONFIG_AM33_2) || defined(CONFIG_AM33_3) + .if \disable_irq + # don't want an interrupt routine seeing a disabled cache + mov epsw,d1 + and ~EPSW_IE,epsw + or EPSW_NMID,epsw + nop + nop + .endif + + # disable the dcache + and ~CHCTR_DCEN,d0 + movhu d0,(a0) + + # and wait for it to calm down + setlb + movhu (a0),d0 + btst CHCTR_DCBUSY,d0 + lne + + # invalidate + or CHCTR_DCINV,d0 + movhu d0,(a0) + + # wait for the cache to finish + setlb + movhu (a0),d0 + btst CHCTR_DCBUSY,d0 + lne + + # and reenable it + or CHCTR_DCEN,d0 + movhu d0,(a0) + movhu (a0),d0 + + .if \disable_irq + LOCAL_IRQ_RESTORE(d1) + .endif + +#else /* CONFIG_AM33_2 || CONFIG_AM33_3 */ + + # invalidate + or CHCTR_DCINV,d0 + movhu d0,(a0) + movhu (a0),d0 + +#endif /* CONFIG_AM33_2 || CONFIG_AM33_3 */ + .endm -- GitLab From 792576b1c5a4da16700f1003b1c3fc1e22cd9e07 Mon Sep 17 00:00:00 2001 From: David Howells Date: Fri, 18 Mar 2011 16:54:30 +0000 Subject: [PATCH 0895/2822] MN10300: Introduce a general config option for kernel debugger hooks Introduce a general config option for kernel debugger hooks so that both gdbstub and kgdb can use it and add a header file for both debuggers to use. Signed-off-by: David Howells --- arch/mn10300/Kconfig | 2 +- arch/mn10300/Kconfig.debug | 4 ++++ arch/mn10300/include/asm/debugger.h | 20 ++++++++++++++++++++ 3 files changed, 25 insertions(+), 1 deletion(-) create mode 100644 arch/mn10300/include/asm/debugger.h diff --git a/arch/mn10300/Kconfig b/arch/mn10300/Kconfig index 10971be430615..25e6a0bc62abc 100644 --- a/arch/mn10300/Kconfig +++ b/arch/mn10300/Kconfig @@ -403,7 +403,7 @@ comment "The following must be set to a higher priority than local_irq_disable() config GDBSTUB_IRQ_LEVEL int "GDBSTUB interrupt priority" - depends on GDBSTUB + depends on KERNEL_DEBUGGER range 0 1 if LINUX_CLI_LEVEL = 2 range 0 2 if LINUX_CLI_LEVEL = 3 range 0 3 if LINUX_CLI_LEVEL = 4 diff --git a/arch/mn10300/Kconfig.debug b/arch/mn10300/Kconfig.debug index a1b8620f65ae4..87adb8f434ee7 100644 --- a/arch/mn10300/Kconfig.debug +++ b/arch/mn10300/Kconfig.debug @@ -150,3 +150,7 @@ config GDBSTUB_ON_TTYSx default y endmenu + +config KERNEL_DEBUGGER + def_bool y + depends on GDBSTUB diff --git a/arch/mn10300/include/asm/debugger.h b/arch/mn10300/include/asm/debugger.h new file mode 100644 index 0000000000000..4816f0dc28b54 --- /dev/null +++ b/arch/mn10300/include/asm/debugger.h @@ -0,0 +1,20 @@ +/* Kernel debugger for MN10300 + * + * Copyright (C) 2011 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public Licence + * as published by the Free Software Foundation; either version + * 2 of the Licence, or (at your option) any later version. + */ + +#ifndef _ASM_DEBUGGER_H +#define _ASM_DEBUGGER_H + +#if defined(CONFIG_KERNEL_DEBUGGER) + +#else /* CONFIG_KERNEL_DEBUGGER */ + +#endif /* CONFIG_KERNEL_DEBUGGER */ +#endif /* _ASM_DEBUGGER_H */ -- GitLab From 7f386ac3272e057fbf51e5b5712fad1a80e77125 Mon Sep 17 00:00:00 2001 From: David Howells Date: Fri, 18 Mar 2011 16:54:30 +0000 Subject: [PATCH 0896/2822] MN10300: Create general kernel debugger cache flushing Create general kernel debugger cache flushing for MN10300 and get rid of the old stuff that gdbstub was using. Signed-off-by: David Howells --- arch/mn10300/include/asm/debugger.h | 8 + arch/mn10300/kernel/Makefile | 4 - arch/mn10300/kernel/entry.S | 31 +--- arch/mn10300/kernel/gdb-cache.S | 105 ------------ arch/mn10300/kernel/gdb-stub.c | 4 +- arch/mn10300/mm/Kconfig.cache | 46 +++++ arch/mn10300/mm/Makefile | 9 + arch/mn10300/mm/cache-dbg-flush-by-reg.S | 160 ++++++++++++++++++ arch/mn10300/mm/cache-dbg-flush-by-tag.S | 114 +++++++++++++ arch/mn10300/mm/cache-dbg-inv-by-reg.S | 69 ++++++++ arch/mn10300/mm/cache-dbg-inv-by-tag.S | 120 +++++++++++++ arch/mn10300/mm/cache-dbg-inv.S | 47 +++++ arch/mn10300/mm/cache-flush-by-tag.S | 13 +- arch/mn10300/mm/cache-inv-by-reg.S | 9 +- arch/mn10300/mm/cache-inv-by-tag.S | 9 +- .../proc-mn103e010/include/proc/cache.h | 1 + .../proc-mn2ws0050/include/proc/cache.h | 1 + 17 files changed, 592 insertions(+), 158 deletions(-) delete mode 100644 arch/mn10300/kernel/gdb-cache.S create mode 100644 arch/mn10300/mm/cache-dbg-flush-by-reg.S create mode 100644 arch/mn10300/mm/cache-dbg-flush-by-tag.S create mode 100644 arch/mn10300/mm/cache-dbg-inv-by-reg.S create mode 100644 arch/mn10300/mm/cache-dbg-inv-by-tag.S create mode 100644 arch/mn10300/mm/cache-dbg-inv.S diff --git a/arch/mn10300/include/asm/debugger.h b/arch/mn10300/include/asm/debugger.h index 4816f0dc28b54..4517f839a9993 100644 --- a/arch/mn10300/include/asm/debugger.h +++ b/arch/mn10300/include/asm/debugger.h @@ -14,6 +14,14 @@ #if defined(CONFIG_KERNEL_DEBUGGER) +#ifndef CONFIG_MN10300_DEBUGGER_CACHE_NO_FLUSH +extern void debugger_local_cache_flushinv(void); +extern void debugger_local_cache_flushinv_one(u8 *); +#else +static inline void debugger_local_cache_flushinv(void) {} +static inline void debugger_local_cache_flushinv_one(u8 *addr) {} +#endif + #else /* CONFIG_KERNEL_DEBUGGER */ #endif /* CONFIG_KERNEL_DEBUGGER */ diff --git a/arch/mn10300/kernel/Makefile b/arch/mn10300/kernel/Makefile index a06a2e10051d5..48ab4017434de 100644 --- a/arch/mn10300/kernel/Makefile +++ b/arch/mn10300/kernel/Makefile @@ -21,10 +21,6 @@ obj-$(CONFIG_GDBSTUB) += gdb-stub.o gdb-low.o obj-$(CONFIG_GDBSTUB_ON_TTYSx) += gdb-io-serial.o gdb-io-serial-low.o obj-$(CONFIG_GDBSTUB_ON_TTYSMx) += gdb-io-ttysm.o gdb-io-ttysm-low.o -ifeq ($(CONFIG_MN10300_CACHE_ENABLED),y) -obj-$(CONFIG_GDBSTUB) += gdb-cache.o -endif - obj-$(CONFIG_MN10300_RTC) += rtc.o obj-$(CONFIG_PROFILE) += profile.o profile-low.o obj-$(CONFIG_MODULES) += module.o diff --git a/arch/mn10300/kernel/entry.S b/arch/mn10300/kernel/entry.S index f00b9bafcd3eb..8e79a04f1cb09 100644 --- a/arch/mn10300/kernel/entry.S +++ b/arch/mn10300/kernel/entry.S @@ -306,36 +306,7 @@ ENTRY(nmi_handler) movbu d0,(GxICR(GDB_NMI_IPI)) movhu (GxICR(GDB_NMI_IPI)),d0 and ~EPSW_NMID,epsw # enable NMI -#ifdef CONFIG_MN10300_CACHE_ENABLED - mov (gdbstub_nmi_opr_type),d0 - cmp GDBSTUB_NMI_CACHE_PURGE,d0 - bne 4f # if not gdb cache purge, jump - - # gdb cache purge nmi ipi - add -20,sp - mov d1,(4,sp) - mov a0,(8,sp) - mov a1,(12,sp) - mov mdr,d0 - mov d0,(16,sp) - call gdbstub_local_purge_cache[],0 - mov 0x1,d0 - mov (CPUID),d1 - asl d1,d0 - mov gdbstub_nmi_cpumask,a0 - bclr d0,(a0) - mov (4,sp),d1 - mov (8,sp),a0 - mov (12,sp),a1 - mov (16,sp),d0 - mov d0,mdr - add 20,sp - mov (sp),d0 - add 4,sp - rti -4: -#endif /* CONFIG_MN10300_CACHE_ENABLED */ - # gdb wait nmi ipi + mov (sp),d0 SAVE_ALL call gdbstub_nmi_wait[],0 diff --git a/arch/mn10300/kernel/gdb-cache.S b/arch/mn10300/kernel/gdb-cache.S deleted file mode 100644 index 1108badc3d327..0000000000000 --- a/arch/mn10300/kernel/gdb-cache.S +++ /dev/null @@ -1,105 +0,0 @@ -############################################################################### -# -# MN10300 Low-level cache purging routines for gdbstub -# -# Copyright (C) 2007 Red Hat, Inc. All Rights Reserved. -# Written by David Howells (dhowells@redhat.com) -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public Licence -# as published by the Free Software Foundation; either version -# 2 of the Licence, or (at your option) any later version. -# -############################################################################### -#include -#include -#include -#include -#include -#include -#include -#include - - .text - -############################################################################### -# -# GDB stub cache purge -# -############################################################################### - .type gdbstub_purge_cache,@function -ENTRY(gdbstub_purge_cache) - ####################################################################### - # read the addresses tagged in the cache's tag RAM and attempt to flush - # those addresses specifically - # - we rely on the hardware to filter out invalid tag entry addresses - mov DCACHE_TAG(0,0),a0 # dcache tag RAM access address - mov DCACHE_PURGE(0,0),a1 # dcache purge request address - mov L1_CACHE_NWAYS*L1_CACHE_NENTRIES,d1 # total number of entries - -mn10300_dcache_flush_loop: - mov (a0),d0 - and L1_CACHE_TAG_ADDRESS|L1_CACHE_TAG_ENTRY,d0 - or L1_CACHE_TAG_VALID,d0 # retain valid entries in the - # cache - mov d0,(a1) # conditional purge - -mn10300_dcache_flush_skip: - add L1_CACHE_BYTES,a0 - add L1_CACHE_BYTES,a1 - add -1,d1 - bne mn10300_dcache_flush_loop - -;; # unconditionally flush and invalidate the dcache -;; mov DCACHE_PURGE(0,0),a1 # dcache purge request address -;; mov L1_CACHE_NWAYS*L1_CACHE_NENTRIES,d1 # total number of -;; # entries -;; -;; gdbstub_purge_cache__dcache_loop: -;; mov (a1),d0 # unconditional purge -;; -;; add L1_CACHE_BYTES,a1 -;; add -1,d1 -;; bne gdbstub_purge_cache__dcache_loop - - ####################################################################### - # now invalidate the icache - mov CHCTR,a0 - movhu (a0),a1 - - mov epsw,d1 - and ~EPSW_IE,epsw - nop - nop - - # disable the icache - and ~CHCTR_ICEN,d0 - movhu d0,(a0) - - # and wait for it to calm down - setlb - movhu (a0),d0 - btst CHCTR_ICBUSY,d0 - lne - - # invalidate - or CHCTR_ICINV,d0 - movhu d0,(a0) - - # wait for the cache to finish - mov CHCTR,a0 - setlb - movhu (a0),d0 - btst CHCTR_ICBUSY,d0 - lne - - # and reenable it - movhu a1,(a0) - movhu (a0),d0 # read back to flush - # (SIGILLs all over without this) - - mov d1,epsw - - ret [],0 - - .size gdbstub_purge_cache,.-gdbstub_purge_cache diff --git a/arch/mn10300/kernel/gdb-stub.c b/arch/mn10300/kernel/gdb-stub.c index a9c1e916687ff..1e8f24f006372 100644 --- a/arch/mn10300/kernel/gdb-stub.c +++ b/arch/mn10300/kernel/gdb-stub.c @@ -133,7 +133,7 @@ #include #include #include -#include +#include #include #include #include @@ -1665,7 +1665,7 @@ done: * NB: We flush both caches, just to be sure... */ if (gdbstub_flush_caches) - gdbstub_purge_cache(); + debugger_local_cache_flushinv(); gdbstub_load_fpu(); mn10300_set_gdbleds(0); diff --git a/arch/mn10300/mm/Kconfig.cache b/arch/mn10300/mm/Kconfig.cache index c4fd923a55a09..bfbe52691f2c8 100644 --- a/arch/mn10300/mm/Kconfig.cache +++ b/arch/mn10300/mm/Kconfig.cache @@ -99,3 +99,49 @@ config MN10300_CACHE_INV_ICACHE help Set if we need the icache to be invalidated, even if the dcache is in write-through mode and doesn't need flushing. + +# +# The kernel debugger gets its own separate cache flushing functions +# +config MN10300_DEBUGGER_CACHE_FLUSH_BY_TAG + def_bool y if KERNEL_DEBUGGER && \ + MN10300_CACHE_WBACK && \ + !MN10300_CACHE_SNOOP && \ + MN10300_CACHE_MANAGE_BY_TAG + help + Set if the debugger needs to flush the dcache and invalidate the + icache using the cache tag registers to make breakpoints work. + +config MN10300_DEBUGGER_CACHE_FLUSH_BY_REG + def_bool y if KERNEL_DEBUGGER && \ + MN10300_CACHE_WBACK && \ + !MN10300_CACHE_SNOOP && \ + MN10300_CACHE_MANAGE_BY_REG + help + Set if the debugger needs to flush the dcache and invalidate the + icache using automatic purge registers to make breakpoints work. + +config MN10300_DEBUGGER_CACHE_INV_BY_TAG + def_bool y if KERNEL_DEBUGGER && \ + MN10300_CACHE_WTHRU && \ + !MN10300_CACHE_SNOOP && \ + MN10300_CACHE_MANAGE_BY_TAG + help + Set if the debugger needs to invalidate the icache using the cache + tag registers to make breakpoints work. + +config MN10300_DEBUGGER_CACHE_INV_BY_REG + def_bool y if KERNEL_DEBUGGER && \ + MN10300_CACHE_WTHRU && \ + !MN10300_CACHE_SNOOP && \ + MN10300_CACHE_MANAGE_BY_REG + help + Set if the debugger needs to invalidate the icache using automatic + purge registers to make breakpoints work. + +config MN10300_DEBUGGER_CACHE_NO_FLUSH + def_bool y if KERNEL_DEBUGGER && \ + (MN10300_CACHE_DISABLED || MN10300_CACHE_SNOOP) + help + Set if the debugger does not need to flush the dcache and/or + invalidate the icache to make breakpoints work. diff --git a/arch/mn10300/mm/Makefile b/arch/mn10300/mm/Makefile index 203fee23f7d70..11f38466ac28e 100644 --- a/arch/mn10300/mm/Makefile +++ b/arch/mn10300/mm/Makefile @@ -13,6 +13,15 @@ cacheflush-$(CONFIG_MN10300_CACHE_INV_BY_REG) += cache-inv-by-reg.o cacheflush-$(CONFIG_MN10300_CACHE_FLUSH_BY_TAG) += cache-flush-by-tag.o cacheflush-$(CONFIG_MN10300_CACHE_FLUSH_BY_REG) += cache-flush-by-reg.o +cacheflush-$(CONFIG_MN10300_DEBUGGER_CACHE_FLUSH_BY_TAG) += \ + cache-dbg-flush-by-tag.o cache-dbg-inv-by-tag.o +cacheflush-$(CONFIG_MN10300_DEBUGGER_CACHE_FLUSH_BY_REG) += \ + cache-dbg-flush-by-reg.o +cacheflush-$(CONFIG_MN10300_DEBUGGER_CACHE_INV_BY_TAG) += \ + cache-dbg-inv-by-tag.o cache-dbg-inv.o +cacheflush-$(CONFIG_MN10300_DEBUGGER_CACHE_INV_BY_REG) += \ + cache-dbg-inv-by-reg.o cache-dbg-inv.o + cacheflush-$(CONFIG_MN10300_CACHE_DISABLED) := cache-disabled.o obj-y := \ diff --git a/arch/mn10300/mm/cache-dbg-flush-by-reg.S b/arch/mn10300/mm/cache-dbg-flush-by-reg.S new file mode 100644 index 0000000000000..665919f2ab62e --- /dev/null +++ b/arch/mn10300/mm/cache-dbg-flush-by-reg.S @@ -0,0 +1,160 @@ +/* MN10300 CPU cache invalidation routines, using automatic purge registers + * + * Copyright (C) 2011 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public Licence + * as published by the Free Software Foundation; either version + * 2 of the Licence, or (at your option) any later version. + */ +#include +#include +#include +#include +#include +#include +#include +#include "cache.inc" + + .am33_2 + +############################################################################### +# +# void debugger_local_cache_flushinv(void) +# Flush the entire data cache back to RAM and invalidate the icache +# +############################################################################### + ALIGN + .globl debugger_local_cache_flushinv + .type debugger_local_cache_flushinv,@function +debugger_local_cache_flushinv: + # + # firstly flush the dcache + # + movhu (CHCTR),d0 + btst CHCTR_DCEN|CHCTR_ICEN,d0 + beq debugger_local_cache_flushinv_end + + mov DCPGCR,a0 + + mov epsw,d1 + and ~EPSW_IE,epsw + or EPSW_NMID,epsw + nop + + btst CHCTR_DCEN,d0 + beq debugger_local_cache_flushinv_no_dcache + + # wait for busy bit of area purge + setlb + mov (a0),d0 + btst DCPGCR_DCPGBSY,d0 + lne + + # set mask + clr d0 + mov d0,(DCPGMR) + + # area purge + # + # DCPGCR = DCPGCR_DCP + # + mov DCPGCR_DCP,d0 + mov d0,(a0) + + # wait for busy bit of area purge + setlb + mov (a0),d0 + btst DCPGCR_DCPGBSY,d0 + lne + +debugger_local_cache_flushinv_no_dcache: + # + # secondly, invalidate the icache if it is enabled + # + mov CHCTR,a0 + movhu (a0),d0 + btst CHCTR_ICEN,d0 + beq debugger_local_cache_flushinv_done + + invalidate_icache 0 + +debugger_local_cache_flushinv_done: + mov d1,epsw + +debugger_local_cache_flushinv_end: + ret [],0 + .size debugger_local_cache_flushinv,.-debugger_local_cache_flushinv + +############################################################################### +# +# void debugger_local_cache_flushinv_one(u8 *addr) +# +# Invalidate one particular cacheline if it's in the icache +# +############################################################################### + ALIGN + .globl debugger_local_cache_flushinv_one + .type debugger_local_cache_flushinv_one,@function +debugger_local_cache_flushinv_one: + movhu (CHCTR),d1 + btst CHCTR_DCEN|CHCTR_ICEN,d1 + beq debugger_local_cache_flushinv_one_end + btst CHCTR_DCEN,d1 + beq debugger_local_cache_flushinv_one_no_dcache + + # round cacheline addr down + and L1_CACHE_TAG_MASK,d0 + mov d0,a1 + mov d0,d1 + + # determine the dcache purge control reg address + mov DCACHE_PURGE(0,0),a0 + and L1_CACHE_TAG_ENTRY,d0 + add d0,a0 + + # retain valid entries in the cache + or L1_CACHE_TAG_VALID,d1 + + # conditionally purge this line in all ways + mov d1,(L1_CACHE_WAYDISP*0,a0) + +debugger_local_cache_flushinv_no_dcache: + # + # now try to flush the icache + # + mov CHCTR,a0 + movhu (a0),d0 + btst CHCTR_ICEN,d0 + beq mn10300_local_icache_inv_range_reg_end + + LOCAL_CLI_SAVE(d1) + + mov ICIVCR,a0 + + # wait for the invalidator to quiesce + setlb + mov (a0),d0 + btst ICIVCR_ICIVBSY,d0 + lne + + # set the mask + mov L1_CACHE_TAG_MASK,d0 + mov d0,(ICIVMR) + + # invalidate the cache line at the given address + or ICIVCR_ICI,a1 + mov a1,(a0) + + # wait for the invalidator to quiesce again + setlb + mov (a0),d0 + btst ICIVCR_ICIVBSY,d0 + lne + + LOCAL_IRQ_RESTORE(d1) + +debugger_local_cache_flushinv_one_end: + ret [],0 + .size debugger_local_cache_flushinv_one,.-debugger_local_cache_flushinv_one diff --git a/arch/mn10300/mm/cache-dbg-flush-by-tag.S b/arch/mn10300/mm/cache-dbg-flush-by-tag.S new file mode 100644 index 0000000000000..bf56930e6e700 --- /dev/null +++ b/arch/mn10300/mm/cache-dbg-flush-by-tag.S @@ -0,0 +1,114 @@ +/* MN10300 CPU cache invalidation routines, using direct tag flushing + * + * Copyright (C) 2011 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public Licence + * as published by the Free Software Foundation; either version + * 2 of the Licence, or (at your option) any later version. + */ +#include +#include +#include +#include +#include +#include +#include +#include "cache.inc" + + .am33_2 + +############################################################################### +# +# void debugger_local_cache_flushinv(void) +# +# Flush the entire data cache back to RAM and invalidate the icache +# +############################################################################### + ALIGN + .globl debugger_local_cache_flushinv + .type debugger_local_cache_flushinv,@function +debugger_local_cache_flushinv: + # + # firstly flush the dcache + # + movhu (CHCTR),d0 + btst CHCTR_DCEN|CHCTR_ICEN,d0 + beq debugger_local_cache_flushinv_end + + btst CHCTR_DCEN,d0 + beq debugger_local_cache_flushinv_no_dcache + + # read the addresses tagged in the cache's tag RAM and attempt to flush + # those addresses specifically + # - we rely on the hardware to filter out invalid tag entry addresses + mov DCACHE_TAG(0,0),a0 # dcache tag RAM access address + mov DCACHE_PURGE(0,0),a1 # dcache purge request address + mov L1_CACHE_NWAYS*L1_CACHE_NENTRIES,e0 # total number of entries + +mn10300_local_dcache_flush_loop: + mov (a0),d0 + and L1_CACHE_TAG_MASK,d0 + or L1_CACHE_TAG_VALID,d0 # retain valid entries in the + # cache + mov d0,(a1) # conditional purge + + add L1_CACHE_BYTES,a0 + add L1_CACHE_BYTES,a1 + add -1,e0 + bne mn10300_local_dcache_flush_loop + +debugger_local_cache_flushinv_no_dcache: + # + # secondly, invalidate the icache if it is enabled + # + mov CHCTR,a0 + movhu (a0),d0 + btst CHCTR_ICEN,d0 + beq debugger_local_cache_flushinv_end + + invalidate_icache 1 + +debugger_local_cache_flushinv_end: + ret [],0 + .size debugger_local_cache_flushinv,.-debugger_local_cache_flushinv + +############################################################################### +# +# void debugger_local_cache_flushinv_one(u8 *addr) +# +# Invalidate one particular cacheline if it's in the icache +# +############################################################################### + ALIGN + .globl debugger_local_cache_flushinv_one + .type debugger_local_cache_flushinv_one,@function +debugger_local_cache_flushinv_one: + movhu (CHCTR),d1 + btst CHCTR_DCEN|CHCTR_ICEN,d1 + beq debugger_local_cache_flushinv_one_end + btst CHCTR_DCEN,d1 + beq debugger_local_cache_flushinv_one_icache + + # round cacheline addr down + and L1_CACHE_TAG_MASK,d0 + mov d0,a1 + + # determine the dcache purge control reg address + mov DCACHE_PURGE(0,0),a0 + and L1_CACHE_TAG_ENTRY,d0 + add d0,a0 + + # retain valid entries in the cache + or L1_CACHE_TAG_VALID,a1 + + # conditionally purge this line in all ways + mov a1,(L1_CACHE_WAYDISP*0,a0) + + # now go and do the icache + bra debugger_local_cache_flushinv_one_icache + +debugger_local_cache_flushinv_one_end: + ret [],0 + .size debugger_local_cache_flushinv_one,.-debugger_local_cache_flushinv_one diff --git a/arch/mn10300/mm/cache-dbg-inv-by-reg.S b/arch/mn10300/mm/cache-dbg-inv-by-reg.S new file mode 100644 index 0000000000000..c4e6252941b11 --- /dev/null +++ b/arch/mn10300/mm/cache-dbg-inv-by-reg.S @@ -0,0 +1,69 @@ +/* MN10300 CPU cache invalidation routines, using automatic purge registers + * + * Copyright (C) 2011 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public Licence + * as published by the Free Software Foundation; either version + * 2 of the Licence, or (at your option) any later version. + */ +#include +#include +#include +#include +#include +#include "cache.inc" + + .am33_2 + + .globl debugger_local_cache_flushinv_one + +############################################################################### +# +# void debugger_local_cache_flushinv_one(u8 *addr) +# +# Invalidate one particular cacheline if it's in the icache +# +############################################################################### + ALIGN + .globl debugger_local_cache_flushinv_one + .type debugger_local_cache_flushinv_one,@function +debugger_local_cache_flushinv_one: + mov d0,a1 + + mov CHCTR,a0 + movhu (a0),d0 + btst CHCTR_ICEN,d0 + beq mn10300_local_icache_inv_range_reg_end + + LOCAL_CLI_SAVE(d1) + + mov ICIVCR,a0 + + # wait for the invalidator to quiesce + setlb + mov (a0),d0 + btst ICIVCR_ICIVBSY,d0 + lne + + # set the mask + mov ~L1_CACHE_TAG_MASK,d0 + mov d0,(ICIVMR) + + # invalidate the cache line at the given address + and ~L1_CACHE_TAG_MASK,a1 + or ICIVCR_ICI,a1 + mov a1,(a0) + + # wait for the invalidator to quiesce again + setlb + mov (a0),d0 + btst ICIVCR_ICIVBSY,d0 + lne + + LOCAL_IRQ_RESTORE(d1) + +mn10300_local_icache_inv_range_reg_end: + ret [],0 + .size debugger_local_cache_flushinv_one,.-debugger_local_cache_flushinv_one diff --git a/arch/mn10300/mm/cache-dbg-inv-by-tag.S b/arch/mn10300/mm/cache-dbg-inv-by-tag.S new file mode 100644 index 0000000000000..d8ec821e5f88d --- /dev/null +++ b/arch/mn10300/mm/cache-dbg-inv-by-tag.S @@ -0,0 +1,120 @@ +/* MN10300 CPU cache invalidation routines, using direct tag flushing + * + * Copyright (C) 2011 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public Licence + * as published by the Free Software Foundation; either version + * 2 of the Licence, or (at your option) any later version. + */ +#include +#include +#include +#include +#include +#include +#include +#include "cache.inc" + + .am33_2 + + .globl debugger_local_cache_flushinv_one_icache + +############################################################################### +# +# void debugger_local_cache_flushinv_one(u8 *addr) +# +# Invalidate one particular cacheline if it's in the icache +# +############################################################################### + ALIGN + .globl debugger_local_cache_flushinv_one_icache + .type debugger_local_cache_flushinv_one_icache,@function +debugger_local_cache_flushinv_one_icache: + movm [d3,a2],(sp) + + mov CHCTR,a2 + movhu (a2),d0 + btst CHCTR_ICEN,d0 + beq debugger_local_cache_flushinv_one_icache_end + + mov d0,a1 + and L1_CACHE_TAG_MASK,a1 + + # read the tags from the tag RAM, and if they indicate a matching valid + # cache line then we invalidate that line + mov ICACHE_TAG(0,0),a0 + mov a1,d0 + and L1_CACHE_TAG_ENTRY,d0 + add d0,a0 # starting icache tag RAM + # access address + + and ~(L1_CACHE_DISPARITY-1),a1 # determine comparator base + or L1_CACHE_TAG_VALID,a1 + mov L1_CACHE_TAG_ADDRESS|L1_CACHE_TAG_VALID,d1 + + LOCAL_CLI_SAVE(d3) + + # disable the icache + movhu (a2),d0 + and ~CHCTR_ICEN,d0 + movhu d0,(a2) + + # and wait for it to calm down + setlb + movhu (a2),d0 + btst CHCTR_ICBUSY,d0 + lne + + # check all the way tags for this cache entry + mov (a0),d0 # read the tag in the way 0 slot + xor a1,d0 + and d1,d0 + beq debugger_local_icache_kill # jump if matched + + add L1_CACHE_WAYDISP,a0 + mov (a0),d0 # read the tag in the way 1 slot + xor a1,d0 + and d1,d0 + beq debugger_local_icache_kill # jump if matched + + add L1_CACHE_WAYDISP,a0 + mov (a0),d0 # read the tag in the way 2 slot + xor a1,d0 + and d1,d0 + beq debugger_local_icache_kill # jump if matched + + add L1_CACHE_WAYDISP,a0 + mov (a0),d0 # read the tag in the way 3 slot + xor a1,d0 + and d1,d0 + bne debugger_local_icache_finish # jump if not matched + +debugger_local_icache_kill: + mov d0,(a0) # kill the tag (D0 is 0 at this point) + +debugger_local_icache_finish: + # wait for the cache to finish what it's doing + setlb + movhu (a2),d0 + btst CHCTR_ICBUSY,d0 + lne + + # and reenable it + or CHCTR_ICEN,d0 + movhu d0,(a2) + movhu (a2),d0 + + # re-enable interrupts + LOCAL_IRQ_RESTORE(d3) + +debugger_local_cache_flushinv_one_icache_end: + ret [d3,a2],8 + .size debugger_local_cache_flushinv_one_icache,.-debugger_local_cache_flushinv_one_icache + +#ifdef CONFIG_MN10300_DEBUGGER_CACHE_INV_BY_TAG + .globl debugger_local_cache_flushinv_one + .type debugger_local_cache_flushinv_one,@function +debugger_local_cache_flushinv_one = debugger_local_cache_flushinv_one_icache +#endif diff --git a/arch/mn10300/mm/cache-dbg-inv.S b/arch/mn10300/mm/cache-dbg-inv.S new file mode 100644 index 0000000000000..eba2d6dca0664 --- /dev/null +++ b/arch/mn10300/mm/cache-dbg-inv.S @@ -0,0 +1,47 @@ +/* MN10300 CPU cache invalidation routines + * + * Copyright (C) 2011 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public Licence + * as published by the Free Software Foundation; either version + * 2 of the Licence, or (at your option) any later version. + */ +#include +#include +#include +#include +#include +#include +#include +#include "cache.inc" + + .am33_2 + + .globl debugger_local_cache_flushinv + +############################################################################### +# +# void debugger_local_cache_flushinv(void) +# +# Invalidate the entire icache +# +############################################################################### + ALIGN + .globl debugger_local_cache_flushinv + .type debugger_local_cache_flushinv,@function +debugger_local_cache_flushinv: + # + # we only need to invalidate the icache in this cache mode + # + mov CHCTR,a0 + movhu (a0),d0 + btst CHCTR_ICEN,d0 + beq debugger_local_cache_flushinv_end + + invalidate_icache 1 + +debugger_local_cache_flushinv_end: + ret [],0 + .size debugger_local_cache_flushinv,.-debugger_local_cache_flushinv diff --git a/arch/mn10300/mm/cache-flush-by-tag.S b/arch/mn10300/mm/cache-flush-by-tag.S index 5cd6a27dd63e0..1ddc068492429 100644 --- a/arch/mn10300/mm/cache-flush-by-tag.S +++ b/arch/mn10300/mm/cache-flush-by-tag.S @@ -62,7 +62,7 @@ mn10300_local_dcache_flush: mn10300_local_dcache_flush_loop: mov (a0),d0 - and L1_CACHE_TAG_ADDRESS|L1_CACHE_TAG_ENTRY,d0 + and L1_CACHE_TAG_MASK,d0 or L1_CACHE_TAG_VALID,d0 # retain valid entries in the # cache mov d0,(a1) # conditional purge @@ -112,11 +112,11 @@ mn10300_local_dcache_flush_range: 1: # round start addr down - and L1_CACHE_TAG_ADDRESS|L1_CACHE_TAG_ENTRY,d0 + and L1_CACHE_TAG_MASK,d0 mov d0,a1 add L1_CACHE_BYTES,d1 # round end addr up - and L1_CACHE_TAG_ADDRESS|L1_CACHE_TAG_ENTRY,d1 + and L1_CACHE_TAG_MASK,d1 # write a request to flush all instances of an address from the cache mov DCACHE_PURGE(0,0),a0 @@ -215,12 +215,11 @@ mn10300_local_dcache_flush_inv_range: bra mn10300_local_dcache_flush_inv 1: - and L1_CACHE_TAG_ADDRESS|L1_CACHE_TAG_ENTRY,d0 # round start - # addr down + and L1_CACHE_TAG_MASK,d0 # round start addr down mov d0,a1 - add L1_CACHE_BYTES,d1 # round end addr up - and L1_CACHE_TAG_ADDRESS|L1_CACHE_TAG_ENTRY,d1 + add L1_CACHE_BYTES,d1 # round end addr up + and L1_CACHE_TAG_MASK,d1 # write a request to flush and invalidate all instances of an address # from the cache diff --git a/arch/mn10300/mm/cache-inv-by-reg.S b/arch/mn10300/mm/cache-inv-by-reg.S index d1f363a8d36b9..a60825b91e772 100644 --- a/arch/mn10300/mm/cache-inv-by-reg.S +++ b/arch/mn10300/mm/cache-inv-by-reg.S @@ -116,9 +116,9 @@ mn10300_local_dcache_inv_range: # and if they're not cacheline-aligned, we must flush any bits outside # the range that share cachelines with stuff inside the range #ifdef CONFIG_MN10300_CACHE_WBACK - btst ~(L1_CACHE_BYTES-1),d0 + btst ~L1_CACHE_TAG_MASK,d0 bne 1f - btst ~(L1_CACHE_BYTES-1),d1 + btst ~L1_CACHE_TAG_MASK,d1 beq 2f 1: bra mn10300_local_dcache_flush_inv_range @@ -136,12 +136,11 @@ mn10300_local_dcache_inv_range: # writeback mode, in which case we would be in flush and invalidate by # now #ifndef CONFIG_MN10300_CACHE_WBACK - and L1_CACHE_TAG_ADDRESS|L1_CACHE_TAG_ENTRY,d0 # round start - # addr down + and L1_CACHE_TAG_MASK,d0 # round start addr down mov L1_CACHE_BYTES-1,d2 add d2,d1 - and L1_CACHE_TAG_ADDRESS|L1_CACHE_TAG_ENTRY,d1 # round end addr up + and L1_CACHE_TAG_MASK,d1 # round end addr up #endif /* !CONFIG_MN10300_CACHE_WBACK */ sub d0,d1,d2 # calculate the total size diff --git a/arch/mn10300/mm/cache-inv-by-tag.S b/arch/mn10300/mm/cache-inv-by-tag.S index c5c80322eefb5..ccedce9c144d3 100644 --- a/arch/mn10300/mm/cache-inv-by-tag.S +++ b/arch/mn10300/mm/cache-inv-by-tag.S @@ -124,9 +124,9 @@ mn10300_local_dcache_inv_range: # and if they're not cacheline-aligned, we must flush any bits outside # the range that share cachelines with stuff inside the range #ifdef CONFIG_MN10300_CACHE_WBACK - btst ~(L1_CACHE_BYTES-1),d0 + btst ~L1_CACHE_TAG_MASK,d0 bne 1f - btst ~(L1_CACHE_BYTES-1),d1 + btst ~L1_CACHE_TAG_MASK,d1 beq 2f 1: bra mn10300_local_dcache_flush_inv_range @@ -141,11 +141,10 @@ mn10300_local_dcache_inv_range: beq mn10300_local_dcache_inv_range_end #ifndef CONFIG_MN10300_CACHE_WBACK - and L1_CACHE_TAG_ADDRESS|L1_CACHE_TAG_ENTRY,d0 # round start - # addr down + and L1_CACHE_TAG_MASK,d0 # round start addr down add L1_CACHE_BYTES,d1 # round end addr up - and L1_CACHE_TAG_ADDRESS|L1_CACHE_TAG_ENTRY,d1 + and L1_CACHE_TAG_MASK,d1 #endif /* !CONFIG_MN10300_CACHE_WBACK */ mov d0,a1 diff --git a/arch/mn10300/proc-mn103e010/include/proc/cache.h b/arch/mn10300/proc-mn103e010/include/proc/cache.h index c1528004163ce..967d144f307e5 100644 --- a/arch/mn10300/proc-mn103e010/include/proc/cache.h +++ b/arch/mn10300/proc-mn103e010/include/proc/cache.h @@ -23,6 +23,7 @@ #define L1_CACHE_TAG_DIRTY 0x00000008 /* data cache tag dirty bit */ #define L1_CACHE_TAG_ENTRY 0x00000ff0 /* cache tag entry address mask */ #define L1_CACHE_TAG_ADDRESS 0xfffff000 /* cache tag line address mask */ +#define L1_CACHE_TAG_MASK +(L1_CACHE_TAG_ADDRESS|L1_CACHE_TAG_ENTRY) /* * specification of the interval between interrupt checking intervals whilst diff --git a/arch/mn10300/proc-mn2ws0050/include/proc/cache.h b/arch/mn10300/proc-mn2ws0050/include/proc/cache.h index cafd7b5b55b44..bcb5df2d892f9 100644 --- a/arch/mn10300/proc-mn2ws0050/include/proc/cache.h +++ b/arch/mn10300/proc-mn2ws0050/include/proc/cache.h @@ -29,6 +29,7 @@ #define L1_CACHE_TAG_DIRTY 0x00000008 /* data cache tag dirty bit */ #define L1_CACHE_TAG_ENTRY 0x00000fe0 /* cache tag entry address mask */ #define L1_CACHE_TAG_ADDRESS 0xfffff000 /* cache tag line address mask */ +#define L1_CACHE_TAG_MASK +(L1_CACHE_TAG_ADDRESS|L1_CACHE_TAG_ENTRY) /* * specification of the interval between interrupt checking intervals whilst -- GitLab From 67ddb4052daac9d449caf2643ac365d42a04219a Mon Sep 17 00:00:00 2001 From: David Howells Date: Fri, 18 Mar 2011 16:54:30 +0000 Subject: [PATCH 0897/2822] MN10300: Create generic kernel debugger hooks Create generic kernel debugger hooks in the MN10300 arch and make gdbstub use them. This is a preparation for KGDB support. Signed-off-by: David Howells --- arch/mn10300/Kconfig | 6 +- arch/mn10300/include/asm/debugger.h | 15 + arch/mn10300/include/asm/fpu.h | 2 - arch/mn10300/include/asm/irqflags.h | 2 +- arch/mn10300/include/asm/smp.h | 3 +- arch/mn10300/kernel/entry.S | 36 ++- arch/mn10300/kernel/fpu.c | 18 -- arch/mn10300/kernel/gdb-io-ttysm.c | 8 +- arch/mn10300/kernel/gdb-stub.c | 25 +- arch/mn10300/kernel/internal.h | 7 + arch/mn10300/kernel/irq.c | 2 +- arch/mn10300/kernel/smp.c | 26 +- arch/mn10300/kernel/traps.c | 406 +++++++++++++++------------- arch/mn10300/mm/fault.c | 9 +- 14 files changed, 317 insertions(+), 248 deletions(-) diff --git a/arch/mn10300/Kconfig b/arch/mn10300/Kconfig index 25e6a0bc62abc..6e9cac9700244 100644 --- a/arch/mn10300/Kconfig +++ b/arch/mn10300/Kconfig @@ -401,8 +401,8 @@ comment "[!] NOTE: A lower number/level indicates a higher priority (0 is highes comment "____Non-maskable interrupt levels____" comment "The following must be set to a higher priority than local_irq_disable() and on-chip serial" -config GDBSTUB_IRQ_LEVEL - int "GDBSTUB interrupt priority" +config DEBUGGER_IRQ_LEVEL + int "DEBUGGER interrupt priority" depends on KERNEL_DEBUGGER range 0 1 if LINUX_CLI_LEVEL = 2 range 0 2 if LINUX_CLI_LEVEL = 3 @@ -437,7 +437,7 @@ config LINUX_CLI_LEVEL EPSW.IM from 7. Any interrupt is permitted for which the level is lower than EPSW.IM. - Certain interrupts, such as GDBSTUB and virtual MN10300 on-chip + Certain interrupts, such as DEBUGGER and virtual MN10300 on-chip serial DMA interrupts are allowed to interrupt normal disabled sections. diff --git a/arch/mn10300/include/asm/debugger.h b/arch/mn10300/include/asm/debugger.h index 4517f839a9993..e1d3b083696cd 100644 --- a/arch/mn10300/include/asm/debugger.h +++ b/arch/mn10300/include/asm/debugger.h @@ -14,6 +14,9 @@ #if defined(CONFIG_KERNEL_DEBUGGER) +extern int debugger_intercept(enum exception_code, int, int, struct pt_regs *); +extern int at_debugger_breakpoint(struct pt_regs *); + #ifndef CONFIG_MN10300_DEBUGGER_CACHE_NO_FLUSH extern void debugger_local_cache_flushinv(void); extern void debugger_local_cache_flushinv_one(u8 *); @@ -24,5 +27,17 @@ static inline void debugger_local_cache_flushinv_one(u8 *addr) {} #else /* CONFIG_KERNEL_DEBUGGER */ +static inline int debugger_intercept(enum exception_code excep, + int signo, int si_code, + struct pt_regs *regs) +{ + return 0; +} + +static inline int at_debugger_breakpoint(struct pt_regs *regs) +{ + return 0; +} + #endif /* CONFIG_KERNEL_DEBUGGER */ #endif /* _ASM_DEBUGGER_H */ diff --git a/arch/mn10300/include/asm/fpu.h b/arch/mn10300/include/asm/fpu.h index b7625de8eade6..738ff72659d52 100644 --- a/arch/mn10300/include/asm/fpu.h +++ b/arch/mn10300/include/asm/fpu.h @@ -55,7 +55,6 @@ static inline void clear_using_fpu(struct task_struct *tsk) extern asmlinkage void fpu_kill_state(struct task_struct *); extern asmlinkage void fpu_exception(struct pt_regs *, enum exception_code); -extern asmlinkage void fpu_invalid_op(struct pt_regs *, enum exception_code); extern asmlinkage void fpu_init_state(void); extern asmlinkage void fpu_save(struct fpu_state_struct *); extern int fpu_setup_sigcontext(struct fpucontext *buf); @@ -113,7 +112,6 @@ static inline void flush_fpu(void) extern asmlinkage void unexpected_fpu_exception(struct pt_regs *, enum exception_code); -#define fpu_invalid_op unexpected_fpu_exception #define fpu_exception unexpected_fpu_exception struct task_struct; diff --git a/arch/mn10300/include/asm/irqflags.h b/arch/mn10300/include/asm/irqflags.h index 7a7ae12c7119e..678f68d5f37bb 100644 --- a/arch/mn10300/include/asm/irqflags.h +++ b/arch/mn10300/include/asm/irqflags.h @@ -20,7 +20,7 @@ /* * interrupt control * - "disabled": run in IM1/2 - * - level 0 - GDB stub + * - level 0 - kernel debugger * - level 1 - virtual serial DMA (if present) * - level 5 - normal interrupt priority * - level 6 - timer interrupt diff --git a/arch/mn10300/include/asm/smp.h b/arch/mn10300/include/asm/smp.h index a3930e43a958d..e3d13a899855b 100644 --- a/arch/mn10300/include/asm/smp.h +++ b/arch/mn10300/include/asm/smp.h @@ -34,7 +34,7 @@ #define LOCAL_TIMER_IPI 193 #define FLUSH_CACHE_IPI 194 #define CALL_FUNCTION_NMI_IPI 195 -#define GDB_NMI_IPI 196 +#define DEBUGGER_NMI_IPI 196 #define SMP_BOOT_IRQ 195 @@ -43,6 +43,7 @@ #define LOCAL_TIMER_GxICR_LV GxICR_LEVEL_4 #define FLUSH_CACHE_GxICR_LV GxICR_LEVEL_0 #define SMP_BOOT_GxICR_LV GxICR_LEVEL_0 +#define DEBUGGER_GxICR_LV CONFIG_DEBUGGER_IRQ_LEVEL #define TIME_OUT_COUNT_BOOT_IPI 100 #define DELAY_TIME_BOOT_IPI 75000 diff --git a/arch/mn10300/kernel/entry.S b/arch/mn10300/kernel/entry.S index 8e79a04f1cb09..fb93ad720b826 100644 --- a/arch/mn10300/kernel/entry.S +++ b/arch/mn10300/kernel/entry.S @@ -266,7 +266,11 @@ ENTRY(raw_bus_error) ############################################################################### # -# Miscellaneous exception entry points +# NMI exception entry points +# +# This is used by ordinary interrupt channels that have the GxICR_NMI bit set +# in addition to the main NMI and Watchdog channels. SMP NMI IPIs use this +# facility. # ############################################################################### ENTRY(nmi_handler) @@ -281,7 +285,7 @@ ENTRY(nmi_handler) and NMIAGR_GN,d0 lsr 0x2,d0 cmp CALL_FUNCTION_NMI_IPI,d0 - bne 5f # if not call function, jump + bne nmi_not_smp_callfunc # if not call function, jump # function call nmi ipi add 4,sp # no need to store TBR @@ -295,30 +299,38 @@ ENTRY(nmi_handler) call smp_nmi_call_function_interrupt[],0 RESTORE_ALL -5: -#ifdef CONFIG_GDBSTUB - cmp GDB_NMI_IPI,d0 - bne 3f # if not gdb nmi ipi, jump +nmi_not_smp_callfunc: +#ifdef CONFIG_KERNEL_DEBUGGER + cmp DEBUGGER_NMI_IPI,d0 + bne nmi_not_debugger # if not kernel debugger NMI IPI, jump - # gdb nmi ipi + # kernel debugger NMI IPI add 4,sp # no need to store TBR mov GxICR_DETECT,d0 # clear NMI - movbu d0,(GxICR(GDB_NMI_IPI)) - movhu (GxICR(GDB_NMI_IPI)),d0 + movbu d0,(GxICR(DEBUGGER_NMI_IPI)) + movhu (GxICR(DEBUGGER_NMI_IPI)),d0 and ~EPSW_NMID,epsw # enable NMI mov (sp),d0 SAVE_ALL - call gdbstub_nmi_wait[],0 + mov fp,d0 # arg 0: stacked register file + mov a2,d1 # arg 1: exception number + call debugger_nmi_interrupt[],0 RESTORE_ALL -3: -#endif /* CONFIG_GDBSTUB */ + +nmi_not_debugger: +#endif /* CONFIG_KERNEL_DEBUGGER */ mov (sp),d0 # restore TBR to d0 add 4,sp #endif /* CONFIG_SMP */ bra __common_exception_nonmi +############################################################################### +# +# General exception entry point +# +############################################################################### ENTRY(__common_exception) add -4,sp mov d0,(sp) diff --git a/arch/mn10300/kernel/fpu.c b/arch/mn10300/kernel/fpu.c index 5f9c3fa19a85f..bb5fa7df6c442 100644 --- a/arch/mn10300/kernel/fpu.c +++ b/arch/mn10300/kernel/fpu.c @@ -69,24 +69,6 @@ asmlinkage void fpu_exception(struct pt_regs *regs, enum exception_code code) force_sig_info(SIGFPE, &info, tsk); } -/* - * handle an FPU invalid_op exception - * - Derived from DO_EINFO() macro in arch/mn10300/kernel/traps.c - */ -asmlinkage void fpu_invalid_op(struct pt_regs *regs, enum exception_code code) -{ - siginfo_t info; - - if (!user_mode(regs)) - die_if_no_fixup("FPU invalid opcode", regs, code); - - info.si_signo = SIGILL; - info.si_errno = 0; - info.si_code = ILL_COPROC; - info.si_addr = (void *) regs->pc; - force_sig_info(info.si_signo, &info, current); -} - /* * save the FPU state to a signal context */ diff --git a/arch/mn10300/kernel/gdb-io-ttysm.c b/arch/mn10300/kernel/gdb-io-ttysm.c index abdeea153c896..c859cacbb9c3b 100644 --- a/arch/mn10300/kernel/gdb-io-ttysm.c +++ b/arch/mn10300/kernel/gdb-io-ttysm.c @@ -59,10 +59,10 @@ void __init gdbstub_io_init(void) /* we want to get serial receive interrupts */ set_intr_level(gdbstub_port->rx_irq, - NUM2GxICR_LEVEL(CONFIG_GDBSTUB_IRQ_LEVEL)); + NUM2GxICR_LEVEL(CONFIG_DEBUGGER_IRQ_LEVEL)); set_intr_level(gdbstub_port->tx_irq, - NUM2GxICR_LEVEL(CONFIG_GDBSTUB_IRQ_LEVEL)); - set_intr_stub(NUM2EXCEP_IRQ_LEVEL(CONFIG_GDBSTUB_IRQ_LEVEL), + NUM2GxICR_LEVEL(CONFIG_DEBUGGER_IRQ_LEVEL)); + set_intr_stub(NUM2EXCEP_IRQ_LEVEL(CONFIG_DEBUGGER_IRQ_LEVEL), gdbstub_io_rx_handler); *gdbstub_port->rx_icr |= GxICR_ENABLE; @@ -88,7 +88,7 @@ void __init gdbstub_io_init(void) /* permit level 0 IRQs only */ arch_local_change_intr_mask_level( - NUM2EPSW_IM(CONFIG_GDBSTUB_IRQ_LEVEL + 1)); + NUM2EPSW_IM(CONFIG_DEBUGGER_IRQ_LEVEL + 1)); } /* diff --git a/arch/mn10300/kernel/gdb-stub.c b/arch/mn10300/kernel/gdb-stub.c index 1e8f24f006372..538266b2c9bc6 100644 --- a/arch/mn10300/kernel/gdb-stub.c +++ b/arch/mn10300/kernel/gdb-stub.c @@ -1173,7 +1173,7 @@ int gdbstub_clear_breakpoint(u8 *addr, int len) /* * This function does all command processing for interfacing to gdb - * - returns 1 if the exception should be skipped, 0 otherwise. + * - returns 0 if the exception should be skipped, -ERROR otherwise. */ static int gdbstub(struct pt_regs *regs, enum exception_code excep) { @@ -1188,7 +1188,7 @@ static int gdbstub(struct pt_regs *regs, enum exception_code excep) int loop; if (excep == EXCEP_FPU_DISABLED) - return 0; + return -ENOTSUPP; gdbstub_flush_caches = 0; @@ -1197,7 +1197,7 @@ static int gdbstub(struct pt_regs *regs, enum exception_code excep) asm volatile("mov mdr,%0" : "=d"(mdr)); local_save_flags(epsw); arch_local_change_intr_mask_level( - NUM2EPSW_IM(CONFIG_GDBSTUB_IRQ_LEVEL + 1)); + NUM2EPSW_IM(CONFIG_DEBUGGER_IRQ_LEVEL + 1)); gdbstub_store_fpu(); @@ -1675,14 +1675,23 @@ done: touch_softlockup_watchdog(); local_irq_restore(epsw); - return 1; + return 0; +} + +/* + * Determine if we hit a debugger special breakpoint that needs skipping over + * automatically. + */ +int at_debugger_breakpoint(struct pt_regs *regs) +{ + return 0; } /* * handle event interception */ -asmlinkage int gdbstub_intercept(struct pt_regs *regs, - enum exception_code excep) +asmlinkage int debugger_intercept(enum exception_code excep, + int signo, int si_code, struct pt_regs *regs) { static u8 notfirst = 1; int ret; @@ -1696,7 +1705,7 @@ asmlinkage int gdbstub_intercept(struct pt_regs *regs, asm("mov mdr,%0" : "=d"(mdr)); gdbstub_entry( - "--> gdbstub_intercept(%p,%04x) [MDR=%lx PC=%lx]\n", + "--> debugger_intercept(%p,%04x) [MDR=%lx PC=%lx]\n", regs, excep, mdr, regs->pc); gdbstub_entry( @@ -1730,7 +1739,7 @@ asmlinkage int gdbstub_intercept(struct pt_regs *regs, ret = gdbstub(regs, excep); - gdbstub_entry("<-- gdbstub_intercept()\n"); + gdbstub_entry("<-- debugger_intercept()\n"); gdbstub_busy = 0; return ret; } diff --git a/arch/mn10300/kernel/internal.h b/arch/mn10300/kernel/internal.h index ea946613f46d1..a5ac755dd69f4 100644 --- a/arch/mn10300/kernel/internal.h +++ b/arch/mn10300/kernel/internal.h @@ -29,6 +29,13 @@ extern void ret_from_fork(struct task_struct *) __attribute__((noreturn)); extern void mn10300_low_ipi_handler(void); #endif +/* + * smp.c + */ +#ifdef CONFIG_SMP +extern void smp_jump_to_debugger(void); +#endif + /* * time.c */ diff --git a/arch/mn10300/kernel/irq.c b/arch/mn10300/kernel/irq.c index f09fed5e6afc2..5f7fc3eb45e60 100644 --- a/arch/mn10300/kernel/irq.c +++ b/arch/mn10300/kernel/irq.c @@ -153,7 +153,7 @@ mn10300_cpupic_setaffinity(struct irq_data *d, const struct cpumask *mask, case LOCAL_TIMER_IPI: case FLUSH_CACHE_IPI: case CALL_FUNCTION_NMI_IPI: - case GDB_NMI_IPI: + case DEBUGGER_NMI_IPI: #ifdef CONFIG_MN10300_TTYSM0 case SC0RXIRQ: case SC0TXIRQ: diff --git a/arch/mn10300/kernel/smp.c b/arch/mn10300/kernel/smp.c index 1ebb79f1650d7..51c02f97dceaa 100644 --- a/arch/mn10300/kernel/smp.c +++ b/arch/mn10300/kernel/smp.c @@ -439,6 +439,22 @@ int smp_nmi_call_function(smp_call_func_t func, void *info, int wait) return ret; } +/** + * smp_jump_to_debugger - Make other CPUs enter the debugger by sending an IPI + * + * Send a non-maskable request to all other CPUs in the system, instructing + * them to jump into the debugger. The caller is responsible for checking that + * the other CPUs responded to the instruction. + * + * The caller should make sure that this CPU's debugger IPI is disabled. + */ +void smp_jump_to_debugger(void) +{ + if (num_online_cpus() > 1) + /* Send a message to all other CPUs */ + send_IPI_allbutself(DEBUGGER_NMI_IPI); +} + /** * stop_this_cpu - Callback to stop a CPU. * @unused: Callback context (ignored). @@ -603,7 +619,7 @@ static void __init smp_cpu_init(void) /** * smp_prepare_cpu_init - Initialise CPU in startup_secondary * - * Set interrupt level 0-6 setting and init ICR of gdbstub. + * Set interrupt level 0-6 setting and init ICR of the kernel debugger. */ void smp_prepare_cpu_init(void) { @@ -622,15 +638,15 @@ void smp_prepare_cpu_init(void) for (loop = 0; loop < GxICR_NUM_IRQS; loop++) GxICR(loop) = GxICR_LEVEL_6 | GxICR_DETECT; -#ifdef CONFIG_GDBSTUB - /* initialise GDB-stub */ +#ifdef CONFIG_KERNEL_DEBUGGER + /* initialise the kernel debugger interrupt */ do { unsigned long flags; u16 tmp16; flags = arch_local_cli_save(); - GxICR(GDB_NMI_IPI) = GxICR_NMI | GxICR_ENABLE | GxICR_DETECT; - tmp16 = GxICR(GDB_NMI_IPI); + GxICR(DEBUGGER_NMI_IPI) = GxICR_NMI | GxICR_ENABLE | GxICR_DETECT; + tmp16 = GxICR(DEBUGGER_NMI_IPI); arch_local_irq_restore(flags); } while (0); #endif diff --git a/arch/mn10300/kernel/traps.c b/arch/mn10300/kernel/traps.c index b90c3f160c77b..f03cb278828f4 100644 --- a/arch/mn10300/kernel/traps.c +++ b/arch/mn10300/kernel/traps.c @@ -38,8 +38,9 @@ #include #include #include -#include #include +#include +#include "internal.h" #if (CONFIG_INTERRUPT_VECTOR_BASE & 0xffffff) #error "INTERRUPT_VECTOR_BASE not aligned to 16MiB boundary!" @@ -49,63 +50,169 @@ int kstack_depth_to_print = 24; spinlock_t die_lock = __SPIN_LOCK_UNLOCKED(die_lock); -ATOMIC_NOTIFIER_HEAD(mn10300_die_chain); +struct exception_to_signal_map { + u8 signo; + u32 si_code; +}; + +static const struct exception_to_signal_map exception_to_signal_map[256] = { + /* MMU exceptions */ + [EXCEP_ITLBMISS >> 3] = { 0, 0 }, + [EXCEP_DTLBMISS >> 3] = { 0, 0 }, + [EXCEP_IAERROR >> 3] = { 0, 0 }, + [EXCEP_DAERROR >> 3] = { 0, 0 }, + + /* system exceptions */ + [EXCEP_TRAP >> 3] = { SIGTRAP, TRAP_BRKPT }, + [EXCEP_ISTEP >> 3] = { SIGTRAP, TRAP_TRACE }, /* Monitor */ + [EXCEP_IBREAK >> 3] = { SIGTRAP, TRAP_HWBKPT }, /* Monitor */ + [EXCEP_OBREAK >> 3] = { SIGTRAP, TRAP_HWBKPT }, /* Monitor */ + [EXCEP_PRIVINS >> 3] = { SIGILL, ILL_PRVOPC }, + [EXCEP_UNIMPINS >> 3] = { SIGILL, ILL_ILLOPC }, + [EXCEP_UNIMPEXINS >> 3] = { SIGILL, ILL_ILLOPC }, + [EXCEP_MEMERR >> 3] = { SIGSEGV, SEGV_ACCERR }, + [EXCEP_MISALIGN >> 3] = { SIGBUS, BUS_ADRALN }, + [EXCEP_BUSERROR >> 3] = { SIGBUS, BUS_ADRERR }, + [EXCEP_ILLINSACC >> 3] = { SIGSEGV, SEGV_ACCERR }, + [EXCEP_ILLDATACC >> 3] = { SIGSEGV, SEGV_ACCERR }, + [EXCEP_IOINSACC >> 3] = { SIGSEGV, SEGV_ACCERR }, + [EXCEP_PRIVINSACC >> 3] = { SIGSEGV, SEGV_ACCERR }, /* userspace */ + [EXCEP_PRIVDATACC >> 3] = { SIGSEGV, SEGV_ACCERR }, /* userspace */ + [EXCEP_DATINSACC >> 3] = { SIGSEGV, SEGV_ACCERR }, + [EXCEP_DOUBLE_FAULT >> 3] = { SIGILL, ILL_BADSTK }, + + /* FPU exceptions */ + [EXCEP_FPU_DISABLED >> 3] = { SIGILL, ILL_COPROC }, + [EXCEP_FPU_UNIMPINS >> 3] = { SIGILL, ILL_COPROC }, + [EXCEP_FPU_OPERATION >> 3] = { SIGFPE, FPE_INTDIV }, + + /* interrupts */ + [EXCEP_WDT >> 3] = { SIGALRM, 0 }, + [EXCEP_NMI >> 3] = { SIGQUIT, 0 }, + [EXCEP_IRQ_LEVEL0 >> 3] = { SIGINT, 0 }, + [EXCEP_IRQ_LEVEL1 >> 3] = { 0, 0 }, + [EXCEP_IRQ_LEVEL2 >> 3] = { 0, 0 }, + [EXCEP_IRQ_LEVEL3 >> 3] = { 0, 0 }, + [EXCEP_IRQ_LEVEL4 >> 3] = { 0, 0 }, + [EXCEP_IRQ_LEVEL5 >> 3] = { 0, 0 }, + [EXCEP_IRQ_LEVEL6 >> 3] = { 0, 0 }, + + /* system calls */ + [EXCEP_SYSCALL0 >> 3] = { 0, 0 }, + [EXCEP_SYSCALL1 >> 3] = { SIGILL, ILL_ILLTRP }, + [EXCEP_SYSCALL2 >> 3] = { SIGILL, ILL_ILLTRP }, + [EXCEP_SYSCALL3 >> 3] = { SIGILL, ILL_ILLTRP }, + [EXCEP_SYSCALL4 >> 3] = { SIGILL, ILL_ILLTRP }, + [EXCEP_SYSCALL5 >> 3] = { SIGILL, ILL_ILLTRP }, + [EXCEP_SYSCALL6 >> 3] = { SIGILL, ILL_ILLTRP }, + [EXCEP_SYSCALL7 >> 3] = { SIGILL, ILL_ILLTRP }, + [EXCEP_SYSCALL8 >> 3] = { SIGILL, ILL_ILLTRP }, + [EXCEP_SYSCALL9 >> 3] = { SIGILL, ILL_ILLTRP }, + [EXCEP_SYSCALL10 >> 3] = { SIGILL, ILL_ILLTRP }, + [EXCEP_SYSCALL11 >> 3] = { SIGILL, ILL_ILLTRP }, + [EXCEP_SYSCALL12 >> 3] = { SIGILL, ILL_ILLTRP }, + [EXCEP_SYSCALL13 >> 3] = { SIGILL, ILL_ILLTRP }, + [EXCEP_SYSCALL14 >> 3] = { SIGILL, ILL_ILLTRP }, + [EXCEP_SYSCALL15 >> 3] = { SIGABRT, 0 }, +}; /* - * These constants are for searching for possible module text - * segments. MODULE_RANGE is a guess of how much space is likely - * to be vmalloced. + * Handle kernel exceptions. + * + * See if there's a fixup handler we can force a jump to when an exception + * happens due to something kernel code did */ -#define MODULE_RANGE (8 * 1024 * 1024) - -#define DO_ERROR(signr, prologue, str, name) \ -asmlinkage void name(struct pt_regs *regs, u32 intcode) \ -{ \ - prologue; \ - if (die_if_no_fixup(str, regs, intcode)) \ - return; \ - force_sig(signr, current); \ -} +int die_if_no_fixup(const char *str, struct pt_regs *regs, + enum exception_code code) +{ + u8 opcode; + int signo, si_code; + + if (user_mode(regs)) + return 0; + + peripheral_leds_display_exception(code); + + signo = exception_to_signal_map[code >> 3].signo; + si_code = exception_to_signal_map[code >> 3].si_code; + + switch (code) { + /* see if we can fixup the kernel accessing memory */ + case EXCEP_ITLBMISS: + case EXCEP_DTLBMISS: + case EXCEP_IAERROR: + case EXCEP_DAERROR: + case EXCEP_MEMERR: + case EXCEP_MISALIGN: + case EXCEP_BUSERROR: + case EXCEP_ILLDATACC: + case EXCEP_IOINSACC: + case EXCEP_PRIVINSACC: + case EXCEP_PRIVDATACC: + case EXCEP_DATINSACC: + if (fixup_exception(regs)) + return 1; + break; -#define DO_EINFO(signr, prologue, str, name, sicode) \ -asmlinkage void name(struct pt_regs *regs, u32 intcode) \ -{ \ - siginfo_t info; \ - prologue; \ - if (die_if_no_fixup(str, regs, intcode)) \ - return; \ - info.si_signo = signr; \ - if (signr == SIGILL && sicode == ILL_ILLOPC) { \ - uint8_t opcode; \ - if (get_user(opcode, (uint8_t __user *)regs->pc) == 0) \ - if (opcode == 0xff) \ - info.si_signo = SIGTRAP; \ - } \ - info.si_errno = 0; \ - info.si_code = sicode; \ - info.si_addr = (void *) regs->pc; \ - force_sig_info(info.si_signo, &info, current); \ + case EXCEP_TRAP: + case EXCEP_UNIMPINS: + if (get_user(opcode, (uint8_t __user *)regs->pc) != 0) + break; + if (opcode == 0xff) { + if (notify_die(DIE_BREAKPOINT, str, regs, code, 0, 0)) + return 1; + if (at_debugger_breakpoint(regs)) + regs->pc++; + signo = SIGTRAP; + si_code = TRAP_BRKPT; + } + break; + + case EXCEP_SYSCALL1 ... EXCEP_SYSCALL14: + /* syscall return addr is _after_ the instruction */ + regs->pc -= 2; + break; + + case EXCEP_SYSCALL15: + if (report_bug(regs->pc, regs) == BUG_TRAP_TYPE_WARN) + return 1; + + /* syscall return addr is _after_ the instruction */ + regs->pc -= 2; + break; + + default: + break; + } + + if (debugger_intercept(code, signo, si_code, regs) == 0) + return 1; + + if (notify_die(DIE_GPF, str, regs, code, 0, 0)) + return 1; + + /* make the process die as the last resort */ + die(str, regs, code); } -DO_ERROR(SIGTRAP, {}, "trap", trap); -DO_ERROR(SIGSEGV, {}, "ibreak", ibreak); -DO_ERROR(SIGSEGV, {}, "obreak", obreak); -DO_EINFO(SIGSEGV, {}, "access error", access_error, SEGV_ACCERR); -DO_EINFO(SIGSEGV, {}, "insn access error", insn_acc_error, SEGV_ACCERR); -DO_EINFO(SIGSEGV, {}, "data access error", data_acc_error, SEGV_ACCERR); -DO_EINFO(SIGILL, {}, "privileged opcode", priv_op, ILL_PRVOPC); -DO_EINFO(SIGILL, {}, "invalid opcode", invalid_op, ILL_ILLOPC); -DO_EINFO(SIGILL, {}, "invalid ex opcode", invalid_exop, ILL_ILLOPC); -DO_EINFO(SIGBUS, {}, "invalid address", mem_error, BUS_ADRERR); -DO_EINFO(SIGBUS, {}, "bus error", bus_error, BUS_ADRERR); - -DO_ERROR(SIGTRAP, -#ifndef CONFIG_MN10300_USING_JTAG - DCR &= ~0x0001, -#else - {}, -#endif - "single step", istep); +/* + * General exception handler + */ +asmlinkage void handle_exception(struct pt_regs *regs, u32 intcode) +{ + siginfo_t info; + + /* deal with kernel exceptions here */ + if (die_if_no_fixup(NULL, regs, intcode)) + return; + + /* otherwise it's a userspace exception */ + info.si_signo = exception_to_signal_map[intcode >> 3].signo; + info.si_code = exception_to_signal_map[intcode >> 3].si_code; + info.si_errno = 0; + info.si_addr = (void *) regs->pc; + force_sig_info(info.si_signo, &info, current); +} /* * handle NMI @@ -113,10 +220,8 @@ DO_ERROR(SIGTRAP, asmlinkage void nmi(struct pt_regs *regs, enum exception_code code) { /* see if gdbstub wants to deal with it */ -#ifdef CONFIG_GDBSTUB - if (gdbstub_intercept(regs, code)) + if (debugger_intercept(code, SIGQUIT, 0, regs)) return; -#endif printk(KERN_WARNING "--- Register Dump ---\n"); show_registers(regs); @@ -128,29 +233,36 @@ asmlinkage void nmi(struct pt_regs *regs, enum exception_code code) */ void show_trace(unsigned long *sp) { - unsigned long *stack, addr, module_start, module_end; - int i; - - printk(KERN_EMERG "\nCall Trace:"); - - stack = sp; - i = 0; - module_start = VMALLOC_START; - module_end = VMALLOC_END; + unsigned long bottom, stack, addr, fp, raslot; + + printk(KERN_EMERG "\nCall Trace:\n"); + + //stack = (unsigned long)sp; + asm("mov sp,%0" : "=a"(stack)); + asm("mov a3,%0" : "=r"(fp)); + + raslot = ULONG_MAX; + bottom = (stack + THREAD_SIZE) & ~(THREAD_SIZE - 1); + for (; stack < bottom; stack += sizeof(addr)) { + addr = *(unsigned long *)stack; + if (stack == fp) { + if (addr > stack && addr < bottom) { + fp = addr; + raslot = stack + sizeof(addr); + continue; + } + fp = 0; + raslot = ULONG_MAX; + } - while (((long) stack & (THREAD_SIZE - 1)) != 0) { - addr = *stack++; if (__kernel_text_address(addr)) { -#if 1 printk(" [<%08lx>]", addr); + if (stack >= raslot) + raslot = ULONG_MAX; + else + printk(" ?"); print_symbol(" %s", addr); printk("\n"); -#else - if ((i % 6) == 0) - printk(KERN_EMERG " "); - printk("[<%08lx>] ", addr); - i++; -#endif } } @@ -322,86 +434,6 @@ void die(const char *str, struct pt_regs *regs, enum exception_code code) do_exit(SIGSEGV); } -/* - * see if there's a fixup handler we can force a jump to when an exception - * happens due to something kernel code did - */ -int die_if_no_fixup(const char *str, struct pt_regs *regs, - enum exception_code code) -{ - if (user_mode(regs)) - return 0; - - peripheral_leds_display_exception(code); - - switch (code) { - /* see if we can fixup the kernel accessing memory */ - case EXCEP_ITLBMISS: - case EXCEP_DTLBMISS: - case EXCEP_IAERROR: - case EXCEP_DAERROR: - case EXCEP_MEMERR: - case EXCEP_MISALIGN: - case EXCEP_BUSERROR: - case EXCEP_ILLDATACC: - case EXCEP_IOINSACC: - case EXCEP_PRIVINSACC: - case EXCEP_PRIVDATACC: - case EXCEP_DATINSACC: - if (fixup_exception(regs)) - return 1; - case EXCEP_UNIMPINS: - if (regs->pc && *(uint8_t *)regs->pc == 0xff) - if (notify_die(DIE_BREAKPOINT, str, regs, code, 0, 0)) - return 1; - break; - default: - break; - } - - /* see if gdbstub wants to deal with it */ -#ifdef CONFIG_GDBSTUB - if (gdbstub_intercept(regs, code)) - return 1; -#endif - - if (notify_die(DIE_GPF, str, regs, code, 0, 0)) - return 1; - - /* make the process die as the last resort */ - die(str, regs, code); -} - -/* - * handle unsupported syscall instructions (syscall 1-15) - */ -static asmlinkage void unsupported_syscall(struct pt_regs *regs, - enum exception_code code) -{ - struct task_struct *tsk = current; - siginfo_t info; - - /* catch a kernel BUG() */ - if (code == EXCEP_SYSCALL15 && !user_mode(regs)) { - if (report_bug(regs->pc, regs) == BUG_TRAP_TYPE_BUG) { -#ifdef CONFIG_GDBSTUB - gdbstub_intercept(regs, code); -#endif - } - } - - regs->pc -= 2; /* syscall return addr is _after_ the instruction */ - - die_if_no_fixup("An unsupported syscall insn was used by the kernel\n", - regs, code); - - info.si_signo = SIGILL; - info.si_errno = ENOSYS; - info.si_code = ILL_ILLTRP; - info.si_addr = (void *) regs->pc; - force_sig_info(SIGILL, &info, tsk); -} - /* * display the register file when the stack pointer gets clobbered */ @@ -481,10 +513,8 @@ asmlinkage void uninitialised_exception(struct pt_regs *regs, { /* see if gdbstub wants to deal with it */ -#ifdef CONFIG_GDBSTUB - if (gdbstub_intercept(regs, code)) + if (debugger_intercept(code, SIGSYS, 0, regs) == 0) return; -#endif peripheral_leds_display_exception(code); printk(KERN_EMERG "Uninitialised Exception 0x%04x\n", code & 0xFFFF); @@ -549,43 +579,43 @@ void __init set_intr_stub(enum exception_code code, void *handler) */ void __init trap_init(void) { - set_excp_vector(EXCEP_TRAP, trap); - set_excp_vector(EXCEP_ISTEP, istep); - set_excp_vector(EXCEP_IBREAK, ibreak); - set_excp_vector(EXCEP_OBREAK, obreak); - - set_excp_vector(EXCEP_PRIVINS, priv_op); - set_excp_vector(EXCEP_UNIMPINS, invalid_op); - set_excp_vector(EXCEP_UNIMPEXINS, invalid_exop); - set_excp_vector(EXCEP_MEMERR, mem_error); + set_excp_vector(EXCEP_TRAP, handle_exception); + set_excp_vector(EXCEP_ISTEP, handle_exception); + set_excp_vector(EXCEP_IBREAK, handle_exception); + set_excp_vector(EXCEP_OBREAK, handle_exception); + + set_excp_vector(EXCEP_PRIVINS, handle_exception); + set_excp_vector(EXCEP_UNIMPINS, handle_exception); + set_excp_vector(EXCEP_UNIMPEXINS, handle_exception); + set_excp_vector(EXCEP_MEMERR, handle_exception); set_excp_vector(EXCEP_MISALIGN, misalignment); - set_excp_vector(EXCEP_BUSERROR, bus_error); - set_excp_vector(EXCEP_ILLINSACC, insn_acc_error); - set_excp_vector(EXCEP_ILLDATACC, data_acc_error); - set_excp_vector(EXCEP_IOINSACC, insn_acc_error); - set_excp_vector(EXCEP_PRIVINSACC, insn_acc_error); - set_excp_vector(EXCEP_PRIVDATACC, data_acc_error); - set_excp_vector(EXCEP_DATINSACC, insn_acc_error); - set_excp_vector(EXCEP_FPU_UNIMPINS, fpu_invalid_op); + set_excp_vector(EXCEP_BUSERROR, handle_exception); + set_excp_vector(EXCEP_ILLINSACC, handle_exception); + set_excp_vector(EXCEP_ILLDATACC, handle_exception); + set_excp_vector(EXCEP_IOINSACC, handle_exception); + set_excp_vector(EXCEP_PRIVINSACC, handle_exception); + set_excp_vector(EXCEP_PRIVDATACC, handle_exception); + set_excp_vector(EXCEP_DATINSACC, handle_exception); + set_excp_vector(EXCEP_FPU_UNIMPINS, handle_exception); set_excp_vector(EXCEP_FPU_OPERATION, fpu_exception); set_excp_vector(EXCEP_NMI, nmi); - set_excp_vector(EXCEP_SYSCALL1, unsupported_syscall); - set_excp_vector(EXCEP_SYSCALL2, unsupported_syscall); - set_excp_vector(EXCEP_SYSCALL3, unsupported_syscall); - set_excp_vector(EXCEP_SYSCALL4, unsupported_syscall); - set_excp_vector(EXCEP_SYSCALL5, unsupported_syscall); - set_excp_vector(EXCEP_SYSCALL6, unsupported_syscall); - set_excp_vector(EXCEP_SYSCALL7, unsupported_syscall); - set_excp_vector(EXCEP_SYSCALL8, unsupported_syscall); - set_excp_vector(EXCEP_SYSCALL9, unsupported_syscall); - set_excp_vector(EXCEP_SYSCALL10, unsupported_syscall); - set_excp_vector(EXCEP_SYSCALL11, unsupported_syscall); - set_excp_vector(EXCEP_SYSCALL12, unsupported_syscall); - set_excp_vector(EXCEP_SYSCALL13, unsupported_syscall); - set_excp_vector(EXCEP_SYSCALL14, unsupported_syscall); - set_excp_vector(EXCEP_SYSCALL15, unsupported_syscall); + set_excp_vector(EXCEP_SYSCALL1, handle_exception); + set_excp_vector(EXCEP_SYSCALL2, handle_exception); + set_excp_vector(EXCEP_SYSCALL3, handle_exception); + set_excp_vector(EXCEP_SYSCALL4, handle_exception); + set_excp_vector(EXCEP_SYSCALL5, handle_exception); + set_excp_vector(EXCEP_SYSCALL6, handle_exception); + set_excp_vector(EXCEP_SYSCALL7, handle_exception); + set_excp_vector(EXCEP_SYSCALL8, handle_exception); + set_excp_vector(EXCEP_SYSCALL9, handle_exception); + set_excp_vector(EXCEP_SYSCALL10, handle_exception); + set_excp_vector(EXCEP_SYSCALL11, handle_exception); + set_excp_vector(EXCEP_SYSCALL12, handle_exception); + set_excp_vector(EXCEP_SYSCALL13, handle_exception); + set_excp_vector(EXCEP_SYSCALL14, handle_exception); + set_excp_vector(EXCEP_SYSCALL15, handle_exception); } /* diff --git a/arch/mn10300/mm/fault.c b/arch/mn10300/mm/fault.c index 59c3da49d9d9e..0945409a80221 100644 --- a/arch/mn10300/mm/fault.c +++ b/arch/mn10300/mm/fault.c @@ -28,8 +28,9 @@ #include #include #include -#include #include +#include +#include /* * Unlock any spinlocks which will prevent us from getting the @@ -306,10 +307,8 @@ no_context: printk(" printing pc:\n"); printk(KERN_ALERT "%08lx\n", regs->pc); -#ifdef CONFIG_GDBSTUB - gdbstub_intercept( - regs, fault_code & 0x00010000 ? EXCEP_IAERROR : EXCEP_DAERROR); -#endif + debugger_intercept(fault_code & 0x00010000 ? EXCEP_IAERROR : EXCEP_DAERROR, + SIGSEGV, SEGV_ACCERR, regs); page = PTBR; page = ((unsigned long *) __va(page))[address >> 22]; -- GitLab From e460d64405c04581e42aa9cbae76815a2d4e9abe Mon Sep 17 00:00:00 2001 From: David Howells Date: Fri, 18 Mar 2011 16:54:31 +0000 Subject: [PATCH 0898/2822] MN10300: Use KGDB --- arch/mn10300/Kconfig | 2 + arch/mn10300/Kconfig.debug | 2 +- arch/mn10300/include/asm/kgdb.h | 81 +++++++++++++ arch/mn10300/include/asm/smp.h | 3 +- arch/mn10300/kernel/Makefile | 1 + arch/mn10300/kernel/kgdb.c | 202 ++++++++++++++++++++++++++++++++ 6 files changed, 289 insertions(+), 2 deletions(-) create mode 100644 arch/mn10300/include/asm/kgdb.h create mode 100644 arch/mn10300/kernel/kgdb.c diff --git a/arch/mn10300/Kconfig b/arch/mn10300/Kconfig index 6e9cac9700244..d8ab97a73db28 100644 --- a/arch/mn10300/Kconfig +++ b/arch/mn10300/Kconfig @@ -3,6 +3,8 @@ config MN10300 select HAVE_OPROFILE select HAVE_GENERIC_HARDIRQS select GENERIC_HARDIRQS_NO_DEPRECATED + select HAVE_ARCH_TRACEHOOK + select HAVE_ARCH_KGDB config AM33_2 def_bool n diff --git a/arch/mn10300/Kconfig.debug b/arch/mn10300/Kconfig.debug index 87adb8f434ee7..c2fa3a8f9eef9 100644 --- a/arch/mn10300/Kconfig.debug +++ b/arch/mn10300/Kconfig.debug @@ -153,4 +153,4 @@ endmenu config KERNEL_DEBUGGER def_bool y - depends on GDBSTUB + depends on GDBSTUB || KGDB diff --git a/arch/mn10300/include/asm/kgdb.h b/arch/mn10300/include/asm/kgdb.h new file mode 100644 index 0000000000000..eb245f18a7083 --- /dev/null +++ b/arch/mn10300/include/asm/kgdb.h @@ -0,0 +1,81 @@ +/* Kernel debugger for MN10300 + * + * Copyright (C) 2010 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public Licence + * as published by the Free Software Foundation; either version + * 2 of the Licence, or (at your option) any later version. + */ + +#ifndef _ASM_KGDB_H +#define _ASM_KGDB_H + +/* + * BUFMAX defines the maximum number of characters in inbound/outbound + * buffers at least NUMREGBYTES*2 are needed for register packets + * Longer buffer is needed to list all threads + */ +#define BUFMAX 1024 + +/* + * Note that this register image is in a different order than the register + * image that Linux produces at interrupt time. + */ +enum regnames { + GDB_FR_D0 = 0, + GDB_FR_D1 = 1, + GDB_FR_D2 = 2, + GDB_FR_D3 = 3, + GDB_FR_A0 = 4, + GDB_FR_A1 = 5, + GDB_FR_A2 = 6, + GDB_FR_A3 = 7, + + GDB_FR_SP = 8, + GDB_FR_PC = 9, + GDB_FR_MDR = 10, + GDB_FR_EPSW = 11, + GDB_FR_LIR = 12, + GDB_FR_LAR = 13, + GDB_FR_MDRQ = 14, + + GDB_FR_E0 = 15, + GDB_FR_E1 = 16, + GDB_FR_E2 = 17, + GDB_FR_E3 = 18, + GDB_FR_E4 = 19, + GDB_FR_E5 = 20, + GDB_FR_E6 = 21, + GDB_FR_E7 = 22, + + GDB_FR_SSP = 23, + GDB_FR_MSP = 24, + GDB_FR_USP = 25, + GDB_FR_MCRH = 26, + GDB_FR_MCRL = 27, + GDB_FR_MCVF = 28, + + GDB_FR_FPCR = 29, + GDB_FR_DUMMY0 = 30, + GDB_FR_DUMMY1 = 31, + + GDB_FR_FS0 = 32, + + GDB_FR_SIZE = 64, +}; + +#define GDB_ORIG_D0 41 +#define NUMREGBYTES (GDB_FR_SIZE*4) + +static inline void arch_kgdb_breakpoint(void) +{ + asm(".globl __arch_kgdb_breakpoint; __arch_kgdb_breakpoint: break"); +} +extern u8 __arch_kgdb_breakpoint; + +#define BREAK_INSTR_SIZE 1 +#define CACHE_FLUSH_IS_SAFE 1 + +#endif /* _ASM_KGDB_H */ diff --git a/arch/mn10300/include/asm/smp.h b/arch/mn10300/include/asm/smp.h index e3d13a899855b..6745dbe649441 100644 --- a/arch/mn10300/include/asm/smp.h +++ b/arch/mn10300/include/asm/smp.h @@ -62,8 +62,9 @@ * An alternate way of dealing with this could be to use the EPSW.S bits to * cache this information for systems with up to four CPUs. */ +#define arch_smp_processor_id() (CPUID) #if 0 -#define raw_smp_processor_id() (CPUID) +#define raw_smp_processor_id() (arch_smp_processor_id()) #else #define raw_smp_processor_id() (current_thread_info()->cpu) #endif diff --git a/arch/mn10300/kernel/Makefile b/arch/mn10300/kernel/Makefile index 48ab4017434de..47ed30fe8178c 100644 --- a/arch/mn10300/kernel/Makefile +++ b/arch/mn10300/kernel/Makefile @@ -25,3 +25,4 @@ obj-$(CONFIG_MN10300_RTC) += rtc.o obj-$(CONFIG_PROFILE) += profile.o profile-low.o obj-$(CONFIG_MODULES) += module.o obj-$(CONFIG_KPROBES) += kprobes.o +obj-$(CONFIG_KGDB) += kgdb.o diff --git a/arch/mn10300/kernel/kgdb.c b/arch/mn10300/kernel/kgdb.c new file mode 100644 index 0000000000000..7d575f5530994 --- /dev/null +++ b/arch/mn10300/kernel/kgdb.c @@ -0,0 +1,202 @@ +/* kgdb support for MN10300 + * + * Copyright (C) 2010 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public Licence + * as published by the Free Software Foundation; either version + * 2 of the Licence, or (at your option) any later version. + */ + +#include +#include +#include +#include +#include +#include +#include +#include "internal.h" + +/* + * Copy kernel exception frame registers to the GDB register file + */ +void pt_regs_to_gdb_regs(unsigned long *gdb_regs, struct pt_regs *regs) +{ + unsigned long ssp = (unsigned long) (regs + 1); + + gdb_regs[GDB_FR_D0] = regs->d0; + gdb_regs[GDB_FR_D1] = regs->d1; + gdb_regs[GDB_FR_D2] = regs->d2; + gdb_regs[GDB_FR_D3] = regs->d3; + gdb_regs[GDB_FR_A0] = regs->a0; + gdb_regs[GDB_FR_A1] = regs->a1; + gdb_regs[GDB_FR_A2] = regs->a2; + gdb_regs[GDB_FR_A3] = regs->a3; + gdb_regs[GDB_FR_SP] = (regs->epsw & EPSW_nSL) ? regs->sp : ssp; + gdb_regs[GDB_FR_PC] = regs->pc; + gdb_regs[GDB_FR_MDR] = regs->mdr; + gdb_regs[GDB_FR_EPSW] = regs->epsw; + gdb_regs[GDB_FR_LIR] = regs->lir; + gdb_regs[GDB_FR_LAR] = regs->lar; + gdb_regs[GDB_FR_MDRQ] = regs->mdrq; + gdb_regs[GDB_FR_E0] = regs->e0; + gdb_regs[GDB_FR_E1] = regs->e1; + gdb_regs[GDB_FR_E2] = regs->e2; + gdb_regs[GDB_FR_E3] = regs->e3; + gdb_regs[GDB_FR_E4] = regs->e4; + gdb_regs[GDB_FR_E5] = regs->e5; + gdb_regs[GDB_FR_E6] = regs->e6; + gdb_regs[GDB_FR_E7] = regs->e7; + gdb_regs[GDB_FR_SSP] = ssp; + gdb_regs[GDB_FR_MSP] = 0; + gdb_regs[GDB_FR_USP] = regs->sp; + gdb_regs[GDB_FR_MCRH] = regs->mcrh; + gdb_regs[GDB_FR_MCRL] = regs->mcrl; + gdb_regs[GDB_FR_MCVF] = regs->mcvf; + gdb_regs[GDB_FR_DUMMY0] = 0; + gdb_regs[GDB_FR_DUMMY1] = 0; + gdb_regs[GDB_FR_FS0] = 0; +} + +/* + * Extracts kernel SP/PC values understandable by gdb from the values + * saved by switch_to(). + */ +void sleeping_thread_to_gdb_regs(unsigned long *gdb_regs, struct task_struct *p) +{ + gdb_regs[GDB_FR_SSP] = p->thread.sp; + gdb_regs[GDB_FR_PC] = p->thread.pc; + gdb_regs[GDB_FR_A3] = p->thread.a3; + gdb_regs[GDB_FR_USP] = p->thread.usp; + gdb_regs[GDB_FR_FPCR] = p->thread.fpu_state.fpcr; +} + +/* + * Fill kernel exception frame registers from the GDB register file + */ +void gdb_regs_to_pt_regs(unsigned long *gdb_regs, struct pt_regs *regs) +{ + regs->d0 = gdb_regs[GDB_FR_D0]; + regs->d1 = gdb_regs[GDB_FR_D1]; + regs->d2 = gdb_regs[GDB_FR_D2]; + regs->d3 = gdb_regs[GDB_FR_D3]; + regs->a0 = gdb_regs[GDB_FR_A0]; + regs->a1 = gdb_regs[GDB_FR_A1]; + regs->a2 = gdb_regs[GDB_FR_A2]; + regs->a3 = gdb_regs[GDB_FR_A3]; + regs->sp = gdb_regs[GDB_FR_SP]; + regs->pc = gdb_regs[GDB_FR_PC]; + regs->mdr = gdb_regs[GDB_FR_MDR]; + regs->epsw = gdb_regs[GDB_FR_EPSW]; + regs->lir = gdb_regs[GDB_FR_LIR]; + regs->lar = gdb_regs[GDB_FR_LAR]; + regs->mdrq = gdb_regs[GDB_FR_MDRQ]; + regs->e0 = gdb_regs[GDB_FR_E0]; + regs->e1 = gdb_regs[GDB_FR_E1]; + regs->e2 = gdb_regs[GDB_FR_E2]; + regs->e3 = gdb_regs[GDB_FR_E3]; + regs->e4 = gdb_regs[GDB_FR_E4]; + regs->e5 = gdb_regs[GDB_FR_E5]; + regs->e6 = gdb_regs[GDB_FR_E6]; + regs->e7 = gdb_regs[GDB_FR_E7]; + regs->sp = gdb_regs[GDB_FR_SSP]; + /* gdb_regs[GDB_FR_MSP]; */ + // regs->usp = gdb_regs[GDB_FR_USP]; + regs->mcrh = gdb_regs[GDB_FR_MCRH]; + regs->mcrl = gdb_regs[GDB_FR_MCRL]; + regs->mcvf = gdb_regs[GDB_FR_MCVF]; + /* gdb_regs[GDB_FR_DUMMY0]; */ + /* gdb_regs[GDB_FR_DUMMY1]; */ + + // regs->fpcr = gdb_regs[GDB_FR_FPCR]; + // regs->fs0 = gdb_regs[GDB_FR_FS0]; +} + +struct kgdb_arch arch_kgdb_ops = { + .gdb_bpt_instr = { 0xff }, + .flags = KGDB_HW_BREAKPOINT, +}; + +/* + * Handle unknown packets and [Ccs] packets + */ +int kgdb_arch_handle_exception(int vector, int signo, int err_code, + char *remcom_in_buffer, char *remcom_out_buffer, + struct pt_regs *regs) +{ + long addr; + char *ptr; + + switch (remcom_in_buffer[0]) { + case 'c': + if (kgdb_contthread && kgdb_contthread != current) { + strcpy(remcom_out_buffer, "E00"); + break; + } + + kgdb_contthread = NULL; + + /* try to read optional parameter, pc unchanged if no parm */ + ptr = &remcom_in_buffer[1]; + if (kgdb_hex2long(&ptr, &addr)) + regs->pc = addr; + return 0; + + case 's': + break; /* we don't do hardware single stepping */ + } + return -1; /* this means that we do not want to exit from the handler */ +} + +/* + * Handle event interception + * - returns 0 if the exception should be skipped, -ERROR otherwise. + */ +int debugger_intercept(enum exception_code excep, int signo, int si_code, + struct pt_regs *regs) +{ + int ret; + + ret = kgdb_handle_exception(excep, signo, si_code, regs); + + debugger_local_cache_flushinv(); + + return ret; +} + +/* + * Determine if we've hit a debugger special breakpoint + */ +int at_debugger_breakpoint(struct pt_regs *regs) +{ + return regs->pc == (unsigned long)&__arch_kgdb_breakpoint; +} + +/* + * Initialise kgdb + */ +int kgdb_arch_init(void) +{ + return 0; +} + +/* + * Do something, perhaps, but don't know what. + */ +void kgdb_arch_exit(void) +{ +} + +#ifdef CONFIG_SMP +void debugger_nmi_interrupt(struct pt_regs *regs, enum exception_code code) +{ + kgdb_nmicallback(arch_smp_processor_id(), regs); + debugger_local_cache_flushinv(); +} + +void kgdb_roundup_cpus(unsigned long flags) +{ + smp_jump_to_debugger(); +} +#endif -- GitLab From d57f078b193981d1b7d24193f3118c6b806db0ff Mon Sep 17 00:00:00 2001 From: David Howells Date: Fri, 18 Mar 2011 16:54:31 +0000 Subject: [PATCH 0899/2822] KGDB: Notify GDB of machine halt, reboot or power off Notify GDB of the machine halting, rebooting or powering off by sending it an exited command (remote protocol command 'W'). This is done by calling: void gdbstub_exit(int status) from the arch's machine_{halt,restart,power_off}() functions with an appropriate exit status to be reported to GDB. Signed-off-by: David Howells --- include/linux/kgdb.h | 1 + kernel/debug/gdbstub.c | 30 ++++++++++++++++++++++++++++++ 2 files changed, 31 insertions(+) diff --git a/include/linux/kgdb.h b/include/linux/kgdb.h index 092e4250a4583..10ca03d0a250e 100644 --- a/include/linux/kgdb.h +++ b/include/linux/kgdb.h @@ -297,6 +297,7 @@ extern int kgdb_handle_exception(int ex_vector, int signo, int err_code, struct pt_regs *regs); extern int kgdb_nmicallback(int cpu, void *regs); +extern void gdbstub_exit(int status); extern int kgdb_single_step; extern atomic_t kgdb_active; diff --git a/kernel/debug/gdbstub.c b/kernel/debug/gdbstub.c index 481a7bd2dfe75..a11db956dd62c 100644 --- a/kernel/debug/gdbstub.c +++ b/kernel/debug/gdbstub.c @@ -1093,3 +1093,33 @@ int gdbstub_state(struct kgdb_state *ks, char *cmd) put_packet(remcom_out_buffer); return 0; } + +/** + * gdbstub_exit - Send an exit message to GDB + * @status: The exit code to report. + */ +void gdbstub_exit(int status) +{ + unsigned char checksum, ch, buffer[3]; + int loop; + + buffer[0] = 'W'; + buffer[1] = hex_asc_hi(status); + buffer[2] = hex_asc_lo(status); + + dbg_io_ops->write_char('$'); + checksum = 0; + + for (loop = 0; loop < 3; loop++) { + ch = buffer[loop]; + checksum += ch; + dbg_io_ops->write_char(ch); + } + + dbg_io_ops->write_char('#'); + dbg_io_ops->write_char(hex_asc_hi(checksum)); + dbg_io_ops->write_char(hex_asc_lo(checksum)); + + /* make sure the output is flushed, lest the bootloader clobber it */ + dbg_io_ops->flush(); +} -- GitLab From 044264bbe34085b550e6429ce97ef310667be9dc Mon Sep 17 00:00:00 2001 From: David Howells Date: Fri, 18 Mar 2011 16:54:31 +0000 Subject: [PATCH 0900/2822] MN10300: Generalise kernel debugger kernel halt, reboot or power off hook Generalise the kernel debugger hook for notification of halt, reboot or power off. This is used by gdbstub to tell the debugger it is exiting. This will be useful for KGDB too. Signed-off-by: David Howells --- arch/mn10300/kernel/process.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/mn10300/kernel/process.c b/arch/mn10300/kernel/process.c index e1b14a6ed5446..28eec3102535c 100644 --- a/arch/mn10300/kernel/process.c +++ b/arch/mn10300/kernel/process.c @@ -135,7 +135,7 @@ void release_segments(struct mm_struct *mm) void machine_restart(char *cmd) { -#ifdef CONFIG_GDBSTUB +#ifdef CONFIG_KERNEL_DEBUGGER gdbstub_exit(0); #endif @@ -148,14 +148,14 @@ void machine_restart(char *cmd) void machine_halt(void) { -#ifdef CONFIG_GDBSTUB +#ifdef CONFIG_KERNEL_DEBUGGER gdbstub_exit(0); #endif } void machine_power_off(void) { -#ifdef CONFIG_GDBSTUB +#ifdef CONFIG_KERNEL_DEBUGGER gdbstub_exit(0); #endif } -- GitLab From 5141c46c6137f4866eb5f29e25ed0556bcc4c634 Mon Sep 17 00:00:00 2001 From: David Howells Date: Fri, 18 Mar 2011 16:54:32 +0000 Subject: [PATCH 0901/2822] MN10300: Emulate single stepping in KGDB on MN10300 Emulate single stepping in KGDB on MN10300 by way of temporary breakpoint insertion. These breakpoints are never actually seen by KGDB, and will overlay KGDB's own breakpoints. The breakpoints are removed by switch_to() and reinstalled on switching back so that if preemption occurs, the preempting task doesn't hit them (though it will still hit KGDB's regular breakpoints). If KGDB is reentered for any reason, then the single step breakpoint is completely erased and must be set again by the debugger. We take advantage of the fact that KGDB will effectively halt all other CPUs whilst this CPU is single-stepping to avoid SMP problems. If the single-stepping task is preempted and killed without KGDB being reinvoked, then the breakpoint(s) will be cleared and KGDB will be jumped back into. Signed-off-by: David Howells --- arch/mn10300/include/asm/thread_info.h | 4 + arch/mn10300/kernel/kgdb.c | 322 ++++++++++++++++++++++++- arch/mn10300/kernel/switch_to.S | 111 ++++++++- 3 files changed, 425 insertions(+), 12 deletions(-) diff --git a/arch/mn10300/include/asm/thread_info.h b/arch/mn10300/include/asm/thread_info.h index aa07a4a5d7949..c139fa17e2e40 100644 --- a/arch/mn10300/include/asm/thread_info.h +++ b/arch/mn10300/include/asm/thread_info.h @@ -129,7 +129,11 @@ static inline unsigned long current_stack_pointer(void) #define alloc_thread_info(tsk) kmalloc(THREAD_SIZE, GFP_KERNEL) #endif +#ifndef CONFIG_KGDB #define free_thread_info(ti) kfree((ti)) +#else +extern void free_thread_info(struct thread_info *); +#endif #define get_thread_info(ti) get_task_struct((ti)->task) #define put_thread_info(ti) put_task_struct((ti)->task) diff --git a/arch/mn10300/kernel/kgdb.c b/arch/mn10300/kernel/kgdb.c index 7d575f5530994..f6c981db2a36c 100644 --- a/arch/mn10300/kernel/kgdb.c +++ b/arch/mn10300/kernel/kgdb.c @@ -9,6 +9,7 @@ * 2 of the Licence, or (at your option) any later version. */ +#include #include #include #include @@ -18,6 +19,13 @@ #include #include "internal.h" +/* + * Software single-stepping breakpoint save (used by __switch_to()) + */ +static struct thread_info *kgdb_sstep_thread; +u8 *kgdb_sstep_bp_addr[2]; +u8 kgdb_sstep_bp[2]; + /* * Copy kernel exception frame registers to the GDB register file */ @@ -118,8 +126,293 @@ struct kgdb_arch arch_kgdb_ops = { .flags = KGDB_HW_BREAKPOINT, }; +static const unsigned char mn10300_kgdb_insn_sizes[256] = +{ + /* 1 2 3 4 5 6 7 8 9 a b c d e f */ + 1, 3, 3, 3, 1, 3, 3, 3, 1, 3, 3, 3, 1, 3, 3, 3, /* 0 */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 1 */ + 2, 2, 2, 2, 3, 3, 3, 3, 2, 2, 2, 2, 3, 3, 3, 3, /* 2 */ + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 1, 1, 1, 1, /* 3 */ + 1, 1, 2, 2, 1, 1, 2, 2, 1, 1, 2, 2, 1, 1, 2, 2, /* 4 */ + 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, /* 5 */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 6 */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 7 */ + 2, 1, 1, 1, 1, 2, 1, 1, 1, 1, 2, 1, 1, 1, 1, 2, /* 8 */ + 2, 1, 1, 1, 1, 2, 1, 1, 1, 1, 2, 1, 1, 1, 1, 2, /* 9 */ + 2, 1, 1, 1, 1, 2, 1, 1, 1, 1, 2, 1, 1, 1, 1, 2, /* a */ + 2, 1, 1, 1, 1, 2, 1, 1, 1, 1, 2, 1, 1, 1, 1, 2, /* b */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 2, 2, /* c */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* d */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* e */ + 0, 2, 2, 2, 2, 2, 2, 4, 0, 3, 0, 4, 0, 6, 7, 1 /* f */ +}; + /* - * Handle unknown packets and [Ccs] packets + * Attempt to emulate single stepping by means of breakpoint instructions. + * Although there is a single-step trace flag in EPSW, its use is not + * sufficiently documented and is only intended for use with the JTAG debugger. + */ +static int kgdb_arch_do_singlestep(struct pt_regs *regs) +{ + unsigned long arg; + unsigned size; + u8 *pc = (u8 *)regs->pc, *sp = (u8 *)(regs + 1), cur; + u8 *x = NULL, *y = NULL; + int ret; + + ret = probe_kernel_read(&cur, pc, 1); + if (ret < 0) + return ret; + + size = mn10300_kgdb_insn_sizes[cur]; + if (size > 0) { + x = pc + size; + goto set_x; + } + + switch (cur) { + /* Bxx (d8,PC) */ + case 0xc0 ... 0xca: + ret = probe_kernel_read(&arg, pc + 1, 1); + if (ret < 0) + return ret; + x = pc + 2; + if (arg >= 0 && arg <= 2) + goto set_x; + y = pc + (s8)arg; + goto set_x_and_y; + + /* LXX (d8,PC) */ + case 0xd0 ... 0xda: + x = pc + 1; + if (regs->pc == regs->lar) + goto set_x; + y = (u8 *)regs->lar; + goto set_x_and_y; + + /* SETLB - loads the next four bytes into the LIR register + * (which mustn't include a breakpoint instruction) */ + case 0xdb: + x = pc + 5; + goto set_x; + + /* JMP (d16,PC) or CALL (d16,PC) */ + case 0xcc: + case 0xcd: + ret = probe_kernel_read(&arg, pc + 1, 2); + if (ret < 0) + return ret; + x = pc + (s16)arg; + goto set_x; + + /* JMP (d32,PC) or CALL (d32,PC) */ + case 0xdc: + case 0xdd: + ret = probe_kernel_read(&arg, pc + 1, 4); + if (ret < 0) + return ret; + x = pc + (s32)arg; + goto set_x; + + /* RETF */ + case 0xde: + x = (u8 *)regs->mdr; + goto set_x; + + /* RET */ + case 0xdf: + ret = probe_kernel_read(&arg, pc + 2, 1); + if (ret < 0) + return ret; + ret = probe_kernel_read(&x, sp + (s8)arg, 4); + if (ret < 0) + return ret; + goto set_x; + + case 0xf0: + ret = probe_kernel_read(&cur, pc + 1, 1); + if (ret < 0) + return ret; + + if (cur >= 0xf0 && cur <= 0xf7) { + /* JMP (An) / CALLS (An) */ + switch (cur & 3) { + case 0: x = (u8 *)regs->a0; break; + case 1: x = (u8 *)regs->a1; break; + case 2: x = (u8 *)regs->a2; break; + case 3: x = (u8 *)regs->a3; break; + } + goto set_x; + } else if (cur == 0xfc) { + /* RETS */ + ret = probe_kernel_read(&x, sp, 4); + if (ret < 0) + return ret; + goto set_x; + } else if (cur == 0xfd) { + /* RTI */ + ret = probe_kernel_read(&x, sp + 4, 4); + if (ret < 0) + return ret; + goto set_x; + } else { + x = pc + 2; + goto set_x; + } + break; + + /* potential 3-byte conditional branches */ + case 0xf8: + ret = probe_kernel_read(&cur, pc + 1, 1); + if (ret < 0) + return ret; + x = pc + 3; + + if (cur >= 0xe8 && cur <= 0xeb) { + ret = probe_kernel_read(&arg, pc + 2, 1); + if (ret < 0) + return ret; + if (arg >= 0 && arg <= 3) + goto set_x; + y = pc + (s8)arg; + goto set_x_and_y; + } + goto set_x; + + case 0xfa: + ret = probe_kernel_read(&cur, pc + 1, 1); + if (ret < 0) + return ret; + + if (cur == 0xff) { + /* CALLS (d16,PC) */ + ret = probe_kernel_read(&arg, pc + 2, 2); + if (ret < 0) + return ret; + x = pc + (s16)arg; + goto set_x; + } + + x = pc + 4; + goto set_x; + + case 0xfc: + ret = probe_kernel_read(&cur, pc + 1, 1); + if (ret < 0) + return ret; + + if (cur == 0xff) { + /* CALLS (d32,PC) */ + ret = probe_kernel_read(&arg, pc + 2, 4); + if (ret < 0) + return ret; + x = pc + (s32)arg; + goto set_x; + } + + x = pc + 6; + goto set_x; + } + + return 0; + +set_x: + kgdb_sstep_bp_addr[0] = x; + kgdb_sstep_bp_addr[1] = NULL; + ret = probe_kernel_read(&kgdb_sstep_bp[0], x, 1); + if (ret < 0) + return ret; + ret = probe_kernel_write(x, &arch_kgdb_ops.gdb_bpt_instr, 1); + if (ret < 0) + return ret; + kgdb_sstep_thread = current_thread_info(); + debugger_local_cache_flushinv_one(x); + return ret; + +set_x_and_y: + kgdb_sstep_bp_addr[0] = x; + kgdb_sstep_bp_addr[1] = y; + ret = probe_kernel_read(&kgdb_sstep_bp[0], x, 1); + if (ret < 0) + return ret; + ret = probe_kernel_read(&kgdb_sstep_bp[1], y, 1); + if (ret < 0) + return ret; + ret = probe_kernel_write(x, &arch_kgdb_ops.gdb_bpt_instr, 1); + if (ret < 0) + return ret; + ret = probe_kernel_write(y, &arch_kgdb_ops.gdb_bpt_instr, 1); + if (ret < 0) { + probe_kernel_write(kgdb_sstep_bp_addr[0], + &kgdb_sstep_bp[0], 1); + } else { + kgdb_sstep_thread = current_thread_info(); + } + debugger_local_cache_flushinv_one(x); + debugger_local_cache_flushinv_one(y); + return ret; +} + +/* + * Remove emplaced single-step breakpoints, returning true if we hit one of + * them. + */ +static bool kgdb_arch_undo_singlestep(struct pt_regs *regs) +{ + bool hit = false; + u8 *x = kgdb_sstep_bp_addr[0], *y = kgdb_sstep_bp_addr[1]; + u8 opcode; + + if (kgdb_sstep_thread == current_thread_info()) { + if (x) { + if (x == (u8 *)regs->pc) + hit = true; + if (probe_kernel_read(&opcode, x, + 1) < 0 || + opcode != 0xff) + BUG(); + probe_kernel_write(x, &kgdb_sstep_bp[0], 1); + debugger_local_cache_flushinv_one(x); + } + if (y) { + if (y == (u8 *)regs->pc) + hit = true; + if (probe_kernel_read(&opcode, y, + 1) < 0 || + opcode != 0xff) + BUG(); + probe_kernel_write(y, &kgdb_sstep_bp[1], 1); + debugger_local_cache_flushinv_one(y); + } + } + + kgdb_sstep_bp_addr[0] = NULL; + kgdb_sstep_bp_addr[1] = NULL; + kgdb_sstep_thread = NULL; + return hit; +} + +/* + * Catch a single-step-pending thread being deleted and make sure the global + * single-step state is cleared. At this point the breakpoints should have + * been removed by __switch_to(). + */ +void free_thread_info(struct thread_info *ti) +{ + if (kgdb_sstep_thread == ti) { + kgdb_sstep_thread = NULL; + + /* However, we may now be running in degraded mode, with most + * of the CPUs disabled until such a time as KGDB is reentered, + * so force immediate reentry */ + kgdb_breakpoint(); + } + kfree(ti); +} + +/* + * Handle unknown packets and [CcsDk] packets + * - at this point breakpoints have been installed */ int kgdb_arch_handle_exception(int vector, int signo, int err_code, char *remcom_in_buffer, char *remcom_out_buffer, @@ -130,21 +423,22 @@ int kgdb_arch_handle_exception(int vector, int signo, int err_code, switch (remcom_in_buffer[0]) { case 'c': - if (kgdb_contthread && kgdb_contthread != current) { - strcpy(remcom_out_buffer, "E00"); - break; - } - - kgdb_contthread = NULL; - + case 's': /* try to read optional parameter, pc unchanged if no parm */ ptr = &remcom_in_buffer[1]; if (kgdb_hex2long(&ptr, &addr)) regs->pc = addr; - return 0; + case 'D': + case 'k': + atomic_set(&kgdb_cpu_doing_single_step, -1); - case 's': - break; /* we don't do hardware single stepping */ + if (remcom_in_buffer[0] == 's') { + kgdb_arch_do_singlestep(regs); + kgdb_single_step = 1; + atomic_set(&kgdb_cpu_doing_single_step, + raw_smp_processor_id()); + } + return 0; } return -1; /* this means that we do not want to exit from the handler */ } @@ -158,6 +452,12 @@ int debugger_intercept(enum exception_code excep, int signo, int si_code, { int ret; + if (kgdb_arch_undo_singlestep(regs)) { + excep = EXCEP_TRAP; + signo = SIGTRAP; + si_code = TRAP_TRACE; + } + ret = kgdb_handle_exception(excep, signo, si_code, regs); debugger_local_cache_flushinv(); diff --git a/arch/mn10300/kernel/switch_to.S b/arch/mn10300/kernel/switch_to.S index 9074d0fb8788f..de3e74fc9ea04 100644 --- a/arch/mn10300/kernel/switch_to.S +++ b/arch/mn10300/kernel/switch_to.S @@ -39,11 +39,17 @@ ENTRY(__switch_to) # save prev context mov __switch_back,d0 - mov d0,(THREAD_PC,a0) mov sp,a2 mov a2,(THREAD_SP,a0) mov a3,(THREAD_A3,a0) +#ifdef CONFIG_KGDB + btst 0xff,(kgdb_single_step) + bne __switch_to__lift_sstep_bp +__switch_to__continue: +#endif + mov d0,(THREAD_PC,a0) + mov (THREAD_A3,a1),a3 mov (THREAD_SP,a1),a2 @@ -68,3 +74,106 @@ ENTRY(__switch_to) __switch_back: and ~EPSW_NMID,epsw ret [d2,d3,a2,a3,exreg1],32 + +#ifdef CONFIG_KGDB +############################################################################### +# +# Lift the single-step breakpoints when the task being traced is switched out +# A0 = prev +# A1 = next +# +############################################################################### +__switch_to__lift_sstep_bp: + add -12,sp + mov a0,e4 + mov a1,e5 + + # Clear the single-step flag to prevent us coming this way until we get + # switched back in + bclr 0xff,(kgdb_single_step) + + # Remove first breakpoint + mov (kgdb_sstep_bp_addr),a2 + cmp 0,a2 + beq 1f + movbu (kgdb_sstep_bp),d0 + movbu d0,(a2) +#if defined(CONFIG_MN10300_CACHE_FLUSH_ICACHE) || defined(CONFIG_MN10300_CACHE_INV_ICACHE) + mov a2,d0 + mov a2,d1 + add 1,d1 + calls flush_icache_range +#endif +1: + + # Remove second breakpoint + mov (kgdb_sstep_bp_addr+4),a2 + cmp 0,a2 + beq 2f + movbu (kgdb_sstep_bp+1),d0 + movbu d0,(a2) +#if defined(CONFIG_MN10300_CACHE_FLUSH_ICACHE) || defined(CONFIG_MN10300_CACHE_INV_ICACHE) + mov a2,d0 + mov a2,d1 + add 1,d1 + calls flush_icache_range +#endif +2: + + # Change the resumption address and return + mov __switch_back__reinstall_sstep_bp,d0 + mov e4,a0 + mov e5,a1 + add 12,sp + bra __switch_to__continue + +############################################################################### +# +# Reinstall the single-step breakpoints when the task being traced is switched +# back in (A1 points to the new thread_struct). +# +############################################################################### +__switch_back__reinstall_sstep_bp: + add -12,sp + mov a0,e4 # save the return value + mov 0xff,d3 + + # Reinstall first breakpoint + mov (kgdb_sstep_bp_addr),a2 + cmp 0,a2 + beq 1f + movbu (a2),d0 + movbu d0,(kgdb_sstep_bp) + movbu d3,(a2) +#if defined(CONFIG_MN10300_CACHE_FLUSH_ICACHE) || defined(CONFIG_MN10300_CACHE_INV_ICACHE) + mov a2,d0 + mov a2,d1 + add 1,d1 + calls flush_icache_range +#endif +1: + + # Reinstall second breakpoint + mov (kgdb_sstep_bp_addr+4),a2 + cmp 0,a2 + beq 2f + movbu (a2),d0 + movbu d0,(kgdb_sstep_bp+1) + movbu d3,(a2) +#if defined(CONFIG_MN10300_CACHE_FLUSH_ICACHE) || defined(CONFIG_MN10300_CACHE_INV_ICACHE) + mov a2,d0 + mov a2,d1 + add 1,d1 + calls flush_icache_range +#endif +2: + + mov d3,(kgdb_single_step) + + # Restore the return value (the previous thread_struct pointer) + mov e4,a0 + mov a0,d0 + add 12,sp + bra __switch_back + +#endif /* CONFIG_KGDB */ -- GitLab From 52885b32a5f7326d9505ca45969a695bad2459c4 Mon Sep 17 00:00:00 2001 From: David Howells Date: Fri, 18 Mar 2011 16:54:32 +0000 Subject: [PATCH 0902/2822] MN10300: Allow KGDB to use the MN10300 serial ports Allow KGDB to use the MN10300 serial ports through the polled I/O interface provided via the TTY/serial layer and the kgdboc driver. This allows the kernel to be started with something like: kgdboc=ttySM0,115200 added to the command line. Signed-off-by: David Howells --- arch/mn10300/kernel/mn10300-serial.c | 75 ++++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) diff --git a/arch/mn10300/kernel/mn10300-serial.c b/arch/mn10300/kernel/mn10300-serial.c index 93c53739cfc94..efca426a2ed4e 100644 --- a/arch/mn10300/kernel/mn10300-serial.c +++ b/arch/mn10300/kernel/mn10300-serial.c @@ -119,6 +119,10 @@ static int mn10300_serial_request_port(struct uart_port *); static void mn10300_serial_config_port(struct uart_port *, int); static int mn10300_serial_verify_port(struct uart_port *, struct serial_struct *); +#ifdef CONFIG_CONSOLE_POLL +static void mn10300_serial_poll_put_char(struct uart_port *, unsigned char); +static int mn10300_serial_poll_get_char(struct uart_port *); +#endif static const struct uart_ops mn10300_serial_ops = { .tx_empty = mn10300_serial_tx_empty, @@ -138,6 +142,10 @@ static const struct uart_ops mn10300_serial_ops = { .request_port = mn10300_serial_request_port, .config_port = mn10300_serial_config_port, .verify_port = mn10300_serial_verify_port, +#ifdef CONFIG_CONSOLE_POLL + .poll_put_char = mn10300_serial_poll_put_char, + .poll_get_char = mn10300_serial_poll_get_char, +#endif }; static irqreturn_t mn10300_serial_interrupt(int irq, void *dev_id); @@ -1634,3 +1642,70 @@ static int __init mn10300_serial_console_init(void) console_initcall(mn10300_serial_console_init); #endif + +#ifdef CONFIG_CONSOLE_POLL +/* + * Polled character reception for the kernel debugger + */ +static int mn10300_serial_poll_get_char(struct uart_port *_port) +{ + struct mn10300_serial_port *port = + container_of(_port, struct mn10300_serial_port, uart); + unsigned ix; + u8 st, ch; + + _enter("%s", port->name); + + do { + /* pull chars out of the hat */ + ix = port->rx_outp; + if (ix == port->rx_inp) + return NO_POLL_CHAR; + + ch = port->rx_buffer[ix++]; + st = port->rx_buffer[ix++]; + smp_rmb(); + port->rx_outp = ix & (MNSC_BUFFER_SIZE - 1); + + } while (st & (SC01STR_FEF | SC01STR_PEF | SC01STR_OEF)); + + return ch; +} + + +/* + * Polled character transmission for the kernel debugger + */ +static void mn10300_serial_poll_put_char(struct uart_port *_port, + unsigned char ch) +{ + struct mn10300_serial_port *port = + container_of(_port, struct mn10300_serial_port, uart); + u8 intr, tmp; + + /* wait for the transmitter to finish anything it might be doing (and + * this includes the virtual DMA handler, so it might take a while) */ + while (*port->_status & (SC01STR_TBF | SC01STR_TXF)) + continue; + + /* disable the Tx ready interrupt */ + intr = *port->_intr; + *port->_intr = intr & ~SC01ICR_TI; + tmp = *port->_intr; + + if (ch == 0x0a) { + *(u8 *) port->_txb = 0x0d; + while (*port->_status & SC01STR_TBF) + continue; + } + + *(u8 *) port->_txb = ch; + while (*port->_status & SC01STR_TBF) + continue; + + /* restore the Tx interrupt flag */ + *port->_intr = intr; + tmp = *port->_intr; +} + +#endif /* CONFIG_CONSOLE_POLL */ -- GitLab From 1a8d59e529d07f7888f9c6c86a9f59ea4ef077aa Mon Sep 17 00:00:00 2001 From: David Howells Date: Fri, 18 Mar 2011 16:54:32 +0000 Subject: [PATCH 0903/2822] MN10300: Deprecate gdbstub Deprecate the MN10300 arch's gdbstub in favour of KGDB, which is more capable in some areas (such as SMP) and almost as capable in others (it's I/O is not as decoupled and it can't start as early). gdbstub will be removed in a later version when we're satisfied with KGDB's working. Signed-off-by: David Howells --- arch/mn10300/Kconfig.debug | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/arch/mn10300/Kconfig.debug b/arch/mn10300/Kconfig.debug index c2fa3a8f9eef9..bdbfd444a9ff9 100644 --- a/arch/mn10300/Kconfig.debug +++ b/arch/mn10300/Kconfig.debug @@ -36,7 +36,7 @@ config KPROBES config GDBSTUB bool "Remote GDB kernel debugging" - depends on DEBUG_KERNEL + depends on DEBUG_KERNEL && DEPRECATED select DEBUG_INFO select FRAME_POINTER help @@ -46,6 +46,9 @@ config GDBSTUB RAM to avoid excessive linking time. This is only useful for kernel hackers. If unsure, say N. + This is deprecated in favour of KGDB and will be removed in a later + version. + config GDBSTUB_IMMEDIATE bool "Break into GDB stub immediately" depends on GDBSTUB -- GitLab From e1620d591a75a10b15cf61dbf8243a0b7e6731a2 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Fri, 18 Mar 2011 19:55:36 +0100 Subject: [PATCH 0904/2822] USB: Move runtime PM callbacks to usb_device_pm_ops USB defines usb_device_type pointing to usb_device_pm_ops that provides system-wide PM callbacks only and usb_bus_type pointing to usb_bus_pm_ops that provides runtime PM callbacks only. However, the USB runtime PM callbacks may be defined in usb_device_pm_ops which makes it possible to drop usb_bus_pm_ops and will allow us to consolidate the handling of subsystems by the PM core code. Signed-off-by: Rafael J. Wysocki Acked-by: Greg Kroah-Hartman --- drivers/usb/core/driver.c | 15 +++------------ drivers/usb/core/usb.c | 5 +++++ drivers/usb/core/usb.h | 3 +++ 3 files changed, 11 insertions(+), 12 deletions(-) diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c index 38072e4e74bd6..e35a17687c05f 100644 --- a/drivers/usb/core/driver.c +++ b/drivers/usb/core/driver.c @@ -1646,7 +1646,7 @@ static int autosuspend_check(struct usb_device *udev) return 0; } -static int usb_runtime_suspend(struct device *dev) +int usb_runtime_suspend(struct device *dev) { struct usb_device *udev = to_usb_device(dev); int status; @@ -1667,7 +1667,7 @@ static int usb_runtime_suspend(struct device *dev) return status; } -static int usb_runtime_resume(struct device *dev) +int usb_runtime_resume(struct device *dev) { struct usb_device *udev = to_usb_device(dev); int status; @@ -1679,7 +1679,7 @@ static int usb_runtime_resume(struct device *dev) return status; } -static int usb_runtime_idle(struct device *dev) +int usb_runtime_idle(struct device *dev) { struct usb_device *udev = to_usb_device(dev); @@ -1691,19 +1691,10 @@ static int usb_runtime_idle(struct device *dev) return 0; } -static const struct dev_pm_ops usb_bus_pm_ops = { - .runtime_suspend = usb_runtime_suspend, - .runtime_resume = usb_runtime_resume, - .runtime_idle = usb_runtime_idle, -}; - #endif /* CONFIG_USB_SUSPEND */ struct bus_type usb_bus_type = { .name = "usb", .match = usb_device_match, .uevent = usb_uevent, -#ifdef CONFIG_USB_SUSPEND - .pm = &usb_bus_pm_ops, -#endif }; diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c index 079cb57bab4f2..d9d4b169404f9 100644 --- a/drivers/usb/core/usb.c +++ b/drivers/usb/core/usb.c @@ -315,6 +315,11 @@ static const struct dev_pm_ops usb_device_pm_ops = { .thaw = usb_dev_thaw, .poweroff = usb_dev_poweroff, .restore = usb_dev_restore, +#ifdef CONFIG_USB_SUSPEND + .runtime_suspend = usb_runtime_suspend, + .runtime_resume = usb_runtime_resume, + .runtime_idle = usb_runtime_idle, +#endif }; #endif /* CONFIG_PM */ diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h index a9cf484ecae4c..d450b742137e4 100644 --- a/drivers/usb/core/usb.h +++ b/drivers/usb/core/usb.h @@ -77,6 +77,9 @@ static inline int usb_port_resume(struct usb_device *udev, pm_message_t msg) extern void usb_autosuspend_device(struct usb_device *udev); extern int usb_autoresume_device(struct usb_device *udev); extern int usb_remote_wakeup(struct usb_device *dev); +extern int usb_runtime_suspend(struct device *dev); +extern int usb_runtime_resume(struct device *dev); +extern int usb_runtime_idle(struct device *dev); #else -- GitLab From 1655068029a6e86682fe97a687db9db0aae5af81 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Fri, 18 Mar 2011 15:03:16 -0700 Subject: [PATCH 0905/2822] sparc: Provide NO_IRQ definition. Signed-off-by: David S. Miller --- arch/sparc/include/asm/irq_32.h | 3 +++ arch/sparc/include/asm/irq_64.h | 2 ++ 2 files changed, 5 insertions(+) diff --git a/arch/sparc/include/asm/irq_32.h b/arch/sparc/include/asm/irq_32.h index cbf4801deaafc..eced3e3ebd30f 100644 --- a/arch/sparc/include/asm/irq_32.h +++ b/arch/sparc/include/asm/irq_32.h @@ -13,4 +13,7 @@ #define irq_canonicalize(irq) (irq) extern void __init init_IRQ(void); + +#define NO_IRQ 0xffffffff + #endif diff --git a/arch/sparc/include/asm/irq_64.h b/arch/sparc/include/asm/irq_64.h index 4f09666f07984..16dcae6d56e7a 100644 --- a/arch/sparc/include/asm/irq_64.h +++ b/arch/sparc/include/asm/irq_64.h @@ -97,4 +97,6 @@ extern void *softirq_stack[NR_CPUS]; #define __ARCH_HAS_DO_SOFTIRQ #define ARCH_HAS_NMI_WATCHDOG +#define NO_IRQ 0xffffffff + #endif -- GitLab From 4d3fbff26c8e91474e30e575c2b7476be11afd83 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Thu, 10 Mar 2011 21:21:23 +0100 Subject: [PATCH 0906/2822] ACPI: Remove the unused EC sysdev class The ACPI EC driver defines a sysdev class, but it doesn't use it, so it can be removed. Signed-off-by: Rafael J. Wysocki Signed-off-by: Len Brown --- drivers/acpi/ec_sys.c | 4 ---- drivers/acpi/internal.h | 3 --- 2 files changed, 7 deletions(-) diff --git a/drivers/acpi/ec_sys.c b/drivers/acpi/ec_sys.c index 411620ef84c2e..05b44201a6147 100644 --- a/drivers/acpi/ec_sys.c +++ b/drivers/acpi/ec_sys.c @@ -24,10 +24,6 @@ MODULE_PARM_DESC(write_support, "Dangerous, reboot and removal of battery may " #define EC_SPACE_SIZE 256 -struct sysdev_class acpi_ec_sysdev_class = { - .name = "ec", -}; - static struct dentry *acpi_ec_debugfs_dir; static int acpi_ec_open_io(struct inode *i, struct file *f) diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h index b1cc81a0431b6..4bfb759deb104 100644 --- a/drivers/acpi/internal.h +++ b/drivers/acpi/internal.h @@ -21,8 +21,6 @@ #ifndef _ACPI_INTERNAL_H_ #define _ACPI_INTERNAL_H_ -#include - #define PREFIX "ACPI: " int init_acpi_device_notify(void); @@ -64,7 +62,6 @@ struct acpi_ec { struct list_head list; struct transaction *curr; spinlock_t curr_lock; - struct sys_device sysdev; }; extern struct acpi_ec *first_ec; -- GitLab From c3146df2b735912eddd1d7c080c9377d5df0ae94 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Sat, 12 Mar 2011 22:16:51 +0100 Subject: [PATCH 0907/2822] ACPI: Use syscore_ops instead of sysdev class and sysdev ACPI uses a sysdev class and a sysdev for executing irqrouter_resume() before turning on interrupts on the boot CPU. However, since irqrouter_resume() ignores its argument, the entire mechanism may be replaced with a struct syscore_ops object which is considerably simpler. Signed-off-by: Rafael J. Wysocki Signed-off-by: Len Brown --- drivers/acpi/pci_link.c | 30 ++++++++---------------------- 1 file changed, 8 insertions(+), 22 deletions(-) diff --git a/drivers/acpi/pci_link.c b/drivers/acpi/pci_link.c index 9ff80a7e9f6ad..4a29763b8eb45 100644 --- a/drivers/acpi/pci_link.c +++ b/drivers/acpi/pci_link.c @@ -29,7 +29,7 @@ * for IRQ management (e.g. start()->_SRS). */ -#include +#include #include #include #include @@ -757,14 +757,13 @@ static int acpi_pci_link_resume(struct acpi_pci_link *link) return 0; } -static int irqrouter_resume(struct sys_device *dev) +static void irqrouter_resume(void) { struct acpi_pci_link *link; list_for_each_entry(link, &acpi_link_list, list) { acpi_pci_link_resume(link); } - return 0; } static int acpi_pci_link_remove(struct acpi_device *device, int type) @@ -871,32 +870,19 @@ static int __init acpi_irq_balance_set(char *str) __setup("acpi_irq_balance", acpi_irq_balance_set); -/* FIXME: we will remove this interface after all drivers call pci_disable_device */ -static struct sysdev_class irqrouter_sysdev_class = { - .name = "irqrouter", +static struct syscore_ops irqrouter_syscore_ops = { .resume = irqrouter_resume, }; -static struct sys_device device_irqrouter = { - .id = 0, - .cls = &irqrouter_sysdev_class, -}; - -static int __init irqrouter_init_sysfs(void) +static int __init irqrouter_init_ops(void) { - int error; + if (!acpi_disabled && !acpi_noirq) + register_syscore_ops(&irqrouter_syscore_ops); - if (acpi_disabled || acpi_noirq) - return 0; - - error = sysdev_class_register(&irqrouter_sysdev_class); - if (!error) - error = sysdev_register(&device_irqrouter); - - return error; + return 0; } -device_initcall(irqrouter_init_sysfs); +device_initcall(irqrouter_init_ops); static int __init acpi_pci_link_init(void) { -- GitLab From 930952af15f8425115528447102ed97610e98949 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Fri, 18 Mar 2011 15:31:19 -0700 Subject: [PATCH 0908/2822] sparc: Implement of_address_to_resource(). Similarly to irq_of_parse_and_map(), find the platform_device object and return the pre-computed resource. Signed-off-by: David S. Miller --- arch/sparc/kernel/of_device_common.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/arch/sparc/kernel/of_device_common.c b/arch/sparc/kernel/of_device_common.c index 49ddff56cb041..0ed0321d84e99 100644 --- a/arch/sparc/kernel/of_device_common.c +++ b/arch/sparc/kernel/of_device_common.c @@ -22,6 +22,19 @@ unsigned int irq_of_parse_and_map(struct device_node *node, int index) } EXPORT_SYMBOL(irq_of_parse_and_map); +int of_address_to_resource(struct device_node *node, int index, + struct resource *r) +{ + struct platform_device *op = of_find_device_by_node(node); + + if (!op || index >= op->num_resources) + return -EINVAL; + + memcpy(r, &op->archdata.resource[index], sizeof(*r)); + return 0; +} +EXPORT_SYMBOL_GPL(of_address_to_resource); + /* Take the archdata values for IOMMU, STC, and HOSTDATA found in * BUS and propagate to all child platform_device objects. */ -- GitLab From 9889376ab91f89a5af7329ae34521dfc4b613ba9 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Fri, 18 Mar 2011 15:47:26 -0700 Subject: [PATCH 0909/2822] sparc: Implement of_iomap(). Grab the pre-computed resource and map using of_ioremap(). Signed-off-by: David S. Miller --- arch/sparc/kernel/of_device_common.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/arch/sparc/kernel/of_device_common.c b/arch/sparc/kernel/of_device_common.c index 0ed0321d84e99..cb15bbf8a2014 100644 --- a/arch/sparc/kernel/of_device_common.c +++ b/arch/sparc/kernel/of_device_common.c @@ -35,6 +35,20 @@ int of_address_to_resource(struct device_node *node, int index, } EXPORT_SYMBOL_GPL(of_address_to_resource); +void __iomem *of_iomap(struct device_node *node, int index) +{ + struct platform_device *op = of_find_device_by_node(node); + struct resource *r; + + if (!op || index >= op->num_resources) + return NULL; + + r = &op->archdata.resource[index]; + + return of_ioremap(r, 0, resource_size(r), (char *) r->name); +} +EXPORT_SYMBOL(of_iomap); + /* Take the archdata values for IOMMU, STC, and HOSTDATA found in * BUS and propagate to all child platform_device objects. */ -- GitLab From 36133869c4b5b70e6acf6ff7ce25df526a6d5cae Mon Sep 17 00:00:00 2001 From: Aaro Koskinen Date: Fri, 18 Mar 2011 16:53:19 -0700 Subject: [PATCH 0910/2822] arm: mach-omap2: devices: fix omap3_l3_init() return value Fix the return value for the successful case. Signed-off-by: Aaro Koskinen Acked-by: Santosh Shilimkar Signed-off-by: Tony Lindgren --- arch/arm/mach-omap2/devices.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/mach-omap2/devices.c b/arch/arm/mach-omap2/devices.c index 0d2d6a9c303c5..d478f53f90843 100644 --- a/arch/arm/mach-omap2/devices.c +++ b/arch/arm/mach-omap2/devices.c @@ -65,7 +65,7 @@ static int __init omap3_l3_init(void) WARN(IS_ERR(od), "could not build omap_device for %s\n", oh_name); - return PTR_ERR(od); + return IS_ERR(od) ? PTR_ERR(od) : 0; } postcore_initcall(omap3_l3_init); -- GitLab From 18a81019b851dae83f7df3e72064de706788ff25 Mon Sep 17 00:00:00 2001 From: Aaro Koskinen Date: Fri, 18 Mar 2011 16:53:20 -0700 Subject: [PATCH 0911/2822] arm: mach-omap2: omap_l3_smx: fix irq handler setup The handler function may be called from the point it is registered. Since the handler inspects IRQ numbers, we must set them up before registration. Signed-off-by: Aaro Koskinen Acked-by: Santosh Shilimkar Signed-off-by: Tony Lindgren --- arch/arm/mach-omap2/omap_l3_smx.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/arch/arm/mach-omap2/omap_l3_smx.c b/arch/arm/mach-omap2/omap_l3_smx.c index 265bff3acb9e7..5f2da7565b68b 100644 --- a/arch/arm/mach-omap2/omap_l3_smx.c +++ b/arch/arm/mach-omap2/omap_l3_smx.c @@ -226,7 +226,6 @@ static int __init omap3_l3_probe(struct platform_device *pdev) struct omap3_l3 *l3; struct resource *res; int ret; - int irq; l3 = kzalloc(sizeof(*l3), GFP_KERNEL); if (!l3) { @@ -249,18 +248,17 @@ static int __init omap3_l3_probe(struct platform_device *pdev) goto err2; } - irq = platform_get_irq(pdev, 0); - ret = request_irq(irq, omap3_l3_app_irq, + l3->debug_irq = platform_get_irq(pdev, 0); + ret = request_irq(l3->debug_irq, omap3_l3_app_irq, IRQF_DISABLED | IRQF_TRIGGER_RISING, "l3-debug-irq", l3); if (ret) { dev_err(&pdev->dev, "couldn't request debug irq\n"); goto err3; } - l3->debug_irq = irq; - irq = platform_get_irq(pdev, 1); - ret = request_irq(irq, omap3_l3_app_irq, + l3->app_irq = platform_get_irq(pdev, 1); + ret = request_irq(l3->app_irq, omap3_l3_app_irq, IRQF_DISABLED | IRQF_TRIGGER_RISING, "l3-app-irq", l3); @@ -269,7 +267,6 @@ static int __init omap3_l3_probe(struct platform_device *pdev) goto err4; } - l3->app_irq = irq; goto err0; err4: -- GitLab From 8b8e2ef328c3378c74fb4347f66df8e58feeaf46 Mon Sep 17 00:00:00 2001 From: David Anders Date: Fri, 18 Mar 2011 16:53:20 -0700 Subject: [PATCH 0912/2822] OMAP4: PandaBoard: remove unused power regulators the pandaboard does not use the VUSIM or VAUX1 power regulators on the TWL6030 and are left floating. if the VUSIM and VAUX1 power regulators are initilized, noise on the unloaded regulators generates an overcurrent interrupt causing the system to power down. this patch removes the initialization of the unused power regulators of VUSIM and VAUX1. Signed-off-by: David Anders Acked-by: Andy Green Acked-by: Anand Gadiyar Tested-by: Kevin Hilman Signed-off-by: Tony Lindgren --- arch/arm/mach-omap2/board-omap4panda.c | 28 -------------------------- 1 file changed, 28 deletions(-) diff --git a/arch/arm/mach-omap2/board-omap4panda.c b/arch/arm/mach-omap2/board-omap4panda.c index 1dd4401e64660..80b8860bc5957 100644 --- a/arch/arm/mach-omap2/board-omap4panda.c +++ b/arch/arm/mach-omap2/board-omap4panda.c @@ -280,19 +280,6 @@ static int __init omap4_twl6030_hsmmc_init(struct omap2_hsmmc_info *controllers) return 0; } -static struct regulator_init_data omap4_panda_vaux1 = { - .constraints = { - .min_uV = 1000000, - .max_uV = 3000000, - .apply_uV = true, - .valid_modes_mask = REGULATOR_MODE_NORMAL - | REGULATOR_MODE_STANDBY, - .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE - | REGULATOR_CHANGE_MODE - | REGULATOR_CHANGE_STATUS, - }, -}; - static struct regulator_init_data omap4_panda_vaux2 = { .constraints = { .min_uV = 1200000, @@ -348,19 +335,6 @@ static struct regulator_init_data omap4_panda_vpp = { }, }; -static struct regulator_init_data omap4_panda_vusim = { - .constraints = { - .min_uV = 1200000, - .max_uV = 2900000, - .apply_uV = true, - .valid_modes_mask = REGULATOR_MODE_NORMAL - | REGULATOR_MODE_STANDBY, - .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE - | REGULATOR_CHANGE_MODE - | REGULATOR_CHANGE_STATUS, - }, -}; - static struct regulator_init_data omap4_panda_vana = { .constraints = { .min_uV = 2100000, @@ -413,12 +387,10 @@ static struct twl4030_platform_data omap4_panda_twldata = { /* Regulators */ .vmmc = &omap4_panda_vmmc, .vpp = &omap4_panda_vpp, - .vusim = &omap4_panda_vusim, .vana = &omap4_panda_vana, .vcxio = &omap4_panda_vcxio, .vdac = &omap4_panda_vdac, .vusb = &omap4_panda_vusb, - .vaux1 = &omap4_panda_vaux1, .vaux2 = &omap4_panda_vaux2, .vaux3 = &omap4_panda_vaux3, .usb = &omap4_usbphy_data, -- GitLab From 77aded2f523c6540f71b1f549373dd8046329a6b Mon Sep 17 00:00:00 2001 From: Balaji T K Date: Fri, 18 Mar 2011 16:53:20 -0700 Subject: [PATCH 0913/2822] ARM: OMAP2+: Fix warnings for GPMC interrupt Commit db97eb7dfe13f6c04f0a0e77c32e2691f563ab8b (omap: gpmc: enable irq mode in gpmc) enabled interrupts for GPMC (General Purpose Memory Controller). However, looks like this patch only works on omap3. Fix the issues to avoid warnings on omap4 during the boot. GPMC: number of chip select is 8, CS0 to CS7. One less IRQ allocated throws below warning at boot: [ 0.429290] Trying to install type control for IRQ409 [ 0.429290] Trying to set irq flags for IRQ409 Resolve following warning messages in boot when irq chip is not set: [ 0.429229] Trying to install interrupt handler for IRQ402 [ 0.429229] Trying to install interrupt handler for IRQ403 [ 0.429229] Trying to install interrupt handler for IRQ404 [ 0.429260] Trying to install interrupt handler for IRQ405 [ 0.429260] Trying to install interrupt handler for IRQ406 [ 0.429260] Trying to install interrupt handler for IRQ407 [ 0.429290] Trying to install interrupt handler for IRQ408 Resolve following warning in OMAP4: [ 0.429290] gpmc: irq-20 could not claim: err -22 Signed-off-by: Balaji T K [tony@atomide.com: combined patches into one, updated comments] Signed-off-by: Tony Lindgren --- arch/arm/mach-omap2/gpmc.c | 13 ++++++++----- arch/arm/plat-omap/include/plat/irqs.h | 2 +- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c index 674174365f787..493505c3b2f56 100644 --- a/arch/arm/mach-omap2/gpmc.c +++ b/arch/arm/mach-omap2/gpmc.c @@ -693,6 +693,7 @@ static int __init gpmc_init(void) { u32 l, irq; int cs, ret = -EINVAL; + int gpmc_irq; char *ck = NULL; if (cpu_is_omap24xx()) { @@ -701,12 +702,15 @@ static int __init gpmc_init(void) l = OMAP2420_GPMC_BASE; else l = OMAP34XX_GPMC_BASE; + gpmc_irq = INT_34XX_GPMC_IRQ; } else if (cpu_is_omap34xx()) { ck = "gpmc_fck"; l = OMAP34XX_GPMC_BASE; + gpmc_irq = INT_34XX_GPMC_IRQ; } else if (cpu_is_omap44xx()) { ck = "gpmc_ck"; l = OMAP44XX_GPMC_BASE; + gpmc_irq = OMAP44XX_IRQ_GPMC; } if (WARN_ON(!ck)) @@ -739,16 +743,17 @@ static int __init gpmc_init(void) /* initalize the irq_chained */ irq = OMAP_GPMC_IRQ_BASE; for (cs = 0; cs < GPMC_CS_NUM; cs++) { - set_irq_handler(irq, handle_simple_irq); + set_irq_chip_and_handler(irq, &dummy_irq_chip, + handle_simple_irq); set_irq_flags(irq, IRQF_VALID); irq++; } - ret = request_irq(INT_34XX_GPMC_IRQ, + ret = request_irq(gpmc_irq, gpmc_handle_irq, IRQF_SHARED, "gpmc", gpmc_base); if (ret) pr_err("gpmc: irq-%d could not claim: err %d\n", - INT_34XX_GPMC_IRQ, ret); + gpmc_irq, ret); return ret; } postcore_initcall(gpmc_init); @@ -757,8 +762,6 @@ static irqreturn_t gpmc_handle_irq(int irq, void *dev) { u8 cs; - if (irq != INT_34XX_GPMC_IRQ) - return IRQ_HANDLED; /* check cs to invoke the irq */ cs = ((gpmc_read_reg(GPMC_PREFETCH_CONFIG1)) >> CS_NUM_SHIFT) & 0x7; if (OMAP_GPMC_IRQ_BASE+cs <= OMAP_GPMC_IRQ_END) diff --git a/arch/arm/plat-omap/include/plat/irqs.h b/arch/arm/plat-omap/include/plat/irqs.h index d779283704631..5a25098ea7ea8 100644 --- a/arch/arm/plat-omap/include/plat/irqs.h +++ b/arch/arm/plat-omap/include/plat/irqs.h @@ -416,7 +416,7 @@ /* GPMC related */ #define OMAP_GPMC_IRQ_BASE (TWL_IRQ_END) -#define OMAP_GPMC_NR_IRQS 7 +#define OMAP_GPMC_NR_IRQS 8 #define OMAP_GPMC_IRQ_END (OMAP_GPMC_IRQ_BASE + OMAP_GPMC_NR_IRQS) -- GitLab From 4fa8eebb045a6d798011f3935a38dd29de30e6c9 Mon Sep 17 00:00:00 2001 From: Ohad Ben-Cohen Date: Fri, 18 Mar 2011 16:53:21 -0700 Subject: [PATCH 0914/2822] hwspinlock: depend on OMAP4 Currently only OMAP4 supports hwspinlocks, so don't bother asking anyone else. Signed-off-by: Ohad Ben-Cohen Signed-off-by: Tony Lindgren --- drivers/hwspinlock/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/hwspinlock/Kconfig b/drivers/hwspinlock/Kconfig index eb4af28f8567d..1f29bab6b3e5a 100644 --- a/drivers/hwspinlock/Kconfig +++ b/drivers/hwspinlock/Kconfig @@ -4,6 +4,7 @@ config HWSPINLOCK tristate "Generic Hardware Spinlock framework" + depends on ARCH_OMAP4 help Say y here to support the generic hardware spinlock framework. You only need to enable this if you have hardware spinlock module -- GitLab From b3f80f6d2b08772d7d00f34a062ff73c95f7c45c Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Fri, 18 Mar 2011 21:50:29 -0700 Subject: [PATCH 0915/2822] sparc: Add {open_by,name_to}_handle_at and clock_adjtime syscalls. Signed-off-by: David S. Miller --- arch/sparc/include/asm/unistd.h | 5 ++++- arch/sparc/kernel/systbls_32.S | 2 +- arch/sparc/kernel/systbls_64.S | 4 ++-- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/arch/sparc/include/asm/unistd.h b/arch/sparc/include/asm/unistd.h index 03eb5a8f6f936..2f475d7c0b53f 100644 --- a/arch/sparc/include/asm/unistd.h +++ b/arch/sparc/include/asm/unistd.h @@ -400,8 +400,11 @@ #define __NR_fanotify_init 329 #define __NR_fanotify_mark 330 #define __NR_prlimit64 331 +#define __NR_name_to_handle_at 332 +#define __NR_open_by_handle_at 333 +#define __NR_clock_adjtime 334 -#define NR_syscalls 332 +#define NR_syscalls 335 #ifdef __32bit_syscall_numbers__ /* Sparc 32-bit only has the "setresuid32", "getresuid32" variants, diff --git a/arch/sparc/kernel/systbls_32.S b/arch/sparc/kernel/systbls_32.S index ec396e1916b92..4b86eaf04fe57 100644 --- a/arch/sparc/kernel/systbls_32.S +++ b/arch/sparc/kernel/systbls_32.S @@ -83,5 +83,5 @@ sys_call_table: /*315*/ .long sys_timerfd_settime, sys_timerfd_gettime, sys_signalfd4, sys_eventfd2, sys_epoll_create1 /*320*/ .long sys_dup3, sys_pipe2, sys_inotify_init1, sys_accept4, sys_preadv /*325*/ .long sys_pwritev, sys_rt_tgsigqueueinfo, sys_perf_event_open, sys_recvmmsg, sys_fanotify_init -/*330*/ .long sys_fanotify_mark, sys_prlimit64 +/*330*/ .long sys_fanotify_mark, sys_prlimit64, sys_name_to_handle_at, sys_open_by_handle_at, sys_clock_adjtime diff --git a/arch/sparc/kernel/systbls_64.S b/arch/sparc/kernel/systbls_64.S index 8cfcaa5495805..0331bafdf3a30 100644 --- a/arch/sparc/kernel/systbls_64.S +++ b/arch/sparc/kernel/systbls_64.S @@ -84,7 +84,7 @@ sys_call_table32: .word compat_sys_timerfd_settime, compat_sys_timerfd_gettime, compat_sys_signalfd4, sys_eventfd2, sys_epoll_create1 /*320*/ .word sys_dup3, sys_pipe2, sys_inotify_init1, sys_accept4, compat_sys_preadv .word compat_sys_pwritev, compat_sys_rt_tgsigqueueinfo, sys_perf_event_open, compat_sys_recvmmsg, sys_fanotify_init -/*330*/ .word sys32_fanotify_mark, sys_prlimit64 +/*330*/ .word sys32_fanotify_mark, sys_prlimit64, sys_name_to_handle_at, compat_sys_open_by_handle_at, compat_sys_clock_adjtime #endif /* CONFIG_COMPAT */ @@ -160,4 +160,4 @@ sys_call_table: .word sys_timerfd_settime, sys_timerfd_gettime, sys_signalfd4, sys_eventfd2, sys_epoll_create1 /*320*/ .word sys_dup3, sys_pipe2, sys_inotify_init1, sys_accept4, sys_preadv .word sys_pwritev, sys_rt_tgsigqueueinfo, sys_perf_event_open, sys_recvmmsg, sys_fanotify_init -/*330*/ .word sys_fanotify_mark, sys_prlimit64 +/*330*/ .word sys_fanotify_mark, sys_prlimit64, sys_name_to_handle_at, sys_open_by_handle_at, sys_clock_adjtime -- GitLab From 4345caba340f051e10847924fc078ae18ed6695c Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Sat, 19 Mar 2011 13:53:31 +0100 Subject: [PATCH 0916/2822] block: NULL dereference on error path in __blkdev_get() "disk" is always NULL when we goto out. There was a check for this before, but it was removed in 69e02c59a7d9 "block: Don't check events while open is in progress". Signed-off-by: Dan Carpenter Acked-by: Tejun Heo Signed-off-by: Jens Axboe --- fs/block_dev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/block_dev.c b/fs/block_dev.c index fbe05cbdd692f..7d02afb2b7f4b 100644 --- a/fs/block_dev.c +++ b/fs/block_dev.c @@ -1181,9 +1181,9 @@ static int __blkdev_get(struct block_device *bdev, fmode_t mode, int for_part) out_unlock_bdev: mutex_unlock(&bdev->bd_mutex); disk_unblock_events(disk); - out: module_put(disk->fops->owner); put_disk(disk); + out: bdput(bdev); return ret; -- GitLab From fc66c5210ec2539e800e87d7b3a985323c7be96e Mon Sep 17 00:00:00 2001 From: Stephane Eranian Date: Sat, 19 Mar 2011 18:20:05 +0100 Subject: [PATCH 0917/2822] perf, x86: Fix Intel fixed counters base initialization The following patch solves the problems introduced by Robert's commit 41bf498 and reported by Arun Sharma. This commit gets rid of the base + index notation for reading and writing PMU msrs. The problem is that for fixed counters, the new calculation for the base did not take into account the fixed counter indexes, thus all fixed counters were read/written from fixed counter 0. Although all fixed counters share the same config MSR, they each have their own counter register. Without: $ task -e unhalted_core_cycles -e instructions_retired -e baclears noploop 1 noploop for 1 seconds 242202299 unhalted_core_cycles (0.00% scaling, ena=1000790892, run=1000790892) 2389685946 instructions_retired (0.00% scaling, ena=1000790892, run=1000790892) 49473 baclears (0.00% scaling, ena=1000790892, run=1000790892) With: $ task -e unhalted_core_cycles -e instructions_retired -e baclears noploop 1 noploop for 1 seconds 2392703238 unhalted_core_cycles (0.00% scaling, ena=1000840809, run=1000840809) 2389793744 instructions_retired (0.00% scaling, ena=1000840809, run=1000840809) 47863 baclears (0.00% scaling, ena=1000840809, run=1000840809) Signed-off-by: Stephane Eranian Cc: peterz@infradead.org Cc: ming.m.lin@intel.com Cc: robert.richter@amd.com Cc: asharma@fb.com Cc: perfmon2-devel@lists.sf.net LKML-Reference: <20110319172005.GB4978@quad> Signed-off-by: Ingo Molnar --- arch/x86/kernel/cpu/perf_event.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/kernel/cpu/perf_event.c b/arch/x86/kernel/cpu/perf_event.c index e8dbe179587fc..ec46eea0c4edd 100644 --- a/arch/x86/kernel/cpu/perf_event.c +++ b/arch/x86/kernel/cpu/perf_event.c @@ -912,7 +912,7 @@ static inline void x86_assign_hw_event(struct perf_event *event, hwc->event_base = 0; } else if (hwc->idx >= X86_PMC_IDX_FIXED) { hwc->config_base = MSR_ARCH_PERFMON_FIXED_CTR_CTRL; - hwc->event_base = MSR_ARCH_PERFMON_FIXED_CTR0; + hwc->event_base = MSR_ARCH_PERFMON_FIXED_CTR0 + (hwc->idx - X86_PMC_IDX_FIXED); } else { hwc->config_base = x86_pmu_config_addr(hwc->idx); hwc->event_base = x86_pmu_event_addr(hwc->idx); -- GitLab From 16addf954d3954a72fd56abc02ffcba3c18529a1 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Fri, 18 Mar 2011 09:34:53 -0700 Subject: [PATCH 0918/2822] sched: Fix yield_to kernel-doc Add missing function parameters for yield_to(): Warning(kernel/sched.c:5470): No description found for parameter 'p' Warning(kernel/sched.c:5470): No description found for parameter 'preempt' Signed-off-by: Randy Dunlap Cc: Peter Zijlstra LKML-Reference: <20110318093453.8f7489a4.randy.dunlap@oracle.com> Signed-off-by: Ingo Molnar --- kernel/sched.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/kernel/sched.c b/kernel/sched.c index 58d66ea7d2004..052120d67706f 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -5467,6 +5467,8 @@ EXPORT_SYMBOL(yield); * yield_to - yield the current processor to another thread in * your thread group, or accelerate that thread toward the * processor it's on. + * @p: target task + * @preempt: whether task preemption is allowed or not * * It's the caller's job to ensure that the target task struct * can't go away on us before we can do any checks. -- GitLab From e5f15b45ddf3afa2bbbb10c7ea34fb32b6de0a0e Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Fri, 18 Feb 2011 11:30:30 +0000 Subject: [PATCH 0919/2822] x86: Cleanup highmap after brk is concluded Now cleanup_highmap actually is in two steps: one is early in head64.c and only clears above _end; a second one is in init_memory_mapping() and tries to clean from _brk_end to _end. It should check if those boundaries are PMD_SIZE aligned but currently does not. Also init_memory_mapping() is called several times for numa or memory hotplug, so we really should not handle initial kernel mappings there. This patch moves cleanup_highmap() down after _brk_end is settled so we can do everything in one step. Also we honor max_pfn_mapped in the implementation of cleanup_highmap. Signed-off-by: Yinghai Lu Signed-off-by: Stefano Stabellini LKML-Reference: Signed-off-by: H. Peter Anvin --- arch/x86/kernel/head64.c | 3 --- arch/x86/kernel/setup.c | 25 +++---------------------- arch/x86/mm/init_64.c | 11 ++++++----- 3 files changed, 9 insertions(+), 30 deletions(-) diff --git a/arch/x86/kernel/head64.c b/arch/x86/kernel/head64.c index 2d2673c28aff2..5655c2272adb8 100644 --- a/arch/x86/kernel/head64.c +++ b/arch/x86/kernel/head64.c @@ -77,9 +77,6 @@ void __init x86_64_start_kernel(char * real_mode_data) /* Make NULL pointers segfault */ zap_identity_mappings(); - /* Cleanup the over mapped high alias */ - cleanup_highmap(); - max_pfn_mapped = KERNEL_IMAGE_SIZE >> PAGE_SHIFT; for (i = 0; i < NUM_EXCEPTION_VECTORS; i++) { diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c index b176f2b1f45d8..4a52a5f9afcbe 100644 --- a/arch/x86/kernel/setup.c +++ b/arch/x86/kernel/setup.c @@ -294,30 +294,11 @@ static void __init init_gbpages(void) else direct_gbpages = 0; } - -static void __init cleanup_highmap_brk_end(void) -{ - pud_t *pud; - pmd_t *pmd; - - mmu_cr4_features = read_cr4(); - - /* - * _brk_end cannot change anymore, but it and _end may be - * located on different 2M pages. cleanup_highmap(), however, - * can only consider _end when it runs, so destroy any - * mappings beyond _brk_end here. - */ - pud = pud_offset(pgd_offset_k(_brk_end), _brk_end); - pmd = pmd_offset(pud, _brk_end - 1); - while (++pmd <= pmd_offset(pud, (unsigned long)_end - 1)) - pmd_clear(pmd); -} #else static inline void init_gbpages(void) { } -static inline void cleanup_highmap_brk_end(void) +static void __init cleanup_highmap(void) { } #endif @@ -330,8 +311,6 @@ static void __init reserve_brk(void) /* Mark brk area as locked down and no longer taking any new allocations */ _brk_start = 0; - - cleanup_highmap_brk_end(); } #ifdef CONFIG_BLK_DEV_INITRD @@ -950,6 +929,8 @@ void __init setup_arch(char **cmdline_p) */ reserve_brk(); + cleanup_highmap(); + memblock.current_limit = get_max_mapped(); memblock_x86_fill(); diff --git a/arch/x86/mm/init_64.c b/arch/x86/mm/init_64.c index a08a62cb136e4..7026505a33ba2 100644 --- a/arch/x86/mm/init_64.c +++ b/arch/x86/mm/init_64.c @@ -51,6 +51,7 @@ #include #include #include +#include static int __init parse_direct_gbpages_off(char *arg) { @@ -293,18 +294,18 @@ void __init init_extra_mapping_uc(unsigned long phys, unsigned long size) * to the compile time generated pmds. This results in invalid pmds up * to the point where we hit the physaddr 0 mapping. * - * We limit the mappings to the region from _text to _end. _end is - * rounded up to the 2MB boundary. This catches the invalid pmds as + * We limit the mappings to the region from _text to _brk_end. _brk_end + * is rounded up to the 2MB boundary. This catches the invalid pmds as * well, as they are located before _text: */ void __init cleanup_highmap(void) { unsigned long vaddr = __START_KERNEL_map; - unsigned long end = roundup((unsigned long)_end, PMD_SIZE) - 1; + unsigned long vaddr_end = __START_KERNEL_map + (max_pfn_mapped << PAGE_SHIFT); + unsigned long end = roundup((unsigned long)_brk_end, PMD_SIZE) - 1; pmd_t *pmd = level2_kernel_pgt; - pmd_t *last_pmd = pmd + PTRS_PER_PMD; - for (; pmd < last_pmd; pmd++, vaddr += PMD_SIZE) { + for (; vaddr + PMD_SIZE - 1 < vaddr_end; pmd++, vaddr += PMD_SIZE) { if (pmd_none(*pmd)) continue; if (vaddr < (unsigned long) _text || vaddr > end) -- GitLab From 14988a4d350ce3b41ecad4f63c4f44c56f5ae34d Mon Sep 17 00:00:00 2001 From: Stefano Stabellini Date: Fri, 18 Feb 2011 11:32:40 +0000 Subject: [PATCH 0920/2822] xen: set max_pfn_mapped to the last pfn mapped Do not set max_pfn_mapped to the end of the initial memory mappings, that also contain pages that don't belong in pfn space (like the mfn list). Set max_pfn_mapped to the last real pfn mapped in the initial memory mappings that is the pfn backing _end. Signed-off-by: Stefano Stabellini Acked-by: Konrad Rzeszutek Wilk LKML-Reference: Signed-off-by: H. Peter Anvin --- arch/x86/xen/mmu.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/arch/x86/xen/mmu.c b/arch/x86/xen/mmu.c index a2d78ad35a55b..6e27979506c1d 100644 --- a/arch/x86/xen/mmu.c +++ b/arch/x86/xen/mmu.c @@ -1701,9 +1701,6 @@ static __init void xen_map_identity_early(pmd_t *pmd, unsigned long max_pfn) for (pteidx = 0; pteidx < PTRS_PER_PTE; pteidx++, pfn++) { pte_t pte; - if (pfn > max_pfn_mapped) - max_pfn_mapped = pfn; - if (!pte_none(pte_page[pteidx])) continue; @@ -1761,6 +1758,12 @@ __init pgd_t *xen_setup_kernel_pagetable(pgd_t *pgd, pud_t *l3; pmd_t *l2; + /* max_pfn_mapped is the last pfn mapped in the initial memory + * mappings. Considering that on Xen after the kernel mappings we + * have the mappings of some pages that don't exist in pfn space, we + * set max_pfn_mapped to the last real pfn mapped. */ + max_pfn_mapped = PFN_DOWN(__pa(xen_start_info->mfn_list)); + /* Zap identity mapping */ init_level4_pgt[0] = __pgd(0); @@ -1865,9 +1868,7 @@ __init pgd_t *xen_setup_kernel_pagetable(pgd_t *pgd, initial_kernel_pmd = extend_brk(sizeof(pmd_t) * PTRS_PER_PMD, PAGE_SIZE); - max_pfn_mapped = PFN_DOWN(__pa(xen_start_info->pt_base) + - xen_start_info->nr_pt_frames * PAGE_SIZE + - 512*1024); + max_pfn_mapped = PFN_DOWN(__pa(xen_start_info->mfn_list)); kernel_pmd = m2v(pgd[KERNEL_PGD_BOUNDARY].pgd); memcpy(initial_kernel_pmd, kernel_pmd, sizeof(pmd_t) * PTRS_PER_PMD); -- GitLab From d8aa5ec3382e6a545b8f25178d1e0992d4927f19 Mon Sep 17 00:00:00 2001 From: Stefano Stabellini Date: Wed, 9 Mar 2011 14:22:05 +0000 Subject: [PATCH 0921/2822] xen: update mask_rw_pte after kernel page tables init changes After "x86-64, mm: Put early page table high" already existing kernel page table pages can be mapped using early_ioremap too so we need to update mask_rw_pte to make sure these pages are still mapped RO. The reason why we have to do that is explain by the commit message of fef5ba797991f9335bcfc295942b684f9bf613a1: "Xen requires that all pages containing pagetable entries to be mapped read-only. If pages used for the initial pagetable are already mapped then we can change the mapping to RO. However, if they are initially unmapped, we need to make sure that when they are later mapped, they are also mapped RO. ..SNIP.. the pagetable setup code early_ioremaps the pages to write their entries, so we must make sure that mappings created in the early_ioremap fixmap area are mapped RW. (Those mappings are removed before the pages are presented to Xen as pagetable pages.)" We accomplish all this in mask_rw_pte by mapping RO all the pages mapped using early_ioremap apart from the last one that has been allocated because it is not a page table page yet (it has not been hooked into the page tables yet). Signed-off-by: Stefano Stabellini Acked-by: Konrad Rzeszutek Wilk LKML-Reference: Signed-off-by: H. Peter Anvin --- arch/x86/xen/mmu.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/arch/x86/xen/mmu.c b/arch/x86/xen/mmu.c index 6e27979506c1d..21058ad1e5e30 100644 --- a/arch/x86/xen/mmu.c +++ b/arch/x86/xen/mmu.c @@ -1488,10 +1488,12 @@ static __init pte_t mask_rw_pte(pte_t *ptep, pte_t pte) /* * If the new pfn is within the range of the newly allocated * kernel pagetable, and it isn't being mapped into an - * early_ioremap fixmap slot, make sure it is RO. + * early_ioremap fixmap slot as a freshly allocated page, make sure + * it is RO. */ - if (!is_early_ioremap_ptep(ptep) && - pfn >= pgt_buf_start && pfn < pgt_buf_end) + if (((!is_early_ioremap_ptep(ptep) && + pfn >= pgt_buf_start && pfn < pgt_buf_end)) || + (is_early_ioremap_ptep(ptep) && pfn != (pgt_buf_end - 1))) pte = pte_wrprotect(pte); return pte; -- GitLab From 5b4787719f8870104fada924ef65ee9fd5eb2514 Mon Sep 17 00:00:00 2001 From: Chris Metcalf Date: Sat, 19 Mar 2011 11:45:34 -0400 Subject: [PATCH 0922/2822] arch/tile: fix futex sanitization definition/prototype mismatch Commit 8d7718aa082aaf30a0b4989e1f04858952f941bc changed "int" to "u32" in the prototypes but not the definition. I missed this when I saw the patch go by on LKML. We cast "u32 *" to "int *" since we are tying into the underlying atomics framework, and atomic_t uses int as its value type. Signed-off-by: Chris Metcalf Reviewed-by: Michel Lespinasse --- arch/tile/lib/atomic_32.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/arch/tile/lib/atomic_32.c b/arch/tile/lib/atomic_32.c index f02040d3614e2..46570211df527 100644 --- a/arch/tile/lib/atomic_32.c +++ b/arch/tile/lib/atomic_32.c @@ -202,32 +202,32 @@ static inline int *__futex_setup(int __user *v) return __atomic_hashed_lock((int __force *)v); } -struct __get_user futex_set(int __user *v, int i) +struct __get_user futex_set(u32 __user *v, int i) { return __atomic_xchg((int __force *)v, __futex_setup(v), i); } -struct __get_user futex_add(int __user *v, int n) +struct __get_user futex_add(u32 __user *v, int n) { return __atomic_xchg_add((int __force *)v, __futex_setup(v), n); } -struct __get_user futex_or(int __user *v, int n) +struct __get_user futex_or(u32 __user *v, int n) { return __atomic_or((int __force *)v, __futex_setup(v), n); } -struct __get_user futex_andn(int __user *v, int n) +struct __get_user futex_andn(u32 __user *v, int n) { return __atomic_andn((int __force *)v, __futex_setup(v), n); } -struct __get_user futex_xor(int __user *v, int n) +struct __get_user futex_xor(u32 __user *v, int n) { return __atomic_xor((int __force *)v, __futex_setup(v), n); } -struct __get_user futex_cmpxchg(int __user *v, int o, int n) +struct __get_user futex_cmpxchg(u32 __user *v, int o, int n) { return __atomic_cmpxchg((int __force *)v, __futex_setup(v), o, n); } -- GitLab From 339dc50e59f4ea697e2b8cd6296328a8015a6c21 Mon Sep 17 00:00:00 2001 From: Chris Metcalf Date: Sat, 19 Mar 2011 11:47:53 -0400 Subject: [PATCH 0923/2822] asm-generic: support clock_adjtime() in A syscall was added without being added to asm-generic, which makes tile (and presumably score and unicore32) break. Signed-off-by: Chris Metcalf Acked-by: Arnd Bergmann Cc: Guan Xuetao Cc: Chen Liqin Cc: Lennox Wu --- include/asm-generic/unistd.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/include/asm-generic/unistd.h b/include/asm-generic/unistd.h index 57af0338d2709..d94f447c667a6 100644 --- a/include/asm-generic/unistd.h +++ b/include/asm-generic/unistd.h @@ -650,9 +650,11 @@ __SYSCALL(__NR_fanotify_mark, sys_fanotify_mark) __SYSCALL(__NR_name_to_handle_at, sys_name_to_handle_at) #define __NR_open_by_handle_at 265 __SYSCALL(__NR_open_by_handle_at, sys_open_by_handle_at) +#define __NR_clock_adjtime 266 +__SYSCALL(__NR_clock_adjtime, sys_clock_adjtime) #undef __NR_syscalls -#define __NR_syscalls 266 +#define __NR_syscalls 267 /* * All syscalls below here should go away really, -- GitLab From a769f4968396093d5cc1b1a86204cef579784b24 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sat, 19 Mar 2011 23:06:33 -0700 Subject: [PATCH 0924/2822] niu: Rename NIU parent platform device name to fix conflict. When the OF device driver bits were converted over to the platform device infrastructure in commit 74888760d40b3ac9054f9c5fa07b566c0676ba2d ("dt/net: Eliminate users of of_platform_{,un}register_driver") we inadvertantly created probing problems in the OF case. The NIU driver creates a dummy platform device to represent the board that contains one or more child NIU devices. Unfortunately we use the same name, "niu", as the OF device driver itself uses. The result is that we try to probe the dummy "niu" parent device we create, and since it has a NULL ofdevice pointer etc. everything explodes: [783019.128243] niu: niu.c:v1.1 (Apr 22, 2010) [783019.128810] Unable to handle kernel NULL pointer dereference [783019.128949] tsk->{mm,active_mm}->context = 000000000000039e [783019.129078] tsk->{mm,active_mm}->pgd = fffff803afc5a000 [783019.129206] \|/ ____ \|/ [783019.129213] "@'/ .. \`@" [783019.129220] /_| \__/ |_\ [783019.129226] \__U_/ [783019.129378] modprobe(2004): Oops [#1] [783019.129423] TSTATE: 0000000011001602 TPC: 0000000010052ff8 TNPC: 000000000061bbb4 Y: 00000000 Not tainted [783019.129542] TPC: [783019.129624] g0: 8080000000000000 g1: 0000000000000000 g2: 0000000010056000 g3: 0000000000000002 [783019.129733] g4: fffff803fc1da0c0 g5: fffff800441e2000 g6: fffff803fba84000 g7: 0000000000000000 [783019.129842] o0: fffff803fe7df010 o1: 0000000010055700 o2: 0000000000000000 o3: fffff803fbacaca0 [783019.129951] o4: 0000000000000080 o5: 0000000000777908 sp: fffff803fba866e1 ret_pc: 0000000010052ff4 [783019.130083] RPC: [783019.130165] l0: fffff803fe7df010 l1: fffff803fbacafc0 l2: fffff803fbacaca0 l3: ffffffffffffffed [783019.130273] l4: 0000000000000000 l5: 000000007fffffff l6: fffff803fba86f40 l7: 0000000000000001 [783019.130382] i0: fffff803fe7df000 i1: fffff803fc20aba0 i2: 0000000000000000 i3: 0000000000000001 [783019.130490] i4: 0000000000000000 i5: 0000000000000000 i6: fffff803fba867a1 i7: 000000000062038c [783019.130614] I7: Fix by simply renaming the parent device to "niu-board". Signed-off-by: David S. Miller --- drivers/net/niu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/niu.c b/drivers/net/niu.c index 40fa59e2fd5c6..32678b6c6b399 100644 --- a/drivers/net/niu.c +++ b/drivers/net/niu.c @@ -9501,7 +9501,7 @@ static struct niu_parent * __devinit niu_new_parent(struct niu *np, struct niu_parent *p; int i; - plat_dev = platform_device_register_simple("niu", niu_parent_index, + plat_dev = platform_device_register_simple("niu-board", niu_parent_index, NULL, 0); if (IS_ERR(plat_dev)) return NULL; -- GitLab From 80b5efbd43f0a21e9fc6db87823be32fcfe3e7ce Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Mon, 28 Feb 2011 17:01:04 +0100 Subject: [PATCH 0925/2822] ARM: 6771/1: vexpress: add support for multiple core tiles The current Versatile Express BSP defines the MACHINE_START macro in the core tile code. This patch moves this into the generic board code and introduces a method for determining the current tile at runtime, allowing the Kernel to have support for multiple tiles compiled in. Tile-specific functions are executed via a descriptor struct containing the correct implementations for the current tile. Signed-off-by: Will Deacon Signed-off-by: Russell King --- arch/arm/mach-vexpress/core.h | 6 -- arch/arm/mach-vexpress/ct-ca9x4.c | 45 ++++++++----- .../arm/mach-vexpress/include/mach/ct-ca9x4.h | 2 + .../mach-vexpress/include/mach/motherboard.h | 22 +++++++ arch/arm/mach-vexpress/platsmp.c | 31 +-------- arch/arm/mach-vexpress/v2m.c | 65 +++++++++++++++---- 6 files changed, 110 insertions(+), 61 deletions(-) diff --git a/arch/arm/mach-vexpress/core.h b/arch/arm/mach-vexpress/core.h index e0312a1dce3a8..f4397159c1732 100644 --- a/arch/arm/mach-vexpress/core.h +++ b/arch/arm/mach-vexpress/core.h @@ -17,9 +17,3 @@ struct amba_device name##_device = { \ .irq = IRQ_##base, \ /* .dma = DMA_##base,*/ \ } - -struct map_desc; - -void v2m_map_io(struct map_desc *tile, size_t num); -void v2m_init_early(void); -extern struct sys_timer v2m_timer; diff --git a/arch/arm/mach-vexpress/ct-ca9x4.c b/arch/arm/mach-vexpress/ct-ca9x4.c index 30d5a5b0ac217..ebc22e759325a 100644 --- a/arch/arm/mach-vexpress/ct-ca9x4.c +++ b/arch/arm/mach-vexpress/ct-ca9x4.c @@ -10,19 +10,17 @@ #include #include -#include #include #include #include -#include #include +#include #include #include #include -#include #include #include @@ -58,7 +56,7 @@ static void __init ct_ca9x4_map_io(void) #ifdef CONFIG_LOCAL_TIMERS twd_base = MMIO_P2V(A9_MPCORE_TWD); #endif - v2m_map_io(ct_ca9x4_io_desc, ARRAY_SIZE(ct_ca9x4_io_desc)); + iotable_init(ct_ca9x4_io_desc, ARRAY_SIZE(ct_ca9x4_io_desc)); } static void __init ct_ca9x4_init_irq(void) @@ -183,8 +181,6 @@ static struct platform_device pmu_device = { static void __init ct_ca9x4_init_early(void) { clkdev_add_table(lookups, ARRAY_SIZE(lookups)); - - v2m_init_early(); } static void __init ct_ca9x4_init(void) @@ -207,15 +203,34 @@ static void __init ct_ca9x4_init(void) platform_device_register(&pmu_device); } -MACHINE_START(VEXPRESS, "ARM-Versatile Express CA9x4") - .boot_params = PLAT_PHYS_OFFSET + 0x00000100, +#ifdef CONFIG_SMP +static void ct_ca9x4_init_cpu_map(void) +{ + int i, ncores = scu_get_core_count(MMIO_P2V(A9_MPCORE_SCU)); + + for (i = 0; i < ncores; ++i) + set_cpu_possible(i, true); +} + +static void ct_ca9x4_smp_enable(unsigned int max_cpus) +{ + int i; + for (i = 0; i < max_cpus; i++) + set_cpu_present(i, true); + + scu_enable(MMIO_P2V(A9_MPCORE_SCU)); +} +#endif + +struct ct_desc ct_ca9x4_desc __initdata = { + .id = V2M_CT_ID_CA9, + .name = "CA9x4", .map_io = ct_ca9x4_map_io, - .init_irq = ct_ca9x4_init_irq, .init_early = ct_ca9x4_init_early, -#if 0 - .timer = &ct_ca9x4_timer, -#else - .timer = &v2m_timer, + .init_irq = ct_ca9x4_init_irq, + .init_tile = ct_ca9x4_init, +#ifdef CONFIG_SMP + .init_cpu_map = ct_ca9x4_init_cpu_map, + .smp_enable = ct_ca9x4_smp_enable, #endif - .init_machine = ct_ca9x4_init, -MACHINE_END +}; diff --git a/arch/arm/mach-vexpress/include/mach/ct-ca9x4.h b/arch/arm/mach-vexpress/include/mach/ct-ca9x4.h index f9e2f8d229623..a34d3d4faae19 100644 --- a/arch/arm/mach-vexpress/include/mach/ct-ca9x4.h +++ b/arch/arm/mach-vexpress/include/mach/ct-ca9x4.h @@ -45,4 +45,6 @@ #define IRQ_CT_CA9X4_PMU_CPU2 94 #define IRQ_CT_CA9X4_PMU_CPU3 95 +extern struct ct_desc ct_ca9x4_desc; + #endif diff --git a/arch/arm/mach-vexpress/include/mach/motherboard.h b/arch/arm/mach-vexpress/include/mach/motherboard.h index 98a8ded055bf8..0a3a375184052 100644 --- a/arch/arm/mach-vexpress/include/mach/motherboard.h +++ b/arch/arm/mach-vexpress/include/mach/motherboard.h @@ -118,4 +118,26 @@ int v2m_cfg_write(u32 devfn, u32 data); int v2m_cfg_read(u32 devfn, u32 *data); +/* + * Core tile IDs + */ +#define V2M_CT_ID_CA9 0x0c000191 +#define V2M_CT_ID_UNSUPPORTED 0xff000191 +#define V2M_CT_ID_MASK 0xff000fff + +struct ct_desc { + u32 id; + const char *name; + void (*map_io)(void); + void (*init_early)(void); + void (*init_irq)(void); + void (*init_tile)(void); +#ifdef CONFIG_SMP + void (*init_cpu_map)(void); + void (*smp_enable)(unsigned int); +#endif +}; + +extern struct ct_desc *ct_desc; + #endif diff --git a/arch/arm/mach-vexpress/platsmp.c b/arch/arm/mach-vexpress/platsmp.c index 18927023c2cc4..2b5f7ac001a33 100644 --- a/arch/arm/mach-vexpress/platsmp.c +++ b/arch/arm/mach-vexpress/platsmp.c @@ -13,10 +13,8 @@ #include #include -#include #include -#include #include #define V2M_PA_CS7 0x10000000 @@ -24,47 +22,22 @@ extern void versatile_secondary_startup(void); -static void __iomem *scu_base_addr(void) -{ - return MMIO_P2V(A9_MPCORE_SCU); -} - /* * Initialise the CPU possible map early - this describes the CPUs * which may be present or become present in the system. */ void __init smp_init_cpus(void) { - void __iomem *scu_base = scu_base_addr(); - unsigned int i, ncores; - - ncores = scu_base ? scu_get_core_count(scu_base) : 1; - - /* sanity check */ - if (ncores > NR_CPUS) { - printk(KERN_WARNING - "vexpress: no. of cores (%d) greater than configured " - "maximum of %d - clipping\n", - ncores, NR_CPUS); - ncores = NR_CPUS; - } - - for (i = 0; i < ncores; i++) - set_cpu_possible(i, true); + ct_desc->init_cpu_map(); } void __init platform_smp_prepare_cpus(unsigned int max_cpus) { - int i; - /* * Initialise the present map, which describes the set of CPUs * actually populated at the present time. */ - for (i = 0; i < max_cpus; i++) - set_cpu_present(i, true); - - scu_enable(scu_base_addr()); + ct_desc->smp_enable(max_cpus); /* * Write the address of secondary startup into the diff --git a/arch/arm/mach-vexpress/v2m.c b/arch/arm/mach-vexpress/v2m.c index 63ef663fb0be7..ba46e8e074371 100644 --- a/arch/arm/mach-vexpress/v2m.c +++ b/arch/arm/mach-vexpress/v2m.c @@ -14,7 +14,9 @@ #include #include +#include #include +#include #include #include #include @@ -22,6 +24,7 @@ #include #include +#include #include #include @@ -43,14 +46,9 @@ static struct map_desc v2m_io_desc[] __initdata = { }, }; -void __init v2m_map_io(struct map_desc *tile, size_t num) -{ - iotable_init(v2m_io_desc, ARRAY_SIZE(v2m_io_desc)); - iotable_init(tile, num); -} - -void __init v2m_init_early(void) +static void __init v2m_init_early(void) { + ct_desc->init_early(); versatile_sched_clock_init(MMIO_P2V(V2M_SYS_24MHZ), 24000000); } @@ -71,7 +69,7 @@ static void __init v2m_timer_init(void) sp804_clockevents_init(MMIO_P2V(V2M_TIMER0), IRQ_V2M_TIMER0); } -struct sys_timer v2m_timer = { +static struct sys_timer v2m_timer = { .init = v2m_timer_init, }; @@ -380,7 +378,44 @@ static void v2m_restart(char str, const char *cmd) printk(KERN_EMERG "Unable to reboot\n"); } -static int __init v2m_init(void) +struct ct_desc *ct_desc; + +static struct ct_desc *ct_descs[] __initdata = { +#ifdef CONFIG_ARCH_VEXPRESS_CA9X4 + &ct_ca9x4_desc, +#endif +}; + +static void __init v2m_populate_ct_desc(void) +{ + int i; + u32 current_tile_id; + + ct_desc = NULL; + current_tile_id = readl(MMIO_P2V(V2M_SYS_PROCID0)) & V2M_CT_ID_MASK; + + for (i = 0; i < ARRAY_SIZE(ct_descs) && !ct_desc; ++i) + if (ct_descs[i]->id == current_tile_id) + ct_desc = ct_descs[i]; + + if (!ct_desc) + panic("vexpress: failed to populate core tile description " + "for tile ID 0x%8x\n", current_tile_id); +} + +static void __init v2m_map_io(void) +{ + iotable_init(v2m_io_desc, ARRAY_SIZE(v2m_io_desc)); + v2m_populate_ct_desc(); + ct_desc->map_io(); +} + +static void __init v2m_init_irq(void) +{ + ct_desc->init_irq(); +} + +static void __init v2m_init(void) { int i; @@ -399,6 +434,14 @@ static int __init v2m_init(void) pm_power_off = v2m_power_off; arm_pm_restart = v2m_restart; - return 0; + ct_desc->init_tile(); } -arch_initcall(v2m_init); + +MACHINE_START(VEXPRESS, "ARM-Versatile Express") + .boot_params = PLAT_PHYS_OFFSET + 0x00000100, + .map_io = v2m_map_io, + .init_early = v2m_init_early, + .init_irq = v2m_init_irq, + .timer = &v2m_timer, + .init_machine = v2m_init, +MACHINE_END -- GitLab From 950a5097855e2d0ac2c91a33f67eeac3be802bf5 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Sun, 20 Mar 2011 14:50:52 +0100 Subject: [PATCH 0926/2822] i2c-boardinfo: Fix typo in comment Signed-off-by: Wolfram Sang Signed-off-by: Jean Delvare --- drivers/i2c/i2c-boardinfo.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/i2c/i2c-boardinfo.c b/drivers/i2c/i2c-boardinfo.c index 7e6a63b571650..3ca2e012e7893 100644 --- a/drivers/i2c/i2c-boardinfo.c +++ b/drivers/i2c/i2c-boardinfo.c @@ -1,5 +1,5 @@ /* - * i2c-boardinfo.h - collect pre-declarations of I2C devices + * i2c-boardinfo.c - collect pre-declarations of I2C devices * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by -- GitLab From 6ced9e6b3901af4ab6ac0a11231402c888286ea6 Mon Sep 17 00:00:00 2001 From: Roman Fietze Date: Sun, 20 Mar 2011 14:50:52 +0100 Subject: [PATCH 0927/2822] i2c: Fix typo in instantiating-devices document The struct i2c_board_info member holding the name is "type", not "name". Signed-off-by: Roman Fietze Signed-off-by: Jean Delvare Cc: stable@kernel.org --- Documentation/i2c/instantiating-devices | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/i2c/instantiating-devices b/Documentation/i2c/instantiating-devices index 87da405a85979..9edb75d8c9b94 100644 --- a/Documentation/i2c/instantiating-devices +++ b/Documentation/i2c/instantiating-devices @@ -100,7 +100,7 @@ static int __devinit usb_hcd_pnx4008_probe(struct platform_device *pdev) (...) i2c_adap = i2c_get_adapter(2); memset(&i2c_info, 0, sizeof(struct i2c_board_info)); - strlcpy(i2c_info.name, "isp1301_pnx", I2C_NAME_SIZE); + strlcpy(i2c_info.type, "isp1301_pnx", I2C_NAME_SIZE); isp1301_i2c_client = i2c_new_probed_device(i2c_adap, &i2c_info, normal_i2c, NULL); i2c_put_adapter(i2c_adap); -- GitLab From d735b34db30b7891ff76b552d18ecb0ce04a2bc2 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Sun, 20 Mar 2011 14:50:52 +0100 Subject: [PATCH 0928/2822] i2c: make i2c_get_adapter prototype clearer Rename the parameter of i2c_get_adapter() to "nr", to make it clear we are passing an adapter number and not an adapter ID (which have gone away by now.) Signed-off-by: Jean Delvare --- drivers/i2c/i2c-core.c | 4 ++-- include/linux/i2c.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c index 045ba6efea48f..f7620cada7820 100644 --- a/drivers/i2c/i2c-core.c +++ b/drivers/i2c/i2c-core.c @@ -1581,12 +1581,12 @@ i2c_new_probed_device(struct i2c_adapter *adap, } EXPORT_SYMBOL_GPL(i2c_new_probed_device); -struct i2c_adapter *i2c_get_adapter(int id) +struct i2c_adapter *i2c_get_adapter(int nr) { struct i2c_adapter *adapter; mutex_lock(&core_lock); - adapter = idr_find(&i2c_adapter_idr, id); + adapter = idr_find(&i2c_adapter_idr, nr); if (adapter && !try_module_get(adapter->owner)) adapter = NULL; diff --git a/include/linux/i2c.h b/include/linux/i2c.h index 06a8d9c7de987..c1e70afe2502f 100644 --- a/include/linux/i2c.h +++ b/include/linux/i2c.h @@ -447,7 +447,7 @@ extern void i2c_release_client(struct i2c_client *client); extern void i2c_clients_command(struct i2c_adapter *adap, unsigned int cmd, void *arg); -extern struct i2c_adapter *i2c_get_adapter(int id); +extern struct i2c_adapter *i2c_get_adapter(int nr); extern void i2c_put_adapter(struct i2c_adapter *adap); -- GitLab From ed065e26b8721553736ce9e38023488c6747e93d Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Sun, 20 Mar 2011 14:50:52 +0100 Subject: [PATCH 0929/2822] i2c: Minor fixes to upgrading-clients document * Typical legacy drivers implemented method .detach_client, not .detach_adapter. * Drop all references to __devexit, as i2c drivers shouldn't use it. Cc: Ben Dooks Signed-off-by: Jean Delvare --- Documentation/i2c/upgrading-clients | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/Documentation/i2c/upgrading-clients b/Documentation/i2c/upgrading-clients index 9a45f9bb6a255..d6991625c407d 100644 --- a/Documentation/i2c/upgrading-clients +++ b/Documentation/i2c/upgrading-clients @@ -61,7 +61,7 @@ static int example_attach(struct i2c_adapter *adap, int addr, int kind) return 0; } -static int __devexit example_detach(struct i2c_client *client) +static int example_detach(struct i2c_client *client) { struct example_state *state = i2c_get_clientdata(client); @@ -81,7 +81,7 @@ static struct i2c_driver example_driver = { .name = "example", }, .attach_adapter = example_attach_adapter, - .detach_client = __devexit_p(example_detach), + .detach_client = example_detach, .suspend = example_suspend, .resume = example_resume, }; @@ -93,7 +93,7 @@ Updating the client The new style binding model will check against a list of supported devices and their associated address supplied by the code registering the busses. This means that the driver .attach_adapter and -.detach_adapter methods can be removed, along with the addr_data, +.detach_client methods can be removed, along with the addr_data, as follows: - static struct i2c_driver example_driver; @@ -110,14 +110,14 @@ as follows: static struct i2c_driver example_driver = { - .attach_adapter = example_attach_adapter, -- .detach_client = __devexit_p(example_detach), +- .detach_client = example_detach, } Add the probe and remove methods to the i2c_driver, as so: static struct i2c_driver example_driver = { + .probe = example_probe, -+ .remove = __devexit_p(example_remove), ++ .remove = example_remove, } Change the example_attach method to accept the new parameters @@ -199,8 +199,8 @@ to delete the i2c_detach_client call. It is possible that you can also remove the ret variable as it is not not needed for any of the core functions. -- static int __devexit example_detach(struct i2c_client *client) -+ static int __devexit example_remove(struct i2c_client *client) +- static int example_detach(struct i2c_client *client) ++ static int example_remove(struct i2c_client *client) { struct example_state *state = i2c_get_clientdata(client); @@ -253,7 +253,7 @@ static int example_probe(struct i2c_client *client, return 0; } -static int __devexit example_remove(struct i2c_client *client) +static int example_remove(struct i2c_client *client) { struct example_state *state = i2c_get_clientdata(client); @@ -275,7 +275,7 @@ static struct i2c_driver example_driver = { }, .id_table = example_idtable, .probe = example_probe, - .remove = __devexit_p(example_remove), + .remove = example_remove, .suspend = example_suspend, .resume = example_resume, }; -- GitLab From 0c31f8e5720e1191b4cf46a9b5374fe6b857c53c Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Sun, 20 Mar 2011 14:50:52 +0100 Subject: [PATCH 0930/2822] i2c: Get rid of The last remaining ID in is no longer used anywhere, so we can finally get rid of it. Signed-off-by: Jean Delvare --- Documentation/video4linux/Zoran | 2 +- include/linux/i2c-id.h | 37 --------------------------------- include/linux/i2c.h | 1 - 3 files changed, 1 insertion(+), 39 deletions(-) delete mode 100644 include/linux/i2c-id.h diff --git a/Documentation/video4linux/Zoran b/Documentation/video4linux/Zoran index 699b60e070d21..c40e3bab08fa3 100644 --- a/Documentation/video4linux/Zoran +++ b/Documentation/video4linux/Zoran @@ -130,7 +130,7 @@ Card number: 4 Note: No module for the mse3000 is available yet Note: No module for the vpx3224 is available yet -Note: use encoder=X or decoder=X for non-default i2c chips (see i2c-id.h) +Note: use encoder=X or decoder=X for non-default i2c chips =========================== diff --git a/include/linux/i2c-id.h b/include/linux/i2c-id.h deleted file mode 100644 index 4bef5c5571601..0000000000000 --- a/include/linux/i2c-id.h +++ /dev/null @@ -1,37 +0,0 @@ -/* ------------------------------------------------------------------------- */ -/* */ -/* i2c-id.h - identifier values for i2c drivers and adapters */ -/* */ -/* ------------------------------------------------------------------------- */ -/* Copyright (C) 1995-1999 Simon G. Vogl - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -/* ------------------------------------------------------------------------- */ - -#ifndef LINUX_I2C_ID_H -#define LINUX_I2C_ID_H - -/* Please note that I2C driver IDs are optional. They are only needed if a - legacy chip driver needs to identify a bus or a bus driver needs to - identify a legacy client. If you don't need them, just don't set them. */ - -/* - * ---- Adapter types ---------------------------------------------------- - */ - -/* --- Bit algorithm adapters */ -#define I2C_HW_B_CX2388x 0x01001b /* connexant 2388x based tv cards */ - -#endif /* LINUX_I2C_ID_H */ diff --git a/include/linux/i2c.h b/include/linux/i2c.h index c1e70afe2502f..3963a55674729 100644 --- a/include/linux/i2c.h +++ b/include/linux/i2c.h @@ -29,7 +29,6 @@ #include #ifdef __KERNEL__ #include -#include #include #include /* for struct device */ #include /* for completion */ -- GitLab From 7ae31482a8376fb0df3a0c5ff0677a92820c06b7 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Sun, 20 Mar 2011 14:50:52 +0100 Subject: [PATCH 0931/2822] i2c: Export i2c_for_each_dev Introduce i2c_for_each_dev(), an i2c device iterator with proper locking for use by i2c-dev. This is needed so that we can get rid of the attach_adapter and detach_adapter legacy callback functions. Signed-off-by: Jean Delvare --- drivers/i2c/i2c-core.c | 20 ++++++++++++++------ include/linux/i2c.h | 2 ++ 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c index f7620cada7820..b9fa1d0320b43 100644 --- a/drivers/i2c/i2c-core.c +++ b/drivers/i2c/i2c-core.c @@ -1091,6 +1091,18 @@ EXPORT_SYMBOL(i2c_del_adapter); /* ------------------------------------------------------------------------- */ +int i2c_for_each_dev(void *data, int (*fn)(struct device *, void *)) +{ + int res; + + mutex_lock(&core_lock); + res = bus_for_each_dev(&i2c_bus_type, NULL, data, fn); + mutex_unlock(&core_lock); + + return res; +} +EXPORT_SYMBOL_GPL(i2c_for_each_dev); + static int __process_new_driver(struct device *dev, void *data) { if (dev->type != &i2c_adapter_type) @@ -1134,9 +1146,7 @@ int i2c_register_driver(struct module *owner, struct i2c_driver *driver) INIT_LIST_HEAD(&driver->clients); /* Walk the adapters that are already present */ - mutex_lock(&core_lock); - bus_for_each_dev(&i2c_bus_type, NULL, driver, __process_new_driver); - mutex_unlock(&core_lock); + i2c_for_each_dev(driver, __process_new_driver); return 0; } @@ -1156,9 +1166,7 @@ static int __process_removed_driver(struct device *dev, void *data) */ void i2c_del_driver(struct i2c_driver *driver) { - mutex_lock(&core_lock); - bus_for_each_dev(&i2c_bus_type, NULL, driver, __process_removed_driver); - mutex_unlock(&core_lock); + i2c_for_each_dev(driver, __process_removed_driver); driver_unregister(&driver->driver); pr_debug("i2c-core: driver [%s] unregistered\n", driver->driver.name); diff --git a/include/linux/i2c.h b/include/linux/i2c.h index 3963a55674729..4df12c7e69d73 100644 --- a/include/linux/i2c.h +++ b/include/linux/i2c.h @@ -395,6 +395,8 @@ i2c_parent_is_i2c_adapter(const struct i2c_adapter *adapter) return NULL; } +int i2c_for_each_dev(void *data, int (*fn)(struct device *, void *)); + /* Adapter locking functions, exported for shared pin cases */ void i2c_lock_adapter(struct i2c_adapter *); void i2c_unlock_adapter(struct i2c_adapter *); -- GitLab From 9ea3e941d161f41f920462c50e9b651cc00eccc7 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Sun, 20 Mar 2011 14:50:52 +0100 Subject: [PATCH 0932/2822] i2c-dev: Use standard bus notification mechanism Use the standard driver core mechanism to keep track of i2c adapters present on the system: i2c_for_each_dev and a notifier. This will let us deprecate and ultimately remove the legacy attach_adapter and detach_adapter callbacks in i2c_driver. Signed-off-by: Jean Delvare --- drivers/i2c/i2c-dev.c | 60 ++++++++++++++++++++++++++++--------------- 1 file changed, 39 insertions(+), 21 deletions(-) diff --git a/drivers/i2c/i2c-dev.c b/drivers/i2c/i2c-dev.c index cec0f3ba97f8b..c90ce50b619f7 100644 --- a/drivers/i2c/i2c-dev.c +++ b/drivers/i2c/i2c-dev.c @@ -28,6 +28,8 @@ #include #include +#include +#include #include #include #include @@ -37,16 +39,13 @@ #include #include -static struct i2c_driver i2cdev_driver; - /* * An i2c_dev represents an i2c_adapter ... an I2C or SMBus master, not a * slave (i2c_client) with which messages will be exchanged. It's coupled * with a character special file which is accessed by user mode drivers. * * The list of i2c_dev structures is parallel to the i2c_adapter lists - * maintained by the driver model, and is updated using notifications - * delivered to the i2cdev_driver. + * maintained by the driver model, and is updated using bus notifications. */ struct i2c_dev { struct list_head list; @@ -491,7 +490,6 @@ static int i2cdev_open(struct inode *inode, struct file *file) return -ENOMEM; } snprintf(client->name, I2C_NAME_SIZE, "i2c-dev %d", adap->nr); - client->driver = &i2cdev_driver; client->adapter = adap; file->private_data = client; @@ -522,19 +520,18 @@ static const struct file_operations i2cdev_fops = { /* ------------------------------------------------------------------------- */ -/* - * The legacy "i2cdev_driver" is used primarily to get notifications when - * I2C adapters are added or removed, so that each one gets an i2c_dev - * and is thus made available to userspace driver code. - */ - static struct class *i2c_dev_class; -static int i2cdev_attach_adapter(struct i2c_adapter *adap) +static int i2cdev_attach_adapter(struct device *dev, void *dummy) { + struct i2c_adapter *adap; struct i2c_dev *i2c_dev; int res; + if (dev->type != &i2c_adapter_type) + return 0; + adap = to_i2c_adapter(dev); + i2c_dev = get_free_i2c_dev(adap); if (IS_ERR(i2c_dev)) return PTR_ERR(i2c_dev); @@ -561,10 +558,15 @@ error: return res; } -static int i2cdev_detach_adapter(struct i2c_adapter *adap) +static int i2cdev_detach_adapter(struct device *dev, void *dummy) { + struct i2c_adapter *adap; struct i2c_dev *i2c_dev; + if (dev->type != &i2c_adapter_type) + return 0; + adap = to_i2c_adapter(dev); + i2c_dev = i2c_dev_get_by_minor(adap->nr); if (!i2c_dev) /* attach_adapter must have failed */ return 0; @@ -577,12 +579,23 @@ static int i2cdev_detach_adapter(struct i2c_adapter *adap) return 0; } -static struct i2c_driver i2cdev_driver = { - .driver = { - .name = "dev_driver", - }, - .attach_adapter = i2cdev_attach_adapter, - .detach_adapter = i2cdev_detach_adapter, +int i2cdev_notifier_call(struct notifier_block *nb, unsigned long action, + void *data) +{ + struct device *dev = data; + + switch (action) { + case BUS_NOTIFY_ADD_DEVICE: + return i2cdev_attach_adapter(dev, NULL); + case BUS_NOTIFY_DEL_DEVICE: + return i2cdev_detach_adapter(dev, NULL); + } + + return 0; +} + +static struct notifier_block i2cdev_notifier = { + .notifier_call = i2cdev_notifier_call, }; /* ------------------------------------------------------------------------- */ @@ -607,10 +620,14 @@ static int __init i2c_dev_init(void) goto out_unreg_chrdev; } - res = i2c_add_driver(&i2cdev_driver); + /* Keep track of adapters which will be added or removed later */ + res = bus_register_notifier(&i2c_bus_type, &i2cdev_notifier); if (res) goto out_unreg_class; + /* Bind to already existing adapters right away */ + i2c_for_each_dev(NULL, i2cdev_attach_adapter); + return 0; out_unreg_class: @@ -624,7 +641,8 @@ out: static void __exit i2c_dev_exit(void) { - i2c_del_driver(&i2cdev_driver); + bus_unregister_notifier(&i2c_bus_type, &i2cdev_notifier); + i2c_for_each_dev(NULL, i2cdev_detach_adapter); class_destroy(i2c_dev_class); unregister_chrdev(I2C_MAJOR, "i2c"); } -- GitLab From fe6fc25857d293546bd400432cdb77866c797c9b Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Sun, 20 Mar 2011 14:50:53 +0100 Subject: [PATCH 0933/2822] i2c: Deprecate i2c_driver.attach_adapter and .detach_adapter The last legitimate user of i2c_driver.attach_adapter and .detach_adapter is gone, so we can finally deprecate these callbacks. The last few drivers which still use these will have to be updated to make use of standard I2C device instantiation ways instead. Signed-off-by: Jean Delvare --- Documentation/feature-removal-schedule.txt | 9 +++++++++ drivers/i2c/Makefile | 1 + drivers/i2c/i2c-core.c | 4 ++++ include/linux/i2c.h | 12 ++++++------ 4 files changed, 20 insertions(+), 6 deletions(-) diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt index f487c6918d787..7ce623bb96374 100644 --- a/Documentation/feature-removal-schedule.txt +++ b/Documentation/feature-removal-schedule.txt @@ -645,3 +645,12 @@ Who: Florian Westphal Files: include/linux/netfilter_ipv4/ipt_addrtype.h ---------------------------- + +What: i2c_driver.attach_adapter + i2c_driver.detach_adapter +When: September 2011 +Why: These legacy callbacks should no longer be used as i2c-core offers + a variety of preferable alternative ways to instantiate I2C devices. +Who: Jean Delvare + +---------------------------- diff --git a/drivers/i2c/Makefile b/drivers/i2c/Makefile index 23ac61e2db398..beee6b2d361db 100644 --- a/drivers/i2c/Makefile +++ b/drivers/i2c/Makefile @@ -10,3 +10,4 @@ obj-$(CONFIG_I2C_MUX) += i2c-mux.o obj-y += algos/ busses/ muxes/ ccflags-$(CONFIG_I2C_DEBUG_CORE) := -DDEBUG +CFLAGS_i2c-core.o := -Wno-deprecated-declarations diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c index b9fa1d0320b43..e5f76a0372fd6 100644 --- a/drivers/i2c/i2c-core.c +++ b/drivers/i2c/i2c-core.c @@ -797,6 +797,9 @@ static int i2c_do_add_adapter(struct i2c_driver *driver, /* Let legacy drivers scan this bus for matching devices */ if (driver->attach_adapter) { + dev_warn(&adap->dev, "attach_adapter method is deprecated\n"); + dev_warn(&adap->dev, "Please use another way to instantiate " + "your i2c_client\n"); /* We ignore the return code; if it fails, too bad */ driver->attach_adapter(adap); } @@ -981,6 +984,7 @@ static int i2c_do_del_adapter(struct i2c_driver *driver, if (!driver->detach_adapter) return 0; + dev_warn(&adapter->dev, "detach_adapter method is deprecated\n"); res = driver->detach_adapter(adapter); if (res) dev_err(&adapter->dev, "detach_adapter failed (%d) " diff --git a/include/linux/i2c.h b/include/linux/i2c.h index 4df12c7e69d73..cd2f75b742ec7 100644 --- a/include/linux/i2c.h +++ b/include/linux/i2c.h @@ -104,8 +104,8 @@ extern s32 i2c_smbus_write_i2c_block_data(const struct i2c_client *client, /** * struct i2c_driver - represent an I2C device driver * @class: What kind of i2c device we instantiate (for detect) - * @attach_adapter: Callback for bus addition (for legacy drivers) - * @detach_adapter: Callback for bus removal (for legacy drivers) + * @attach_adapter: Callback for bus addition (deprecated) + * @detach_adapter: Callback for bus removal (deprecated) * @probe: Callback for device binding * @remove: Callback for device unbinding * @shutdown: Callback for device shutdown @@ -143,11 +143,11 @@ struct i2c_driver { unsigned int class; /* Notifies the driver that a new bus has appeared or is about to be - * removed. You should avoid using this if you can, it will probably - * be removed in a near future. + * removed. You should avoid using this, it will be removed in a + * near future. */ - int (*attach_adapter)(struct i2c_adapter *); - int (*detach_adapter)(struct i2c_adapter *); + int (*attach_adapter)(struct i2c_adapter *) __deprecated; + int (*detach_adapter)(struct i2c_adapter *) __deprecated; /* Standard driver model interfaces */ int (*probe)(struct i2c_client *, const struct i2c_device_id *); -- GitLab From c185a9420bd1c645252249018e6887a968d3e1de Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Sun, 20 Mar 2011 14:50:53 +0100 Subject: [PATCH 0934/2822] i2c: Drop i2c_adapter.id There is no user left of i2c_adapter.id, so we can get rid of it. Finally! :) Signed-off-by: Jean Delvare --- Documentation/feature-removal-schedule.txt | 10 ---------- include/linux/i2c.h | 1 - 2 files changed, 11 deletions(-) diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt index 7ce623bb96374..895330940f5df 100644 --- a/Documentation/feature-removal-schedule.txt +++ b/Documentation/feature-removal-schedule.txt @@ -585,16 +585,6 @@ Who: NeilBrown ---------------------------- -What: i2c_adapter.id -When: June 2011 -Why: This field is deprecated. I2C device drivers shouldn't change their - behavior based on the underlying I2C adapter. Instead, the I2C - adapter driver should instantiate the I2C devices and provide the - needed platform-specific information. -Who: Jean Delvare - ----------------------------- - What: cancel_rearming_delayed_work[queue]() When: 2.6.39 diff --git a/include/linux/i2c.h b/include/linux/i2c.h index cd2f75b742ec7..f1e3ff5880a9f 100644 --- a/include/linux/i2c.h +++ b/include/linux/i2c.h @@ -353,7 +353,6 @@ struct i2c_algorithm { */ struct i2c_adapter { struct module *owner; - unsigned int id __deprecated; unsigned int class; /* classes to allow probing for */ const struct i2c_algorithm *algo; /* the algorithm to access the bus */ void *algo_data; -- GitLab From 662cda8abb278f58237fa12b8ab3060ebefca4b8 Mon Sep 17 00:00:00 2001 From: Seth Heasley Date: Sun, 20 Mar 2011 14:50:53 +0100 Subject: [PATCH 0935/2822] i2c-i801: SMBus patch for Intel DH89xxCC DeviceIDs Add the SMBus Controller DeviceIDs for the Intel DH89xxCC PCH. Signed-off-by: Seth Heasley Signed-off-by: Jean Delvare --- Documentation/i2c/busses/i2c-i801 | 3 ++- drivers/i2c/busses/Kconfig | 3 ++- drivers/i2c/busses/i2c-i801.c | 4 +++- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/Documentation/i2c/busses/i2c-i801 b/Documentation/i2c/busses/i2c-i801 index 93fe76e56522a..6df69765ccb75 100644 --- a/Documentation/i2c/busses/i2c-i801 +++ b/Documentation/i2c/busses/i2c-i801 @@ -16,8 +16,9 @@ Supported adapters: * Intel EP80579 (Tolapai) * Intel 82801JI (ICH10) * Intel 5/3400 Series (PCH) - * Intel Cougar Point (PCH) + * Intel 6 Series (PCH) * Intel Patsburg (PCH) + * Intel DH89xxCC (PCH) Datasheets: Publicly available at the Intel website On Intel Patsburg and later chipsets, both the normal host SMBus controller diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig index 230601e8853ff..ad415e6ec5a10 100644 --- a/drivers/i2c/busses/Kconfig +++ b/drivers/i2c/busses/Kconfig @@ -98,8 +98,9 @@ config I2C_I801 EP80579 (Tolapai) ICH10 5/3400 Series (PCH) - Cougar Point (PCH) + 6 Series (PCH) Patsburg (PCH) + DH89xxCC (PCH) This driver can also be built as a module. If so, the module will be called i2c-i801. diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c index 7979aef7ee7b2..ed2e0c5ea37c7 100644 --- a/drivers/i2c/busses/i2c-i801.c +++ b/drivers/i2c/busses/i2c-i801.c @@ -44,11 +44,12 @@ ICH10 0x3a30 32 hard yes yes yes ICH10 0x3a60 32 hard yes yes yes 5/3400 Series (PCH) 0x3b30 32 hard yes yes yes - Cougar Point (PCH) 0x1c22 32 hard yes yes yes + 6 Series (PCH) 0x1c22 32 hard yes yes yes Patsburg (PCH) 0x1d22 32 hard yes yes yes Patsburg (PCH) IDF 0x1d70 32 hard yes yes yes Patsburg (PCH) IDF 0x1d71 32 hard yes yes yes Patsburg (PCH) IDF 0x1d72 32 hard yes yes yes + DH89xxCC (PCH) 0x2330 32 hard yes yes yes Features supported by this driver: Software PEC no @@ -621,6 +622,7 @@ static const struct pci_device_id i801_ids[] = { { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_PATSBURG_SMBUS_IDF0) }, { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_PATSBURG_SMBUS_IDF1) }, { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_PATSBURG_SMBUS_IDF2) }, + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_DH89XXCC_SMBUS) }, { 0, } }; -- GitLab From dd5eeb99f47d18c05efffcd247c0aa07eaa9ffaa Mon Sep 17 00:00:00 2001 From: Clemens Ladisch Date: Mon, 7 Mar 2011 11:21:15 +0100 Subject: [PATCH 0936/2822] firewire: core: increase default SPLIT_TIMEOUT value The SPLIT_TIMEOUT mechanism is intended to detect requests that somehow got lost. However, when the timeout value is too low, transactions that could have been completed successfully will be cancelled. Furthermore, there are chips whose firmwares ignore the configured split timeout and send late split response; known examples are the DM1x00 (BeBoB), TCD22x0 (DICE), and some OXUF936QSE firmwares. This patch changes the default timeout to two seconds, which happens to be the default on other OSes, too. Actual lost requests are extremely rare, so there should be no practical downside to increasing the split timeout even on devices that work correctly. Signed-off-by: Clemens Ladisch Signed-off-by: Stefan Richter --- drivers/firewire/core-card.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/drivers/firewire/core-card.c b/drivers/firewire/core-card.c index 3241dc4e1fc9f..3c44fbc81acba 100644 --- a/drivers/firewire/core-card.c +++ b/drivers/firewire/core-card.c @@ -75,6 +75,13 @@ static size_t config_rom_length = 1 + 4 + 1 + 1; #define BIB_IRMC ((1) << 31) #define NODE_CAPABILITIES 0x0c0083c0 /* per IEEE 1394 clause 8.3.2.6.5.2 */ +/* + * IEEE-1394 specifies a default SPLIT_TIMEOUT value of 800 cycles (100 ms), + * but we have to make it longer because there are many devices whose firmware + * is just too slow for that. + */ +#define DEFAULT_SPLIT_TIMEOUT (2 * 8000) + #define CANON_OUI 0x000085 static void generate_config_rom(struct fw_card *card, __be32 *config_rom) @@ -512,10 +519,11 @@ void fw_card_initialize(struct fw_card *card, card->device = device; card->current_tlabel = 0; card->tlabel_mask = 0; - card->split_timeout_hi = 0; - card->split_timeout_lo = 800 << 19; - card->split_timeout_cycles = 800; - card->split_timeout_jiffies = DIV_ROUND_UP(HZ, 10); + card->split_timeout_hi = DEFAULT_SPLIT_TIMEOUT / 8000; + card->split_timeout_lo = (DEFAULT_SPLIT_TIMEOUT % 8000) << 19; + card->split_timeout_cycles = DEFAULT_SPLIT_TIMEOUT; + card->split_timeout_jiffies = + DIV_ROUND_UP(DEFAULT_SPLIT_TIMEOUT * HZ, 8000); card->color = 0; card->broadcast_channel = BROADCAST_CHANNEL_INITIAL; -- GitLab From 7a4e1e9c682cd87fe8a749b435b13afeef083c34 Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Tue, 15 Mar 2011 00:04:42 +0100 Subject: [PATCH 0937/2822] firewire: sbp2: revert obsolete 'fix stall with "Unsolicited response"' Now that firewire-core sets the local node's SPLIT_TIMEOUT to 2 seconds per default, commit a481e97d3cdc40b9d58271675bd4f0abb79d4872 is no longer required. Signed-off-by: Stefan Richter --- drivers/firewire/sbp2.c | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/drivers/firewire/sbp2.c b/drivers/firewire/sbp2.c index afa576a75a8ed..77ed589b360d7 100644 --- a/drivers/firewire/sbp2.c +++ b/drivers/firewire/sbp2.c @@ -472,18 +472,12 @@ static void complete_transaction(struct fw_card *card, int rcode, * So this callback only sets the rcode if it hasn't already * been set and only does the cleanup if the transaction * failed and we didn't already get a status write. - * - * Here we treat RCODE_CANCELLED like RCODE_COMPLETE because some - * OXUF936QSE firmwares occasionally respond after Split_Timeout and - * complete the ORB just fine. Note, we also get RCODE_CANCELLED - * from sbp2_cancel_orbs() if fw_cancel_transaction() == 0. */ spin_lock_irqsave(&card->lock, flags); if (orb->rcode == -1) orb->rcode = rcode; - - if (orb->rcode != RCODE_COMPLETE && orb->rcode != RCODE_CANCELLED) { + if (orb->rcode != RCODE_COMPLETE) { list_del(&orb->link); spin_unlock_irqrestore(&card->lock, flags); @@ -532,7 +526,8 @@ static int sbp2_cancel_orbs(struct sbp2_logical_unit *lu) list_for_each_entry_safe(orb, next, &list, link) { retval = 0; - fw_cancel_transaction(device->card, &orb->t); + if (fw_cancel_transaction(device->card, &orb->t) == 0) + continue; orb->rcode = RCODE_CANCELLED; orb->callback(orb, NULL); -- GitLab From 115881d395959b75c8c3bb94913f2ce869b8aa7a Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Tue, 15 Mar 2011 00:08:41 +0100 Subject: [PATCH 0938/2822] firewire: core: ignore link-active bit of new nodes, fix device recognition Like the older ieee1394 core driver, firewire-core skipped scanning of any new node whose PHY sent a self ID without "link active" bit. If a device had this bit off mistakenly, it meant that it was inaccessible to kernel drivers with the old IEEE 1394 driver stack but could still be accessed by userspace drivers through the raw1394 interface. But with firewire-core, userspace drivers don't get to see such buggy devices anymore. This is effectively a driver regression since this device bug is otherwise harmless. We now attempt to scan all devices, even repeaters that don't have a link or powered-down devices that have everything but their PHY shut down when plugged in. This results in futile repeated scanning attempts in case of such devices that really don't have an active link, but this doesn't hurt since recent workqueue infrastructure lets us run more concurrent scanning jobs than we can shake a stick at. This should fix accessibility of Focusrite Saffire PRO 26 I/O: http://sourceforge.net/mailarchive/forum.php?thread_name=20110314215622.5c751bb0%40stein&forum_name=ffado-user Signed-off-by: Stefan Richter --- drivers/firewire/core-device.c | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/drivers/firewire/core-device.c b/drivers/firewire/core-device.c index 57461923bacff..9a262439e3a72 100644 --- a/drivers/firewire/core-device.c +++ b/drivers/firewire/core-device.c @@ -955,8 +955,9 @@ static void fw_device_init(struct work_struct *work) device->config_rom_retries++; schedule_delayed_work(&device->work, RETRY_DELAY); } else { - fw_notify("giving up on config rom for node id %x\n", - device->node_id); + if (device->node->link_on) + fw_notify("giving up on config rom for node id %x\n", + device->node_id); if (device->node == device->card->root_node) fw_schedule_bm_work(device->card, 0); fw_device_release(&device->device); @@ -1169,9 +1170,12 @@ void fw_node_event(struct fw_card *card, struct fw_node *node, int event) switch (event) { case FW_NODE_CREATED: - case FW_NODE_LINK_ON: - if (!node->link_on) - break; + /* + * Attempt to scan the node, regardless whether its self ID has + * the L (link active) flag set or not. Some broken devices + * send L=0 but have an up-and-running link; others send L=1 + * without actually having a link. + */ create: device = kzalloc(sizeof(*device), GFP_ATOMIC); if (device == NULL) @@ -1214,6 +1218,7 @@ void fw_node_event(struct fw_card *card, struct fw_node *node, int event) break; case FW_NODE_INITIATED_RESET: + case FW_NODE_LINK_ON: device = node->data; if (device == NULL) goto create; @@ -1231,10 +1236,10 @@ void fw_node_event(struct fw_card *card, struct fw_node *node, int event) break; case FW_NODE_UPDATED: - if (!node->link_on || node->data == NULL) + device = node->data; + if (device == NULL) break; - device = node->data; device->node_id = node->node_id; smp_wmb(); /* update node_id before generation */ device->generation = card->generation; -- GitLab From a24c5a0ea902bcda348f086bd909cc2d6e305bf8 Mon Sep 17 00:00:00 2001 From: Christoph Lameter Date: Tue, 15 Mar 2011 12:45:21 -0500 Subject: [PATCH 0939/2822] slub: Dont define useless label in the !CONFIG_CMPXCHG_LOCAL case The redo label needs #ifdeffery. Fixes the following problem introduced by commit 8a5ec0ba42c4 ("Lockless (and preemptless) fastpaths for slub"): mm/slub.c: In function 'slab_free': mm/slub.c:2124: warning: label 'redo' defined but not used Reported-by: Stephen Rothwell Signed-off-by: Christoph Lameter Signed-off-by: Pekka Enberg --- mm/slub.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/mm/slub.c b/mm/slub.c index 65030c7fd7e22..f32aee37840b3 100644 --- a/mm/slub.c +++ b/mm/slub.c @@ -2073,9 +2073,11 @@ static __always_inline void slab_free(struct kmem_cache *s, #ifndef CONFIG_CMPXCHG_LOCAL local_irq_save(flags); -#endif +#else redo: +#endif + /* * Determine the currently cpus per cpu slab. * The cpu may change afterward. However that does not matter since -- GitLab From 6f82f4db80189281a8ac42f2e72396accb719b57 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sun, 20 Mar 2011 09:50:05 +0000 Subject: [PATCH 0940/2822] ARM: Update (and cut down) mach-types As many entries have never been submitted to mainline, there's no point them existing in this file. So remove the entries which aren't relevant for mainline. Signed-off-by: Russell King --- arch/arm/tools/mach-types | 2395 ++----------------------------------- 1 file changed, 89 insertions(+), 2306 deletions(-) diff --git a/arch/arm/tools/mach-types b/arch/arm/tools/mach-types index 9d6feaabbe7d1..7ca41f0a09b12 100644 --- a/arch/arm/tools/mach-types +++ b/arch/arm/tools/mach-types @@ -12,2745 +12,458 @@ # # http://www.arm.linux.org.uk/developer/machines/?action=new # -# Last update: Mon Feb 7 08:59:27 2011 +# XXX: This is a cut-down version of the file; it contains only machines that +# XXX: are in mainline or have been submitted to the machine database within +# XXX: the last 12 months. If your entry is missing please email rmk at +# XXX: +# +# Last update: Sun Mar 20 18:06:11 2011 # # machine_is_xxx CONFIG_xxxx MACH_TYPE_xxx number # ebsa110 ARCH_EBSA110 EBSA110 0 riscpc ARCH_RPC RISCPC 1 -nexuspci ARCH_NEXUSPCI NEXUSPCI 3 ebsa285 ARCH_EBSA285 EBSA285 4 netwinder ARCH_NETWINDER NETWINDER 5 cats ARCH_CATS CATS 6 -tbox ARCH_TBOX TBOX 7 -co285 ARCH_CO285 CO285 8 -clps7110 ARCH_CLPS7110 CLPS7110 9 -archimedes ARCH_ARC ARCHIMEDES 10 -a5k ARCH_A5K A5K 11 -etoile ARCH_ETOILE ETOILE 12 -lacie_nas ARCH_LACIE_NAS LACIE_NAS 13 -clps7500 ARCH_CLPS7500 CLPS7500 14 shark ARCH_SHARK SHARK 15 brutus SA1100_BRUTUS BRUTUS 16 personal_server ARCH_PERSONAL_SERVER PERSONAL_SERVER 17 -itsy SA1100_ITSY ITSY 18 l7200 ARCH_L7200 L7200 19 pleb SA1100_PLEB PLEB 20 integrator ARCH_INTEGRATOR INTEGRATOR 21 h3600 SA1100_H3600 H3600 22 -ixp1200 ARCH_IXP1200 IXP1200 23 p720t ARCH_P720T P720T 24 assabet SA1100_ASSABET ASSABET 25 -victor SA1100_VICTOR VICTOR 26 lart SA1100_LART LART 27 -ranger SA1100_RANGER RANGER 28 graphicsclient SA1100_GRAPHICSCLIENT GRAPHICSCLIENT 29 xp860 SA1100_XP860 XP860 30 cerf SA1100_CERF CERF 31 nanoengine SA1100_NANOENGINE NANOENGINE 32 -fpic SA1100_FPIC FPIC 33 -extenex1 SA1100_EXTENEX1 EXTENEX1 34 -sherman SA1100_SHERMAN SHERMAN 35 -accelent_sa SA1100_ACCELENT ACCELENT_SA 36 -accelent_l7200 ARCH_L7200_ACCELENT ACCELENT_L7200 37 -netport SA1100_NETPORT NETPORT 38 -pangolin SA1100_PANGOLIN PANGOLIN 39 -yopy SA1100_YOPY YOPY 40 -coolidge SA1100_COOLIDGE COOLIDGE 41 -huw_webpanel SA1100_HUW_WEBPANEL HUW_WEBPANEL 42 -spotme ARCH_SPOTME SPOTME 43 -freebird ARCH_FREEBIRD FREEBIRD 44 -ti925 ARCH_TI925 TI925 45 -riscstation ARCH_RISCSTATION RISCSTATION 46 -cavy SA1100_CAVY CAVY 47 jornada720 SA1100_JORNADA720 JORNADA720 48 -omnimeter SA1100_OMNIMETER OMNIMETER 49 edb7211 ARCH_EDB7211 EDB7211 50 -citygo SA1100_CITYGO CITYGO 51 pfs168 SA1100_PFS168 PFS168 52 -spot SA1100_SPOT SPOT 53 flexanet SA1100_FLEXANET FLEXANET 54 -webpal ARCH_WEBPAL WEBPAL 55 -linpda SA1100_LINPDA LINPDA 56 -anakin ARCH_ANAKIN ANAKIN 57 -mvi SA1100_MVI MVI 58 -jupiter SA1100_JUPITER JUPITER 59 -psionw ARCH_PSIONW PSIONW 60 -aln SA1100_ALN ALN 61 -epxa ARCH_CAMELOT CAMELOT 62 -gds2200 SA1100_GDS2200 GDS2200 63 -netbook SA1100_PSION_SERIES7 PSION_SERIES7 64 -xfile SA1100_XFILE XFILE 65 -accelent_ep9312 ARCH_ACCELENT_EP9312 ACCELENT_EP9312 66 -ic200 ARCH_IC200 IC200 67 -creditlart SA1100_CREDITLART CREDITLART 68 -htm SA1100_HTM HTM 69 -iq80310 ARCH_IQ80310 IQ80310 70 -freebot SA1100_FREEBOT FREEBOT 71 -entel ARCH_ENTEL ENTEL 72 -enp3510 ARCH_ENP3510 ENP3510 73 -trizeps SA1100_TRIZEPS TRIZEPS 74 -nesa SA1100_NESA NESA 75 -venus ARCH_VENUS VENUS 76 -tardis ARCH_TARDIS TARDIS 77 -mercury ARCH_MERCURY MERCURY 78 -empeg SA1100_EMPEG EMPEG 79 -adi_evb ARCH_I80200FCC I80200FCC 80 -itt_cpb SA1100_ITT_CPB ITT_CPB 81 -svc SA1100_SVC SVC 82 -alpha2 SA1100_ALPHA2 ALPHA2 84 -alpha1 SA1100_ALPHA1 ALPHA1 85 -netarm ARCH_NETARM NETARM 86 simpad SA1100_SIMPAD SIMPAD 87 -pda1 ARCH_PDA1 PDA1 88 lubbock ARCH_LUBBOCK LUBBOCK 89 -aniko ARCH_ANIKO ANIKO 90 clep7212 ARCH_CLEP7212 CLEP7212 91 -cs89712 ARCH_CS89712 CS89712 92 -weararm SA1100_WEARARM WEARARM 93 -possio_px SA1100_POSSIO_PX POSSIO_PX 94 -sidearm SA1100_SIDEARM SIDEARM 95 -stork SA1100_STORK STORK 96 shannon SA1100_SHANNON SHANNON 97 -ace ARCH_ACE ACE 98 -ballyarm SA1100_BALLYARM BALLYARM 99 -simputer SA1100_SIMPUTER SIMPUTER 100 -nexterm SA1100_NEXTERM NEXTERM 101 -sa1100_elf SA1100_SA1100_ELF SA1100_ELF 102 -gator SA1100_GATOR GATOR 103 -granite ARCH_GRANITE GRANITE 104 consus SA1100_CONSUS CONSUS 105 aaed2000 ARCH_AAED2000 AAED2000 106 cdb89712 ARCH_CDB89712 CDB89712 107 graphicsmaster SA1100_GRAPHICSMASTER GRAPHICSMASTER 108 adsbitsy SA1100_ADSBITSY ADSBITSY 109 pxa_idp ARCH_PXA_IDP PXA_IDP 110 -plce ARCH_PLCE PLCE 111 pt_system3 SA1100_PT_SYSTEM3 PT_SYSTEM3 112 -murphy ARCH_MEDALB MEDALB 113 -eagle ARCH_EAGLE EAGLE 114 -dsc21 ARCH_DSC21 DSC21 115 -dsc24 ARCH_DSC24 DSC24 116 -ti5472 ARCH_TI5472 TI5472 117 autcpu12 ARCH_AUTCPU12 AUTCPU12 118 -uengine ARCH_UENGINE UENGINE 119 -bluestem SA1100_BLUESTEM BLUESTEM 120 -xingu8 ARCH_XINGU8 XINGU8 121 -bushstb ARCH_BUSHSTB BUSHSTB 122 -epsilon1 SA1100_EPSILON1 EPSILON1 123 -balloon SA1100_BALLOON BALLOON 124 -puppy ARCH_PUPPY PUPPY 125 -elroy SA1100_ELROY ELROY 126 -gms720 ARCH_GMS720 GMS720 127 -s24x ARCH_S24X S24X 128 -jtel_clep7312 ARCH_JTEL_CLEP7312 JTEL_CLEP7312 129 -cx821xx ARCH_CX821XX CX821XX 130 -edb7312 ARCH_EDB7312 EDB7312 131 -bsa1110 SA1100_BSA1110 BSA1110 132 -powerpin ARCH_POWERPIN POWERPIN 133 -openarm ARCH_OPENARM OPENARM 134 -whitechapel SA1100_WHITECHAPEL WHITECHAPEL 135 h3100 SA1100_H3100 H3100 136 -h3800 SA1100_H3800 H3800 137 -blue_v1 ARCH_BLUE_V1 BLUE_V1 138 -pxa_cerf ARCH_PXA_CERF PXA_CERF 139 -arm7tevb ARCH_ARM7TEVB ARM7TEVB 140 -d7400 SA1100_D7400 D7400 141 -piranha ARCH_PIRANHA PIRANHA 142 -sbcamelot SA1100_SBCAMELOT SBCAMELOT 143 -kings SA1100_KINGS KINGS 144 -smdk2400 ARCH_SMDK2400 SMDK2400 145 collie SA1100_COLLIE COLLIE 146 -idr ARCH_IDR IDR 147 badge4 SA1100_BADGE4 BADGE4 148 -webnet ARCH_WEBNET WEBNET 149 -d7300 SA1100_D7300 D7300 150 -cep SA1100_CEP CEP 151 fortunet ARCH_FORTUNET FORTUNET 152 -vc547x ARCH_VC547X VC547X 153 -filewalker SA1100_FILEWALKER FILEWALKER 154 -netgateway SA1100_NETGATEWAY NETGATEWAY 155 -symbol2800 SA1100_SYMBOL2800 SYMBOL2800 156 -suns SA1100_SUNS SUNS 157 -frodo SA1100_FRODO FRODO 158 -ms301 SA1100_MACH_TYTE_MS301 MACH_TYTE_MS301 159 mx1ads ARCH_MX1ADS MX1ADS 160 h7201 ARCH_H7201 H7201 161 h7202 ARCH_H7202 H7202 162 -amico ARCH_AMICO AMICO 163 -iam SA1100_IAM IAM 164 -tt530 SA1100_TT530 TT530 165 -sam2400 ARCH_SAM2400 SAM2400 166 -jornada56x SA1100_JORNADA56X JORNADA56X 167 -active SA1100_ACTIVE ACTIVE 168 iq80321 ARCH_IQ80321 IQ80321 169 -wid SA1100_WID WID 170 -sabinal ARCH_SABINAL SABINAL 171 -ixp425_matacumbe ARCH_IXP425_MATACUMBE IXP425_MATACUMBE 172 -miniprint SA1100_MINIPRINT MINIPRINT 173 -adm510x ARCH_ADM510X ADM510X 174 -svs200 SA1100_SVS200 SVS200 175 -atg_tcu ARCH_ATG_TCU ATG_TCU 176 -jornada820 SA1100_JORNADA820 JORNADA820 177 -s3c44b0 ARCH_S3C44B0 S3C44B0 178 -margis2 ARCH_MARGIS2 MARGIS2 179 ks8695 ARCH_KS8695 KS8695 180 -brh ARCH_BRH BRH 181 -s3c2410 ARCH_S3C2410 S3C2410 182 -possio_px30 ARCH_POSSIO_PX30 POSSIO_PX30 183 -s3c2800 ARCH_S3C2800 S3C2800 184 -fleetwood SA1100_FLEETWOOD FLEETWOOD 185 -omaha ARCH_OMAHA OMAHA 186 -ta7 ARCH_TA7 TA7 187 -nova SA1100_NOVA NOVA 188 -hmk ARCH_HMK HMK 189 -karo ARCH_KARO KARO 190 -fester SA1100_FESTER FESTER 191 -gpi ARCH_GPI GPI 192 smdk2410 ARCH_SMDK2410 SMDK2410 193 -i519 ARCH_I519 I519 194 -nexio SA1100_NEXIO NEXIO 195 -bitbox SA1100_BITBOX BITBOX 196 -g200 SA1100_G200 G200 197 -gill SA1100_GILL GILL 198 -pxa_mercury ARCH_PXA_MERCURY PXA_MERCURY 199 ceiva ARCH_CEIVA CEIVA 200 -fret SA1100_FRET FRET 201 -emailphone SA1100_EMAILPHONE EMAILPHONE 202 -h3900 ARCH_H3900 H3900 203 -pxa1 ARCH_PXA1 PXA1 204 -koan369 SA1100_KOAN369 KOAN369 205 -cogent ARCH_COGENT COGENT 206 -esl_simputer ARCH_ESL_SIMPUTER ESL_SIMPUTER 207 -esl_simputer_clr ARCH_ESL_SIMPUTER_CLR ESL_SIMPUTER_CLR 208 -esl_simputer_bw ARCH_ESL_SIMPUTER_BW ESL_SIMPUTER_BW 209 -hhp_cradle ARCH_HHP_CRADLE HHP_CRADLE 210 -he500 ARCH_HE500 HE500 211 -inhandelf2 SA1100_INHANDELF2 INHANDELF2 212 -inhandftip SA1100_INHANDFTIP INHANDFTIP 213 -dnp1110 SA1100_DNP1110 DNP1110 214 -pnp1110 SA1100_PNP1110 PNP1110 215 -csb226 ARCH_CSB226 CSB226 216 -arnold SA1100_ARNOLD ARNOLD 217 voiceblue MACH_VOICEBLUE VOICEBLUE 218 -jz8028 ARCH_JZ8028 JZ8028 219 h5400 ARCH_H5400 H5400 220 -forte SA1100_FORTE FORTE 221 -acam SA1100_ACAM ACAM 222 -abox SA1100_ABOX ABOX 223 -atmel ARCH_ATMEL ATMEL 224 -sitsang ARCH_SITSANG SITSANG 225 -cpu1110lcdnet SA1100_CPU1110LCDNET CPU1110LCDNET 226 -mpl_vcma9 ARCH_MPL_VCMA9 MPL_VCMA9 227 -opus_a1 ARCH_OPUS_A1 OPUS_A1 228 -daytona ARCH_DAYTONA DAYTONA 229 -killbear SA1100_KILLBEAR KILLBEAR 230 -yoho ARCH_YOHO YOHO 231 -jasper ARCH_JASPER JASPER 232 -dsc25 ARCH_DSC25 DSC25 233 omap_innovator MACH_OMAP_INNOVATOR OMAP_INNOVATOR 234 -mnci ARCH_RAMSES RAMSES 235 -s28x ARCH_S28X S28X 236 -mport3 ARCH_MPORT3 MPORT3 237 -pxa_eagle250 ARCH_PXA_EAGLE250 PXA_EAGLE250 238 -pdb ARCH_PDB PDB 239 -blue_2g SA1100_BLUE_2G BLUE_2G 240 -bluearch SA1100_BLUEARCH BLUEARCH 241 ixdp2400 ARCH_IXDP2400 IXDP2400 242 ixdp2800 ARCH_IXDP2800 IXDP2800 243 -explorer SA1100_EXPLORER EXPLORER 244 ixdp425 ARCH_IXDP425 IXDP425 245 -chimp ARCH_CHIMP CHIMP 246 -stork_nest ARCH_STORK_NEST STORK_NEST 247 -stork_egg ARCH_STORK_EGG STORK_EGG 248 -wismo SA1100_WISMO WISMO 249 -ezlinx ARCH_EZLINX EZLINX 250 -at91rm9200 ARCH_AT91RM9200 AT91RM9200 251 -adtech_orion ARCH_ADTECH_ORION ADTECH_ORION 252 -neptune ARCH_NEPTUNE NEPTUNE 253 hackkit SA1100_HACKKIT HACKKIT 254 -pxa_wins30 ARCH_PXA_WINS30 PXA_WINS30 255 -lavinna SA1100_LAVINNA LAVINNA 256 -pxa_uengine ARCH_PXA_UENGINE PXA_UENGINE 257 -innokom ARCH_INNOKOM INNOKOM 258 -bms ARCH_BMS BMS 259 ixcdp1100 ARCH_IXCDP1100 IXCDP1100 260 -prpmc1100 ARCH_PRPMC1100 PRPMC1100 261 at91rm9200dk ARCH_AT91RM9200DK AT91RM9200DK 262 -armstick ARCH_ARMSTICK ARMSTICK 263 -armonie ARCH_ARMONIE ARMONIE 264 -mport1 ARCH_MPORT1 MPORT1 265 -s3c5410 ARCH_S3C5410 S3C5410 266 -zcp320a ARCH_ZCP320A ZCP320A 267 -i_box ARCH_I_BOX I_BOX 268 -stlc1502 ARCH_STLC1502 STLC1502 269 -siren ARCH_SIREN SIREN 270 -greenlake ARCH_GREENLAKE GREENLAKE 271 -argus ARCH_ARGUS ARGUS 272 -combadge SA1100_COMBADGE COMBADGE 273 -rokepxa ARCH_ROKEPXA ROKEPXA 274 cintegrator ARCH_CINTEGRATOR CINTEGRATOR 275 -guidea07 ARCH_GUIDEA07 GUIDEA07 276 -tat257 ARCH_TAT257 TAT257 277 -igp2425 ARCH_IGP2425 IGP2425 278 -bluegrama ARCH_BLUEGRAMMA BLUEGRAMMA 279 -ipod ARCH_IPOD IPOD 280 -adsbitsyx ARCH_ADSBITSYX ADSBITSYX 281 -trizeps2 ARCH_TRIZEPS2 TRIZEPS2 282 viper ARCH_VIPER VIPER 283 -adsbitsyplus SA1100_ADSBITSYPLUS ADSBITSYPLUS 284 -adsagc SA1100_ADSAGC ADSAGC 285 -stp7312 ARCH_STP7312 STP7312 286 -nx_phnx MACH_NX_PHNX NX_PHNX 287 -wep_ep250 ARCH_WEP_EP250 WEP_EP250 288 -inhandelf3 ARCH_INHANDELF3 INHANDELF3 289 adi_coyote ARCH_ADI_COYOTE ADI_COYOTE 290 -iyonix ARCH_IYONIX IYONIX 291 -damicam1 ARCH_DAMICAM_SA1110 DAMICAM_SA1110 292 -meg03 ARCH_MEG03 MEG03 293 -pxa_whitechapel ARCH_PXA_WHITECHAPEL PXA_WHITECHAPEL 294 -nwsc ARCH_NWSC NWSC 295 -nwlarm ARCH_NWLARM NWLARM 296 -ixp425_mguard ARCH_IXP425_MGUARD IXP425_MGUARD 297 -pxa_netdcu4 ARCH_PXA_NETDCU4 PXA_NETDCU4 298 ixdp2401 ARCH_IXDP2401 IXDP2401 299 ixdp2801 ARCH_IXDP2801 IXDP2801 300 -zodiac ARCH_ZODIAC ZODIAC 301 -armmodul ARCH_ARMMODUL ARMMODUL 302 -ketop SA1100_KETOP KETOP 303 -av7200 ARCH_AV7200 AV7200 304 -arch_ti925 ARCH_ARCH_TI925 ARCH_TI925 305 -acq200 ARCH_ACQ200 ACQ200 306 -pt_dafit SA1100_PT_DAFIT PT_DAFIT 307 -ihba ARCH_IHBA IHBA 308 -quinque ARCH_QUINQUE QUINQUE 309 -nimbraone ARCH_NIMBRAONE NIMBRAONE 310 -nimbra29x ARCH_NIMBRA29X NIMBRA29X 311 -nimbra210 ARCH_NIMBRA210 NIMBRA210 312 -hhp_d95xx ARCH_HHP_D95XX HHP_D95XX 313 -labarm ARCH_LABARM LABARM 314 -m825xx ARCH_M825XX M825XX 315 -m7100 SA1100_M7100 M7100 316 -nipc2 ARCH_NIPC2 NIPC2 317 -fu7202 ARCH_FU7202 FU7202 318 -adsagx ARCH_ADSAGX ADSAGX 319 -pxa_pooh ARCH_PXA_POOH PXA_POOH 320 -bandon ARCH_BANDON BANDON 321 -pcm7210 ARCH_PCM7210 PCM7210 322 -nms9200 ARCH_NMS9200 NMS9200 323 -logodl ARCH_LOGODL LOGODL 324 -m7140 SA1100_M7140 M7140 325 -korebot ARCH_KOREBOT KOREBOT 326 iq31244 ARCH_IQ31244 IQ31244 327 -koan393 SA1100_KOAN393 KOAN393 328 -inhandftip3 ARCH_INHANDFTIP3 INHANDFTIP3 329 -gonzo ARCH_GONZO GONZO 330 bast ARCH_BAST BAST 331 -scanpass ARCH_SCANPASS SCANPASS 332 -ep7312_pooh ARCH_EP7312_POOH EP7312_POOH 333 -ta7s ARCH_TA7S TA7S 334 -ta7v ARCH_TA7V TA7V 335 -icarus SA1100_ICARUS ICARUS 336 -h1900 ARCH_H1900 H1900 337 -gemini SA1100_GEMINI GEMINI 338 -axim ARCH_AXIM AXIM 339 -audiotron ARCH_AUDIOTRON AUDIOTRON 340 -h2200 ARCH_H2200 H2200 341 -loox600 ARCH_LOOX600 LOOX600 342 -niop ARCH_NIOP NIOP 343 -dm310 ARCH_DM310 DM310 344 -seedpxa_c2 ARCH_SEEDPXA_C2 SEEDPXA_C2 345 -ixp4xx_mguardpci ARCH_IXP4XX_MGUARD_PCI IXP4XX_MGUARD_PCI 346 h1940 ARCH_H1940 H1940 347 -scorpio ARCH_SCORPIO SCORPIO 348 -viva ARCH_VIVA VIVA 349 -pxa_xcard ARCH_PXA_XCARD PXA_XCARD 350 -csb335 ARCH_CSB335 CSB335 351 -ixrd425 ARCH_IXRD425 IXRD425 352 -iq80315 ARCH_IQ80315 IQ80315 353 -nmp7312 ARCH_NMP7312 NMP7312 354 -cx861xx ARCH_CX861XX CX861XX 355 enp2611 ARCH_ENP2611 ENP2611 356 -xda SA1100_XDA XDA 357 -csir_ims ARCH_CSIR_IMS CSIR_IMS 358 -ixp421_dnaeeth ARCH_IXP421_DNAEETH IXP421_DNAEETH 359 -pocketserv9200 ARCH_POCKETSERV9200 POCKETSERV9200 360 -toto ARCH_TOTO TOTO 361 s3c2440 ARCH_S3C2440 S3C2440 362 -ks8695p ARCH_KS8695P KS8695P 363 -se4000 ARCH_SE4000 SE4000 364 -quadriceps ARCH_QUADRICEPS QUADRICEPS 365 -bronco ARCH_BRONCO BRONCO 366 -esl_wireless_tab ARCH_ESL_WIRELESS_TAB ESL_WIRELESS_TAB 367 -esl_sofcomp ARCH_ESL_SOFCOMP ESL_SOFCOMP 368 -s5c7375 ARCH_S5C7375 S5C7375 369 -spearhead ARCH_SPEARHEAD SPEARHEAD 370 -pantera ARCH_PANTERA PANTERA 371 -prayoglite ARCH_PRAYOGLITE PRAYOGLITE 372 gumstix ARCH_GUMSTIX GUMSTIX 373 -rcube ARCH_RCUBE RCUBE 374 -rea_olv ARCH_REA_OLV REA_OLV 375 -pxa_iphone ARCH_PXA_IPHONE PXA_IPHONE 376 -s3c3410 ARCH_S3C3410 S3C3410 377 -espd_4510b ARCH_ESPD_4510B ESPD_4510B 378 -mp1x ARCH_MP1X MP1X 379 -at91rm9200tb ARCH_AT91RM9200TB AT91RM9200TB 380 -adsvgx ARCH_ADSVGX ADSVGX 381 omap_h2 MACH_OMAP_H2 OMAP_H2 382 -pelee ARCH_PELEE PELEE 383 e740 MACH_E740 E740 384 iq80331 ARCH_IQ80331 IQ80331 385 versatile_pb ARCH_VERSATILE_PB VERSATILE_PB 387 kev7a400 MACH_KEV7A400 KEV7A400 388 lpd7a400 MACH_LPD7A400 LPD7A400 389 lpd7a404 MACH_LPD7A404 LPD7A404 390 -fujitsu_camelot ARCH_FUJITSU_CAMELOT FUJITSU_CAMELOT 391 -janus2m ARCH_JANUS2M JANUS2M 392 -embtf MACH_EMBTF EMBTF 393 -hpm MACH_HPM HPM 394 -smdk2410tk MACH_SMDK2410TK SMDK2410TK 395 -smdk2410aj MACH_SMDK2410AJ SMDK2410AJ 396 -streetracer MACH_STREETRACER STREETRACER 397 -eframe MACH_EFRAME EFRAME 398 csb337 MACH_CSB337 CSB337 399 -pxa_lark MACH_PXA_LARK PXA_LARK 400 -pxa_pnp2110 MACH_PNP2110 PNP2110 401 -tcc72x MACH_TCC72X TCC72X 402 -altair MACH_ALTAIR ALTAIR 403 -kc3 MACH_KC3 KC3 404 -sinteftd MACH_SINTEFTD SINTEFTD 405 mainstone MACH_MAINSTONE MAINSTONE 406 -aday4x MACH_ADAY4X ADAY4X 407 -lite300 MACH_LITE300 LITE300 408 -s5c7376 MACH_S5C7376 S5C7376 409 -mt02 MACH_MT02 MT02 410 -mport3s MACH_MPORT3S MPORT3S 411 -ra_alpha MACH_RA_ALPHA RA_ALPHA 412 xcep MACH_XCEP XCEP 413 arcom_vulcan MACH_ARCOM_VULCAN ARCOM_VULCAN 414 -stargate MACH_STARGATE STARGATE 415 -armadilloj MACH_ARMADILLOJ ARMADILLOJ 416 -elroy_jack MACH_ELROY_JACK ELROY_JACK 417 -backend MACH_BACKEND BACKEND 418 -s5linbox MACH_S5LINBOX S5LINBOX 419 nomadik MACH_NOMADIK NOMADIK 420 -ia_cpu_9200 MACH_IA_CPU_9200 IA_CPU_9200 421 -at91_bja1 MACH_AT91_BJA1 AT91_BJA1 422 corgi MACH_CORGI CORGI 423 poodle MACH_POODLE POODLE 424 -ten MACH_TEN TEN 425 -roverp5p MACH_ROVERP5P ROVERP5P 426 -sc2700 MACH_SC2700 SC2700 427 -ex_eagle MACH_EX_EAGLE EX_EAGLE 428 -nx_pxa12 MACH_NX_PXA12 NX_PXA12 429 -nx_pxa5 MACH_NX_PXA5 NX_PXA5 430 -blackboard2 MACH_BLACKBOARD2 BLACKBOARD2 431 -i819 MACH_I819 I819 432 -ixmb995e MACH_IXMB995E IXMB995E 433 -skyrider MACH_SKYRIDER SKYRIDER 434 -skyhawk MACH_SKYHAWK SKYHAWK 435 -enterprise MACH_ENTERPRISE ENTERPRISE 436 -dep2410 MACH_DEP2410 DEP2410 437 armcore MACH_ARMCORE ARMCORE 438 -hobbit MACH_HOBBIT HOBBIT 439 -h7210 MACH_H7210 H7210 440 -pxa_netdcu5 MACH_PXA_NETDCU5 PXA_NETDCU5 441 -acc MACH_ACC ACC 442 -esl_sarva MACH_ESL_SARVA ESL_SARVA 443 -xm250 MACH_XM250 XM250 444 -t6tc1xb MACH_T6TC1XB T6TC1XB 445 -ess710 MACH_ESS710 ESS710 446 mx31ads MACH_MX31ADS MX31ADS 447 himalaya MACH_HIMALAYA HIMALAYA 448 -bolfenk MACH_BOLFENK BOLFENK 449 -at91rm9200kr MACH_AT91RM9200KR AT91RM9200KR 450 edb9312 MACH_EDB9312 EDB9312 451 omap_generic MACH_OMAP_GENERIC OMAP_GENERIC 452 -aximx3 MACH_AXIMX3 AXIMX3 453 -eb67xdip MACH_EB67XDIP EB67XDIP 454 -webtxs MACH_WEBTXS WEBTXS 455 -hawk MACH_HAWK HAWK 456 -ccat91sbc001 MACH_CCAT91SBC001 CCAT91SBC001 457 -expresso MACH_EXPRESSO EXPRESSO 458 -h4000 MACH_H4000 H4000 459 -dino MACH_DINO DINO 460 -ml675k MACH_ML675K ML675K 461 edb9301 MACH_EDB9301 EDB9301 462 edb9315 MACH_EDB9315 EDB9315 463 -reciva_tt MACH_RECIVA_TT RECIVA_TT 464 -cstcb01 MACH_CSTCB01 CSTCB01 465 -cstcb1 MACH_CSTCB1 CSTCB1 466 -shadwell MACH_SHADWELL SHADWELL 467 -goepel263 MACH_GOEPEL263 GOEPEL263 468 -acq100 MACH_ACQ100 ACQ100 469 -mx1fs2 MACH_MX1FS2 MX1FS2 470 -hiptop_g1 MACH_HIPTOP_G1 HIPTOP_G1 471 -sparky MACH_SPARKY SPARKY 472 -ns9750 MACH_NS9750 NS9750 473 -phoenix MACH_PHOENIX PHOENIX 474 vr1000 MACH_VR1000 VR1000 475 -deisterpxa MACH_DEISTERPXA DEISTERPXA 476 -bcm1160 MACH_BCM1160 BCM1160 477 -pcm022 MACH_PCM022 PCM022 478 -adsgcx MACH_ADSGCX ADSGCX 479 -dreadnaught MACH_DREADNAUGHT DREADNAUGHT 480 -dm320 MACH_DM320 DM320 481 -markov MACH_MARKOV MARKOV 482 -cos7a400 MACH_COS7A400 COS7A400 483 -milano MACH_MILANO MILANO 484 -ue9328 MACH_UE9328 UE9328 485 -uex255 MACH_UEX255 UEX255 486 -ue2410 MACH_UE2410 UE2410 487 -a620 MACH_A620 A620 488 -ocelot MACH_OCELOT OCELOT 489 -cheetah MACH_CHEETAH CHEETAH 490 omap_perseus2 MACH_OMAP_PERSEUS2 OMAP_PERSEUS2 491 -zvue MACH_ZVUE ZVUE 492 -roverp1 MACH_ROVERP1 ROVERP1 493 -asidial2 MACH_ASIDIAL2 ASIDIAL2 494 -s3c24a0 MACH_S3C24A0 S3C24A0 495 e800 MACH_E800 E800 496 e750 MACH_E750 E750 497 -s3c5500 MACH_S3C5500 S3C5500 498 -smdk5500 MACH_SMDK5500 SMDK5500 499 -signalsync MACH_SIGNALSYNC SIGNALSYNC 500 -nbc MACH_NBC NBC 501 -kodiak MACH_KODIAK KODIAK 502 -netbookpro MACH_NETBOOKPRO NETBOOKPRO 503 -hw90200 MACH_HW90200 HW90200 504 -condor MACH_CONDOR CONDOR 505 -cup MACH_CUP CUP 506 -kite MACH_KITE KITE 507 scb9328 MACH_SCB9328 SCB9328 508 omap_h3 MACH_OMAP_H3 OMAP_H3 509 omap_h4 MACH_OMAP_H4 OMAP_H4 510 -n10 MACH_N10 N10 511 -montejade MACH_MONTAJADE MONTAJADE 512 -sg560 MACH_SG560 SG560 513 -dp1000 MACH_DP1000 DP1000 514 omap_osk MACH_OMAP_OSK OMAP_OSK 515 -rg100v3 MACH_RG100V3 RG100V3 516 -mx2ads MACH_MX2ADS MX2ADS 517 -pxa_kilo MACH_PXA_KILO PXA_KILO 518 -ixp4xx_eagle MACH_IXP4XX_EAGLE IXP4XX_EAGLE 519 tosa MACH_TOSA TOSA 520 -mb2520f MACH_MB2520F MB2520F 521 -emc1000 MACH_EMC1000 EMC1000 522 -tidsc25 MACH_TIDSC25 TIDSC25 523 -akcpmxl MACH_AKCPMXL AKCPMXL 524 -av3xx MACH_AV3XX AV3XX 525 avila MACH_AVILA AVILA 526 -pxa_mpm10 MACH_PXA_MPM10 PXA_MPM10 527 -pxa_kyanite MACH_PXA_KYANITE PXA_KYANITE 528 -sgold MACH_SGOLD SGOLD 529 -oscar MACH_OSCAR OSCAR 530 -epxa4usb2 MACH_EPXA4USB2 EPXA4USB2 531 -xsengine MACH_XSENGINE XSENGINE 532 -ip600 MACH_IP600 IP600 533 -mcan2 MACH_MCAN2 MCAN2 534 -ddi_blueridge MACH_DDI_BLUERIDGE DDI_BLUERIDGE 535 -skyminder MACH_SKYMINDER SKYMINDER 536 -lpd79520 MACH_LPD79520 LPD79520 537 edb9302 MACH_EDB9302 EDB9302 538 -hw90340 MACH_HW90340 HW90340 539 -cip_box MACH_CIP_BOX CIP_BOX 540 -ivpn MACH_IVPN IVPN 541 -rsoc2 MACH_RSOC2 RSOC2 542 husky MACH_HUSKY HUSKY 543 -boxer MACH_BOXER BOXER 544 shepherd MACH_SHEPHERD SHEPHERD 545 -aml42800aa MACH_AML42800AA AML42800AA 546 -lpc2294 MACH_LPC2294 LPC2294 548 -switchgrass MACH_SWITCHGRASS SWITCHGRASS 549 -ens_cmu MACH_ENS_CMU ENS_CMU 550 -mm6_sdb MACH_MM6_SDB MM6_SDB 551 -saturn MACH_SATURN SATURN 552 -i30030evb MACH_I30030EVB I30030EVB 553 -mxc27530evb MACH_MXC27530EVB MXC27530EVB 554 -smdk2800 MACH_SMDK2800 SMDK2800 555 -mtwilson MACH_MTWILSON MTWILSON 556 -ziti MACH_ZITI ZITI 557 -grandfather MACH_GRANDFATHER GRANDFATHER 558 -tengine MACH_TENGINE TENGINE 559 -s3c2460 MACH_S3C2460 S3C2460 560 -pdm MACH_PDM PDM 561 h4700 MACH_H4700 H4700 562 -h6300 MACH_H6300 H6300 563 -rz1700 MACH_RZ1700 RZ1700 564 -a716 MACH_A716 A716 565 -estk2440a MACH_ESTK2440A ESTK2440A 566 -atwixp425 MACH_ATWIXP425 ATWIXP425 567 -csb336 MACH_CSB336 CSB336 568 -rirm2 MACH_RIRM2 RIRM2 569 -cx23518 MACH_CX23518 CX23518 570 -cx2351x MACH_CX2351X CX2351X 571 -computime MACH_COMPUTIME COMPUTIME 572 -izarus MACH_IZARUS IZARUS 573 -pxa_rts MACH_RTS RTS 574 -se5100 MACH_SE5100 SE5100 575 -s3c2510 MACH_S3C2510 S3C2510 576 -csb437tl MACH_CSB437TL CSB437TL 577 -slauson MACH_SLAUSON SLAUSON 578 -pearlriver MACH_PEARLRIVER PEARLRIVER 579 -tdc_p210 MACH_TDC_P210 TDC_P210 580 -sg580 MACH_SG580 SG580 581 -wrsbcarm7 MACH_WRSBCARM7 WRSBCARM7 582 -ipd MACH_IPD IPD 583 -pxa_dnp2110 MACH_PXA_DNP2110 PXA_DNP2110 584 -xaeniax MACH_XAENIAX XAENIAX 585 -somn4250 MACH_SOMN4250 SOMN4250 586 -pleb2 MACH_PLEB2 PLEB2 587 -cornwallis MACH_CORNWALLIS CORNWALLIS 588 -gurney_drv MACH_GURNEY_DRV GURNEY_DRV 589 -chaffee MACH_CHAFFEE CHAFFEE 590 -rms101 MACH_RMS101 RMS101 591 rx3715 MACH_RX3715 RX3715 592 -swift MACH_SWIFT SWIFT 593 -roverp7 MACH_ROVERP7 ROVERP7 594 -pr818s MACH_PR818S PR818S 595 -trxpro MACH_TRXPRO TRXPRO 596 nslu2 MACH_NSLU2 NSLU2 597 e400 MACH_E400 E400 598 -trab MACH_TRAB TRAB 599 -cmc_pu2 MACH_CMC_PU2 CMC_PU2 600 -fulcrum MACH_FULCRUM FULCRUM 601 -netgate42x MACH_NETGATE42X NETGATE42X 602 -str710 MACH_STR710 STR710 603 ixdpg425 MACH_IXDPG425 IXDPG425 604 -tomtomgo MACH_TOMTOMGO TOMTOMGO 605 versatile_ab MACH_VERSATILE_AB VERSATILE_AB 606 edb9307 MACH_EDB9307 EDB9307 607 -sg565 MACH_SG565 SG565 608 -lpd79524 MACH_LPD79524 LPD79524 609 -lpd79525 MACH_LPD79525 LPD79525 610 -rms100 MACH_RMS100 RMS100 611 kb9200 MACH_KB9200 KB9200 612 sx1 MACH_SX1 SX1 613 -hms39c7092 MACH_HMS39C7092 HMS39C7092 614 -armadillo MACH_ARMADILLO ARMADILLO 615 -ipcu MACH_IPCU IPCU 616 -loox720 MACH_LOOX720 LOOX720 617 ixdp465 MACH_IXDP465 IXDP465 618 ixdp2351 MACH_IXDP2351 IXDP2351 619 -adsvix MACH_ADSVIX ADSVIX 620 -dm270 MACH_DM270 DM270 621 -socltplus MACH_SOCLTPLUS SOCLTPLUS 622 -ecia MACH_ECIA ECIA 623 -cm4008 MACH_CM4008 CM4008 624 -p2001 MACH_P2001 P2001 625 -twister MACH_TWISTER TWISTER 626 -mudshark MACH_MUDSHARK MUDSHARK 627 -hb2 MACH_HB2 HB2 628 iq80332 MACH_IQ80332 IQ80332 629 -sendt MACH_SENDT SENDT 630 -mx2jazz MACH_MX2JAZZ MX2JAZZ 631 -multiio MACH_MULTIIO MULTIIO 632 -hrdisplay MACH_HRDISPLAY HRDISPLAY 633 -mxc27530ads MACH_MXC27530ADS MXC27530ADS 634 -trizeps3 MACH_TRIZEPS3 TRIZEPS3 635 -zefeerdza MACH_ZEFEERDZA ZEFEERDZA 636 -zefeerdzb MACH_ZEFEERDZB ZEFEERDZB 637 -zefeerdzg MACH_ZEFEERDZG ZEFEERDZG 638 -zefeerdzn MACH_ZEFEERDZN ZEFEERDZN 639 -zefeerdzq MACH_ZEFEERDZQ ZEFEERDZQ 640 gtwx5715 MACH_GTWX5715 GTWX5715 641 -astro_jack MACH_ASTRO_JACK ASTRO_JACK 643 -tip03 MACH_TIP03 TIP03 644 -a9200ec MACH_A9200EC A9200EC 645 -pnx0105 MACH_PNX0105 PNX0105 646 -adcpoecpu MACH_ADCPOECPU ADCPOECPU 647 csb637 MACH_CSB637 CSB637 648 -mb9200 MACH_MB9200 MB9200 650 -kulun MACH_KULUN KULUN 651 -snapper MACH_SNAPPER SNAPPER 652 -optima MACH_OPTIMA OPTIMA 653 -dlhsbc MACH_DLHSBC DLHSBC 654 -x30 MACH_X30 X30 655 n30 MACH_N30 N30 656 -manga_ks8695 MACH_MANGA_KS8695 MANGA_KS8695 657 -ajax MACH_AJAX AJAX 658 nec_mp900 MACH_NEC_MP900 NEC_MP900 659 -vvtk1000 MACH_VVTK1000 VVTK1000 661 kafa MACH_KAFA KAFA 662 -vvtk3000 MACH_VVTK3000 VVTK3000 663 -pimx1 MACH_PIMX1 PIMX1 664 -ollie MACH_OLLIE OLLIE 665 -skymax MACH_SKYMAX SKYMAX 666 -jazz MACH_JAZZ JAZZ 667 -tel_t3 MACH_TEL_T3 TEL_T3 668 -aisino_fcr255 MACH_AISINO_FCR255 AISINO_FCR255 669 -btweb MACH_BTWEB BTWEB 670 -dbg_lh79520 MACH_DBG_LH79520 DBG_LH79520 671 -cm41xx MACH_CM41XX CM41XX 672 ts72xx MACH_TS72XX TS72XX 673 -nggpxa MACH_NGGPXA NGGPXA 674 -csb535 MACH_CSB535 CSB535 675 -csb536 MACH_CSB536 CSB536 676 -pxa_trakpod MACH_PXA_TRAKPOD PXA_TRAKPOD 677 -praxis MACH_PRAXIS PRAXIS 678 -lh75411 MACH_LH75411 LH75411 679 otom MACH_OTOM OTOM 680 nexcoder_2440 MACH_NEXCODER_2440 NEXCODER_2440 681 -loox410 MACH_LOOX410 LOOX410 682 -westlake MACH_WESTLAKE WESTLAKE 683 -nsb MACH_NSB NSB 684 -esl_sarva_stn MACH_ESL_SARVA_STN ESL_SARVA_STN 685 -esl_sarva_tft MACH_ESL_SARVA_TFT ESL_SARVA_TFT 686 -esl_sarva_iad MACH_ESL_SARVA_IAD ESL_SARVA_IAD 687 -esl_sarva_acc MACH_ESL_SARVA_ACC ESL_SARVA_ACC 688 -typhoon MACH_TYPHOON TYPHOON 689 -cnav MACH_CNAV CNAV 690 -a730 MACH_A730 A730 691 -netstar MACH_NETSTAR NETSTAR 692 -supercon MACH_PHASEFALE_SUPERCON PHASEFALE_SUPERCON 693 -shiva1100 MACH_SHIVA1100 SHIVA1100 694 -etexsc MACH_ETEXSC ETEXSC 695 -ixdpg465 MACH_IXDPG465 IXDPG465 696 -a9m2410 MACH_A9M2410 A9M2410 697 -a9m2440 MACH_A9M2440 A9M2440 698 -a9m9750 MACH_A9M9750 A9M9750 699 -a9m9360 MACH_A9M9360 A9M9360 700 -unc90 MACH_UNC90 UNC90 701 eco920 MACH_ECO920 ECO920 702 -satview MACH_SATVIEW SATVIEW 703 roadrunner MACH_ROADRUNNER ROADRUNNER 704 at91rm9200ek MACH_AT91RM9200EK AT91RM9200EK 705 -gp32 MACH_GP32 GP32 706 -gem MACH_GEM GEM 707 -i858 MACH_I858 I858 708 -hx2750 MACH_HX2750 HX2750 709 -mxc91131evb MACH_MXC91131EVB MXC91131EVB 710 -p700 MACH_P700 P700 711 -cpe MACH_CPE CPE 712 spitz MACH_SPITZ SPITZ 713 -nimbra340 MACH_NIMBRA340 NIMBRA340 714 -lpc22xx MACH_LPC22XX LPC22XX 715 -omap_comet3 MACH_COMET3 COMET3 716 -omap_comet4 MACH_COMET4 COMET4 717 -csb625 MACH_CSB625 CSB625 718 -fortunet2 MACH_FORTUNET2 FORTUNET2 719 -s5h2200 MACH_S5H2200 S5H2200 720 -optorm920 MACH_OPTORM920 OPTORM920 721 -adsbitsyxb MACH_ADSBITSYXB ADSBITSYXB 722 adssphere MACH_ADSSPHERE ADSSPHERE 723 -adsportal MACH_ADSPORTAL ADSPORTAL 724 -ln2410sbc MACH_LN2410SBC LN2410SBC 725 -cb3rufc MACH_CB3RUFC CB3RUFC 726 -mp2usb MACH_MP2USB MP2USB 727 -ntnp425c MACH_NTNP425C NTNP425C 728 colibri MACH_COLIBRI COLIBRI 729 -pcm7220 MACH_PCM7220 PCM7220 730 gateway7001 MACH_GATEWAY7001 GATEWAY7001 731 pcm027 MACH_PCM027 PCM027 732 -cmpxa MACH_CMPXA CMPXA 733 anubis MACH_ANUBIS ANUBIS 734 -ite8152 MACH_ITE8152 ITE8152 735 -lpc3xxx MACH_LPC3XXX LPC3XXX 736 -puppeteer MACH_PUPPETEER PUPPETEER 737 -e570 MACH_E570 E570 739 -x50 MACH_X50 X50 740 -recon MACH_RECON RECON 741 -xboardgp8 MACH_XBOARDGP8 XBOARDGP8 742 -fpic2 MACH_FPIC2 FPIC2 743 akita MACH_AKITA AKITA 744 -a81 MACH_A81 A81 745 -svm_sc25x MACH_SVM_SC25X SVM_SC25X 746 -vt020 MACH_VADATECH020 VADATECH020 747 -tli MACH_TLI TLI 748 -edb9315lc MACH_EDB9315LC EDB9315LC 749 -passec MACH_PASSEC PASSEC 750 -ds_tiger MACH_DS_TIGER DS_TIGER 751 -e310 MACH_E310 E310 752 e330 MACH_E330 E330 753 -rt3000 MACH_RT3000 RT3000 754 nokia770 MACH_NOKIA770 NOKIA770 755 -pnx0106 MACH_PNX0106 PNX0106 756 -hx21xx MACH_HX21XX HX21XX 757 -faraday MACH_FARADAY FARADAY 758 -sbc9312 MACH_SBC9312 SBC9312 759 -batman MACH_BATMAN BATMAN 760 -jpd201 MACH_JPD201 JPD201 761 -mipsa MACH_MIPSA MIPSA 762 -kacom MACH_KACOM KACOM 763 -swarcocpu MACH_SWARCOCPU SWARCOCPU 764 -swarcodsl MACH_SWARCODSL SWARCODSL 765 -blueangel MACH_BLUEANGEL BLUEANGEL 766 -hairygrama MACH_HAIRYGRAMA HAIRYGRAMA 767 -banff MACH_BANFF BANFF 768 carmeva MACH_CARMEVA CARMEVA 769 -sam255 MACH_SAM255 SAM255 770 -ppm10 MACH_PPM10 PPM10 771 edb9315a MACH_EDB9315A EDB9315A 772 -sunset MACH_SUNSET SUNSET 773 stargate2 MACH_STARGATE2 STARGATE2 774 intelmote2 MACH_INTELMOTE2 INTELMOTE2 775 trizeps4 MACH_TRIZEPS4 TRIZEPS4 776 -mainstone2 MACH_MAINSTONE2 MAINSTONE2 777 -ez_ixp42x MACH_EZ_IXP42X EZ_IXP42X 778 -tapwave_zodiac MACH_TAPWAVE_ZODIAC TAPWAVE_ZODIAC 779 -universalmeter MACH_UNIVERSALMETER UNIVERSALMETER 780 -hicoarm9 MACH_HICOARM9 HICOARM9 781 pnx4008 MACH_PNX4008 PNX4008 782 -kws6000 MACH_KWS6000 KWS6000 783 -portux920t MACH_PORTUX920T PORTUX920T 784 -ez_x5 MACH_EZ_X5 EZ_X5 785 -omap_rudolph MACH_OMAP_RUDOLPH OMAP_RUDOLPH 786 cpuat91 MACH_CPUAT91 CPUAT91 787 -rea9200 MACH_REA9200 REA9200 788 -acts_pune_sa1110 MACH_ACTS_PUNE_SA1110 ACTS_PUNE_SA1110 789 -ixp425 MACH_IXP425 IXP425 790 -i30030ads MACH_I30030ADS I30030ADS 791 -perch MACH_PERCH PERCH 792 -eis05r1 MACH_EIS05R1 EIS05R1 793 -pepperpad MACH_PEPPERPAD PEPPERPAD 794 -sb3010 MACH_SB3010 SB3010 795 -rm9200 MACH_RM9200 RM9200 796 -dma03 MACH_DMA03 DMA03 797 -road_s101 MACH_ROAD_S101 ROAD_S101 798 iq81340sc MACH_IQ81340SC IQ81340SC 799 -iq_nextgen_b MACH_IQ_NEXTGEN_B IQ_NEXTGEN_B 800 iq81340mc MACH_IQ81340MC IQ81340MC 801 -iq_nextgen_d MACH_IQ_NEXTGEN_D IQ_NEXTGEN_D 802 -iq_nextgen_e MACH_IQ_NEXTGEN_E IQ_NEXTGEN_E 803 -mallow_at91 MACH_MALLOW_AT91 MALLOW_AT91 804 -cybertracker_i MACH_CYBERTRACKER_I CYBERTRACKER_I 805 -gesbc931x MACH_GESBC931X GESBC931X 806 -centipad MACH_CENTIPAD CENTIPAD 807 -armsoc MACH_ARMSOC ARMSOC 808 -se4200 MACH_SE4200 SE4200 809 -ems197a MACH_EMS197A EMS197A 810 micro9 MACH_MICRO9 MICRO9 811 micro9l MACH_MICRO9L MICRO9L 812 -uc5471dsp MACH_UC5471DSP UC5471DSP 813 -sj5471eng MACH_SJ5471ENG SJ5471ENG 814 -none MACH_CMPXA26X CMPXA26X 815 -nc1 MACH_NC NC 816 omap_palmte MACH_OMAP_PALMTE OMAP_PALMTE 817 -ajax52x MACH_AJAX52X AJAX52X 818 -siriustar MACH_SIRIUSTAR SIRIUSTAR 819 -iodata_hdlg MACH_IODATA_HDLG IODATA_HDLG 820 -at91rm9200utl MACH_AT91RM9200UTL AT91RM9200UTL 821 -biosafe MACH_BIOSAFE BIOSAFE 822 -mp1000 MACH_MP1000 MP1000 823 -parsy MACH_PARSY PARSY 824 -ccxp270 MACH_CCXP CCXP 825 -omap_gsample MACH_OMAP_GSAMPLE OMAP_GSAMPLE 826 realview_eb MACH_REALVIEW_EB REALVIEW_EB 827 -samoa MACH_SAMOA SAMOA 828 -palmt3 MACH_PALMT3 PALMT3 829 -i878 MACH_I878 I878 830 borzoi MACH_BORZOI BORZOI 831 -gecko MACH_GECKO GECKO 832 -ds101 MACH_DS101 DS101 833 -omap_palmtt2 MACH_OMAP_PALMTT2 OMAP_PALMTT2 834 palmld MACH_PALMLD PALMLD 835 -cc9c MACH_CC9C CC9C 836 -sbc1670 MACH_SBC1670 SBC1670 837 ixdp28x5 MACH_IXDP28X5 IXDP28X5 838 omap_palmtt MACH_OMAP_PALMTT OMAP_PALMTT 839 -ml696k MACH_ML696K ML696K 840 arcom_zeus MACH_ARCOM_ZEUS ARCOM_ZEUS 841 osiris MACH_OSIRIS OSIRIS 842 -maestro MACH_MAESTRO MAESTRO 843 palmte2 MACH_PALMTE2 PALMTE2 844 -ixbbm MACH_IXBBM IXBBM 845 mx27ads MACH_MX27ADS MX27ADS 846 -ax8004 MACH_AX8004 AX8004 847 at91sam9261ek MACH_AT91SAM9261EK AT91SAM9261EK 848 loft MACH_LOFT LOFT 849 -magpie MACH_MAGPIE MAGPIE 850 mx21ads MACH_MX21ADS MX21ADS 851 -mb87m3400 MACH_MB87M3400 MB87M3400 852 -mguard_delta MACH_MGUARD_DELTA MGUARD_DELTA 853 -davinci_dvdp MACH_DAVINCI_DVDP DAVINCI_DVDP 854 -htcuniversal MACH_HTCUNIVERSAL HTCUNIVERSAL 855 -tpad MACH_TPAD TPAD 856 -roverp3 MACH_ROVERP3 ROVERP3 857 -jornada928 MACH_JORNADA928 JORNADA928 858 -mv88fxx81 MACH_MV88FXX81 MV88FXX81 859 -stmp36xx MACH_STMP36XX STMP36XX 860 -sxni79524 MACH_SXNI79524 SXNI79524 861 ams_delta MACH_AMS_DELTA AMS_DELTA 862 -uranium MACH_URANIUM URANIUM 863 -ucon MACH_UCON UCON 864 nas100d MACH_NAS100D NAS100D 865 -l083 MACH_L083_1000 L083_1000 866 -ezx MACH_EZX EZX 867 -pnx5220 MACH_PNX5220 PNX5220 868 -butte MACH_BUTTE BUTTE 869 -srm2 MACH_SRM2 SRM2 870 -dsbr MACH_DSBR DSBR 871 -crystalball MACH_CRYSTALBALL CRYSTALBALL 872 -tinypxa27x MACH_TINYPXA27X TINYPXA27X 873 -herbie MACH_HERBIE HERBIE 874 magician MACH_MAGICIAN MAGICIAN 875 -cm4002 MACH_CM4002 CM4002 876 -b4 MACH_B4 B4 877 -maui MACH_MAUI MAUI 878 -cybertracker_g MACH_CYBERTRACKER_G CYBERTRACKER_G 879 nxdkn MACH_NXDKN NXDKN 880 -mio8390 MACH_MIO8390 MIO8390 881 -omi_board MACH_OMI_BOARD OMI_BOARD 882 -mx21civ MACH_MX21CIV MX21CIV 883 -mahi_cdac MACH_MAHI_CDAC MAHI_CDAC 884 palmtx MACH_PALMTX PALMTX 885 s3c2413 MACH_S3C2413 S3C2413 887 -samsys_ep0 MACH_SAMSYS_EP0 SAMSYS_EP0 888 -wg302v1 MACH_WG302V1 WG302V1 889 wg302v2 MACH_WG302V2 WG302V2 890 -eb42x MACH_EB42X EB42X 891 -iq331es MACH_IQ331ES IQ331ES 892 -cosydsp MACH_COSYDSP COSYDSP 893 -uplat7d_proto MACH_UPLAT7D UPLAT7D 894 -ptdavinci MACH_PTDAVINCI PTDAVINCI 895 -mbus MACH_MBUS MBUS 896 -nadia2vb MACH_NADIA2VB NADIA2VB 897 -r1000 MACH_R1000 R1000 898 -hw90250 MACH_HW90250 HW90250 899 omap_2430sdp MACH_OMAP_2430SDP OMAP_2430SDP 900 davinci_evm MACH_DAVINCI_EVM DAVINCI_EVM 901 -omap_tornado MACH_OMAP_TORNADO OMAP_TORNADO 902 -olocreek MACH_OLOCREEK OLOCREEK 903 palmz72 MACH_PALMZ72 PALMZ72 904 nxdb500 MACH_NXDB500 NXDB500 905 -apf9328 MACH_APF9328 APF9328 906 -omap_wipoq MACH_OMAP_WIPOQ OMAP_WIPOQ 907 -omap_twip MACH_OMAP_TWIP OMAP_TWIP 908 -treo650 MACH_TREO650 TREO650 909 -acumen MACH_ACUMEN ACUMEN 910 -xp100 MACH_XP100 XP100 911 -fs2410 MACH_FS2410 FS2410 912 -pxa270_cerf MACH_PXA270_CERF PXA270_CERF 913 -sq2ftlpalm MACH_SQ2FTLPALM SQ2FTLPALM 914 -bsemserver MACH_BSEMSERVER BSEMSERVER 915 -netclient MACH_NETCLIENT NETCLIENT 916 palmt5 MACH_PALMT5 PALMT5 917 palmtc MACH_PALMTC PALMTC 918 omap_apollon MACH_OMAP_APOLLON OMAP_APOLLON 919 -mxc30030evb MACH_MXC30030EVB MXC30030EVB 920 -rea_cpu2 MACH_REA_2D REA_2D 921 -eti3e524 MACH_TI3E524 TI3E524 922 ateb9200 MACH_ATEB9200 ATEB9200 923 -auckland MACH_AUCKLAND AUCKLAND 924 -ak3220m MACH_AK3320M AK3320M 925 -duramax MACH_DURAMAX DURAMAX 926 n35 MACH_N35 N35 927 -pronghorn MACH_PRONGHORN PRONGHORN 928 -fundy MACH_FUNDY FUNDY 929 logicpd_pxa270 MACH_LOGICPD_PXA270 LOGICPD_PXA270 930 -cpu777 MACH_CPU777 CPU777 931 -simicon9201 MACH_SIMICON9201 SIMICON9201 932 -leap2_hpm MACH_LEAP2_HPM LEAP2_HPM 933 -cm922txa10 MACH_CM922TXA10 CM922TXA10 934 -sandgate MACH_PXA PXA 935 -sandgate2 MACH_SANDGATE2 SANDGATE2 936 -sandgate2g MACH_SANDGATE2G SANDGATE2G 937 -sandgate2p MACH_SANDGATE2P SANDGATE2P 938 -fred_jack MACH_FRED_JACK FRED_JACK 939 -ttg_color1 MACH_TTG_COLOR1 TTG_COLOR1 940 nxeb500hmi MACH_NXEB500HMI NXEB500HMI 941 -netdcu8 MACH_NETDCU8 NETDCU8 942 -ng_fvx538 MACH_NG_FVX538 NG_FVX538 944 -ng_fvs338 MACH_NG_FVS338 NG_FVS338 945 -pnx4103 MACH_PNX4103 PNX4103 946 -hesdb MACH_HESDB HESDB 947 -xsilo MACH_XSILO XSILO 948 espresso MACH_ESPRESSO ESPRESSO 949 -emlc MACH_EMLC EMLC 950 -sisteron MACH_SISTERON SISTERON 951 rx1950 MACH_RX1950 RX1950 952 -tsc_venus MACH_TSC_VENUS TSC_VENUS 953 -ds101j MACH_DS101J DS101J 954 -mxc30030ads MACH_MXC30030ADS MXC30030ADS 955 -fujitsu_wimaxsoc MACH_FUJITSU_WIMAXSOC FUJITSU_WIMAXSOC 956 -dualpcmodem MACH_DUALPCMODEM DUALPCMODEM 957 gesbc9312 MACH_GESBC9312 GESBC9312 958 -htcapache MACH_HTCAPACHE HTCAPACHE 959 -ixdp435 MACH_IXDP435 IXDP435 960 -catprovt100 MACH_CATPROVT100 CATPROVT100 961 -picotux1xx MACH_PICOTUX1XX PICOTUX1XX 962 picotux2xx MACH_PICOTUX2XX PICOTUX2XX 963 dsmg600 MACH_DSMG600 DSMG600 964 -empc2 MACH_EMPC2 EMPC2 965 -ventura MACH_VENTURA VENTURA 966 -phidget_sbc MACH_PHIDGET_SBC PHIDGET_SBC 967 -ij3k MACH_IJ3K IJ3K 968 -pisgah MACH_PISGAH PISGAH 969 omap_fsample MACH_OMAP_FSAMPLE OMAP_FSAMPLE 970 -sg720 MACH_SG720 SG720 971 -redfox MACH_REDFOX REDFOX 972 -mysh_ep9315_1 MACH_MYSH_EP9315_1 MYSH_EP9315_1 973 -tpf106 MACH_TPF106 TPF106 974 -at91rm9200kg MACH_AT91RM9200KG AT91RM9200KG 975 -rcmt2 MACH_SLEDB SLEDB 976 -ontrack MACH_ONTRACK ONTRACK 977 -pm1200 MACH_PM1200 PM1200 978 -ess24562 MACH_ESS24XXX ESS24XXX 979 -coremp7 MACH_COREMP7 COREMP7 980 -nexcoder_6446 MACH_NEXCODER_6446 NEXCODER_6446 981 -stvc8380 MACH_STVC8380 STVC8380 982 -teklynx MACH_TEKLYNX TEKLYNX 983 -carbonado MACH_CARBONADO CARBONADO 984 -sysmos_mp730 MACH_SYSMOS_MP730 SYSMOS_MP730 985 snapper_cl15 MACH_SNAPPER_CL15 SNAPPER_CL15 986 -pgigim MACH_PGIGIM PGIGIM 987 -ptx9160p2 MACH_PTX9160P2 PTX9160P2 988 -dcore1 MACH_DCORE1 DCORE1 989 -victorpxa MACH_VICTORPXA VICTORPXA 990 -mx2dtb MACH_MX2DTB MX2DTB 991 -pxa_irex_er0100 MACH_PXA_IREX_ER0100 PXA_IREX_ER0100 992 omap_palmz71 MACH_OMAP_PALMZ71 OMAP_PALMZ71 993 -bartec_deg MACH_BARTEC_DEG BARTEC_DEG 994 -hw50251 MACH_HW50251 HW50251 995 -ibox MACH_IBOX IBOX 996 -atlaslh7a404 MACH_ATLASLH7A404 ATLASLH7A404 997 -pt2026 MACH_PT2026 PT2026 998 -htcalpine MACH_HTCALPINE HTCALPINE 999 -bartec_vtu MACH_BARTEC_VTU BARTEC_VTU 1000 -vcoreii MACH_VCOREII VCOREII 1001 -pdnb3 MACH_PDNB3 PDNB3 1002 -htcbeetles MACH_HTCBEETLES HTCBEETLES 1003 -s3c6400 MACH_S3C6400 S3C6400 1004 -s3c2443 MACH_S3C2443 S3C2443 1005 -omap_ldk MACH_OMAP_LDK OMAP_LDK 1006 -smdk2460 MACH_SMDK2460 SMDK2460 1007 -smdk2440 MACH_SMDK2440 SMDK2440 1008 smdk2412 MACH_SMDK2412 SMDK2412 1009 -webbox MACH_WEBBOX WEBBOX 1010 -cwwndp MACH_CWWNDP CWWNDP 1011 -i839 MACH_DRAGON DRAGON 1012 -opendo_cpu_board MACH_OPENDO_CPU_BOARD OPENDO_CPU_BOARD 1013 -ccm2200 MACH_CCM2200 CCM2200 1014 -etwarm MACH_ETWARM ETWARM 1015 -m93030 MACH_M93030 M93030 1016 -cc7u MACH_CC7U CC7U 1017 -mtt_ranger MACH_MTT_RANGER MTT_RANGER 1018 -nexus MACH_NEXUS NEXUS 1019 -desman MACH_DESMAN DESMAN 1020 -bkde303 MACH_BKDE303 BKDE303 1021 smdk2413 MACH_SMDK2413 SMDK2413 1022 -aml_m7200 MACH_AML_M7200 AML_M7200 1023 aml_m5900 MACH_AML_M5900 AML_M5900 1024 -sg640 MACH_SG640 SG640 1025 -edg79524 MACH_EDG79524 EDG79524 1026 -ai2410 MACH_AI2410 AI2410 1027 -ixp465 MACH_IXP465 IXP465 1028 balloon3 MACH_BALLOON3 BALLOON3 1029 -heins MACH_HEINS HEINS 1030 -mpluseva MACH_MPLUSEVA MPLUSEVA 1031 -rt042 MACH_RT042 RT042 1032 -cwiem MACH_CWIEM CWIEM 1033 -cm_x270 MACH_CM_X270 CM_X270 1034 -cm_x255 MACH_CM_X255 CM_X255 1035 -esh_at91 MACH_ESH_AT91 ESH_AT91 1036 -sandgate3 MACH_SANDGATE3 SANDGATE3 1037 -primo MACH_PRIMO PRIMO 1038 -gemstone MACH_GEMSTONE GEMSTONE 1039 -pronghorn_metro MACH_PRONGHORNMETRO PRONGHORNMETRO 1040 -sidewinder MACH_SIDEWINDER SIDEWINDER 1041 -picomod1 MACH_PICOMOD1 PICOMOD1 1042 -sg590 MACH_SG590 SG590 1043 -akai9307 MACH_AKAI9307 AKAI9307 1044 -fontaine MACH_FONTAINE FONTAINE 1045 -wombat MACH_WOMBAT WOMBAT 1046 -acq300 MACH_ACQ300 ACQ300 1047 -mod272 MACH_MOD_270 MOD_270 1048 -vmc_vc0820 MACH_VC0820 VC0820 1049 -ani_aim MACH_ANI_AIM ANI_AIM 1050 -jellyfish MACH_JELLYFISH JELLYFISH 1051 -amanita MACH_AMANITA AMANITA 1052 -vlink MACH_VLINK VLINK 1053 -dexflex MACH_DEXFLEX DEXFLEX 1054 -eigen_ttq MACH_EIGEN_TTQ EIGEN_TTQ 1055 -arcom_titan MACH_ARCOM_TITAN ARCOM_TITAN 1056 -tabla MACH_TABLA TABLA 1057 -mdirac3 MACH_MDIRAC3 MDIRAC3 1058 -mrhfbp2 MACH_MRHFBP2 MRHFBP2 1059 -at91rm9200rb MACH_AT91RM9200RB AT91RM9200RB 1060 -ani_apm MACH_ANI_APM ANI_APM 1061 -ella1 MACH_ELLA1 ELLA1 1062 -inhand_pxa27x MACH_INHAND_PXA27X INHAND_PXA27X 1063 -inhand_pxa25x MACH_INHAND_PXA25X INHAND_PXA25X 1064 -empos_xm MACH_EMPOS_XM EMPOS_XM 1065 -empos MACH_EMPOS EMPOS 1066 -empos_tiny MACH_EMPOS_TINY EMPOS_TINY 1067 -empos_sm MACH_EMPOS_SM EMPOS_SM 1068 -egret MACH_EGRET EGRET 1069 -ostrich MACH_OSTRICH OSTRICH 1070 -n50 MACH_N50 N50 1071 ecbat91 MACH_ECBAT91 ECBAT91 1072 -stareast MACH_STAREAST STAREAST 1073 -dspg_dw MACH_DSPG_DW DSPG_DW 1074 onearm MACH_ONEARM ONEARM 1075 -mrg110_6 MACH_MRG110_6 MRG110_6 1076 -wrt300nv2 MACH_WRT300NV2 WRT300NV2 1077 -xm_bulverde MACH_XM_BULVERDE XM_BULVERDE 1078 -msm6100 MACH_MSM6100 MSM6100 1079 -eti_b1 MACH_ETI_B1 ETI_B1 1080 -za9l_series MACH_ZILOG_ZA9L ZILOG_ZA9L 1081 -bit2440 MACH_BIT2440 BIT2440 1082 -nbi MACH_NBI NBI 1083 smdk2443 MACH_SMDK2443 SMDK2443 1084 -vdavinci MACH_VDAVINCI VDAVINCI 1085 -atc6 MACH_ATC6 ATC6 1086 -multmdw MACH_MULTMDW MULTMDW 1087 -mba2440 MACH_MBA2440 MBA2440 1088 -ecsd MACH_ECSD ECSD 1089 -palmz31 MACH_PALMZ31 PALMZ31 1090 fsg MACH_FSG FSG 1091 -razor101 MACH_RAZOR101 RAZOR101 1092 -opera_tdm MACH_OPERA_TDM OPERA_TDM 1093 -comcerto MACH_COMCERTO COMCERTO 1094 -tb0319 MACH_TB0319 TB0319 1095 -kws8000 MACH_KWS8000 KWS8000 1096 -b2 MACH_B2 B2 1097 -lcl54 MACH_LCL54 LCL54 1098 at91sam9260ek MACH_AT91SAM9260EK AT91SAM9260EK 1099 glantank MACH_GLANTANK GLANTANK 1100 n2100 MACH_N2100 N2100 1101 -n4100 MACH_N4100 N4100 1102 -rsc4 MACH_VERTICAL_RSC4 VERTICAL_RSC4 1103 -sg8100 MACH_SG8100 SG8100 1104 -im42xx MACH_IM42XX IM42XX 1105 -ftxx MACH_FTXX FTXX 1106 -lwfusion MACH_LWFUSION LWFUSION 1107 qt2410 MACH_QT2410 QT2410 1108 kixrp435 MACH_KIXRP435 KIXRP435 1109 -ccw9c MACH_CCW9C CCW9C 1110 -dabhs MACH_DABHS DABHS 1111 -gzmx MACH_GZMX GZMX 1112 -ipnw100ap MACH_IPNW100AP IPNW100AP 1113 cc9p9360dev MACH_CC9P9360DEV CC9P9360DEV 1114 -cc9p9750dev MACH_CC9P9750DEV CC9P9750DEV 1115 -cc9p9360val MACH_CC9P9360VAL CC9P9360VAL 1116 -cc9p9750val MACH_CC9P9750VAL CC9P9750VAL 1117 -nx70v MACH_NX70V NX70V 1118 -at91rm9200df MACH_AT91RM9200DF AT91RM9200DF 1119 -se_pilot2 MACH_SE_PILOT2 SE_PILOT2 1120 -mtcn_t800 MACH_MTCN_T800 MTCN_T800 1121 -vcmx212 MACH_VCMX212 VCMX212 1122 -lynx MACH_LYNX LYNX 1123 -at91sam9260id MACH_AT91SAM9260ID AT91SAM9260ID 1124 -hw86052 MACH_HW86052 HW86052 1125 -pilz_pmi3 MACH_PILZ_PMI3 PILZ_PMI3 1126 edb9302a MACH_EDB9302A EDB9302A 1127 edb9307a MACH_EDB9307A EDB9307A 1128 -ct_dfs MACH_CT_DFS CT_DFS 1129 -pilz_pmi4 MACH_PILZ_PMI4 PILZ_PMI4 1130 -xceednp_ixp MACH_XCEEDNP_IXP XCEEDNP_IXP 1131 -smdk2442b MACH_SMDK2442B SMDK2442B 1132 -xnode MACH_XNODE XNODE 1133 -aidx270 MACH_AIDX270 AIDX270 1134 -rema MACH_REMA REMA 1135 -bps1000 MACH_BPS1000 BPS1000 1136 -hw90350 MACH_HW90350 HW90350 1137 omap_3430sdp MACH_OMAP_3430SDP OMAP_3430SDP 1138 -bluetouch MACH_BLUETOUCH BLUETOUCH 1139 vstms MACH_VSTMS VSTMS 1140 -xsbase270 MACH_XSBASE270 XSBASE270 1141 -at91sam9260ek_cn MACH_AT91SAM9260EK_CN AT91SAM9260EK_CN 1142 -adsturboxb MACH_ADSTURBOXB ADSTURBOXB 1143 -oti4110 MACH_OTI4110 OTI4110 1144 -hme_pxa MACH_HME_PXA HME_PXA 1145 -deisterdca MACH_DEISTERDCA DEISTERDCA 1146 -ces_ssem2 MACH_CES_SSEM2 CES_SSEM2 1147 -ces_mtr MACH_CES_MTR CES_MTR 1148 -tds_avng_sbc MACH_TDS_AVNG_SBC TDS_AVNG_SBC 1149 -everest MACH_EVEREST EVEREST 1150 -pnx4010 MACH_PNX4010 PNX4010 1151 -oxnas MACH_OXNAS OXNAS 1152 -fiori MACH_FIORI FIORI 1153 -ml1200 MACH_ML1200 ML1200 1154 -pecos MACH_PECOS PECOS 1155 -nb2xxx MACH_NB2XXX NB2XXX 1156 -hw6900 MACH_HW6900 HW6900 1157 -cdcs_quoll MACH_CDCS_QUOLL CDCS_QUOLL 1158 -quicksilver MACH_QUICKSILVER QUICKSILVER 1159 -uplat926 MACH_UPLAT926 UPLAT926 1160 -dep2410_dep2410 MACH_DEP2410_THOMAS DEP2410_THOMAS 1161 -dtk2410 MACH_DTK2410 DTK2410 1162 -chili MACH_CHILI CHILI 1163 -demeter MACH_DEMETER DEMETER 1164 -dionysus MACH_DIONYSUS DIONYSUS 1165 -as352x MACH_AS352X AS352X 1166 -service MACH_SERVICE SERVICE 1167 -cs_e9301 MACH_CS_E9301 CS_E9301 1168 micro9m MACH_MICRO9M MICRO9M 1169 -ia_mospck MACH_IA_MOSPCK IA_MOSPCK 1170 -ql201b MACH_QL201B QL201B 1171 -bbm MACH_BBM BBM 1174 -exxx MACH_EXXX EXXX 1175 -wma11b MACH_WMA11B WMA11B 1176 -pelco_atlas MACH_PELCO_ATLAS PELCO_ATLAS 1177 -g500 MACH_G500 G500 1178 bug MACH_BUG BUG 1179 -mx33ads MACH_MX33ADS MX33ADS 1180 -chub MACH_CHUB CHUB 1181 -neo1973_gta01 MACH_NEO1973_GTA01 NEO1973_GTA01 1182 -w90n740 MACH_W90N740 W90N740 1183 -medallion_sa2410 MACH_MEDALLION_SA2410 MEDALLION_SA2410 1184 -ia_cpu_9200_2 MACH_IA_CPU_9200_2 IA_CPU_9200_2 1185 -dimmrm9200 MACH_DIMMRM9200 DIMMRM9200 1186 -pm9261 MACH_PM9261 PM9261 1187 -ml7304 MACH_ML7304 ML7304 1189 -ucp250 MACH_UCP250 UCP250 1190 -intboard MACH_INTBOARD INTBOARD 1191 -gulfstream MACH_GULFSTREAM GULFSTREAM 1192 -labquest MACH_LABQUEST LABQUEST 1193 -vcmx313 MACH_VCMX313 VCMX313 1194 -urg200 MACH_URG200 URG200 1195 -cpux255lcdnet MACH_CPUX255LCDNET CPUX255LCDNET 1196 -netdcu9 MACH_NETDCU9 NETDCU9 1197 -netdcu10 MACH_NETDCU10 NETDCU10 1198 -dspg_dga MACH_DSPG_DGA DSPG_DGA 1199 -dspg_dvw MACH_DSPG_DVW DSPG_DVW 1200 -solos MACH_SOLOS SOLOS 1201 at91sam9263ek MACH_AT91SAM9263EK AT91SAM9263EK 1202 -osstbox MACH_OSSTBOX OSSTBOX 1203 -kbat9261 MACH_KBAT9261 KBAT9261 1204 -ct1100 MACH_CT1100 CT1100 1205 -akcppxa MACH_AKCPPXA AKCPPXA 1206 -ochaya1020 MACH_OCHAYA1020 OCHAYA1020 1207 -hitrack MACH_HITRACK HITRACK 1208 -syme1 MACH_SYME1 SYME1 1209 -syhl1 MACH_SYHL1 SYHL1 1210 -empca400 MACH_EMPCA400 EMPCA400 1211 em7210 MACH_EM7210 EM7210 1212 -htchermes MACH_HTCHERMES HTCHERMES 1213 -eti_c1 MACH_ETI_C1 ETI_C1 1214 -ac100 MACH_AC100 AC100 1216 -sneetch MACH_SNEETCH SNEETCH 1217 -studentmate MACH_STUDENTMATE STUDENTMATE 1218 -zir2410 MACH_ZIR2410 ZIR2410 1219 -zir2413 MACH_ZIR2413 ZIR2413 1220 -dlonip3 MACH_DLONIP3 DLONIP3 1221 -instream MACH_INSTREAM INSTREAM 1222 -ambarella MACH_AMBARELLA AMBARELLA 1223 -nevis MACH_NEVIS NEVIS 1224 -htc_trinity MACH_HTC_TRINITY HTC_TRINITY 1225 -ql202b MACH_QL202B QL202B 1226 vpac270 MACH_VPAC270 VPAC270 1227 -rd129 MACH_RD129 RD129 1228 -htcwizard MACH_HTCWIZARD HTCWIZARD 1229 treo680 MACH_TREO680 TREO680 1230 -tecon_tmezon MACH_TECON_TMEZON TECON_TMEZON 1231 zylonite MACH_ZYLONITE ZYLONITE 1233 -gene1270 MACH_GENE1270 GENE1270 1234 -zir2412 MACH_ZIR2412 ZIR2412 1235 mx31lite MACH_MX31LITE MX31LITE 1236 -t700wx MACH_T700WX T700WX 1237 -vf100 MACH_VF100 VF100 1238 -nsb2 MACH_NSB2 NSB2 1239 -nxhmi_bb MACH_NXHMI_BB NXHMI_BB 1240 -nxhmi_re MACH_NXHMI_RE NXHMI_RE 1241 -n4100pro MACH_N4100PRO N4100PRO 1242 -sam9260 MACH_SAM9260 SAM9260 1243 -omap_treo600 MACH_OMAP_TREO600 OMAP_TREO600 1244 -indy2410 MACH_INDY2410 INDY2410 1245 -nelt_a MACH_NELT_A NELT_A 1246 -n311 MACH_N311 N311 1248 -at91sam9260vgk MACH_AT91SAM9260VGK AT91SAM9260VGK 1249 -at91leppe MACH_AT91LEPPE AT91LEPPE 1250 -at91lepccn MACH_AT91LEPCCN AT91LEPCCN 1251 -apc7100 MACH_APC7100 APC7100 1252 -stargazer MACH_STARGAZER STARGAZER 1253 -sonata MACH_SONATA SONATA 1254 -schmoogie MACH_SCHMOOGIE SCHMOOGIE 1255 -aztool MACH_AZTOOL AZTOOL 1256 mioa701 MACH_MIOA701 MIOA701 1257 -sxni9260 MACH_SXNI9260 SXNI9260 1258 -mxc27520evb MACH_MXC27520EVB MXC27520EVB 1259 armadillo5x0 MACH_ARMADILLO5X0 ARMADILLO5X0 1260 -mb9260 MACH_MB9260 MB9260 1261 -mb9263 MACH_MB9263 MB9263 1262 -ipac9302 MACH_IPAC9302 IPAC9302 1263 cc9p9360js MACH_CC9P9360JS CC9P9360JS 1264 -gallium MACH_GALLIUM GALLIUM 1265 -msc2410 MACH_MSC2410 MSC2410 1266 -ghi270 MACH_GHI270 GHI270 1267 -davinci_leonardo MACH_DAVINCI_LEONARDO DAVINCI_LEONARDO 1268 -oiab MACH_OIAB OIAB 1269 smdk6400 MACH_SMDK6400 SMDK6400 1270 nokia_n800 MACH_NOKIA_N800 NOKIA_N800 1271 -greenphone MACH_GREENPHONE GREENPHONE 1272 -compex42x MACH_COMPEXWP18 COMPEXWP18 1273 -xmate MACH_XMATE XMATE 1274 -energizer MACH_ENERGIZER ENERGIZER 1275 -ime1 MACH_IME1 IME1 1276 -sweda_tms MACH_SWEDATMS SWEDATMS 1277 -ntnp435c MACH_NTNP435C NTNP435C 1278 -spectro2 MACH_SPECTRO2 SPECTRO2 1279 -h6039 MACH_H6039 H6039 1280 ep80219 MACH_EP80219 EP80219 1281 -samoa_ii MACH_SAMOA_II SAMOA_II 1282 -cwmxl MACH_CWMXL CWMXL 1283 -as9200 MACH_AS9200 AS9200 1284 -sfx1149 MACH_SFX1149 SFX1149 1285 -navi010 MACH_NAVI010 NAVI010 1286 -multmdp MACH_MULTMDP MULTMDP 1287 -scb9520 MACH_SCB9520 SCB9520 1288 -htcathena MACH_HTCATHENA HTCATHENA 1289 -xp179 MACH_XP179 XP179 1290 -h4300 MACH_H4300 H4300 1291 goramo_mlr MACH_GORAMO_MLR GORAMO_MLR 1292 -mxc30020evb MACH_MXC30020EVB MXC30020EVB 1293 -adsbitsyg5 MACH_ADSBITSYG5 ADSBITSYG5 1294 -adsportalplus MACH_ADSPORTALPLUS ADSPORTALPLUS 1295 -mmsp2plus MACH_MMSP2PLUS MMSP2PLUS 1296 em_x270 MACH_EM_X270 EM_X270 1297 -tpp302 MACH_TPP302 TPP302 1298 -tpp104 MACH_TPM104 TPM104 1299 -tpm102 MACH_TPM102 TPM102 1300 -tpm109 MACH_TPM109 TPM109 1301 -fbxo1 MACH_FBXO1 FBXO1 1302 -hxd8 MACH_HXD8 HXD8 1303 neo1973_gta02 MACH_NEO1973_GTA02 NEO1973_GTA02 1304 -emtest MACH_EMTEST EMTEST 1305 -ad6900 MACH_AD6900 AD6900 1306 -europa MACH_EUROPA EUROPA 1307 -metroconnect MACH_METROCONNECT METROCONNECT 1308 -ez_s2410 MACH_EZ_S2410 EZ_S2410 1309 -ez_s2440 MACH_EZ_S2440 EZ_S2440 1310 -ez_ep9312 MACH_EZ_EP9312 EZ_EP9312 1311 -ez_ep9315 MACH_EZ_EP9315 EZ_EP9315 1312 -ez_x7 MACH_EZ_X7 EZ_X7 1313 -godotdb MACH_GODOTDB GODOTDB 1314 -mistral MACH_MISTRAL MISTRAL 1315 -msm MACH_MSM MSM 1316 -ct5910 MACH_CT5910 CT5910 1317 -ct5912 MACH_CT5912 CT5912 1318 -hynet_ine MACH_HYNET_INE HYNET_INE 1319 -hynet_app MACH_HYNET_APP HYNET_APP 1320 -msm7200 MACH_MSM7200 MSM7200 1321 -msm7600 MACH_MSM7600 MSM7600 1322 -ceb255 MACH_CEB255 CEB255 1323 -ciel MACH_CIEL CIEL 1324 -slm5650 MACH_SLM5650 SLM5650 1325 at91sam9rlek MACH_AT91SAM9RLEK AT91SAM9RLEK 1326 -comtech_router MACH_COMTECH_ROUTER COMTECH_ROUTER 1327 -sbc2410x MACH_SBC2410X SBC2410X 1328 -at4x0bd MACH_AT4X0BD AT4X0BD 1329 -cbifr MACH_CBIFR CBIFR 1330 -arcom_quantum MACH_ARCOM_QUANTUM ARCOM_QUANTUM 1331 -matrix520 MACH_MATRIX520 MATRIX520 1332 -matrix510 MACH_MATRIX510 MATRIX510 1333 -matrix500 MACH_MATRIX500 MATRIX500 1334 -m501 MACH_M501 M501 1335 -aaeon1270 MACH_AAEON1270 AAEON1270 1336 -matrix500ev MACH_MATRIX500EV MATRIX500EV 1337 -pac500 MACH_PAC500 PAC500 1338 -pnx8181 MACH_PNX8181 PNX8181 1339 colibri320 MACH_COLIBRI320 COLIBRI320 1340 -aztoolbb MACH_AZTOOLBB AZTOOLBB 1341 -aztoolg2 MACH_AZTOOLG2 AZTOOLG2 1342 -dvlhost MACH_DVLHOST DVLHOST 1343 -zir9200 MACH_ZIR9200 ZIR9200 1344 -zir9260 MACH_ZIR9260 ZIR9260 1345 -cocopah MACH_COCOPAH COCOPAH 1346 -nds MACH_NDS NDS 1347 -rosencrantz MACH_ROSENCRANTZ ROSENCRANTZ 1348 -fttx_odsc MACH_FTTX_ODSC FTTX_ODSC 1349 -classe_r6904 MACH_CLASSE_R6904 CLASSE_R6904 1350 cam60 MACH_CAM60 CAM60 1351 -mxc30031ads MACH_MXC30031ADS MXC30031ADS 1352 -datacall MACH_DATACALL DATACALL 1353 at91eb01 MACH_AT91EB01 AT91EB01 1354 -rty MACH_RTY RTY 1355 -dwl2100 MACH_DWL2100 DWL2100 1356 -vinsi MACH_VINSI VINSI 1357 db88f5281 MACH_DB88F5281 DB88F5281 1358 csb726 MACH_CSB726 CSB726 1359 -tik27 MACH_TIK27 TIK27 1360 -mx_uc7420 MACH_MX_UC7420 MX_UC7420 1361 -rirm3 MACH_RIRM3 RIRM3 1362 -pelco_odyssey MACH_PELCO_ODYSSEY PELCO_ODYSSEY 1363 -adx_abox MACH_ADX_ABOX ADX_ABOX 1365 -adx_tpid MACH_ADX_TPID ADX_TPID 1366 -minicheck MACH_MINICHECK MINICHECK 1367 -idam MACH_IDAM IDAM 1368 -mario_mx MACH_MARIO_MX MARIO_MX 1369 -vi1888 MACH_VI1888 VI1888 1370 -zr4230 MACH_ZR4230 ZR4230 1371 -t1_ix_blue MACH_T1_IX_BLUE T1_IX_BLUE 1372 -syhq2 MACH_SYHQ2 SYHQ2 1373 -computime_r3 MACH_COMPUTIME_R3 COMPUTIME_R3 1374 -oratis MACH_ORATIS ORATIS 1375 -mikko MACH_MIKKO MIKKO 1376 -holon MACH_HOLON HOLON 1377 -olip8 MACH_OLIP8 OLIP8 1378 -ghi270hg MACH_GHI270HG GHI270HG 1379 davinci_dm6467_evm MACH_DAVINCI_DM6467_EVM DAVINCI_DM6467_EVM 1380 davinci_dm355_evm MACH_DAVINCI_DM355_EVM DAVINCI_DM355_EVM 1381 -blackriver MACH_BLACKRIVER BLACKRIVER 1383 -sandgate_wp MACH_SANDGATEWP SANDGATEWP 1384 -cdotbwsg MACH_CDOTBWSG CDOTBWSG 1385 -quark963 MACH_QUARK963 QUARK963 1386 -csb735 MACH_CSB735 CSB735 1387 littleton MACH_LITTLETON LITTLETON 1388 -mio_p550 MACH_MIO_P550 MIO_P550 1389 -motion2440 MACH_MOTION2440 MOTION2440 1390 -imm500 MACH_IMM500 IMM500 1391 -homematic MACH_HOMEMATIC HOMEMATIC 1392 -ermine MACH_ERMINE ERMINE 1393 -kb9202b MACH_KB9202B KB9202B 1394 -hs1xx MACH_HS1XX HS1XX 1395 -studentmate2440 MACH_STUDENTMATE2440 STUDENTMATE2440 1396 -arvoo_l1_z1 MACH_ARVOO_L1_Z1 ARVOO_L1_Z1 1397 -dep2410k MACH_DEP2410K DEP2410K 1398 -xxsvideo MACH_XXSVIDEO XXSVIDEO 1399 -im4004 MACH_IM4004 IM4004 1400 -ochaya1050 MACH_OCHAYA1050 OCHAYA1050 1401 -lep9261 MACH_LEP9261 LEP9261 1402 -svenmeb MACH_SVENMEB SVENMEB 1403 -fortunet2ne MACH_FORTUNET2NE FORTUNET2NE 1404 -nxhx MACH_NXHX NXHX 1406 realview_pb11mp MACH_REALVIEW_PB11MP REALVIEW_PB11MP 1407 -ids500 MACH_IDS500 IDS500 1408 -ors_n725 MACH_ORS_N725 ORS_N725 1409 -hsdarm MACH_HSDARM HSDARM 1410 -sha_pon003 MACH_SHA_PON003 SHA_PON003 1411 -sha_pon004 MACH_SHA_PON004 SHA_PON004 1412 -sha_pon007 MACH_SHA_PON007 SHA_PON007 1413 -sha_pon011 MACH_SHA_PON011 SHA_PON011 1414 -h6042 MACH_H6042 H6042 1415 -h6043 MACH_H6043 H6043 1416 -looxc550 MACH_LOOXC550 LOOXC550 1417 -cnty_titan MACH_CNTY_TITAN CNTY_TITAN 1418 -app3xx MACH_APP3XX APP3XX 1419 -sideoatsgrama MACH_SIDEOATSGRAMA SIDEOATSGRAMA 1420 -treo700p MACH_TREO700P TREO700P 1421 -treo700w MACH_TREO700W TREO700W 1422 -treo750 MACH_TREO750 TREO750 1423 -treo755p MACH_TREO755P TREO755P 1424 -ezreganut9200 MACH_EZREGANUT9200 EZREGANUT9200 1425 -sarge MACH_SARGE SARGE 1426 -a696 MACH_A696 A696 1427 -turtle1916 MACH_TURTLE TURTLE 1428 mx27_3ds MACH_MX27_3DS MX27_3DS 1430 -bishop MACH_BISHOP BISHOP 1431 -pxx MACH_PXX PXX 1432 -redwood MACH_REDWOOD REDWOOD 1433 -omap_2430dlp MACH_OMAP_2430DLP OMAP_2430DLP 1436 -omap_2430osk MACH_OMAP_2430OSK OMAP_2430OSK 1437 -sardine MACH_SARDINE SARDINE 1438 halibut MACH_HALIBUT HALIBUT 1439 trout MACH_TROUT TROUT 1440 -goldfish MACH_GOLDFISH GOLDFISH 1441 -gesbc2440 MACH_GESBC2440 GESBC2440 1442 -nomad MACH_NOMAD NOMAD 1443 -rosalind MACH_ROSALIND ROSALIND 1444 -cc9p9215 MACH_CC9P9215 CC9P9215 1445 -cc9p9210 MACH_CC9P9210 CC9P9210 1446 -cc9p9215js MACH_CC9P9215JS CC9P9215JS 1447 -cc9p9210js MACH_CC9P9210JS CC9P9210JS 1448 -nasffe MACH_NASFFE NASFFE 1449 -tn2x0bd MACH_TN2X0BD TN2X0BD 1450 -gwmpxa MACH_GWMPXA GWMPXA 1451 -exyplus MACH_EXYPLUS EXYPLUS 1452 -jadoo21 MACH_JADOO21 JADOO21 1453 -looxn560 MACH_LOOXN560 LOOXN560 1454 -bonsai MACH_BONSAI BONSAI 1455 -adsmilgato MACH_ADSMILGATO ADSMILGATO 1456 -gba MACH_GBA GBA 1457 -h6044 MACH_H6044 H6044 1458 -app MACH_APP APP 1459 tct_hammer MACH_TCT_HAMMER TCT_HAMMER 1460 herald MACH_HERALD HERALD 1461 -artemis MACH_ARTEMIS ARTEMIS 1462 -htctitan MACH_HTCTITAN HTCTITAN 1463 -qranium MACH_QRANIUM QRANIUM 1464 -adx_wsc2 MACH_ADX_WSC2 ADX_WSC2 1465 -adx_medcom MACH_ADX_MEDCOM ADX_MEDCOM 1466 -bboard MACH_BBOARD BBOARD 1467 -cambria MACH_CAMBRIA CAMBRIA 1468 -mt7xxx MACH_MT7XXX MT7XXX 1469 -matrix512 MACH_MATRIX512 MATRIX512 1470 -matrix522 MACH_MATRIX522 MATRIX522 1471 -ipac5010 MACH_IPAC5010 IPAC5010 1472 -sakura MACH_SAKURA SAKURA 1473 -grocx MACH_GROCX GROCX 1474 -pm9263 MACH_PM9263 PM9263 1475 sim_one MACH_SIM_ONE SIM_ONE 1476 -acq132 MACH_ACQ132 ACQ132 1477 -datr MACH_DATR DATR 1478 -actux1 MACH_ACTUX1 ACTUX1 1479 -actux2 MACH_ACTUX2 ACTUX2 1480 -actux3 MACH_ACTUX3 ACTUX3 1481 -flexit MACH_FLEXIT FLEXIT 1482 -bh2x0bd MACH_BH2X0BD BH2X0BD 1483 -atb2002 MACH_ATB2002 ATB2002 1484 -xenon MACH_XENON XENON 1485 -fm607 MACH_FM607 FM607 1486 -matrix514 MACH_MATRIX514 MATRIX514 1487 -matrix524 MACH_MATRIX524 MATRIX524 1488 -inpod MACH_INPOD INPOD 1489 jive MACH_JIVE JIVE 1490 -tll_mx21 MACH_TLL_MX21 TLL_MX21 1491 -sbc2800 MACH_SBC2800 SBC2800 1492 -cc7ucamry MACH_CC7UCAMRY CC7UCAMRY 1493 -ubisys_p9_sc15 MACH_UBISYS_P9_SC15 UBISYS_P9_SC15 1494 -ubisys_p9_ssc2d10 MACH_UBISYS_P9_SSC2D10 UBISYS_P9_SSC2D10 1495 -ubisys_p9_rcu3 MACH_UBISYS_P9_RCU3 UBISYS_P9_RCU3 1496 -aml_m8000 MACH_AML_M8000 AML_M8000 1497 -snapper_270 MACH_SNAPPER_270 SNAPPER_270 1498 -omap_bbx MACH_OMAP_BBX OMAP_BBX 1499 -ucn2410 MACH_UCN2410 UCN2410 1500 sam9_l9260 MACH_SAM9_L9260 SAM9_L9260 1501 -eti_c2 MACH_ETI_C2 ETI_C2 1502 -avalanche MACH_AVALANCHE AVALANCHE 1503 realview_pb1176 MACH_REALVIEW_PB1176 REALVIEW_PB1176 1504 -dp1500 MACH_DP1500 DP1500 1505 -apple_iphone MACH_APPLE_IPHONE APPLE_IPHONE 1506 yl9200 MACH_YL9200 YL9200 1507 rd88f5182 MACH_RD88F5182 RD88F5182 1508 kurobox_pro MACH_KUROBOX_PRO KUROBOX_PRO 1509 -se_poet MACH_SE_POET SE_POET 1510 mx31_3ds MACH_MX31_3DS MX31_3DS 1511 -r270 MACH_R270 R270 1512 -armour21 MACH_ARMOUR21 ARMOUR21 1513 -dt2 MACH_DT2 DT2 1514 -vt4 MACH_VT4 VT4 1515 -tyco320 MACH_TYCO320 TYCO320 1516 -adma MACH_ADMA ADMA 1517 -wp188 MACH_WP188 WP188 1518 -corsica MACH_CORSICA CORSICA 1519 -bigeye MACH_BIGEYE BIGEYE 1520 -tll5000 MACH_TLL5000 TLL5000 1522 -bebot MACH_BEBOT BEBOT 1523 qong MACH_QONG QONG 1524 -tcompact MACH_TCOMPACT TCOMPACT 1525 -puma5 MACH_PUMA5 PUMA5 1526 -elara MACH_ELARA ELARA 1527 -ellington MACH_ELLINGTON ELLINGTON 1528 -xda_atom MACH_XDA_ATOM XDA_ATOM 1529 -energizer2 MACH_ENERGIZER2 ENERGIZER2 1530 -odin MACH_ODIN ODIN 1531 -actux4 MACH_ACTUX4 ACTUX4 1532 -esl_omap MACH_ESL_OMAP ESL_OMAP 1533 omap2evm MACH_OMAP2EVM OMAP2EVM 1534 omap3evm MACH_OMAP3EVM OMAP3EVM 1535 -adx_pcu57 MACH_ADX_PCU57 ADX_PCU57 1536 -monaco MACH_MONACO MONACO 1537 -levante MACH_LEVANTE LEVANTE 1538 -tmxipx425 MACH_TMXIPX425 TMXIPX425 1539 -leep MACH_LEEP LEEP 1540 -raad MACH_RAAD RAAD 1541 dns323 MACH_DNS323 DNS323 1542 -ap1000 MACH_AP1000 AP1000 1543 -a9sam6432 MACH_A9SAM6432 A9SAM6432 1544 -shiny MACH_SHINY SHINY 1545 omap3_beagle MACH_OMAP3_BEAGLE OMAP3_BEAGLE 1546 -csr_bdb2 MACH_CSR_BDB2 CSR_BDB2 1547 nokia_n810 MACH_NOKIA_N810 NOKIA_N810 1548 -c270 MACH_C270 C270 1549 -sentry MACH_SENTRY SENTRY 1550 pcm038 MACH_PCM038 PCM038 1551 -anc300 MACH_ANC300 ANC300 1552 -htckaiser MACH_HTCKAISER HTCKAISER 1553 -sbat100 MACH_SBAT100 SBAT100 1554 -modunorm MACH_MODUNORM MODUNORM 1555 -pelos_twarm MACH_PELOS_TWARM PELOS_TWARM 1556 -flank MACH_FLANK FLANK 1557 -sirloin MACH_SIRLOIN SIRLOIN 1558 -brisket MACH_BRISKET BRISKET 1559 -chuck MACH_CHUCK CHUCK 1560 -otter MACH_OTTER OTTER 1561 -davinci_ldk MACH_DAVINCI_LDK DAVINCI_LDK 1562 -phreedom MACH_PHREEDOM PHREEDOM 1563 -sg310 MACH_SG310 SG310 1564 ts_x09 MACH_TS209 TS209 1565 at91cap9adk MACH_AT91CAP9ADK AT91CAP9ADK 1566 -tion9315 MACH_TION9315 TION9315 1567 -mast MACH_MAST MAST 1568 -pfw MACH_PFW PFW 1569 -yl_p2440 MACH_YL_P2440 YL_P2440 1570 -zsbc32 MACH_ZSBC32 ZSBC32 1571 -omap_pace2 MACH_OMAP_PACE2 OMAP_PACE2 1572 -imx_pace2 MACH_IMX_PACE2 IMX_PACE2 1573 mx31moboard MACH_MX31MOBOARD MX31MOBOARD 1574 -mx37_3ds MACH_MX37_3DS MX37_3DS 1575 -rcc MACH_RCC RCC 1576 -dmp MACH_ARM9 ARM9 1577 -vision_ep9307 MACH_VISION_EP9307 VISION_EP9307 1578 -scly1000 MACH_SCLY1000 SCLY1000 1579 -fontel_ep MACH_FONTEL_EP FONTEL_EP 1580 -voiceblue3g MACH_VOICEBLUE3G VOICEBLUE3G 1581 -tt9200 MACH_TT9200 TT9200 1582 -digi2410 MACH_DIGI2410 DIGI2410 1583 terastation_pro2 MACH_TERASTATION_PRO2 TERASTATION_PRO2 1584 linkstation_pro MACH_LINKSTATION_PRO LINKSTATION_PRO 1585 -motorola_a780 MACH_MOTOROLA_A780 MOTOROLA_A780 1587 -motorola_e6 MACH_MOTOROLA_E6 MOTOROLA_E6 1588 -motorola_e2 MACH_MOTOROLA_E2 MOTOROLA_E2 1589 -motorola_e680 MACH_MOTOROLA_E680 MOTOROLA_E680 1590 -ur2410 MACH_UR2410 UR2410 1591 -tas9261 MACH_TAS9261 TAS9261 1592 -davinci_hermes_hd MACH_HERMES_HD HERMES_HD 1593 -davinci_perseo_hd MACH_PERSEO_HD PERSEO_HD 1594 -stargazer2 MACH_STARGAZER2 STARGAZER2 1595 e350 MACH_E350 E350 1596 -wpcm450 MACH_WPCM450 WPCM450 1597 -cartesio MACH_CARTESIO CARTESIO 1598 -toybox MACH_TOYBOX TOYBOX 1599 -tx27 MACH_TX27 TX27 1600 ts409 MACH_TS409 TS409 1601 -p300 MACH_P300 P300 1602 -xdacomet MACH_XDACOMET XDACOMET 1603 -dexflex2 MACH_DEXFLEX2 DEXFLEX2 1604 -ow MACH_OW OW 1605 -armebs3 MACH_ARMEBS3 ARMEBS3 1606 -u3 MACH_U3 U3 1607 -smdk2450 MACH_SMDK2450 SMDK2450 1608 -rsi_ews MACH_RSI_EWS RSI_EWS 1609 -tnb MACH_TNB TNB 1610 -toepath MACH_TOEPATH TOEPATH 1611 -kb9263 MACH_KB9263 KB9263 1612 -mt7108 MACH_MT7108 MT7108 1613 -smtr2440 MACH_SMTR2440 SMTR2440 1614 -manao MACH_MANAO MANAO 1615 cm_x300 MACH_CM_X300 CM_X300 1616 -gulfstream_kp MACH_GULFSTREAM_KP GULFSTREAM_KP 1617 -lanreadyfn522 MACH_LANREADYFN522 LANREADYFN522 1618 -arma37 MACH_ARMA37 ARMA37 1619 -mendel MACH_MENDEL MENDEL 1620 -pelco_iliad MACH_PELCO_ILIAD PELCO_ILIAD 1621 -unit2p MACH_UNIT2P UNIT2P 1622 -inc20otter MACH_INC20OTTER INC20OTTER 1623 at91sam9g20ek MACH_AT91SAM9G20EK AT91SAM9G20EK 1624 -sc_ge2 MACH_STORCENTER STORCENTER 1625 smdk6410 MACH_SMDK6410 SMDK6410 1626 u300 MACH_U300 U300 1627 -u500 MACH_U500 U500 1628 -ds9260 MACH_DS9260 DS9260 1629 -riverrock MACH_RIVERROCK RIVERROCK 1630 -scibath MACH_SCIBATH SCIBATH 1631 -at91sam7se MACH_AT91SAM7SE512EK AT91SAM7SE512EK 1632 wrt350n_v2 MACH_WRT350N_V2 WRT350N_V2 1633 -multimedia MACH_MULTIMEDIA MULTIMEDIA 1634 -marvin MACH_MARVIN MARVIN 1635 -x500 MACH_X500 X500 1636 -awlug4lcu MACH_AWLUG4LCU AWLUG4LCU 1637 -palermoc MACH_PALERMOC PALERMOC 1638 omap_ldp MACH_OMAP_LDP OMAP_LDP 1639 -ip500 MACH_IP500 IP500 1640 -ase2 MACH_ASE2 ASE2 1642 -mx35evb MACH_MX35EVB MX35EVB 1643 -aml_m8050 MACH_AML_M8050 AML_M8050 1644 mx35_3ds MACH_MX35_3DS MX35_3DS 1645 -mars MACH_MARS MARS 1646 neuros_osd2 MACH_NEUROS_OSD2 NEUROS_OSD2 1647 -badger MACH_BADGER BADGER 1648 trizeps4wl MACH_TRIZEPS4WL TRIZEPS4WL 1649 -trizeps5 MACH_TRIZEPS5 TRIZEPS5 1650 -marlin MACH_MARLIN MARLIN 1651 ts78xx MACH_TS78XX TS78XX 1652 -hpipaq214 MACH_HPIPAQ214 HPIPAQ214 1653 -at572d940dcm MACH_AT572D940DCM AT572D940DCM 1654 -ne1board MACH_NE1BOARD NE1BOARD 1655 -zante MACH_ZANTE ZANTE 1656 sffsdr MACH_SFFSDR SFFSDR 1657 -tw2662 MACH_TW2662 TW2662 1658 -vf10xx MACH_VF10XX VF10XX 1659 -zoran43xx MACH_ZORAN43XX ZORAN43XX 1660 -sonix926 MACH_SONIX926 SONIX926 1661 -celestialsemi MACH_CELESTIALSEMI CELESTIALSEMI 1662 -cc9m2443js MACH_CC9M2443JS CC9M2443JS 1663 -tw5334 MACH_TW5334 TW5334 1664 -omap_htcartemis MACH_HTCARTEMIS HTCARTEMIS 1665 -nal_hlite MACH_NAL_HLITE NAL_HLITE 1666 -htcvogue MACH_HTCVOGUE HTCVOGUE 1667 -smartweb MACH_SMARTWEB SMARTWEB 1668 -mv86xx MACH_MV86XX MV86XX 1669 -mv87xx MACH_MV87XX MV87XX 1670 -songyoungho MACH_SONGYOUNGHO SONGYOUNGHO 1671 -younghotema MACH_YOUNGHOTEMA YOUNGHOTEMA 1672 pcm037 MACH_PCM037 PCM037 1673 -mmvp MACH_MMVP MMVP 1674 -mmap MACH_MMAP MMAP 1675 -ptid2410 MACH_PTID2410 PTID2410 1676 -james_926 MACH_JAMES_926 JAMES_926 1677 -fm6000 MACH_FM6000 FM6000 1678 db88f6281_bp MACH_DB88F6281_BP DB88F6281_BP 1680 rd88f6192_nas MACH_RD88F6192_NAS RD88F6192_NAS 1681 rd88f6281 MACH_RD88F6281 RD88F6281 1682 db78x00_bp MACH_DB78X00_BP DB78X00_BP 1683 smdk2416 MACH_SMDK2416 SMDK2416 1685 -oce_spider_si MACH_OCE_SPIDER_SI OCE_SPIDER_SI 1686 -oce_spider_sk MACH_OCE_SPIDER_SK OCE_SPIDER_SK 1687 -rovern6 MACH_ROVERN6 ROVERN6 1688 -pelco_evolution MACH_PELCO_EVOLUTION PELCO_EVOLUTION 1689 wbd111 MACH_WBD111 WBD111 1690 -elaracpe MACH_ELARACPE ELARACPE 1691 -mabv3 MACH_MABV3 MABV3 1692 mv2120 MACH_MV2120 MV2120 1693 -csb737 MACH_CSB737 CSB737 1695 mx51_3ds MACH_MX51_3DS MX51_3DS 1696 -g900 MACH_G900 G900 1697 -apf27 MACH_APF27 APF27 1698 -ggus2000 MACH_GGUS2000 GGUS2000 1699 -omap_2430_mimic MACH_OMAP_2430_MIMIC OMAP_2430_MIMIC 1700 imx27lite MACH_IMX27LITE IMX27LITE 1701 -almex MACH_ALMEX ALMEX 1702 -control MACH_CONTROL CONTROL 1703 -mba2410 MACH_MBA2410 MBA2410 1704 -volcano MACH_VOLCANO VOLCANO 1705 -zenith MACH_ZENITH ZENITH 1706 -muchip MACH_MUCHIP MUCHIP 1707 -magellan MACH_MAGELLAN MAGELLAN 1708 usb_a9260 MACH_USB_A9260 USB_A9260 1709 usb_a9263 MACH_USB_A9263 USB_A9263 1710 qil_a9260 MACH_QIL_A9260 QIL_A9260 1711 -cme9210 MACH_CME9210 CME9210 1712 -hczh4 MACH_HCZH4 HCZH4 1713 -spearbasic MACH_SPEARBASIC SPEARBASIC 1714 -dep2440 MACH_DEP2440 DEP2440 1715 -hdl_gxr MACH_HDL_GXR HDL_GXR 1716 -hdl_gt MACH_HDL_GT HDL_GT 1717 -hdl_4g MACH_HDL_4G HDL_4G 1718 -s3c6000 MACH_S3C6000 S3C6000 1719 -mmsp2_mdk MACH_MMSP2_MDK MMSP2_MDK 1720 -mpx220 MACH_MPX220 MPX220 1721 kzm_arm11_01 MACH_KZM_ARM11_01 KZM_ARM11_01 1722 -htc_polaris MACH_HTC_POLARIS HTC_POLARIS 1723 -htc_kaiser MACH_HTC_KAISER HTC_KAISER 1724 -lg_ks20 MACH_LG_KS20 LG_KS20 1725 -hhgps MACH_HHGPS HHGPS 1726 nokia_n810_wimax MACH_NOKIA_N810_WIMAX NOKIA_N810_WIMAX 1727 -insight MACH_INSIGHT INSIGHT 1728 sapphire MACH_SAPPHIRE SAPPHIRE 1729 -csb637xo MACH_CSB637XO CSB637XO 1730 -evisiong MACH_EVISIONG EVISIONG 1731 stmp37xx MACH_STMP37XX STMP37XX 1732 stmp378x MACH_STMP378X STMP378X 1733 -tnt MACH_TNT TNT 1734 -tbxt MACH_TBXT TBXT 1735 -playmate MACH_PLAYMATE PLAYMATE 1736 -pns10 MACH_PNS10 PNS10 1737 -eznavi MACH_EZNAVI EZNAVI 1738 -ps4000 MACH_PS4000 PS4000 1739 ezx_a780 MACH_EZX_A780 EZX_A780 1740 ezx_e680 MACH_EZX_E680 EZX_E680 1741 ezx_a1200 MACH_EZX_A1200 EZX_A1200 1742 ezx_e6 MACH_EZX_E6 EZX_E6 1743 ezx_e2 MACH_EZX_E2 EZX_E2 1744 ezx_a910 MACH_EZX_A910 EZX_A910 1745 -cwmx31 MACH_CWMX31 CWMX31 1746 -sl2312 MACH_SL2312 SL2312 1747 -blenny MACH_BLENNY BLENNY 1748 -ds107 MACH_DS107 DS107 1749 -dsx07 MACH_DSX07 DSX07 1750 -picocom1 MACH_PICOCOM1 PICOCOM1 1751 -lynx_wolverine MACH_LYNX_WOLVERINE LYNX_WOLVERINE 1752 -ubisys_p9_sc19 MACH_UBISYS_P9_SC19 UBISYS_P9_SC19 1753 -kratos_low MACH_KRATOS_LOW KRATOS_LOW 1754 -m700 MACH_M700 M700 1755 edmini_v2 MACH_EDMINI_V2 EDMINI_V2 1756 zipit2 MACH_ZIPIT2 ZIPIT2 1757 -hslfemtocell MACH_HSLFEMTOCELL HSLFEMTOCELL 1758 -daintree_at91 MACH_DAINTREE_AT91 DAINTREE_AT91 1759 -sg560usb MACH_SG560USB SG560USB 1760 omap3_pandora MACH_OMAP3_PANDORA OMAP3_PANDORA 1761 -usr8200 MACH_USR8200 USR8200 1762 -s1s65k MACH_S1S65K S1S65K 1763 -s2s65a MACH_S2S65A S2S65A 1764 -icore MACH_ICORE ICORE 1765 mss2 MACH_MSS2 MSS2 1766 -belmont MACH_BELMONT BELMONT 1767 -asusp525 MACH_ASUSP525 ASUSP525 1768 lb88rc8480 MACH_LB88RC8480 LB88RC8480 1769 -hipxa MACH_HIPXA HIPXA 1770 mx25_3ds MACH_MX25_3DS MX25_3DS 1771 -m800 MACH_M800 M800 1772 omap3530_lv_som MACH_OMAP3530_LV_SOM OMAP3530_LV_SOM 1773 -prima_evb MACH_PRIMA_EVB PRIMA_EVB 1774 -mx31bt1 MACH_MX31BT1 MX31BT1 1775 -atlas4_evb MACH_ATLAS4_EVB ATLAS4_EVB 1776 -mx31cicada MACH_MX31CICADA MX31CICADA 1777 -mi424wr MACH_MI424WR MI424WR 1778 -axs_ultrax MACH_AXS_ULTRAX AXS_ULTRAX 1779 -at572d940deb MACH_AT572D940DEB AT572D940DEB 1780 davinci_da830_evm MACH_DAVINCI_DA830_EVM DAVINCI_DA830_EVM 1781 -ep9302 MACH_EP9302 EP9302 1782 at572d940hfek MACH_AT572D940HFEB AT572D940HFEB 1783 -cybook3 MACH_CYBOOK3 CYBOOK3 1784 -wdg002 MACH_WDG002 WDG002 1785 -sg560adsl MACH_SG560ADSL SG560ADSL 1786 -nextio_n2800_ica MACH_NEXTIO_N2800_ICA NEXTIO_N2800_ICA 1787 dove_db MACH_DOVE_DB DOVE_DB 1788 -marvell_newdb MACH_MARVELL_NEWDB MARVELL_NEWDB 1789 -vandihud MACH_VANDIHUD VANDIHUD 1790 -magx_e8 MACH_MAGX_E8 MAGX_E8 1791 -magx_z6 MACH_MAGX_Z6 MAGX_Z6 1792 -magx_v8 MACH_MAGX_V8 MAGX_V8 1793 -magx_u9 MACH_MAGX_U9 MAGX_U9 1794 -toughcf08 MACH_TOUGHCF08 TOUGHCF08 1795 -zw4400 MACH_ZW4400 ZW4400 1796 -marat91 MACH_MARAT91 MARAT91 1797 overo MACH_OVERO OVERO 1798 at2440evb MACH_AT2440EVB AT2440EVB 1799 neocore926 MACH_NEOCORE926 NEOCORE926 1800 wnr854t MACH_WNR854T WNR854T 1801 -imx27 MACH_IMX27 IMX27 1802 -moose_db MACH_MOOSE_DB MOOSE_DB 1803 -fab4 MACH_FAB4 FAB4 1804 -htcdiamond MACH_HTCDIAMOND HTCDIAMOND 1805 -fiona MACH_FIONA FIONA 1806 -mxc30030_x MACH_MXC30030_X MXC30030_X 1807 -bmp1000 MACH_BMP1000 BMP1000 1808 -logi9200 MACH_LOGI9200 LOGI9200 1809 -tqma31 MACH_TQMA31 TQMA31 1810 -ccw9p9215js MACH_CCW9P9215JS CCW9P9215JS 1811 rd88f5181l_ge MACH_RD88F5181L_GE RD88F5181L_GE 1812 -sifmain MACH_SIFMAIN SIFMAIN 1813 -sam9_l9261 MACH_SAM9_L9261 SAM9_L9261 1814 -cc9m2443 MACH_CC9M2443 CC9M2443 1815 -xaria300 MACH_XARIA300 XARIA300 1816 -it9200 MACH_IT9200 IT9200 1817 rd88f5181l_fxo MACH_RD88F5181L_FXO RD88F5181L_FXO 1818 -kriss_sensor MACH_KRISS_SENSOR KRISS_SENSOR 1819 -pilz_pmi5 MACH_PILZ_PMI5 PILZ_PMI5 1820 -jade MACH_JADE JADE 1821 -ks8695_softplc MACH_KS8695_SOFTPLC KS8695_SOFTPLC 1822 -gprisc3 MACH_GPRISC3 GPRISC3 1823 stamp9g20 MACH_STAMP9G20 STAMP9G20 1824 -smdk6430 MACH_SMDK6430 SMDK6430 1825 smdkc100 MACH_SMDKC100 SMDKC100 1826 tavorevb MACH_TAVOREVB TAVOREVB 1827 saar MACH_SAAR SAAR 1828 -deister_eyecam MACH_DEISTER_EYECAM DEISTER_EYECAM 1829 at91sam9m10g45ek MACH_AT91SAM9M10G45EK AT91SAM9M10G45EK 1830 -linkstation_produo MACH_LINKSTATION_PRODUO LINKSTATION_PRODUO 1831 -hit_b0 MACH_HIT_B0 HIT_B0 1832 -adx_rmu MACH_ADX_RMU ADX_RMU 1833 -xg_cpe_main MACH_XG_CPE_MAIN XG_CPE_MAIN 1834 -edb9407a MACH_EDB9407A EDB9407A 1835 -dtb9608 MACH_DTB9608 DTB9608 1836 -em104v1 MACH_EM104V1 EM104V1 1837 -demo MACH_DEMO DEMO 1838 -logi9260 MACH_LOGI9260 LOGI9260 1839 -mx31_exm32 MACH_MX31_EXM32 MX31_EXM32 1840 -usb_a9g20 MACH_USB_A9G20 USB_A9G20 1841 -picproje2008 MACH_PICPROJE2008 PICPROJE2008 1842 -cs_e9315 MACH_CS_E9315 CS_E9315 1843 -qil_a9g20 MACH_QIL_A9G20 QIL_A9G20 1844 -sha_pon020 MACH_SHA_PON020 SHA_PON020 1845 -nad MACH_NAD NAD 1846 -sbc35_a9260 MACH_SBC35_A9260 SBC35_A9260 1847 -sbc35_a9g20 MACH_SBC35_A9G20 SBC35_A9G20 1848 -davinci_beginning MACH_DAVINCI_BEGINNING DAVINCI_BEGINNING 1849 -uwc MACH_UWC UWC 1850 mxlads MACH_MXLADS MXLADS 1851 -htcnike MACH_HTCNIKE HTCNIKE 1852 -deister_pxa270 MACH_DEISTER_PXA270 DEISTER_PXA270 1853 -cme9210js MACH_CME9210JS CME9210JS 1854 -cc9p9360 MACH_CC9P9360 CC9P9360 1855 -mocha MACH_MOCHA MOCHA 1856 -wapd170ag MACH_WAPD170AG WAPD170AG 1857 linkstation_mini MACH_LINKSTATION_MINI LINKSTATION_MINI 1858 afeb9260 MACH_AFEB9260 AFEB9260 1859 -w90x900 MACH_W90X900 W90X900 1860 -w90x700 MACH_W90X700 W90X700 1861 -kt300ip MACH_KT300IP KT300IP 1862 -kt300ip_g20 MACH_KT300IP_G20 KT300IP_G20 1863 -srcm MACH_SRCM SRCM 1864 -wlnx_9260 MACH_WLNX_9260 WLNX_9260 1865 -openmoko_gta03 MACH_OPENMOKO_GTA03 OPENMOKO_GTA03 1866 -osprey2 MACH_OSPREY2 OSPREY2 1867 -kbio9260 MACH_KBIO9260 KBIO9260 1868 -ginza MACH_GINZA GINZA 1869 -a636n MACH_A636N A636N 1870 imx27ipcam MACH_IMX27IPCAM IMX27IPCAM 1871 -nemoc MACH_NEMOC NEMOC 1872 -geneva MACH_GENEVA GENEVA 1873 -htcpharos MACH_HTCPHAROS HTCPHAROS 1874 -neonc MACH_NEONC NEONC 1875 -nas7100 MACH_NAS7100 NAS7100 1876 -teuphone MACH_TEUPHONE TEUPHONE 1877 -annax_eth2 MACH_ANNAX_ETH2 ANNAX_ETH2 1878 -csb733 MACH_CSB733 CSB733 1879 -bk3 MACH_BK3 BK3 1880 -omap_em32 MACH_OMAP_EM32 OMAP_EM32 1881 -et9261cp MACH_ET9261CP ET9261CP 1882 -jasperc MACH_JASPERC JASPERC 1883 -issi_arm9 MACH_ISSI_ARM9 ISSI_ARM9 1884 -ued MACH_UED UED 1885 -esiblade MACH_ESIBLADE ESIBLADE 1886 -eye02 MACH_EYE02 EYE02 1887 -imx27kbd MACH_IMX27KBD IMX27KBD 1888 -sst61vc010_fpga MACH_SST61VC010_FPGA SST61VC010_FPGA 1889 -kixvp435 MACH_KIXVP435 KIXVP435 1890 -kixnp435 MACH_KIXNP435 KIXNP435 1891 -africa MACH_AFRICA AFRICA 1892 -nh233 MACH_NH233 NH233 1893 rd88f6183ap_ge MACH_RD88F6183AP_GE RD88F6183AP_GE 1894 -bcm4760 MACH_BCM4760 BCM4760 1895 -eddy_v2 MACH_EDDY_V2 EDDY_V2 1896 realview_pba8 MACH_REALVIEW_PBA8 REALVIEW_PBA8 1897 -hid_a7 MACH_HID_A7 HID_A7 1898 -hero MACH_HERO HERO 1899 -omap_poseidon MACH_OMAP_POSEIDON OMAP_POSEIDON 1900 realview_pbx MACH_REALVIEW_PBX REALVIEW_PBX 1901 micro9s MACH_MICRO9S MICRO9S 1902 -mako MACH_MAKO MAKO 1903 -xdaflame MACH_XDAFLAME XDAFLAME 1904 -phidget_sbc2 MACH_PHIDGET_SBC2 PHIDGET_SBC2 1905 -limestone MACH_LIMESTONE LIMESTONE 1906 -iprobe_c32 MACH_IPROBE_C32 IPROBE_C32 1907 rut100 MACH_RUT100 RUT100 1908 -asusp535 MACH_ASUSP535 ASUSP535 1909 -htcraphael MACH_HTCRAPHAEL HTCRAPHAEL 1910 -sygdg1 MACH_SYGDG1 SYGDG1 1911 -sygdg2 MACH_SYGDG2 SYGDG2 1912 -seoul MACH_SEOUL SEOUL 1913 -salerno MACH_SALERNO SALERNO 1914 -ucn_s3c64xx MACH_UCN_S3C64XX UCN_S3C64XX 1915 -msm7201a MACH_MSM7201A MSM7201A 1916 -lpr1 MACH_LPR1 LPR1 1917 -armadillo500fx MACH_ARMADILLO500FX ARMADILLO500FX 1918 g3evm MACH_G3EVM G3EVM 1919 -z3_dm355 MACH_Z3_DM355 Z3_DM355 1920 w90p910evb MACH_W90P910EVB W90P910EVB 1921 -w90p920evb MACH_W90P920EVB W90P920EVB 1922 w90p950evb MACH_W90P950EVB W90P950EVB 1923 w90n960evb MACH_W90N960EVB W90N960EVB 1924 -camhd MACH_CAMHD CAMHD 1925 -mvc100 MACH_MVC100 MVC100 1926 -electrum_200 MACH_ELECTRUM_200 ELECTRUM_200 1927 -htcjade MACH_HTCJADE HTCJADE 1928 -memphis MACH_MEMPHIS MEMPHIS 1929 -imx27sbc MACH_IMX27SBC IMX27SBC 1930 -lextar MACH_LEXTAR LEXTAR 1931 mv88f6281gtw_ge MACH_MV88F6281GTW_GE MV88F6281GTW_GE 1932 ncp MACH_NCP NCP 1933 -z32an_series MACH_Z32AN Z32AN 1934 -tmq_capd MACH_TMQ_CAPD TMQ_CAPD 1935 -omap3_wl MACH_OMAP3_WL OMAP3_WL 1936 -chumby MACH_CHUMBY CHUMBY 1937 -atsarm9 MACH_ATSARM9 ATSARM9 1938 davinci_dm365_evm MACH_DAVINCI_DM365_EVM DAVINCI_DM365_EVM 1939 -bahamas MACH_BAHAMAS BAHAMAS 1940 -das MACH_DAS DAS 1941 -minidas MACH_MINIDAS MINIDAS 1942 -vk1000 MACH_VK1000 VK1000 1943 centro MACH_CENTRO CENTRO 1944 -ctera_2bay MACH_CTERA_2BAY CTERA_2BAY 1945 -edgeconnect MACH_EDGECONNECT EDGECONNECT 1946 -nd27000 MACH_ND27000 ND27000 1947 -cobra MACH_GEMALTO_COBRA GEMALTO_COBRA 1948 -ingelabs_comet MACH_INGELABS_COMET INGELABS_COMET 1949 -pollux_wiz MACH_POLLUX_WIZ POLLUX_WIZ 1950 -blackstone MACH_BLACKSTONE BLACKSTONE 1951 -topaz MACH_TOPAZ TOPAZ 1952 -aixle MACH_AIXLE AIXLE 1953 -mw998 MACH_MW998 MW998 1954 nokia_rx51 MACH_NOKIA_RX51 NOKIA_RX51 1955 -vsc5605ev MACH_VSC5605EV VSC5605EV 1956 -nt98700dk MACH_NT98700DK NT98700DK 1957 -icontact MACH_ICONTACT ICONTACT 1958 -swarco_frcpu MACH_SWARCO_FRCPU SWARCO_FRCPU 1959 -swarco_scpu MACH_SWARCO_SCPU SWARCO_SCPU 1960 -bbox_p16 MACH_BBOX_P16 BBOX_P16 1961 -bstd MACH_BSTD BSTD 1962 -sbc2440ii MACH_SBC2440II SBC2440II 1963 -pcm034 MACH_PCM034 PCM034 1964 -neso MACH_NESO NESO 1965 -wlnx_9g20 MACH_WLNX_9G20 WLNX_9G20 1966 omap_zoom2 MACH_OMAP_ZOOM2 OMAP_ZOOM2 1967 -totemnova MACH_TOTEMNOVA TOTEMNOVA 1968 -c5000 MACH_C5000 C5000 1969 -unipo_at91sam9263 MACH_UNIPO_AT91SAM9263 UNIPO_AT91SAM9263 1970 -ethernut5 MACH_ETHERNUT5 ETHERNUT5 1971 -arm11 MACH_ARM11 ARM11 1972 cpuat9260 MACH_CPUAT9260 CPUAT9260 1973 -cpupxa255 MACH_CPUPXA255 CPUPXA255 1974 eukrea_cpuimx27 MACH_CPUIMX27 CPUIMX27 1975 -cheflux MACH_CHEFLUX CHEFLUX 1976 -eb_cpux9k2 MACH_EB_CPUX9K2 EB_CPUX9K2 1977 -opcotec MACH_OPCOTEC OPCOTEC 1978 -yt MACH_YT YT 1979 -motoq MACH_MOTOQ MOTOQ 1980 -bsb1 MACH_BSB1 BSB1 1981 acs5k MACH_ACS5K ACS5K 1982 -milan MACH_MILAN MILAN 1983 -quartzv2 MACH_QUARTZV2 QUARTZV2 1984 -rsvp MACH_RSVP RSVP 1985 -rmp200 MACH_RMP200 RMP200 1986 snapper_9260 MACH_SNAPPER_9260 SNAPPER_9260 1987 dsm320 MACH_DSM320 DSM320 1988 -adsgcm MACH_ADSGCM ADSGCM 1989 -ase2_400 MACH_ASE2_400 ASE2_400 1990 -pizza MACH_PIZZA PIZZA 1991 -spot_ngpl MACH_SPOT_NGPL SPOT_NGPL 1992 -armata MACH_ARMATA ARMATA 1993 exeda MACH_EXEDA EXEDA 1994 -mx31sf005 MACH_MX31SF005 MX31SF005 1995 -f5d8231_4_v2 MACH_F5D8231_4_V2 F5D8231_4_V2 1996 -q2440 MACH_Q2440 Q2440 1997 -qq2440 MACH_QQ2440 QQ2440 1998 mini2440 MACH_MINI2440 MINI2440 1999 colibri300 MACH_COLIBRI300 COLIBRI300 2000 -jades MACH_JADES JADES 2001 -spark MACH_SPARK SPARK 2002 -benzina MACH_BENZINA BENZINA 2003 -blaze MACH_BLAZE BLAZE 2004 linkstation_ls_hgl MACH_LINKSTATION_LS_HGL LINKSTATION_LS_HGL 2005 -htckovsky MACH_HTCKOVSKY HTCKOVSKY 2006 -sony_prs505 MACH_SONY_PRS505 SONY_PRS505 2007 -hanlin_v3 MACH_HANLIN_V3 HANLIN_V3 2008 -sapphira MACH_SAPPHIRA SAPPHIRA 2009 -dack_sda_01 MACH_DACK_SDA_01 DACK_SDA_01 2010 -armbox MACH_ARMBOX ARMBOX 2011 -harris_rvp MACH_HARRIS_RVP HARRIS_RVP 2012 -ribaldo MACH_RIBALDO RIBALDO 2013 -agora MACH_AGORA AGORA 2014 -omap3_mini MACH_OMAP3_MINI OMAP3_MINI 2015 -a9sam6432_b MACH_A9SAM6432_B A9SAM6432_B 2016 -usg2410 MACH_USG2410 USG2410 2017 -pc72052_i10_revb MACH_PC72052_I10_REVB PC72052_I10_REVB 2018 -mx35_exm32 MACH_MX35_EXM32 MX35_EXM32 2019 -topas910 MACH_TOPAS910 TOPAS910 2020 -hyena MACH_HYENA HYENA 2021 -pospax MACH_POSPAX POSPAX 2022 -hdl_gx MACH_HDL_GX HDL_GX 2023 -ctera_4bay MACH_CTERA_4BAY CTERA_4BAY 2024 -ctera_plug_c MACH_CTERA_PLUG_C CTERA_PLUG_C 2025 -crwea_plug_i MACH_CRWEA_PLUG_I CRWEA_PLUG_I 2026 -egauge2 MACH_EGAUGE2 EGAUGE2 2027 -didj MACH_DIDJ DIDJ 2028 -m_s3c2443 MACH_MEISTER MEISTER 2029 -htcblackstone MACH_HTCBLACKSTONE HTCBLACKSTONE 2030 cpuat9g20 MACH_CPUAT9G20 CPUAT9G20 2031 smdk6440 MACH_SMDK6440 SMDK6440 2032 -omap_35xx_mvp MACH_OMAP_35XX_MVP OMAP_35XX_MVP 2033 -ctera_plug_i MACH_CTERA_PLUG_I CTERA_PLUG_I 2034 -pvg610_100 MACH_PVG610 PVG610 2035 -hprw6815 MACH_HPRW6815 HPRW6815 2036 -omap3_oswald MACH_OMAP3_OSWALD OMAP3_OSWALD 2037 nas4220b MACH_NAS4220B NAS4220B 2038 -htcraphael_cdma MACH_HTCRAPHAEL_CDMA HTCRAPHAEL_CDMA 2039 -htcdiamond_cdma MACH_HTCDIAMOND_CDMA HTCDIAMOND_CDMA 2040 -scaler MACH_SCALER SCALER 2041 zylonite2 MACH_ZYLONITE2 ZYLONITE2 2042 aspenite MACH_ASPENITE ASPENITE 2043 -teton MACH_TETON TETON 2044 ttc_dkb MACH_TTC_DKB TTC_DKB 2045 -bishop2 MACH_BISHOP2 BISHOP2 2046 -ippv5 MACH_IPPV5 IPPV5 2047 -farm926 MACH_FARM926 FARM926 2048 -mmccpu MACH_MMCCPU MMCCPU 2049 -sgmsfl MACH_SGMSFL SGMSFL 2050 -tt8000 MACH_TT8000 TT8000 2051 -zrn4300lp MACH_ZRN4300LP ZRN4300LP 2052 -mptc MACH_MPTC MPTC 2053 -h6051 MACH_H6051 H6051 2054 -pvg610_101 MACH_PVG610_101 PVG610_101 2055 -stamp9261_pc_evb MACH_STAMP9261_PC_EVB STAMP9261_PC_EVB 2056 -pelco_odysseus MACH_PELCO_ODYSSEUS PELCO_ODYSSEUS 2057 -tny_a9260 MACH_TNY_A9260 TNY_A9260 2058 -tny_a9g20 MACH_TNY_A9G20 TNY_A9G20 2059 -aesop_mp2530f MACH_AESOP_MP2530F AESOP_MP2530F 2060 -dx900 MACH_DX900 DX900 2061 -cpodc2 MACH_CPODC2 CPODC2 2062 -tilt_8925 MACH_TILT_8925 TILT_8925 2063 -davinci_dm357_evm MACH_DAVINCI_DM357_EVM DAVINCI_DM357_EVM 2064 -swordfish MACH_SWORDFISH SWORDFISH 2065 -corvus MACH_CORVUS CORVUS 2066 -taurus MACH_TAURUS TAURUS 2067 -axm MACH_AXM AXM 2068 -axc MACH_AXC AXC 2069 -baby MACH_BABY BABY 2070 -mp200 MACH_MP200 MP200 2071 pcm043 MACH_PCM043 PCM043 2072 -hanlin_v3c MACH_HANLIN_V3C HANLIN_V3C 2073 -kbk9g20 MACH_KBK9G20 KBK9G20 2074 -adsturbog5 MACH_ADSTURBOG5 ADSTURBOG5 2075 -avenger_lite1 MACH_AVENGER_LITE1 AVENGER_LITE1 2076 -suc82x MACH_SUC SUC 2077 -at91sam7s256 MACH_AT91SAM7S256 AT91SAM7S256 2078 -mendoza MACH_MENDOZA MENDOZA 2079 -kira MACH_KIRA KIRA 2080 -mx1hbm MACH_MX1HBM MX1HBM 2081 -quatro43xx MACH_QUATRO43XX QUATRO43XX 2082 -quatro4230 MACH_QUATRO4230 QUATRO4230 2083 -nsb400 MACH_NSB400 NSB400 2084 -drp255 MACH_DRP255 DRP255 2085 -thoth MACH_THOTH THOTH 2086 -firestone MACH_FIRESTONE FIRESTONE 2087 -asusp750 MACH_ASUSP750 ASUSP750 2088 -ctera_dl MACH_CTERA_DL CTERA_DL 2089 -socr MACH_SOCR SOCR 2090 -htcoxygen MACH_HTCOXYGEN HTCOXYGEN 2091 -heroc MACH_HEROC HEROC 2092 -zeno6800 MACH_ZENO6800 ZENO6800 2093 -sc2mcs MACH_SC2MCS SC2MCS 2094 -gene100 MACH_GENE100 GENE100 2095 -as353x MACH_AS353X AS353X 2096 sheevaplug MACH_SHEEVAPLUG SHEEVAPLUG 2097 -at91sam9g20 MACH_AT91SAM9G20 AT91SAM9G20 2098 -mv88f6192gtw_fe MACH_MV88F6192GTW_FE MV88F6192GTW_FE 2099 -cc9200 MACH_CC9200 CC9200 2100 -sm9200 MACH_SM9200 SM9200 2101 -tp9200 MACH_TP9200 TP9200 2102 -snapperdv MACH_SNAPPERDV SNAPPERDV 2103 avengers_lite MACH_AVENGERS_LITE AVENGERS_LITE 2104 -avengers_lite1 MACH_AVENGERS_LITE1 AVENGERS_LITE1 2105 -omap3axon MACH_OMAP3AXON OMAP3AXON 2106 -ma8xx MACH_MA8XX MA8XX 2107 -mp201ek MACH_MP201EK MP201EK 2108 -davinci_tux MACH_DAVINCI_TUX DAVINCI_TUX 2109 -mpa1600 MACH_MPA1600 MPA1600 2110 -pelco_troy MACH_PELCO_TROY PELCO_TROY 2111 -nsb667 MACH_NSB667 NSB667 2112 -rovers5_4mpix MACH_ROVERS5_4MPIX ROVERS5_4MPIX 2113 -twocom MACH_TWOCOM TWOCOM 2114 -ubisys_p9_rcu3r2 MACH_UBISYS_P9_RCU3R2 UBISYS_P9_RCU3R2 2115 -hero_espresso MACH_HERO_ESPRESSO HERO_ESPRESSO 2116 -afeusb MACH_AFEUSB AFEUSB 2117 -t830 MACH_T830 T830 2118 -spd8020_cc MACH_SPD8020_CC SPD8020_CC 2119 -om_3d7k MACH_OM_3D7K OM_3D7K 2120 -picocom2 MACH_PICOCOM2 PICOCOM2 2121 -uwg4mx27 MACH_UWG4MX27 UWG4MX27 2122 -uwg4mx31 MACH_UWG4MX31 UWG4MX31 2123 -cherry MACH_CHERRY CHERRY 2124 mx51_babbage MACH_MX51_BABBAGE MX51_BABBAGE 2125 -s3c2440turkiye MACH_S3C2440TURKIYE S3C2440TURKIYE 2126 -tx37 MACH_TX37 TX37 2127 -sbc2800_9g20 MACH_SBC2800_9G20 SBC2800_9G20 2128 -benzglb MACH_BENZGLB BENZGLB 2129 -benztd MACH_BENZTD BENZTD 2130 -cartesio_plus MACH_CARTESIO_PLUS CARTESIO_PLUS 2131 -solrad_g20 MACH_SOLRAD_G20 SOLRAD_G20 2132 -mx27wallace MACH_MX27WALLACE MX27WALLACE 2133 -fmzwebmodul MACH_FMZWEBMODUL FMZWEBMODUL 2134 rd78x00_masa MACH_RD78X00_MASA RD78X00_MASA 2135 -smallogger MACH_SMALLOGGER SMALLOGGER 2136 -ccw9p9215 MACH_CCW9P9215 CCW9P9215 2137 dm355_leopard MACH_DM355_LEOPARD DM355_LEOPARD 2138 ts219 MACH_TS219 TS219 2139 -tny_a9263 MACH_TNY_A9263 TNY_A9263 2140 -apollo MACH_APOLLO APOLLO 2141 -at91cap9stk MACH_AT91CAP9STK AT91CAP9STK 2142 -spc300 MACH_SPC300 SPC300 2143 -eko MACH_EKO EKO 2144 -ccw9m2443 MACH_CCW9M2443 CCW9M2443 2145 -ccw9m2443js MACH_CCW9M2443JS CCW9M2443JS 2146 -m2m_router_device MACH_M2M_ROUTER_DEVICE M2M_ROUTER_DEVICE 2147 -str9104nas MACH_STAR9104NAS STAR9104NAS 2148 pca100 MACH_PCA100 PCA100 2149 -z3_dm365_mod_01 MACH_Z3_DM365_MOD_01 Z3_DM365_MOD_01 2150 -hipox MACH_HIPOX HIPOX 2151 -omap3_piteds MACH_OMAP3_PITEDS OMAP3_PITEDS 2152 -bm150r MACH_BM150R BM150R 2153 -tbone MACH_TBONE TBONE 2154 -merlin MACH_MERLIN MERLIN 2155 -falcon MACH_FALCON FALCON 2156 davinci_da850_evm MACH_DAVINCI_DA850_EVM DAVINCI_DA850_EVM 2157 -s5p6440 MACH_S5P6440 S5P6440 2158 at91sam9g10ek MACH_AT91SAM9G10EK AT91SAM9G10EK 2159 omap_4430sdp MACH_OMAP_4430SDP OMAP_4430SDP 2160 -lpc313x MACH_LPC313X LPC313X 2161 magx_zn5 MACH_MAGX_ZN5 MAGX_ZN5 2162 -magx_em30 MACH_MAGX_EM30 MAGX_EM30 2163 -magx_ve66 MACH_MAGX_VE66 MAGX_VE66 2164 -meesc MACH_MEESC MEESC 2165 -otc570 MACH_OTC570 OTC570 2166 -bcu2412 MACH_BCU2412 BCU2412 2167 -beacon MACH_BEACON BEACON 2168 -actia_tgw MACH_ACTIA_TGW ACTIA_TGW 2169 -e4430 MACH_E4430 E4430 2170 -ql300 MACH_QL300 QL300 2171 -btmavb101 MACH_BTMAVB101 BTMAVB101 2172 -btmawb101 MACH_BTMAWB101 BTMAWB101 2173 -sq201 MACH_SQ201 SQ201 2174 -quatro45xx MACH_QUATRO45XX QUATRO45XX 2175 -openpad MACH_OPENPAD OPENPAD 2176 -tx25 MACH_TX25 TX25 2177 omap3_torpedo MACH_OMAP3_TORPEDO OMAP3_TORPEDO 2178 -htcraphael_k MACH_HTCRAPHAEL_K HTCRAPHAEL_K 2179 -lal43 MACH_LAL43 LAL43 2181 -htcraphael_cdma500 MACH_HTCRAPHAEL_CDMA500 HTCRAPHAEL_CDMA500 2182 anw6410 MACH_ANW6410 ANW6410 2183 -htcprophet MACH_HTCPROPHET HTCPROPHET 2185 -cfa_10022 MACH_CFA_10022 CFA_10022 2186 imx27_visstrim_m10 MACH_IMX27_VISSTRIM_M10 IMX27_VISSTRIM_M10 2187 -px2imx27 MACH_PX2IMX27 PX2IMX27 2188 -stm3210e_eval MACH_STM3210E_EVAL STM3210E_EVAL 2189 -dvs10 MACH_DVS10 DVS10 2190 portuxg20 MACH_PORTUXG20 PORTUXG20 2191 -arm_spv MACH_ARM_SPV ARM_SPV 2192 smdkc110 MACH_SMDKC110 SMDKC110 2193 -cabespresso MACH_CABESPRESSO CABESPRESSO 2194 -hmc800 MACH_HMC800 HMC800 2195 -sholes MACH_SHOLES SHOLES 2196 -btmxc31 MACH_BTMXC31 BTMXC31 2197 -dt501 MACH_DT501 DT501 2198 -ktx MACH_KTX KTX 2199 omap3517evm MACH_OMAP3517EVM OMAP3517EVM 2200 netspace_v2 MACH_NETSPACE_V2 NETSPACE_V2 2201 netspace_max_v2 MACH_NETSPACE_MAX_V2 NETSPACE_MAX_V2 2202 d2net_v2 MACH_D2NET_V2 D2NET_V2 2203 net2big_v2 MACH_NET2BIG_V2 NET2BIG_V2 2204 -net4big_v2 MACH_NET4BIG_V2 NET4BIG_V2 2205 net5big_v2 MACH_NET5BIG_V2 NET5BIG_V2 2206 -endb2443 MACH_ENDB2443 ENDB2443 2207 inetspace_v2 MACH_INETSPACE_V2 INETSPACE_V2 2208 -tros MACH_TROS TROS 2209 -pelco_homer MACH_PELCO_HOMER PELCO_HOMER 2210 -ofsp8 MACH_OFSP8 OFSP8 2211 at91sam9g45ekes MACH_AT91SAM9G45EKES AT91SAM9G45EKES 2212 -guf_cupid MACH_GUF_CUPID GUF_CUPID 2213 -eab1r MACH_EAB1R EAB1R 2214 -desirec MACH_DESIREC DESIREC 2215 -cordoba MACH_CORDOBA CORDOBA 2216 -irvine MACH_IRVINE IRVINE 2217 -sff772 MACH_SFF772 SFF772 2218 -pelco_milano MACH_PELCO_MILANO PELCO_MILANO 2219 pc7302 MACH_PC7302 PC7302 2220 -bip6000 MACH_BIP6000 BIP6000 2221 -silvermoon MACH_SILVERMOON SILVERMOON 2222 -vc0830 MACH_VC0830 VC0830 2223 -dt430 MACH_DT430 DT430 2224 -ji42pf MACH_JI42PF JI42PF 2225 -gnet_ksm MACH_GNET_KSM GNET_KSM 2226 -gnet_sgm MACH_GNET_SGM GNET_SGM 2227 -gnet_sgr MACH_GNET_SGR GNET_SGR 2228 -omap3_icetekevm MACH_OMAP3_ICETEKEVM OMAP3_ICETEKEVM 2229 -pnp MACH_PNP PNP 2230 -ctera_2bay_k MACH_CTERA_2BAY_K CTERA_2BAY_K 2231 -ctera_2bay_u MACH_CTERA_2BAY_U CTERA_2BAY_U 2232 -sas_c MACH_SAS_C SAS_C 2233 -vma2315 MACH_VMA2315 VMA2315 2234 -vcs MACH_VCS VCS 2235 spear600 MACH_SPEAR600 SPEAR600 2236 spear300 MACH_SPEAR300 SPEAR300 2237 -spear1300 MACH_SPEAR1300 SPEAR1300 2238 lilly1131 MACH_LILLY1131 LILLY1131 2239 -arvoo_ax301 MACH_ARVOO_AX301 ARVOO_AX301 2240 -mapphone MACH_MAPPHONE MAPPHONE 2241 -legend MACH_LEGEND LEGEND 2242 -salsa MACH_SALSA SALSA 2243 -lounge MACH_LOUNGE LOUNGE 2244 -vision MACH_VISION VISION 2245 -vmb20 MACH_VMB20 VMB20 2246 -hy2410 MACH_HY2410 HY2410 2247 -hy9315 MACH_HY9315 HY9315 2248 -bullwinkle MACH_BULLWINKLE BULLWINKLE 2249 -arm_ultimator2 MACH_ARM_ULTIMATOR2 ARM_ULTIMATOR2 2250 -vs_v210 MACH_VS_V210 VS_V210 2252 -vs_v212 MACH_VS_V212 VS_V212 2253 hmt MACH_HMT HMT 2254 -km_kirkwood MACH_KM_KIRKWOOD KM_KIRKWOOD 2255 -vesper MACH_VESPER VESPER 2256 -str9 MACH_STR9 STR9 2257 -omap3_wl_ff MACH_OMAP3_WL_FF OMAP3_WL_FF 2258 -simcom MACH_SIMCOM SIMCOM 2259 -mcwebio MACH_MCWEBIO MCWEBIO 2260 -omap3_phrazer MACH_OMAP3_PHRAZER OMAP3_PHRAZER 2261 -darwin MACH_DARWIN DARWIN 2262 -oratiscomu MACH_ORATISCOMU ORATISCOMU 2263 -rtsbc20 MACH_RTSBC20 RTSBC20 2264 -sgh_i780 MACH_I780 I780 2265 -gemini324 MACH_GEMINI324 GEMINI324 2266 -oratislan MACH_ORATISLAN ORATISLAN 2267 -oratisalog MACH_ORATISALOG ORATISALOG 2268 -oratismadi MACH_ORATISMADI ORATISMADI 2269 -oratisot16 MACH_ORATISOT16 ORATISOT16 2270 -oratisdesk MACH_ORATISDESK ORATISDESK 2271 vexpress MACH_VEXPRESS VEXPRESS 2272 -sintexo MACH_SINTEXO SINTEXO 2273 -cm3389 MACH_CM3389 CM3389 2274 -omap3_cio MACH_OMAP3_CIO OMAP3_CIO 2275 -sgh_i900 MACH_SGH_I900 SGH_I900 2276 -bst100 MACH_BST100 BST100 2277 -passion MACH_PASSION PASSION 2278 -indesign_at91sam MACH_INDESIGN_AT91SAM INDESIGN_AT91SAM 2279 -c4_badger MACH_C4_BADGER C4_BADGER 2280 -c4_viper MACH_C4_VIPER C4_VIPER 2281 d2net MACH_D2NET D2NET 2282 bigdisk MACH_BIGDISK BIGDISK 2283 -notalvision MACH_NOTALVISION NOTALVISION 2284 -omap3_kboc MACH_OMAP3_KBOC OMAP3_KBOC 2285 -cyclone MACH_CYCLONE CYCLONE 2286 -ninja MACH_NINJA NINJA 2287 at91sam9g20ek_2mmc MACH_AT91SAM9G20EK_2MMC AT91SAM9G20EK_2MMC 2288 bcmring MACH_BCMRING BCMRING 2289 -resol_dl2 MACH_RESOL_DL2 RESOL_DL2 2290 -ifosw MACH_IFOSW IFOSW 2291 -htcrhodium MACH_HTCRHODIUM HTCRHODIUM 2292 -htctopaz MACH_HTCTOPAZ HTCTOPAZ 2293 -matrix504 MACH_MATRIX504 MATRIX504 2294 -mrfsa MACH_MRFSA MRFSA 2295 -sc_p270 MACH_SC_P270 SC_P270 2296 -atlas5_evb MACH_ATLAS5_EVB ATLAS5_EVB 2297 -pelco_lobox MACH_PELCO_LOBOX PELCO_LOBOX 2298 -dilax_pcu200 MACH_DILAX_PCU200 DILAX_PCU200 2299 -leonardo MACH_LEONARDO LEONARDO 2300 -zoran_approach7 MACH_ZORAN_APPROACH7 ZORAN_APPROACH7 2301 -dp6xx MACH_DP6XX DP6XX 2302 -bcm2153_vesper MACH_BCM2153_VESPER BCM2153_VESPER 2303 mahimahi MACH_MAHIMAHI MAHIMAHI 2304 -clickc MACH_CLICKC CLICKC 2305 -zb_gateway MACH_ZB_GATEWAY ZB_GATEWAY 2306 -tazcard MACH_TAZCARD TAZCARD 2307 -tazdev MACH_TAZDEV TAZDEV 2308 -annax_cb_arm MACH_ANNAX_CB_ARM ANNAX_CB_ARM 2309 -annax_dm3 MACH_ANNAX_DM3 ANNAX_DM3 2310 -cerebric MACH_CEREBRIC CEREBRIC 2311 -orca MACH_ORCA ORCA 2312 -pc9260 MACH_PC9260 PC9260 2313 -ems285a MACH_EMS285A EMS285A 2314 -gec2410 MACH_GEC2410 GEC2410 2315 -gec2440 MACH_GEC2440 GEC2440 2316 -mw903 MACH_ARCH_MW903 ARCH_MW903 2317 -mw2440 MACH_MW2440 MW2440 2318 -ecac2378 MACH_ECAC2378 ECAC2378 2319 -tazkiosk MACH_TAZKIOSK TAZKIOSK 2320 -whiterabbit_mch MACH_WHITERABBIT_MCH WHITERABBIT_MCH 2321 -sbox9263 MACH_SBOX9263 SBOX9263 2322 -oreo MACH_OREO OREO 2323 smdk6442 MACH_SMDK6442 SMDK6442 2324 openrd_base MACH_OPENRD_BASE OPENRD_BASE 2325 -incredible MACH_INCREDIBLE INCREDIBLE 2326 -incrediblec MACH_INCREDIBLEC INCREDIBLEC 2327 -heroct MACH_HEROCT HEROCT 2328 -mmnet1000 MACH_MMNET1000 MMNET1000 2329 devkit8000 MACH_DEVKIT8000 DEVKIT8000 2330 -devkit9000 MACH_DEVKIT9000 DEVKIT9000 2331 -mx31txtr MACH_MX31TXTR MX31TXTR 2332 -u380 MACH_U380 U380 2333 -oamp3_hualu MACH_HUALU_BOARD HUALU_BOARD 2334 -npcmx50 MACH_NPCMX50 NPCMX50 2335 mx51_efikamx MACH_MX51_EFIKAMX MX51_EFIKAMX 2336 -mx51_lange52 MACH_MX51_LANGE52 MX51_LANGE52 2337 -riom MACH_RIOM RIOM 2338 -comcas MACH_COMCAS COMCAS 2339 -wsi_mx27 MACH_WSI_MX27 WSI_MX27 2340 cm_t35 MACH_CM_T35 CM_T35 2341 net2big MACH_NET2BIG NET2BIG 2342 -motorola_a1600 MACH_MOTOROLA_A1600 MOTOROLA_A1600 2343 igep0020 MACH_IGEP0020 IGEP0020 2344 -igep0010 MACH_IGEP0010 IGEP0010 2345 -mv6281gtwge2 MACH_MV6281GTWGE2 MV6281GTWGE2 2346 -scat100 MACH_SCAT100 SCAT100 2347 -sanmina MACH_SANMINA SANMINA 2348 -momento MACH_MOMENTO MOMENTO 2349 -nuc9xx MACH_NUC9XX NUC9XX 2350 -nuc910evb MACH_NUC910EVB NUC910EVB 2351 -nuc920evb MACH_NUC920EVB NUC920EVB 2352 -nuc950evb MACH_NUC950EVB NUC950EVB 2353 -nuc945evb MACH_NUC945EVB NUC945EVB 2354 -nuc960evb MACH_NUC960EVB NUC960EVB 2355 nuc932evb MACH_NUC932EVB NUC932EVB 2356 -nuc900 MACH_NUC900 NUC900 2357 -sd1soc MACH_SD1SOC SD1SOC 2358 -ln2440bc MACH_LN2440BC LN2440BC 2359 -rsbc MACH_RSBC RSBC 2360 openrd_client MACH_OPENRD_CLIENT OPENRD_CLIENT 2361 -hpipaq11x MACH_HPIPAQ11X HPIPAQ11X 2362 -wayland MACH_WAYLAND WAYLAND 2363 -acnbsx102 MACH_ACNBSX102 ACNBSX102 2364 -hwat91 MACH_HWAT91 HWAT91 2365 -at91sam9263cs MACH_AT91SAM9263CS AT91SAM9263CS 2366 -csb732 MACH_CSB732 CSB732 2367 u8500 MACH_U8500 U8500 2368 -huqiu MACH_HUQIU HUQIU 2369 mx51_efikasb MACH_MX51_EFIKASB MX51_EFIKASB 2370 -pmt1g MACH_PMT1G PMT1G 2371 -htcelf MACH_HTCELF HTCELF 2372 -armadillo420 MACH_ARMADILLO420 ARMADILLO420 2373 -armadillo440 MACH_ARMADILLO440 ARMADILLO440 2374 -u_chip_dual_arm MACH_U_CHIP_DUAL_ARM U_CHIP_DUAL_ARM 2375 -csr_bdb3 MACH_CSR_BDB3 CSR_BDB3 2376 -dolby_cat1018 MACH_DOLBY_CAT1018 DOLBY_CAT1018 2377 -hy9307 MACH_HY9307 HY9307 2378 -aspire_easystore MACH_A_ES A_ES 2379 -davinci_irif MACH_DAVINCI_IRIF DAVINCI_IRIF 2380 -agama9263 MACH_AGAMA9263 AGAMA9263 2381 marvell_jasper MACH_MARVELL_JASPER MARVELL_JASPER 2382 flint MACH_FLINT FLINT 2383 tavorevb3 MACH_TAVOREVB3 TAVOREVB3 2384 -sch_m490 MACH_SCH_M490 SCH_M490 2386 -rbl01 MACH_RBL01 RBL01 2387 -omnifi MACH_OMNIFI OMNIFI 2388 -otavalo MACH_OTAVALO OTAVALO 2389 -sienna MACH_SIENNA SIENNA 2390 -htc_excalibur_s620 MACH_HTC_EXCALIBUR_S620 HTC_EXCALIBUR_S620 2391 -htc_opal MACH_HTC_OPAL HTC_OPAL 2392 touchbook MACH_TOUCHBOOK TOUCHBOOK 2393 -latte MACH_LATTE LATTE 2394 -xa200 MACH_XA200 XA200 2395 -nimrod MACH_NIMROD NIMROD 2396 -cc9p9215_3g MACH_CC9P9215_3G CC9P9215_3G 2397 -cc9p9215_3gjs MACH_CC9P9215_3GJS CC9P9215_3GJS 2398 -tk71 MACH_TK71 TK71 2399 -comham3525 MACH_COMHAM3525 COMHAM3525 2400 -mx31erebus MACH_MX31EREBUS MX31EREBUS 2401 -mcardmx27 MACH_MCARDMX27 MCARDMX27 2402 -paradise MACH_PARADISE PARADISE 2403 -tide MACH_TIDE TIDE 2404 -wzl2440 MACH_WZL2440 WZL2440 2405 -sdrdemo MACH_SDRDEMO SDRDEMO 2406 -ethercan2 MACH_ETHERCAN2 ETHERCAN2 2407 -ecmimg20 MACH_ECMIMG20 ECMIMG20 2408 -omap_dragon MACH_OMAP_DRAGON OMAP_DRAGON 2409 -halo MACH_HALO HALO 2410 -huangshan MACH_HUANGSHAN HUANGSHAN 2411 -vl_ma2sc MACH_VL_MA2SC VL_MA2SC 2412 raumfeld_rc MACH_RAUMFELD_RC RAUMFELD_RC 2413 raumfeld_connector MACH_RAUMFELD_CONNECTOR RAUMFELD_CONNECTOR 2414 raumfeld_speaker MACH_RAUMFELD_SPEAKER RAUMFELD_SPEAKER 2415 -multibus_master MACH_MULTIBUS_MASTER MULTIBUS_MASTER 2416 -multibus_pbk MACH_MULTIBUS_PBK MULTIBUS_PBK 2417 tnetv107x MACH_TNETV107X TNETV107X 2418 -snake MACH_SNAKE SNAKE 2419 -cwmx27 MACH_CWMX27 CWMX27 2420 -sch_m480 MACH_SCH_M480 SCH_M480 2421 -platypus MACH_PLATYPUS PLATYPUS 2422 -pss2 MACH_PSS2 PSS2 2423 -davinci_apm150 MACH_DAVINCI_APM150 DAVINCI_APM150 2424 -str9100 MACH_STR9100 STR9100 2425 -net5big MACH_NET5BIG NET5BIG 2426 -seabed9263 MACH_SEABED9263 SEABED9263 2427 -mx51_m2id MACH_MX51_M2ID MX51_M2ID 2428 -octvocplus_eb MACH_OCTVOCPLUS_EB OCTVOCPLUS_EB 2429 -klk_firefox MACH_KLK_FIREFOX KLK_FIREFOX 2430 -klk_wirma_module MACH_KLK_WIRMA_MODULE KLK_WIRMA_MODULE 2431 -klk_wirma_mmi MACH_KLK_WIRMA_MMI KLK_WIRMA_MMI 2432 -supersonic MACH_SUPERSONIC SUPERSONIC 2433 -liberty MACH_LIBERTY LIBERTY 2434 -mh355 MACH_MH355 MH355 2435 -pc7802 MACH_PC7802 PC7802 2436 -gnet_sgc MACH_GNET_SGC GNET_SGC 2437 -einstein15 MACH_EINSTEIN15 EINSTEIN15 2438 -cmpd MACH_CMPD CMPD 2439 -davinci_hase1 MACH_DAVINCI_HASE1 DAVINCI_HASE1 2440 -lgeincitephone MACH_LGEINCITEPHONE LGEINCITEPHONE 2441 -ea313x MACH_EA313X EA313X 2442 -fwbd_39064 MACH_FWBD_39064 FWBD_39064 2443 -fwbd_390128 MACH_FWBD_390128 FWBD_390128 2444 -pelco_moe MACH_PELCO_MOE PELCO_MOE 2445 -minimix27 MACH_MINIMIX27 MINIMIX27 2446 -omap3_thunder MACH_OMAP3_THUNDER OMAP3_THUNDER 2447 -passionc MACH_PASSIONC PASSIONC 2448 -mx27amata MACH_MX27AMATA MX27AMATA 2449 -bgat1 MACH_BGAT1 BGAT1 2450 -buzz MACH_BUZZ BUZZ 2451 -mb9g20 MACH_MB9G20 MB9G20 2452 -yushan MACH_YUSHAN YUSHAN 2453 -lizard MACH_LIZARD LIZARD 2454 -omap3polycom MACH_OMAP3POLYCOM OMAP3POLYCOM 2455 smdkv210 MACH_SMDKV210 SMDKV210 2456 -bravo MACH_BRAVO BRAVO 2457 -siogentoo1 MACH_SIOGENTOO1 SIOGENTOO1 2458 -siogentoo2 MACH_SIOGENTOO2 SIOGENTOO2 2459 -sm3k MACH_SM3K SM3K 2460 -acer_tempo_f900 MACH_ACER_TEMPO_F900 ACER_TEMPO_F900 2461 -sst61vc010_dev MACH_SST61VC010_DEV SST61VC010_DEV 2462 -glittertind MACH_GLITTERTIND GLITTERTIND 2463 omap_zoom3 MACH_OMAP_ZOOM3 OMAP_ZOOM3 2464 omap_3630sdp MACH_OMAP_3630SDP OMAP_3630SDP 2465 -cybook2440 MACH_CYBOOK2440 CYBOOK2440 2466 -torino_s MACH_TORINO_S TORINO_S 2467 -havana MACH_HAVANA HAVANA 2468 -beaumont_11 MACH_BEAUMONT_11 BEAUMONT_11 2469 -vanguard MACH_VANGUARD VANGUARD 2470 -s5pc110_draco MACH_S5PC110_DRACO S5PC110_DRACO 2471 -cartesio_two MACH_CARTESIO_TWO CARTESIO_TWO 2472 -aster MACH_ASTER ASTER 2473 -voguesv210 MACH_VOGUESV210 VOGUESV210 2474 -acm500x MACH_ACM500X ACM500X 2475 -km9260 MACH_KM9260 KM9260 2476 -nideflexg1 MACH_NIDEFLEXG1 NIDEFLEXG1 2477 -ctera_plug_io MACH_CTERA_PLUG_IO CTERA_PLUG_IO 2478 smartq7 MACH_SMARTQ7 SMARTQ7 2479 -at91sam9g10ek2 MACH_AT91SAM9G10EK2 AT91SAM9G10EK2 2480 -asusp527 MACH_ASUSP527 ASUSP527 2481 -at91sam9g20mpm2 MACH_AT91SAM9G20MPM2 AT91SAM9G20MPM2 2482 -topasa900 MACH_TOPASA900 TOPASA900 2483 -electrum_100 MACH_ELECTRUM_100 ELECTRUM_100 2484 -mx51grb MACH_MX51GRB MX51GRB 2485 -xea300 MACH_XEA300 XEA300 2486 -htcstartrek MACH_HTCSTARTREK HTCSTARTREK 2487 -lima MACH_LIMA LIMA 2488 -csb740 MACH_CSB740 CSB740 2489 -usb_s8815 MACH_USB_S8815 USB_S8815 2490 -watson_efm_plugin MACH_WATSON_EFM_PLUGIN WATSON_EFM_PLUGIN 2491 -milkyway MACH_MILKYWAY MILKYWAY 2492 g4evm MACH_G4EVM G4EVM 2493 -picomod6 MACH_PICOMOD6 PICOMOD6 2494 omapl138_hawkboard MACH_OMAPL138_HAWKBOARD OMAPL138_HAWKBOARD 2495 -ip6000 MACH_IP6000 IP6000 2496 -ip6010 MACH_IP6010 IP6010 2497 -utm400 MACH_UTM400 UTM400 2498 -omap3_zybex MACH_OMAP3_ZYBEX OMAP3_ZYBEX 2499 -wireless_space MACH_WIRELESS_SPACE WIRELESS_SPACE 2500 -sx560 MACH_SX560 SX560 2501 ts41x MACH_TS41X TS41X 2502 -elphel10373 MACH_ELPHEL10373 ELPHEL10373 2503 -rhobot MACH_RHOBOT RHOBOT 2504 -mx51_refresh MACH_MX51_REFRESH MX51_REFRESH 2505 -ls9260 MACH_LS9260 LS9260 2506 -shank MACH_SHANK SHANK 2507 -qsd8x50_st1 MACH_QSD8X50_ST1 QSD8X50_ST1 2508 -at91sam9m10ekes MACH_AT91SAM9M10EKES AT91SAM9M10EKES 2509 -hiram MACH_HIRAM HIRAM 2510 phy3250 MACH_PHY3250 PHY3250 2511 -ea3250 MACH_EA3250 EA3250 2512 -fdi3250 MACH_FDI3250 FDI3250 2513 -whitestone MACH_WHITESTONE WHITESTONE 2514 -at91sam9263nit MACH_AT91SAM9263NIT AT91SAM9263NIT 2515 -ccmx51 MACH_CCMX51 CCMX51 2516 -ccmx51js MACH_CCMX51JS CCMX51JS 2517 -ccwmx51 MACH_CCWMX51 CCWMX51 2518 -ccwmx51js MACH_CCWMX51JS CCWMX51JS 2519 mini6410 MACH_MINI6410 MINI6410 2520 -tiny6410 MACH_TINY6410 TINY6410 2521 -nano6410 MACH_NANO6410 NANO6410 2522 -at572d940hfnldb MACH_AT572D940HFNLDB AT572D940HFNLDB 2523 -htcleo MACH_HTCLEO HTCLEO 2524 -avp13 MACH_AVP13 AVP13 2525 -xxsvideod MACH_XXSVIDEOD XXSVIDEOD 2526 -vpnext MACH_VPNEXT VPNEXT 2527 -swarco_itc3 MACH_SWARCO_ITC3 SWARCO_ITC3 2528 -tx51 MACH_TX51 TX51 2529 -dolby_cat1021 MACH_DOLBY_CAT1021 DOLBY_CAT1021 2530 mx28evk MACH_MX28EVK MX28EVK 2531 -phoenix260 MACH_PHOENIX260 PHOENIX260 2532 -uvaca_stork MACH_UVACA_STORK UVACA_STORK 2533 smartq5 MACH_SMARTQ5 SMARTQ5 2534 -all3078 MACH_ALL3078 ALL3078 2535 -ctera_2bay_ds MACH_CTERA_2BAY_DS CTERA_2BAY_DS 2536 -siogentoo3 MACH_SIOGENTOO3 SIOGENTOO3 2537 -epb5000 MACH_EPB5000 EPB5000 2538 -hy9263 MACH_HY9263 HY9263 2539 -acer_tempo_m900 MACH_ACER_TEMPO_M900 ACER_TEMPO_M900 2540 -acer_tempo_dx650 MACH_ACER_TEMPO_DX900 ACER_TEMPO_DX900 2541 -acer_tempo_x960 MACH_ACER_TEMPO_X960 ACER_TEMPO_X960 2542 -acer_eten_v900 MACH_ACER_ETEN_V900 ACER_ETEN_V900 2543 -acer_eten_x900 MACH_ACER_ETEN_X900 ACER_ETEN_X900 2544 -bonnell MACH_BONNELL BONNELL 2545 -oht_mx27 MACH_OHT_MX27 OHT_MX27 2546 -htcquartz MACH_HTCQUARTZ HTCQUARTZ 2547 davinci_dm6467tevm MACH_DAVINCI_DM6467TEVM DAVINCI_DM6467TEVM 2548 -c3ax03 MACH_C3AX03 C3AX03 2549 mxt_td60 MACH_MXT_TD60 MXT_TD60 2550 -esyx MACH_ESYX ESYX 2551 -dove_db2 MACH_DOVE_DB2 DOVE_DB2 2552 -bulldog MACH_BULLDOG BULLDOG 2553 -derell_me2000 MACH_DERELL_ME2000 DERELL_ME2000 2554 -bcmring_base MACH_BCMRING_BASE BCMRING_BASE 2555 -bcmring_evm MACH_BCMRING_EVM BCMRING_EVM 2556 -bcmring_evm_jazz MACH_BCMRING_EVM_JAZZ BCMRING_EVM_JAZZ 2557 -bcmring_sp MACH_BCMRING_SP BCMRING_SP 2558 -bcmring_sv MACH_BCMRING_SV BCMRING_SV 2559 -bcmring_sv_jazz MACH_BCMRING_SV_JAZZ BCMRING_SV_JAZZ 2560 -bcmring_tablet MACH_BCMRING_TABLET BCMRING_TABLET 2561 -bcmring_vp MACH_BCMRING_VP BCMRING_VP 2562 -bcmring_evm_seikor MACH_BCMRING_EVM_SEIKOR BCMRING_EVM_SEIKOR 2563 -bcmring_sp_wqvga MACH_BCMRING_SP_WQVGA BCMRING_SP_WQVGA 2564 -bcmring_custom MACH_BCMRING_CUSTOM BCMRING_CUSTOM 2565 -acer_s200 MACH_ACER_S200 ACER_S200 2566 -bt270 MACH_BT270 BT270 2567 -iseo MACH_ISEO ISEO 2568 -cezanne MACH_CEZANNE CEZANNE 2569 -lucca MACH_LUCCA LUCCA 2570 -supersmart MACH_SUPERSMART SUPERSMART 2571 -arm11_board MACH_CS_MISANO CS_MISANO 2572 -magnolia2 MACH_MAGNOLIA2 MAGNOLIA2 2573 -emxx MACH_EMXX EMXX 2574 -outlaw MACH_OUTLAW OUTLAW 2575 -riot_bei2 MACH_RIOT_BEI2 RIOT_BEI2 2576 -riot_vox MACH_RIOT_VOX RIOT_VOX 2577 -riot_x37 MACH_RIOT_X37 RIOT_X37 2578 -mega25mx MACH_MEGA25MX MEGA25MX 2579 -benzina2 MACH_BENZINA2 BENZINA2 2580 -ignite MACH_IGNITE IGNITE 2581 -foggia MACH_FOGGIA FOGGIA 2582 -arezzo MACH_AREZZO AREZZO 2583 -leica_skywalker MACH_LEICA_SKYWALKER LEICA_SKYWALKER 2584 -jacinto2_jamr MACH_JACINTO2_JAMR JACINTO2_JAMR 2585 -gts_nova MACH_GTS_NOVA GTS_NOVA 2586 -p3600 MACH_P3600 P3600 2587 -dlt2 MACH_DLT2 DLT2 2588 -df3120 MACH_DF3120 DF3120 2589 -ecucore_9g20 MACH_ECUCORE_9G20 ECUCORE_9G20 2590 -nautel_lpc3240 MACH_NAUTEL_LPC3240 NAUTEL_LPC3240 2591 -glacier MACH_GLACIER GLACIER 2592 -phrazer_bulldog MACH_PHRAZER_BULLDOG PHRAZER_BULLDOG 2593 -omap3_bulldog MACH_OMAP3_BULLDOG OMAP3_BULLDOG 2594 -pca101 MACH_PCA101 PCA101 2595 -buzzc MACH_BUZZC BUZZC 2596 -sasie2 MACH_SASIE2 SASIE2 2597 -davinci_cio MACH_DAVINCI_CIO DAVINCI_CIO 2598 -smartmeter_dl MACH_SMARTMETER_DL SMARTMETER_DL 2599 -wzl6410 MACH_WZL6410 WZL6410 2600 -wzl6410m MACH_WZL6410M WZL6410M 2601 -wzl6410f MACH_WZL6410F WZL6410F 2602 -wzl6410i MACH_WZL6410I WZL6410I 2603 -spacecom1 MACH_SPACECOM1 SPACECOM1 2604 -pingu920 MACH_PINGU920 PINGU920 2605 -bravoc MACH_BRAVOC BRAVOC 2606 -cybo2440 MACH_CYBO2440 CYBO2440 2607 -vdssw MACH_VDSSW VDSSW 2608 -romulus MACH_ROMULUS ROMULUS 2609 -omap_magic MACH_OMAP_MAGIC OMAP_MAGIC 2610 -eltd100 MACH_ELTD100 ELTD100 2611 capc7117 MACH_CAPC7117 CAPC7117 2612 -swan MACH_SWAN SWAN 2613 -veu MACH_VEU VEU 2614 -rm2 MACH_RM2 RM2 2615 -tt2100 MACH_TT2100 TT2100 2616 -venice MACH_VENICE VENICE 2617 -pc7323 MACH_PC7323 PC7323 2618 -masp MACH_MASP MASP 2619 -fujitsu_tvstbsoc0 MACH_FUJITSU_TVSTBSOC FUJITSU_TVSTBSOC 2620 -fujitsu_tvstbsoc1 MACH_FUJITSU_TVSTBSOC1 FUJITSU_TVSTBSOC1 2621 -lexikon MACH_LEXIKON LEXIKON 2622 -mini2440v2 MACH_MINI2440V2 MINI2440V2 2623 icontrol MACH_ICONTROL ICONTROL 2624 -gplugd MACH_SHEEVAD SHEEVAD 2625 -qsd8x50a_st1_1 MACH_QSD8X50A_ST1_1 QSD8X50A_ST1_1 2626 qsd8x50a_st1_5 MACH_QSD8X50A_ST1_5 QSD8X50A_ST1_5 2627 -bee MACH_BEE BEE 2628 mx23evk MACH_MX23EVK MX23EVK 2629 ap4evb MACH_AP4EVB AP4EVB 2630 -stockholm MACH_STOCKHOLM STOCKHOLM 2631 -lpc_h3131 MACH_LPC_H3131 LPC_H3131 2632 -stingray MACH_STINGRAY STINGRAY 2633 -kraken MACH_KRAKEN KRAKEN 2634 -gw2388 MACH_GW2388 GW2388 2635 -jadecpu MACH_JADECPU JADECPU 2636 -carlisle MACH_CARLISLE CARLISLE 2637 -lux_sf9 MACH_LUX_SF9 LUX_SF9 2638 -nemid_tb MACH_NEMID_TB NEMID_TB 2639 -terrier MACH_TERRIER TERRIER 2640 -turbot MACH_TURBOT TURBOT 2641 -sanddab MACH_SANDDAB SANDDAB 2642 -mx35_cicada MACH_MX35_CICADA MX35_CICADA 2643 -ghi2703d MACH_GHI2703D GHI2703D 2644 -lux_sfx9 MACH_LUX_SFX9 LUX_SFX9 2645 -lux_sf9g MACH_LUX_SF9G LUX_SF9G 2646 -lux_edk9 MACH_LUX_EDK9 LUX_EDK9 2647 -hw90240 MACH_HW90240 HW90240 2648 -dm365_leopard MACH_DM365_LEOPARD DM365_LEOPARD 2649 mityomapl138 MACH_MITYOMAPL138 MITYOMAPL138 2650 -scat110 MACH_SCAT110 SCAT110 2651 -acer_a1 MACH_ACER_A1 ACER_A1 2652 -cmcontrol MACH_CMCONTROL CMCONTROL 2653 -pelco_lamar MACH_PELCO_LAMAR PELCO_LAMAR 2654 -rfp43 MACH_RFP43 RFP43 2655 -sk86r0301 MACH_SK86R0301 SK86R0301 2656 -ctpxa MACH_CTPXA CTPXA 2657 -epb_arm9_a MACH_EPB_ARM9_A EPB_ARM9_A 2658 guruplug MACH_GURUPLUG GURUPLUG 2659 spear310 MACH_SPEAR310 SPEAR310 2660 spear320 MACH_SPEAR320 SPEAR320 2661 -robotx MACH_ROBOTX ROBOTX 2662 -lsxhl MACH_LSXHL LSXHL 2663 -smartlite MACH_SMARTLITE SMARTLITE 2664 -cws2 MACH_CWS2 CWS2 2665 -m619 MACH_M619 M619 2666 -smartview MACH_SMARTVIEW SMARTVIEW 2667 -lsa_salsa MACH_LSA_SALSA LSA_SALSA 2668 -kizbox MACH_KIZBOX KIZBOX 2669 -htccharmer MACH_HTCCHARMER HTCCHARMER 2670 -guf_neso_lt MACH_GUF_NESO_LT GUF_NESO_LT 2671 -pm9g45 MACH_PM9G45 PM9G45 2672 -htcpanther MACH_HTCPANTHER HTCPANTHER 2673 -htcpanther_cdma MACH_HTCPANTHER_CDMA HTCPANTHER_CDMA 2674 -reb01 MACH_REB01 REB01 2675 aquila MACH_AQUILA AQUILA 2676 -spark_sls_hw2 MACH_SPARK_SLS_HW2 SPARK_SLS_HW2 2677 sheeva_esata MACH_ESATA_SHEEVAPLUG ESATA_SHEEVAPLUG 2678 msm7x30_surf MACH_MSM7X30_SURF MSM7X30_SURF 2679 -micro2440 MACH_MICRO2440 MICRO2440 2680 -am2440 MACH_AM2440 AM2440 2681 -tq2440 MACH_TQ2440 TQ2440 2682 -lpc2478oem MACH_LPC2478OEM LPC2478OEM 2683 -ak880x MACH_AK880X AK880X 2684 -cobra3530 MACH_COBRA3530 COBRA3530 2685 -pmppb MACH_PMPPB PMPPB 2686 -u6715 MACH_U6715 U6715 2687 -axar1500_sender MACH_AXAR1500_SENDER AXAR1500_SENDER 2688 -g30_dvb MACH_G30_DVB G30_DVB 2689 -vc088x MACH_VC088X VC088X 2690 -mioa702 MACH_MIOA702 MIOA702 2691 -hpmin MACH_HPMIN HPMIN 2692 -ak880xak MACH_AK880XAK AK880XAK 2693 -arm926tomap850 MACH_ARM926TOMAP850 ARM926TOMAP850 2694 -lkevm MACH_LKEVM LKEVM 2695 -mw6410 MACH_MW6410 MW6410 2696 terastation_wxl MACH_TERASTATION_WXL TERASTATION_WXL 2697 -cpu8000e MACH_CPU8000E CPU8000E 2698 -catania MACH_CATANIA CATANIA 2699 -tokyo MACH_TOKYO TOKYO 2700 -msm7201a_surf MACH_MSM7201A_SURF MSM7201A_SURF 2701 -msm7201a_ffa MACH_MSM7201A_FFA MSM7201A_FFA 2702 msm7x25_surf MACH_MSM7X25_SURF MSM7X25_SURF 2703 msm7x25_ffa MACH_MSM7X25_FFA MSM7X25_FFA 2704 msm7x27_surf MACH_MSM7X27_SURF MSM7X27_SURF 2705 msm7x27_ffa MACH_MSM7X27_FFA MSM7X27_FFA 2706 msm7x30_ffa MACH_MSM7X30_FFA MSM7X30_FFA 2707 qsd8x50_surf MACH_QSD8X50_SURF QSD8X50_SURF 2708 -qsd8x50_comet MACH_QSD8X50_COMET QSD8X50_COMET 2709 -qsd8x50_ffa MACH_QSD8X50_FFA QSD8X50_FFA 2710 -qsd8x50a_surf MACH_QSD8X50A_SURF QSD8X50A_SURF 2711 -qsd8x50a_ffa MACH_QSD8X50A_FFA QSD8X50A_FFA 2712 -adx_xgcp10 MACH_ADX_XGCP10 ADX_XGCP10 2713 -mcgwumts2a MACH_MCGWUMTS2A MCGWUMTS2A 2714 -mobikt MACH_MOBIKT MOBIKT 2715 mx53_evk MACH_MX53_EVK MX53_EVK 2716 igep0030 MACH_IGEP0030 IGEP0030 2717 -axell_h40_h50_ctrl MACH_AXELL_H40_H50_CTRL AXELL_H40_H50_CTRL 2718 -dtcommod MACH_DTCOMMOD DTCOMMOD 2719 -gould MACH_GOULD GOULD 2720 -siberia MACH_SIBERIA SIBERIA 2721 sbc3530 MACH_SBC3530 SBC3530 2722 -qarm MACH_QARM QARM 2723 -mips MACH_MIPS MIPS 2724 -mx27grb MACH_MX27GRB MX27GRB 2725 -sbc8100 MACH_SBC8100 SBC8100 2726 saarb MACH_SAARB SAARB 2727 -omap3mini MACH_OMAP3MINI OMAP3MINI 2728 -cnmbook7se MACH_CNMBOOK7SE CNMBOOK7SE 2729 -catan MACH_CATAN CATAN 2730 harmony MACH_HARMONY HARMONY 2731 -tonga MACH_TONGA TONGA 2732 -cybook_orizon MACH_CYBOOK_ORIZON CYBOOK_ORIZON 2733 -htcrhodiumcdma MACH_HTCRHODIUMCDMA HTCRHODIUMCDMA 2734 -epc_g45 MACH_EPC_G45 EPC_G45 2735 -epc_lpc3250 MACH_EPC_LPC3250 EPC_LPC3250 2736 -mxc91341evb MACH_MXC91341EVB MXC91341EVB 2737 -rtw1000 MACH_RTW1000 RTW1000 2738 -bobcat MACH_BOBCAT BOBCAT 2739 -trizeps6 MACH_TRIZEPS6 TRIZEPS6 2740 msm7x30_fluid MACH_MSM7X30_FLUID MSM7X30_FLUID 2741 -nedap9263 MACH_NEDAP9263 NEDAP9263 2742 -netgear_ms2110 MACH_NETGEAR_MS2110 NETGEAR_MS2110 2743 -bmx MACH_BMX BMX 2744 -netstream MACH_NETSTREAM NETSTREAM 2745 -vpnext_rcu MACH_VPNEXT_RCU VPNEXT_RCU 2746 -vpnext_mpu MACH_VPNEXT_MPU VPNEXT_MPU 2747 -bcmring_tablet_v1 MACH_BCMRING_TABLET_V1 BCMRING_TABLET_V1 2748 -sgarm10 MACH_SGARM10 SGARM10 2749 cm_t3517 MACH_CM_T3517 CM_T3517 2750 -omap3_cps MACH_OMAP3_CPS OMAP3_CPS 2751 -axar1500_receiver MACH_AXAR1500_RECEIVER AXAR1500_RECEIVER 2752 wbd222 MACH_WBD222 WBD222 2753 -mt65xx MACH_MT65XX MT65XX 2754 msm8x60_surf MACH_MSM8X60_SURF MSM8X60_SURF 2755 msm8x60_sim MACH_MSM8X60_SIM MSM8X60_SIM 2756 -vmc300 MACH_VMC300 VMC300 2757 tcc8000_sdk MACH_TCC8000_SDK TCC8000_SDK 2758 -nanos MACH_NANOS NANOS 2759 -stamp9g10 MACH_STAMP9G10 STAMP9G10 2760 -stamp9g45 MACH_STAMP9G45 STAMP9G45 2761 -h6053 MACH_H6053 H6053 2762 -smint01 MACH_SMINT01 SMINT01 2763 -prtlvt2 MACH_PRTLVT2 PRTLVT2 2764 ap420 MACH_AP420 AP420 2765 -htcshift MACH_HTCSHIFT HTCSHIFT 2766 davinci_dm365_fc MACH_DAVINCI_DM365_FC DAVINCI_DM365_FC 2767 msm8x55_surf MACH_MSM8X55_SURF MSM8X55_SURF 2768 msm8x55_ffa MACH_MSM8X55_FFA MSM8X55_FFA 2769 @@ -2761,7 +474,6 @@ oreo_controller MACH_OREO_CONTROLLER OREO_CONTROLLER 2773 kopin_models MACH_KOPIN_MODELS KOPIN_MODELS 2774 ttc_vision2 MACH_TTC_VISION2 TTC_VISION2 2775 cns3420vb MACH_CNS3420VB CNS3420VB 2776 -lpc2 MACH_LPC2 LPC2 2777 olympus MACH_OLYMPUS OLYMPUS 2778 vortex MACH_VORTEX VORTEX 2779 s5pc200 MACH_S5PC200 S5PC200 2780 @@ -2788,7 +500,6 @@ ti8168evm MACH_TI8168EVM TI8168EVM 2800 neocoreomap MACH_NEOCOREOMAP NEOCOREOMAP 2801 withings_wbp MACH_WITHINGS_WBP WITHINGS_WBP 2802 dbps MACH_DBPS DBPS 2803 -sbc9261 MACH_SBC9261 SBC9261 2804 pcbfp0001 MACH_PCBFP0001 PCBFP0001 2805 speedy MACH_SPEEDY SPEEDY 2806 chrysaor MACH_CHRYSAOR CHRYSAOR 2807 @@ -2812,7 +523,6 @@ p565 MACH_P565 P565 2824 acer_a4 MACH_ACER_A4 ACER_A4 2825 davinci_dm368_bip MACH_DAVINCI_DM368_BIP DAVINCI_DM368_BIP 2826 eshare MACH_ESHARE ESHARE 2827 -hw_omapl138_europa MACH_HW_OMAPL138_EUROPA HW_OMAPL138_EUROPA 2828 wlbargn MACH_WLBARGN WLBARGN 2829 bm170 MACH_BM170 BM170 2830 netspace_mini_v2 MACH_NETSPACE_MINI_V2 NETSPACE_MINI_V2 2831 @@ -2879,7 +589,6 @@ davinci_picto MACH_DAVINCI_PICTO DAVINCI_PICTO 2891 mecha MACH_MECHA MECHA 2892 bubba3 MACH_BUBBA3 BUBBA3 2893 pupitre MACH_PUPITRE PUPITRE 2894 -tegra_harmony MACH_TEGRA_HARMONY TEGRA_HARMONY 2895 tegra_vogue MACH_TEGRA_VOGUE TEGRA_VOGUE 2896 tegra_e1165 MACH_TEGRA_E1165 TEGRA_E1165 2897 simplenet MACH_SIMPLENET SIMPLENET 2898 @@ -2969,7 +678,6 @@ netspace_lite_v2 MACH_NETSPACE_LITE_V2 NETSPACE_LITE_V2 2983 ssc MACH_SSC SSC 2984 premierwave_en MACH_PREMIERWAVE_EN PREMIERWAVE_EN 2985 wasabi MACH_WASABI WASABI 2986 -vivow MACH_VIVOW VIVOW 2987 mx50_rdp MACH_MX50_RDP MX50_RDP 2988 universal_c210 MACH_UNIVERSAL_C210 UNIVERSAL_C210 2989 real6410 MACH_REAL6410 REAL6410 2990 @@ -3017,12 +725,10 @@ remus MACH_REMUS REMUS 3031 at91cap7xdk MACH_AT91CAP7XDK AT91CAP7XDK 3032 at91cap7stk MACH_AT91CAP7STK AT91CAP7STK 3033 kt_sbc_sam9_1 MACH_KT_SBC_SAM9_1 KT_SBC_SAM9_1 3034 -oratisrouter MACH_ORATISROUTER ORATISROUTER 3035 armada_xp_db MACH_ARMADA_XP_DB ARMADA_XP_DB 3036 spdm MACH_SPDM SPDM 3037 gtib MACH_GTIB GTIB 3038 dgm3240 MACH_DGM3240 DGM3240 3039 -atlas_i_lpe MACH_ATLAS_I_LPE ATLAS_I_LPE 3040 htcmega MACH_HTCMEGA HTCMEGA 3041 tricorder MACH_TRICORDER TRICORDER 3042 tx28 MACH_TX28 TX28 3043 @@ -3062,7 +768,6 @@ clod MACH_CLOD CLOD 3077 rump MACH_RUMP RUMP 3078 tenderloin MACH_TENDERLOIN TENDERLOIN 3079 shortloin MACH_SHORTLOIN SHORTLOIN 3080 -crespo MACH_CRESPO CRESPO 3081 antares MACH_ANTARES ANTARES 3082 wb40n MACH_WB40N WB40N 3083 herring MACH_HERRING HERRING 3084 @@ -3111,7 +816,6 @@ smartqv3 MACH_SMARTQV3 SMARTQV3 3126 smartqv7 MACH_SMARTQV7 SMARTQV7 3127 paz00 MACH_PAZ00 PAZ00 3128 acmenetusfoxg20 MACH_ACMENETUSFOXG20 ACMENETUSFOXG20 3129 -htcwillow MACH_HTCWILLOW HTCWILLOW 3130 fwbd_0404 MACH_FWBD_0404 FWBD_0404 3131 hdgu MACH_HDGU HDGU 3132 pyramid MACH_PYRAMID PYRAMID 3133 @@ -3162,7 +866,6 @@ b5500 MACH_B5500 B5500 3177 s5500 MACH_S5500 S5500 3178 icon MACH_ICON ICON 3179 elephant MACH_ELEPHANT ELEPHANT 3180 -msm8x60_fusion MACH_MSM8X60_FUSION MSM8X60_FUSION 3181 shooter MACH_SHOOTER SHOOTER 3182 spade_lte MACH_SPADE_LTE SPADE_LTE 3183 philhwani MACH_PHILHWANI PHILHWANI 3184 @@ -3174,13 +877,11 @@ ag5evm MACH_AG5EVM AG5EVM 3189 sc575plc MACH_SC575PLC SC575PLC 3190 sc575hmi MACH_SC575IPC SC575IPC 3191 omap3_tdm3730 MACH_OMAP3_TDM3730 OMAP3_TDM3730 3192 -g7 MACH_G7 G7 3193 top9000_eval MACH_TOP9000_EVAL TOP9000_EVAL 3194 top9000_su MACH_TOP9000_SU TOP9000_SU 3195 utm300 MACH_UTM300 UTM300 3196 tsunagi MACH_TSUNAGI TSUNAGI 3197 ts75xx MACH_TS75XX TS75XX 3198 -msm8x60_fusn_ffa MACH_MSM8X60_FUSN_FFA MSM8X60_FUSN_FFA 3199 ts47xx MACH_TS47XX TS47XX 3200 da850_k5 MACH_DA850_K5 DA850_K5 3201 ax502 MACH_AX502 AX502 3202 @@ -3285,7 +986,6 @@ rfl109145_ssrv MACH_RFL109145_SSRV RFL109145_SSRV 3304 nmh MACH_NMH NMH 3305 wn802t MACH_WN802T WN802T 3306 dragonet MACH_DRAGONET DRAGONET 3307 -geneva_b MACH_GENEVA_B GENEVA_B 3308 at91sam9263desk16l MACH_AT91SAM9263DESK16L AT91SAM9263DESK16L 3309 bcmhana_sv MACH_BCMHANA_SV BCMHANA_SV 3310 bcmhana_tablet MACH_BCMHANA_TABLET BCMHANA_TABLET 3311 @@ -3316,3 +1016,86 @@ rover_g8 MACH_ROVER_G8 ROVER_G8 3335 t5388p MACH_T5388P T5388P 3336 dingo MACH_DINGO DINGO 3337 goflexhome MACH_GOFLEXHOME GOFLEXHOME 3338 +lanreadyfn511 MACH_LANREADYFN511 LANREADYFN511 3340 +omap3_baia MACH_OMAP3_BAIA OMAP3_BAIA 3341 +omap3smartdisplay MACH_OMAP3SMARTDISPLAY OMAP3SMARTDISPLAY 3342 +xilinx MACH_XILINX XILINX 3343 +a2f MACH_A2F A2F 3344 +sky25 MACH_SKY25 SKY25 3345 +ccmx53 MACH_CCMX53 CCMX53 3346 +ccmx53js MACH_CCMX53JS CCMX53JS 3347 +ccwmx53 MACH_CCWMX53 CCWMX53 3348 +ccwmx53js MACH_CCWMX53JS CCWMX53JS 3349 +frisms MACH_FRISMS FRISMS 3350 +msm7x27a_ffa MACH_MSM7X27A_FFA MSM7X27A_FFA 3351 +msm7x27a_surf MACH_MSM7X27A_SURF MSM7X27A_SURF 3352 +msm7x27a_rumi3 MACH_MSM7X27A_RUMI3 MSM7X27A_RUMI3 3353 +dimmsam9g20 MACH_DIMMSAM9G20 DIMMSAM9G20 3354 +dimm_imx28 MACH_DIMM_IMX28 DIMM_IMX28 3355 +amk_a4 MACH_AMK_A4 AMK_A4 3356 +gnet_sgme MACH_GNET_SGME GNET_SGME 3357 +shooter_u MACH_SHOOTER_U SHOOTER_U 3358 +vmx53 MACH_VMX53 VMX53 3359 +rhino MACH_RHINO RHINO 3360 +armlex4210 MACH_ARMLEX4210 ARMLEX4210 3361 +swarcoextmodem MACH_SWARCOEXTMODEM SWARCOEXTMODEM 3362 +snowball MACH_SNOWBALL SNOWBALL 3363 +pcm049 MACH_PCM049 PCM049 3364 +vigor MACH_VIGOR VIGOR 3365 +oslo_amundsen MACH_OSLO_AMUNDSEN OSLO_AMUNDSEN 3366 +gsl_diamond MACH_GSL_DIAMOND GSL_DIAMOND 3367 +cv2201 MACH_CV2201 CV2201 3368 +cv2202 MACH_CV2202 CV2202 3369 +cv2203 MACH_CV2203 CV2203 3370 +vit_ibox MACH_VIT_IBOX VIT_IBOX 3371 +dm6441_esp MACH_DM6441_ESP DM6441_ESP 3372 +at91sam9x5ek MACH_AT91SAM9X5EK AT91SAM9X5EK 3373 +libra MACH_LIBRA LIBRA 3374 +easycrrh MACH_EASYCRRH EASYCRRH 3375 +tripel MACH_TRIPEL TRIPEL 3376 +endian_mini MACH_ENDIAN_MINI ENDIAN_MINI 3377 +xilinx_ep107 MACH_XILINX_EP107 XILINX_EP107 3378 +nuri MACH_NURI NURI 3379 +janus MACH_JANUS JANUS 3380 +ddnas MACH_DDNAS DDNAS 3381 +tag MACH_TAG TAG 3382 +tagw MACH_TAGW TAGW 3383 +nitrogen_vm_imx51 MACH_NITROGEN_VM_IMX51 NITROGEN_VM_IMX51 3384 +viprinet MACH_VIPRINET VIPRINET 3385 +bockw MACH_BOCKW BOCKW 3386 +eva2000 MACH_EVA2000 EVA2000 3387 +steelyard MACH_STEELYARD STEELYARD 3388 +sdh001 MACH_MACH_SDH001 MACH_SDH001 3390 +nsslsboard MACH_NSSLSBOARD NSSLSBOARD 3392 +geneva_b5 MACH_GENEVA_B5 GENEVA_B5 3393 +spear1340 MACH_SPEAR1340 SPEAR1340 3394 +rexmas MACH_REXMAS REXMAS 3395 +msm8960_cdp MACH_MSM8960_CDP MSM8960_CDP 3396 +msm8960_mdp MACH_MSM8960_MDP MSM8960_MDP 3397 +msm8960_fluid MACH_MSM8960_FLUID MSM8960_FLUID 3398 +msm8960_apq MACH_MSM8960_APQ MSM8960_APQ 3399 +helios_v2 MACH_HELIOS_V2 HELIOS_V2 3400 +mif10p MACH_MIF10P MIF10P 3401 +iam28 MACH_IAM28 IAM28 3402 +picasso MACH_PICASSO PICASSO 3403 +mr301a MACH_MR301A MR301A 3404 +notle MACH_NOTLE NOTLE 3405 +eelx2 MACH_EELX2 EELX2 3406 +moon MACH_MOON MOON 3407 +ruby MACH_RUBY RUBY 3408 +goldengate MACH_GOLDENGATE GOLDENGATE 3409 +ctbu_gen2 MACH_CTBU_GEN2 CTBU_GEN2 3410 +kmp_am17_01 MACH_KMP_AM17_01 KMP_AM17_01 3411 +wtplug MACH_WTPLUG WTPLUG 3412 +mx27su2 MACH_MX27SU2 MX27SU2 3413 +nb31 MACH_NB31 NB31 3414 +hjsdu MACH_HJSDU HJSDU 3415 +td3_rev1 MACH_TD3_REV1 TD3_REV1 3416 +eag_ci4000 MACH_EAG_CI4000 EAG_CI4000 3417 +net5big_nand_v2 MACH_NET5BIG_NAND_V2 NET5BIG_NAND_V2 3418 +cpx2 MACH_CPX2 CPX2 3419 +net2big_nand_v2 MACH_NET2BIG_NAND_V2 NET2BIG_NAND_V2 3420 +ecuv5 MACH_ECUV5 ECUV5 3421 +hsgx6d MACH_HSGX6D HSGX6D 3422 +dawad7 MACH_DAWAD7 DAWAD7 3423 +sam9repeater MACH_SAM9REPEATER SAM9REPEATER 3424 -- GitLab From bbb1c832ac52f61b926a4635dc1a708f03250e88 Mon Sep 17 00:00:00 2001 From: "Arnaud Patard (Rtp)" Date: Thu, 6 Jan 2011 21:52:46 +0200 Subject: [PATCH 0941/2822] ARM: S3C2410: H1940: Add keys device Add buttons definition for H1940. Signed-off-by: Vasily Khoruzhick Signed-off-by: Ben Dooks --- arch/arm/mach-s3c2410/mach-h1940.c | 39 ++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/arch/arm/mach-s3c2410/mach-h1940.c b/arch/arm/mach-s3c2410/mach-h1940.c index 1e93f176c1de8..07564404fb899 100644 --- a/arch/arm/mach-s3c2410/mach-h1940.c +++ b/arch/arm/mach-s3c2410/mach-h1940.c @@ -23,6 +23,8 @@ #include #include #include +#include +#include #include #include #include