mirror of
				git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
				synced 2025-10-31 08:44:41 +00:00 
			
		
		
		
	Merge branches 'sh/hwblk' and 'sh/platform-updates'
This commit is contained in:
		
						commit
						c358fc46ef
					
				
					 455 changed files with 4603 additions and 4270 deletions
				
			
		|  | @ -207,8 +207,8 @@ Attributes | |||
| ~~~~~~~~~~ | ||||
| struct driver_attribute { | ||||
|         struct attribute        attr; | ||||
|         ssize_t (*show)(struct device_driver *, char * buf, size_t count, loff_t off); | ||||
|         ssize_t (*store)(struct device_driver *, const char * buf, size_t count, loff_t off); | ||||
|         ssize_t (*show)(struct device_driver *driver, char *buf); | ||||
|         ssize_t (*store)(struct device_driver *, const char * buf, size_t count); | ||||
| }; | ||||
| 
 | ||||
| Device drivers can export attributes via their sysfs directories.  | ||||
|  |  | |||
|  | @ -73,7 +73,7 @@ The remaining CPU time will be used for user input and other tasks. Because | |||
| realtime tasks have explicitly allocated the CPU time they need to perform | ||||
| their tasks, buffer underruns in the graphics or audio can be eliminated. | ||||
| 
 | ||||
| NOTE: the above example is not fully implemented as of yet (2.6.25). We still | ||||
| NOTE: the above example is not fully implemented yet. We still | ||||
| lack an EDF scheduler to make non-uniform periods usable. | ||||
| 
 | ||||
| 
 | ||||
|  | @ -140,14 +140,15 @@ The other option is: | |||
| 
 | ||||
| .o CONFIG_CGROUP_SCHED (aka "Basis for grouping tasks" = "Control groups") | ||||
| 
 | ||||
| This uses the /cgroup virtual file system and "/cgroup/<cgroup>/cpu.rt_runtime_us" | ||||
| to control the CPU time reserved for each control group instead. | ||||
| This uses the /cgroup virtual file system and | ||||
| "/cgroup/<cgroup>/cpu.rt_runtime_us" to control the CPU time reserved for each | ||||
| control group instead. | ||||
| 
 | ||||
| For more information on working with control groups, you should read | ||||
| Documentation/cgroups/cgroups.txt as well. | ||||
| 
 | ||||
| Group settings are checked against the following limits in order to keep the configuration | ||||
| schedulable: | ||||
| Group settings are checked against the following limits in order to keep the | ||||
| configuration schedulable: | ||||
| 
 | ||||
|    \Sum_{i} runtime_{i} / global_period <= global_runtime / global_period | ||||
| 
 | ||||
|  | @ -189,7 +190,7 @@ Implementing SCHED_EDF might take a while to complete. Priority Inheritance is | |||
| the biggest challenge as the current linux PI infrastructure is geared towards | ||||
| the limited static priority levels 0-99. With deadline scheduling you need to | ||||
| do deadline inheritance (since priority is inversely proportional to the | ||||
| deadline delta (deadline - now). | ||||
| deadline delta (deadline - now)). | ||||
| 
 | ||||
| This means the whole PI machinery will have to be reworked - and that is one of | ||||
| the most complex pieces of code we have. | ||||
|  |  | |||
|  | @ -2,3 +2,5 @@ | |||
| 	- this file | ||||
| mtrr.txt | ||||
| 	- how to use x86 Memory Type Range Registers to increase performance | ||||
| exception-tables.txt | ||||
| 	- why and how Linux kernel uses exception tables on x86 | ||||
|  |  | |||
|  | @ -1,123 +1,123 @@ | |||
|      Kernel level exception handling in Linux 2.1.8 | ||||
|      Kernel level exception handling in Linux | ||||
|   Commentary by Joerg Pommnitz <joerg@raleigh.ibm.com> | ||||
| 
 | ||||
| When a process runs in kernel mode, it often has to access user  | ||||
| mode memory whose address has been passed by an untrusted program.  | ||||
| When a process runs in kernel mode, it often has to access user | ||||
| mode memory whose address has been passed by an untrusted program. | ||||
| To protect itself the kernel has to verify this address. | ||||
| 
 | ||||
| In older versions of Linux this was done with the  | ||||
| int verify_area(int type, const void * addr, unsigned long size)  | ||||
| In older versions of Linux this was done with the | ||||
| int verify_area(int type, const void * addr, unsigned long size) | ||||
| function (which has since been replaced by access_ok()). | ||||
| 
 | ||||
| This function verified that the memory area starting at address  | ||||
| This function verified that the memory area starting at address | ||||
| 'addr' and of size 'size' was accessible for the operation specified | ||||
| in type (read or write). To do this, verify_read had to look up the  | ||||
| virtual memory area (vma) that contained the address addr. In the  | ||||
| normal case (correctly working program), this test was successful.  | ||||
| in type (read or write). To do this, verify_read had to look up the | ||||
| virtual memory area (vma) that contained the address addr. In the | ||||
| normal case (correctly working program), this test was successful. | ||||
| It only failed for a few buggy programs. In some kernel profiling | ||||
| tests, this normally unneeded verification used up a considerable | ||||
| amount of time. | ||||
| 
 | ||||
| To overcome this situation, Linus decided to let the virtual memory  | ||||
| To overcome this situation, Linus decided to let the virtual memory | ||||
| hardware present in every Linux-capable CPU handle this test. | ||||
| 
 | ||||
| How does this work? | ||||
| 
 | ||||
| Whenever the kernel tries to access an address that is currently not  | ||||
| accessible, the CPU generates a page fault exception and calls the  | ||||
| page fault handler  | ||||
| Whenever the kernel tries to access an address that is currently not | ||||
| accessible, the CPU generates a page fault exception and calls the | ||||
| page fault handler | ||||
| 
 | ||||
| void do_page_fault(struct pt_regs *regs, unsigned long error_code) | ||||
| 
 | ||||
| in arch/i386/mm/fault.c. The parameters on the stack are set up by  | ||||
| the low level assembly glue in arch/i386/kernel/entry.S. The parameter | ||||
| regs is a pointer to the saved registers on the stack, error_code  | ||||
| in arch/x86/mm/fault.c. The parameters on the stack are set up by | ||||
| the low level assembly glue in arch/x86/kernel/entry_32.S. The parameter | ||||
| regs is a pointer to the saved registers on the stack, error_code | ||||
| contains a reason code for the exception. | ||||
| 
 | ||||
| do_page_fault first obtains the unaccessible address from the CPU  | ||||
| control register CR2. If the address is within the virtual address  | ||||
| space of the process, the fault probably occurred, because the page  | ||||
| was not swapped in, write protected or something similar. However,  | ||||
| we are interested in the other case: the address is not valid, there  | ||||
| is no vma that contains this address. In this case, the kernel jumps  | ||||
| to the bad_area label.  | ||||
| do_page_fault first obtains the unaccessible address from the CPU | ||||
| control register CR2. If the address is within the virtual address | ||||
| space of the process, the fault probably occurred, because the page | ||||
| was not swapped in, write protected or something similar. However, | ||||
| we are interested in the other case: the address is not valid, there | ||||
| is no vma that contains this address. In this case, the kernel jumps | ||||
| to the bad_area label. | ||||
| 
 | ||||
| There it uses the address of the instruction that caused the exception  | ||||
| (i.e. regs->eip) to find an address where the execution can continue  | ||||
| (fixup). If this search is successful, the fault handler modifies the  | ||||
| return address (again regs->eip) and returns. The execution will  | ||||
| There it uses the address of the instruction that caused the exception | ||||
| (i.e. regs->eip) to find an address where the execution can continue | ||||
| (fixup). If this search is successful, the fault handler modifies the | ||||
| return address (again regs->eip) and returns. The execution will | ||||
| continue at the address in fixup. | ||||
| 
 | ||||
| Where does fixup point to? | ||||
| 
 | ||||
| Since we jump to the contents of fixup, fixup obviously points  | ||||
| to executable code. This code is hidden inside the user access macros.  | ||||
| I have picked the get_user macro defined in include/asm/uaccess.h as an | ||||
| example. The definition is somewhat hard to follow, so let's peek at  | ||||
| Since we jump to the contents of fixup, fixup obviously points | ||||
| to executable code. This code is hidden inside the user access macros. | ||||
| I have picked the get_user macro defined in arch/x86/include/asm/uaccess.h | ||||
| as an example. The definition is somewhat hard to follow, so let's peek at | ||||
| the code generated by the preprocessor and the compiler. I selected | ||||
| the get_user call in drivers/char/console.c for a detailed examination. | ||||
| the get_user call in drivers/char/sysrq.c for a detailed examination. | ||||
| 
 | ||||
| The original code in console.c line 1405: | ||||
| The original code in sysrq.c line 587: | ||||
|         get_user(c, buf); | ||||
| 
 | ||||
| The preprocessor output (edited to become somewhat readable): | ||||
| 
 | ||||
| ( | ||||
|   {         | ||||
|     long __gu_err = - 14 , __gu_val = 0;         | ||||
|     const __typeof__(*( (  buf ) )) *__gu_addr = ((buf));         | ||||
|     if (((((0 + current_set[0])->tss.segment) == 0x18 )  ||  | ||||
|        (((sizeof(*(buf))) <= 0xC0000000UL) &&  | ||||
|        ((unsigned long)(__gu_addr ) <= 0xC0000000UL - (sizeof(*(buf)))))))         | ||||
|   { | ||||
|     long __gu_err = - 14 , __gu_val = 0; | ||||
|     const __typeof__(*( (  buf ) )) *__gu_addr = ((buf)); | ||||
|     if (((((0 + current_set[0])->tss.segment) == 0x18 )  || | ||||
|        (((sizeof(*(buf))) <= 0xC0000000UL) && | ||||
|        ((unsigned long)(__gu_addr ) <= 0xC0000000UL - (sizeof(*(buf))))))) | ||||
|       do { | ||||
|         __gu_err  = 0;         | ||||
|         switch ((sizeof(*(buf)))) {         | ||||
|           case 1:  | ||||
|             __asm__ __volatile__(         | ||||
|               "1:      mov" "b" " %2,%" "b" "1\n"         | ||||
|               "2:\n"         | ||||
|               ".section .fixup,\"ax\"\n"         | ||||
|               "3:      movl %3,%0\n"         | ||||
|               "        xor" "b" " %" "b" "1,%" "b" "1\n"         | ||||
|               "        jmp 2b\n"         | ||||
|               ".section __ex_table,\"a\"\n"         | ||||
|               "        .align 4\n"         | ||||
|               "        .long 1b,3b\n"         | ||||
|               ".text"        : "=r"(__gu_err), "=q" (__gu_val): "m"((*(struct __large_struct *) | ||||
|                             (   __gu_addr   )) ), "i"(- 14 ), "0"(  __gu_err  )) ;  | ||||
|               break;         | ||||
|           case 2:  | ||||
|         __gu_err  = 0; | ||||
|         switch ((sizeof(*(buf)))) { | ||||
|           case 1: | ||||
|             __asm__ __volatile__( | ||||
|               "1:      mov" "w" " %2,%" "w" "1\n"         | ||||
|               "2:\n"         | ||||
|               ".section .fixup,\"ax\"\n"         | ||||
|               "3:      movl %3,%0\n"         | ||||
|               "        xor" "w" " %" "w" "1,%" "w" "1\n"         | ||||
|               "        jmp 2b\n"         | ||||
|               ".section __ex_table,\"a\"\n"         | ||||
|               "        .align 4\n"         | ||||
|               "        .long 1b,3b\n"         | ||||
|               "1:      mov" "b" " %2,%" "b" "1\n" | ||||
|               "2:\n" | ||||
|               ".section .fixup,\"ax\"\n" | ||||
|               "3:      movl %3,%0\n" | ||||
|               "        xor" "b" " %" "b" "1,%" "b" "1\n" | ||||
|               "        jmp 2b\n" | ||||
|               ".section __ex_table,\"a\"\n" | ||||
|               "        .align 4\n" | ||||
|               "        .long 1b,3b\n" | ||||
|               ".text"        : "=r"(__gu_err), "=q" (__gu_val): "m"((*(struct __large_struct *) | ||||
|                             (   __gu_addr   )) ), "i"(- 14 ), "0"(  __gu_err  )) ; | ||||
|               break; | ||||
|           case 2: | ||||
|             __asm__ __volatile__( | ||||
|               "1:      mov" "w" " %2,%" "w" "1\n" | ||||
|               "2:\n" | ||||
|               ".section .fixup,\"ax\"\n" | ||||
|               "3:      movl %3,%0\n" | ||||
|               "        xor" "w" " %" "w" "1,%" "w" "1\n" | ||||
|               "        jmp 2b\n" | ||||
|               ".section __ex_table,\"a\"\n" | ||||
|               "        .align 4\n" | ||||
|               "        .long 1b,3b\n" | ||||
|               ".text"        : "=r"(__gu_err), "=r" (__gu_val) : "m"((*(struct __large_struct *) | ||||
|                             (   __gu_addr   )) ), "i"(- 14 ), "0"(  __gu_err  ));  | ||||
|               break;         | ||||
|           case 4:  | ||||
|             __asm__ __volatile__(         | ||||
|               "1:      mov" "l" " %2,%" "" "1\n"         | ||||
|               "2:\n"         | ||||
|               ".section .fixup,\"ax\"\n"         | ||||
|               "3:      movl %3,%0\n"         | ||||
|               "        xor" "l" " %" "" "1,%" "" "1\n"         | ||||
|               "        jmp 2b\n"         | ||||
|               ".section __ex_table,\"a\"\n"         | ||||
|               "        .align 4\n"        "        .long 1b,3b\n"         | ||||
|                             (   __gu_addr   )) ), "i"(- 14 ), "0"(  __gu_err  )); | ||||
|               break; | ||||
|           case 4: | ||||
|             __asm__ __volatile__( | ||||
|               "1:      mov" "l" " %2,%" "" "1\n" | ||||
|               "2:\n" | ||||
|               ".section .fixup,\"ax\"\n" | ||||
|               "3:      movl %3,%0\n" | ||||
|               "        xor" "l" " %" "" "1,%" "" "1\n" | ||||
|               "        jmp 2b\n" | ||||
|               ".section __ex_table,\"a\"\n" | ||||
|               "        .align 4\n"        "        .long 1b,3b\n" | ||||
|               ".text"        : "=r"(__gu_err), "=r" (__gu_val) : "m"((*(struct __large_struct *) | ||||
|                             (   __gu_addr   )) ), "i"(- 14 ), "0"(__gu_err));  | ||||
|               break;         | ||||
|           default:  | ||||
|             (__gu_val) = __get_user_bad();         | ||||
|         }         | ||||
|       } while (0) ;         | ||||
|     ((c)) = (__typeof__(*((buf))))__gu_val;         | ||||
|                             (   __gu_addr   )) ), "i"(- 14 ), "0"(__gu_err)); | ||||
|               break; | ||||
|           default: | ||||
|             (__gu_val) = __get_user_bad(); | ||||
|         } | ||||
|       } while (0) ; | ||||
|     ((c)) = (__typeof__(*((buf))))__gu_val; | ||||
|     __gu_err; | ||||
|   } | ||||
| ); | ||||
|  | @ -127,12 +127,12 @@ see what code gcc generates: | |||
| 
 | ||||
|  >         xorl %edx,%edx | ||||
|  >         movl current_set,%eax | ||||
|  >         cmpl $24,788(%eax)         | ||||
|  >         je .L1424         | ||||
|  >         cmpl $24,788(%eax) | ||||
|  >         je .L1424 | ||||
|  >         cmpl $-1073741825,64(%esp) | ||||
|  >         ja .L1423                 | ||||
|  >         ja .L1423 | ||||
|  > .L1424: | ||||
|  >         movl %edx,%eax                         | ||||
|  >         movl %edx,%eax | ||||
|  >         movl 64(%esp),%ebx | ||||
|  > #APP | ||||
|  > 1:      movb (%ebx),%dl                /* this is the actual user access */ | ||||
|  | @ -149,17 +149,17 @@ see what code gcc generates: | |||
|  > .L1423: | ||||
|  >         movzbl %dl,%esi | ||||
| 
 | ||||
| The optimizer does a good job and gives us something we can actually  | ||||
| understand. Can we? The actual user access is quite obvious. Thanks  | ||||
| to the unified address space we can just access the address in user  | ||||
| The optimizer does a good job and gives us something we can actually | ||||
| understand. Can we? The actual user access is quite obvious. Thanks | ||||
| to the unified address space we can just access the address in user | ||||
| memory. But what does the .section stuff do????? | ||||
| 
 | ||||
| To understand this we have to look at the final kernel: | ||||
| 
 | ||||
|  > objdump --section-headers vmlinux | ||||
|  >  | ||||
|  > | ||||
|  > vmlinux:     file format elf32-i386 | ||||
|  >  | ||||
|  > | ||||
|  > Sections: | ||||
|  > Idx Name          Size      VMA       LMA       File off  Algn | ||||
|  >   0 .text         00098f40  c0100000  c0100000  00001000  2**4 | ||||
|  | @ -198,18 +198,18 @@ final kernel executable: | |||
| 
 | ||||
| The whole user memory access is reduced to 10 x86 machine instructions. | ||||
| The instructions bracketed in the .section directives are no longer | ||||
| in the normal execution path. They are located in a different section  | ||||
| in the normal execution path. They are located in a different section | ||||
| of the executable file: | ||||
| 
 | ||||
|  > objdump --disassemble --section=.fixup vmlinux | ||||
|  >  | ||||
|  > | ||||
|  > c0199ff5 <.fixup+10b5> movl   $0xfffffff2,%eax | ||||
|  > c0199ffa <.fixup+10ba> xorb   %dl,%dl | ||||
|  > c0199ffc <.fixup+10bc> jmp    c017e7a7 <do_con_write+e3> | ||||
| 
 | ||||
| And finally: | ||||
|  > objdump --full-contents --section=__ex_table vmlinux | ||||
|  >  | ||||
|  > | ||||
|  >  c01aa7c4 93c017c0 e09f19c0 97c017c0 99c017c0  ................ | ||||
|  >  c01aa7d4 f6c217c0 e99f19c0 a5e717c0 f59f19c0  ................ | ||||
|  >  c01aa7e4 080a18c0 01a019c0 0a0a18c0 04a019c0  ................ | ||||
|  | @ -235,8 +235,8 @@ sections in the ELF object file. So the instructions | |||
| ended up in the .fixup section of the object file and the addresses | ||||
|         .long 1b,3b | ||||
| ended up in the __ex_table section of the object file. 1b and 3b | ||||
| are local labels. The local label 1b (1b stands for next label 1  | ||||
| backward) is the address of the instruction that might fault, i.e.  | ||||
| are local labels. The local label 1b (1b stands for next label 1 | ||||
| backward) is the address of the instruction that might fault, i.e. | ||||
| in our case the address of the label 1 is c017e7a5: | ||||
| the original assembly code: > 1:      movb (%ebx),%dl | ||||
| and linked in vmlinux     : > c017e7a5 <do_con_write+e1> movb   (%ebx),%dl | ||||
|  | @ -254,7 +254,7 @@ The assembly code | |||
| becomes the value pair | ||||
|  >  c01aa7d4 c017c2f6 c0199fe9 c017e7a5 c0199ff5  ................ | ||||
|                                ^this is ^this is | ||||
|                                1b       3b  | ||||
|                                1b       3b | ||||
| c017e7a5,c0199ff5 in the exception table of the kernel. | ||||
| 
 | ||||
| So, what actually happens if a fault from kernel mode with no suitable | ||||
|  | @ -266,9 +266,9 @@ vma occurs? | |||
| 3.) CPU calls do_page_fault | ||||
| 4.) do page fault calls search_exception_table (regs->eip == c017e7a5); | ||||
| 5.) search_exception_table looks up the address c017e7a5 in the | ||||
|     exception table (i.e. the contents of the ELF section __ex_table)  | ||||
|     exception table (i.e. the contents of the ELF section __ex_table) | ||||
|     and returns the address of the associated fault handle code c0199ff5. | ||||
| 6.) do_page_fault modifies its own return address to point to the fault  | ||||
| 6.) do_page_fault modifies its own return address to point to the fault | ||||
|     handle code and returns. | ||||
| 7.) execution continues in the fault handling code. | ||||
| 8.) 8a) EAX becomes -EFAULT (== -14) | ||||
							
								
								
									
										11
									
								
								MAINTAINERS
									
										
									
									
									
								
							
							
						
						
									
										11
									
								
								MAINTAINERS
									
										
									
									
									
								
							|  | @ -3287,11 +3287,11 @@ F:	include/linux/ivtv* | |||
| 
 | ||||
| JFS FILESYSTEM | ||||
| P:	Dave Kleikamp | ||||
| M:	shaggy@austin.ibm.com | ||||
| M:	shaggy@linux.vnet.ibm.com | ||||
| L:	jfs-discussion@lists.sourceforge.net | ||||
| W:	http://jfs.sourceforge.net/ | ||||
| T:	git git://git.kernel.org/pub/scm/linux/kernel/git/shaggy/jfs-2.6.git | ||||
| S:	Supported | ||||
| S:	Maintained | ||||
| F:	Documentation/filesystems/jfs.txt | ||||
| F:	fs/jfs/ | ||||
| 
 | ||||
|  | @ -4407,7 +4407,7 @@ W:	http://www.nongnu.org/orinoco/ | |||
| S:	Maintained | ||||
| F:	drivers/net/wireless/orinoco/ | ||||
| 
 | ||||
| OSD LIBRARY | ||||
| OSD LIBRARY and FILESYSTEM | ||||
| P:	Boaz Harrosh | ||||
| M:	bharrosh@panasas.com | ||||
| P:	Benny Halevy | ||||
|  | @ -4416,6 +4416,9 @@ L:	osd-dev@open-osd.org | |||
| W:	http://open-osd.org | ||||
| T:	git git://git.open-osd.org/open-osd.git | ||||
| S:	Maintained | ||||
| F:	drivers/scsi/osd/ | ||||
| F:	drivers/include/scsi/osd_* | ||||
| F:	fs/exofs/ | ||||
| 
 | ||||
| P54 WIRELESS DRIVER | ||||
| P:	Michael Wu | ||||
|  | @ -5851,7 +5854,7 @@ UBI FILE SYSTEM (UBIFS) | |||
| P:	Artem Bityutskiy | ||||
| M:	dedekind@infradead.org | ||||
| P:	Adrian Hunter | ||||
| M:	ext-adrian.hunter@nokia.com | ||||
| M:	adrian.hunter@nokia.com | ||||
| L:	linux-mtd@lists.infradead.org | ||||
| T:	git git://git.infradead.org/ubifs-2.6.git | ||||
| W:	http://www.linux-mtd.infradead.org/doc/ubifs.html | ||||
|  |  | |||
							
								
								
									
										7
									
								
								Makefile
									
										
									
									
									
								
							
							
						
						
									
										7
									
								
								Makefile
									
										
									
									
									
								
							|  | @ -1,7 +1,7 @@ | |||
| VERSION = 2 | ||||
| PATCHLEVEL = 6 | ||||
| SUBLEVEL = 31 | ||||
| EXTRAVERSION = -rc2 | ||||
| EXTRAVERSION = -rc3 | ||||
| NAME = Man-Eating Seals of Antiquity | ||||
| 
 | ||||
| # *DOCUMENTATION*
 | ||||
|  | @ -343,7 +343,8 @@ KBUILD_CPPFLAGS := -D__KERNEL__ | |||
| KBUILD_CFLAGS   := -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs \
 | ||||
| 		   -fno-strict-aliasing -fno-common \
 | ||||
| 		   -Werror-implicit-function-declaration \
 | ||||
| 		   -Wno-format-security | ||||
| 		   -Wno-format-security \
 | ||||
| 		   -fno-delete-null-pointer-checks | ||||
| KBUILD_AFLAGS   := -D__ASSEMBLY__ | ||||
| 
 | ||||
| # Read KERNELRELEASE from include/config/kernel.release (if it exists)
 | ||||
|  | @ -565,7 +566,7 @@ KBUILD_CFLAGS += $(call cc-option,-Wdeclaration-after-statement,) | |||
| KBUILD_CFLAGS += $(call cc-option,-Wno-pointer-sign,) | ||||
| 
 | ||||
| # disable invalid "can't wrap" optimizations for signed / pointers
 | ||||
| KBUILD_CFLAGS	+= $(call cc-option,-fwrapv) | ||||
| KBUILD_CFLAGS	+= $(call cc-option,-fno-strict-overflow) | ||||
| 
 | ||||
| # revert to pre-gcc-4.4 behaviour of .eh_frame
 | ||||
| KBUILD_CFLAGS	+= $(call cc-option,-fno-dwarf2-cfi-asm) | ||||
|  |  | |||
|  | @ -8,7 +8,6 @@ | |||
| #include <linux/sched.h> | ||||
| #include <linux/mm.h> | ||||
| #include <linux/smp.h> | ||||
| #include <linux/smp_lock.h> | ||||
| #include <linux/errno.h> | ||||
| #include <linux/ptrace.h> | ||||
| #include <linux/user.h> | ||||
|  |  | |||
|  | @ -31,7 +31,6 @@ | |||
| #include <linux/sched.h> | ||||
| #include <linux/mm.h> | ||||
| #include <linux/smp.h> | ||||
| #include <linux/smp_lock.h> | ||||
| #include <linux/errno.h> | ||||
| #include <linux/ptrace.h> | ||||
| #include <linux/user.h> | ||||
|  |  | |||
|  | @ -29,7 +29,6 @@ | |||
|  * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA | ||||
|  */ | ||||
| 
 | ||||
| #include <linux/smp_lock.h> | ||||
| #include <linux/spinlock.h> | ||||
| #include <linux/sem.h> | ||||
| #include <linux/msg.h> | ||||
|  |  | |||
|  | @ -15,7 +15,6 @@ | |||
| #include <linux/mm.h> | ||||
| #include <linux/fs.h> | ||||
| #include <linux/smp.h> | ||||
| #include <linux/smp_lock.h> | ||||
| #include <linux/sem.h> | ||||
| #include <linux/msg.h> | ||||
| #include <linux/shm.h> | ||||
|  |  | |||
|  | @ -6,6 +6,8 @@ | |||
|  *	David Mosberger-Tang <davidm@hpl.hp.com> | ||||
|  */ | ||||
| 
 | ||||
| #include <linux/types.h> | ||||
| 
 | ||||
| /* floating point status register: */ | ||||
| #define FPSR_TRAP_VD	(1 << 0)	/* invalid op trap disabled */ | ||||
| #define FPSR_TRAP_DD	(1 << 1)	/* denormal trap disabled */ | ||||
|  |  | |||
|  | @ -33,6 +33,7 @@ | |||
| #ifndef _ASM_IA64_XEN_HYPERVISOR_H | ||||
| #define _ASM_IA64_XEN_HYPERVISOR_H | ||||
| 
 | ||||
| #include <linux/err.h> | ||||
| #include <xen/interface/xen.h> | ||||
| #include <xen/interface/version.h>	/* to compile feature.c */ | ||||
| #include <xen/features.h>		/* to comiple xen-netfront.c */ | ||||
|  |  | |||
|  | @ -6,6 +6,14 @@ int iommu_detected __read_mostly; | |||
| struct dma_map_ops *dma_ops; | ||||
| EXPORT_SYMBOL(dma_ops); | ||||
| 
 | ||||
| #define PREALLOC_DMA_DEBUG_ENTRIES (1 << 16) | ||||
| 
 | ||||
| static int __init dma_init(void) | ||||
| { | ||||
|        dma_debug_init(PREALLOC_DMA_DEBUG_ENTRIES); | ||||
| } | ||||
| fs_initcall(dma_init); | ||||
| 
 | ||||
| struct dma_map_ops *dma_get_ops(struct device *dev) | ||||
| { | ||||
| 	return dma_ops; | ||||
|  |  | |||
|  | @ -15,7 +15,6 @@ | |||
| #include <linux/mm.h> | ||||
| #include <linux/errno.h> | ||||
| #include <linux/ptrace.h> | ||||
| #include <linux/smp_lock.h> | ||||
| #include <linux/user.h> | ||||
| #include <linux/security.h> | ||||
| #include <linux/audit.h> | ||||
|  |  | |||
|  | @ -19,7 +19,6 @@ | |||
| #include <linux/mm.h> | ||||
| #include <linux/err.h> | ||||
| #include <linux/smp.h> | ||||
| #include <linux/smp_lock.h> | ||||
| #include <linux/errno.h> | ||||
| #include <linux/ptrace.h> | ||||
| #include <linux/user.h> | ||||
|  |  | |||
|  | @ -27,7 +27,6 @@ | |||
| #include <linux/kernel.h> | ||||
| #include <linux/mm.h> | ||||
| #include <linux/sched.h> | ||||
| #include <linux/smp_lock.h> | ||||
| #include <linux/ptrace.h> | ||||
| #include <linux/signal.h> | ||||
| 
 | ||||
|  |  | |||
|  | @ -21,7 +21,6 @@ | |||
| #include <linux/sched.h> | ||||
| #include <linux/mm.h> | ||||
| #include <linux/smp.h> | ||||
| #include <linux/smp_lock.h> | ||||
| #include <linux/kernel.h> | ||||
| #include <linux/signal.h> | ||||
| #include <linux/errno.h> | ||||
|  |  | |||
|  | @ -15,7 +15,6 @@ | |||
| #include <linux/errno.h> | ||||
| #include <linux/mm.h> | ||||
| #include <linux/smp.h> | ||||
| #include <linux/smp_lock.h> | ||||
| #include <linux/syscalls.h> | ||||
| #include <linux/sem.h> | ||||
| #include <linux/msg.h> | ||||
|  |  | |||
|  | @ -22,7 +22,6 @@ | |||
| #include <linux/errno.h> | ||||
| #include <linux/ptrace.h> | ||||
| #include <linux/smp.h> | ||||
| #include <linux/smp_lock.h> | ||||
| #include <linux/user.h> | ||||
| #include <linux/security.h> | ||||
| 
 | ||||
|  |  | |||
|  | @ -16,7 +16,6 @@ | |||
| #include <linux/mm.h> | ||||
| #include <linux/hugetlb.h> | ||||
| #include <linux/pagemap.h> | ||||
| #include <linux/smp_lock.h> | ||||
| #include <linux/slab.h> | ||||
| #include <linux/err.h> | ||||
| #include <linux/sysctl.h> | ||||
|  |  | |||
|  | @ -13,7 +13,6 @@ | |||
| #include <linux/sched.h> | ||||
| #include <linux/mm.h> | ||||
| #include <linux/smp.h> | ||||
| #include <linux/smp_lock.h> | ||||
| #include <linux/errno.h> | ||||
| #include <linux/ptrace.h> | ||||
| #include <linux/user.h> | ||||
|  |  | |||
|  | @ -12,7 +12,6 @@ | |||
| #include <linux/sched.h> | ||||
| #include <linux/mm.h> | ||||
| #include <linux/smp.h> | ||||
| #include <linux/smp_lock.h> | ||||
| #include <linux/kernel.h> | ||||
| #include <linux/signal.h> | ||||
| #include <linux/errno.h> | ||||
|  |  | |||
|  | @ -13,7 +13,6 @@ | |||
| #include <linux/syscalls.h> | ||||
| #include <linux/mm.h> | ||||
| #include <linux/smp.h> | ||||
| #include <linux/smp_lock.h> | ||||
| #include <linux/sem.h> | ||||
| #include <linux/msg.h> | ||||
| #include <linux/shm.h> | ||||
|  | @ -21,7 +20,6 @@ | |||
| #include <linux/mman.h> | ||||
| #include <linux/file.h> | ||||
| #include <linux/utsname.h> | ||||
| #include <linux/syscalls.h> | ||||
| #include <linux/tty.h> | ||||
| 
 | ||||
| #include <asm/uaccess.h> | ||||
|  |  | |||
|  | @ -17,7 +17,6 @@ | |||
| #include <linux/timer.h> | ||||
| #include <linux/mm.h> | ||||
| #include <linux/smp.h> | ||||
| #include <linux/smp_lock.h> | ||||
| #include <linux/init.h> | ||||
| #include <linux/delay.h> | ||||
| #include <linux/spinlock.h> | ||||
|  |  | |||
|  | @ -20,7 +20,6 @@ | |||
| #include <linux/mman.h> | ||||
| #include <linux/mm.h> | ||||
| #include <linux/smp.h> | ||||
| #include <linux/smp_lock.h> | ||||
| #include <linux/interrupt.h> | ||||
| #include <linux/init.h> | ||||
| #include <linux/vt_kern.h>		/* For unblank_screen() */ | ||||
|  |  | |||
|  | @ -17,7 +17,6 @@ | |||
| #include <linux/timer.h> | ||||
| #include <linux/mm.h> | ||||
| #include <linux/smp.h> | ||||
| #include <linux/smp_lock.h> | ||||
| #include <linux/init.h> | ||||
| #include <linux/delay.h> | ||||
| #include <linux/spinlock.h> | ||||
|  |  | |||
|  | @ -736,15 +736,16 @@ void user_disable_single_step(struct task_struct *task) | |||
| { | ||||
| 	struct pt_regs *regs = task->thread.regs; | ||||
| 
 | ||||
| 
 | ||||
| #if defined(CONFIG_BOOKE) | ||||
| 	/* If DAC then do not single step, skip */ | ||||
| 	if (task->thread.dabr) | ||||
| 		return; | ||||
| #endif | ||||
| 
 | ||||
| 	if (regs != NULL) { | ||||
| #if defined(CONFIG_40x) || defined(CONFIG_BOOKE) | ||||
| #if defined(CONFIG_BOOKE) | ||||
| 		/* If DAC don't clear DBCRO_IDM or MSR_DE */ | ||||
| 		if (task->thread.dabr) | ||||
| 			task->thread.dbcr0 &= ~(DBCR0_IC | DBCR0_BT); | ||||
| 		else { | ||||
| 			task->thread.dbcr0 &= ~(DBCR0_IC | DBCR0_BT | DBCR0_IDM); | ||||
| 			regs->msr &= ~MSR_DE; | ||||
| 		} | ||||
| #elif defined(CONFIG_40x) | ||||
| 		task->thread.dbcr0 &= ~(DBCR0_IC | DBCR0_BT | DBCR0_IDM); | ||||
| 		regs->msr &= ~MSR_DE; | ||||
| #else | ||||
|  |  | |||
|  | @ -21,7 +21,6 @@ | |||
| #include <linux/sched.h> | ||||
| #include <linux/mm.h> | ||||
| #include <linux/smp.h> | ||||
| #include <linux/smp_lock.h> | ||||
| #include <linux/errno.h> | ||||
| #include <linux/ptrace.h> | ||||
| #include <linux/regset.h> | ||||
|  |  | |||
|  | @ -80,10 +80,10 @@ _GLOBAL(load_up_altivec) | |||
| 	mtvscr	vr0 | ||||
| 	REST_32VRS(0,r4,r5) | ||||
| #ifndef CONFIG_SMP | ||||
| 	/* Update last_task_used_math to 'current' */ | ||||
| 	/* Update last_task_used_altivec to 'current' */ | ||||
| 	subi	r4,r5,THREAD		/* Back to 'current' */ | ||||
| 	fromreal(r4) | ||||
| 	PPC_STL	r4,ADDROFF(last_task_used_math)(r3) | ||||
| 	PPC_STL	r4,ADDROFF(last_task_used_altivec)(r3) | ||||
| #endif /* CONFIG_SMP */ | ||||
| 	/* restore registers and return */ | ||||
| 	blr | ||||
|  | @ -172,7 +172,7 @@ _GLOBAL(load_up_vsx) | |||
| 	oris	r12,r12,MSR_VSX@h
 | ||||
| 	std	r12,_MSR(r1) | ||||
| #ifndef CONFIG_SMP | ||||
| 	/* Update last_task_used_math to 'current' */ | ||||
| 	/* Update last_task_used_vsx to 'current' */ | ||||
| 	ld	r4,PACACURRENT(r13) | ||||
| 	std	r4,0(r3) | ||||
| #endif /* CONFIG_SMP */ | ||||
|  |  | |||
|  | @ -95,6 +95,11 @@ config S390 | |||
| 	select HAVE_ARCH_TRACEHOOK | ||||
| 	select INIT_ALL_POSSIBLE | ||||
| 	select HAVE_PERF_COUNTERS | ||||
| 	select GENERIC_ATOMIC64 if !64BIT | ||||
| 
 | ||||
| config SCHED_OMIT_FRAME_POINTER | ||||
| 	bool | ||||
| 	default y | ||||
| 
 | ||||
| source "init/Kconfig" | ||||
| 
 | ||||
|  | @ -116,6 +121,9 @@ config 32BIT | |||
| 	bool | ||||
| 	default y if !64BIT | ||||
| 
 | ||||
| config KTIME_SCALAR | ||||
| 	def_bool 32BIT | ||||
| 
 | ||||
| config SMP | ||||
| 	bool "Symmetric multi-processing support" | ||||
| 	---help--- | ||||
|  |  | |||
|  | @ -268,7 +268,12 @@ static __inline__ int atomic64_add_unless(atomic64_t *v, | |||
| #define atomic64_inc_not_zero(v) atomic64_add_unless((v), 1, 0) | ||||
| 
 | ||||
| #undef __CSG_LOOP | ||||
| #endif | ||||
| 
 | ||||
| #else /* __s390x__ */ | ||||
| 
 | ||||
| #include <asm-generic/atomic64.h> | ||||
| 
 | ||||
| #endif /* __s390x__ */ | ||||
| 
 | ||||
| #define smp_mb__before_atomic_dec()	smp_mb() | ||||
| #define smp_mb__after_atomic_dec()	smp_mb() | ||||
|  |  | |||
|  | @ -6,3 +6,5 @@ | |||
| 
 | ||||
| static inline void set_perf_counter_pending(void) {} | ||||
| static inline void clear_perf_counter_pending(void) {} | ||||
| 
 | ||||
| #define PERF_COUNTER_INDEX_OFFSET 0 | ||||
|  |  | |||
|  | @ -15,7 +15,6 @@ | |||
| #include <linux/timer.h> | ||||
| #include <linux/mm.h> | ||||
| #include <linux/smp.h> | ||||
| #include <linux/smp_lock.h> | ||||
| #include <linux/init.h> | ||||
| #include <linux/interrupt.h> | ||||
| #include <linux/delay.h> | ||||
|  |  | |||
|  | @ -70,6 +70,7 @@ struct shutdown_action { | |||
| 	char *name; | ||||
| 	void (*fn) (struct shutdown_trigger *trigger); | ||||
| 	int (*init) (void); | ||||
| 	int init_rc; | ||||
| }; | ||||
| 
 | ||||
| static char *ipl_type_str(enum ipl_type type) | ||||
|  | @ -1486,11 +1487,13 @@ static int set_trigger(const char *buf, struct shutdown_trigger *trigger, | |||
| 	int i; | ||||
| 
 | ||||
| 	for (i = 0; i < SHUTDOWN_ACTIONS_COUNT; i++) { | ||||
| 		if (!shutdown_actions_list[i]) | ||||
| 			continue; | ||||
| 		if (sysfs_streq(buf, shutdown_actions_list[i]->name)) { | ||||
| 			trigger->action = shutdown_actions_list[i]; | ||||
| 			return len; | ||||
| 			if (shutdown_actions_list[i]->init_rc) { | ||||
| 				return shutdown_actions_list[i]->init_rc; | ||||
| 			} else { | ||||
| 				trigger->action = shutdown_actions_list[i]; | ||||
| 				return len; | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 	return -EINVAL; | ||||
|  | @ -1640,8 +1643,8 @@ static void __init shutdown_actions_init(void) | |||
| 	for (i = 0; i < SHUTDOWN_ACTIONS_COUNT; i++) { | ||||
| 		if (!shutdown_actions_list[i]->init) | ||||
| 			continue; | ||||
| 		if (shutdown_actions_list[i]->init()) | ||||
| 			shutdown_actions_list[i] = NULL; | ||||
| 		shutdown_actions_list[i]->init_rc = | ||||
| 			shutdown_actions_list[i]->init(); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -26,7 +26,6 @@ | |||
| #include <linux/sched.h> | ||||
| #include <linux/mm.h> | ||||
| #include <linux/smp.h> | ||||
| #include <linux/smp_lock.h> | ||||
| #include <linux/errno.h> | ||||
| #include <linux/ptrace.h> | ||||
| #include <linux/user.h> | ||||
|  |  | |||
|  | @ -3,6 +3,6 @@ | |||
| #
 | ||||
| 
 | ||||
| lib-y += delay.o string.o uaccess_std.o uaccess_pt.o | ||||
| obj-$(CONFIG_32BIT) += div64.o qrnnd.o | ||||
| obj-$(CONFIG_32BIT) += div64.o qrnnd.o ucmpdi2.o | ||||
| lib-$(CONFIG_64BIT) += uaccess_mvcos.o | ||||
| lib-$(CONFIG_SMP) += spinlock.o | ||||
|  |  | |||
|  | @ -36,9 +36,11 @@ static void __udelay_disabled(unsigned long usecs) | |||
| 	cr0 = (cr0_saved & 0xffff00e0) | 0x00000800; | ||||
| 	__ctl_load(cr0 , 0, 0); | ||||
| 	mask = psw_kernel_bits | PSW_MASK_WAIT | PSW_MASK_EXT; | ||||
| 	lockdep_off(); | ||||
| 	trace_hardirqs_on(); | ||||
| 	__load_psw_mask(mask); | ||||
| 	local_irq_disable(); | ||||
| 	lockdep_on(); | ||||
| 	__ctl_load(cr0_saved, 0, 0); | ||||
| 	local_tick_enable(clock_saved); | ||||
| 	set_clock_comparator(S390_lowcore.clock_comparator); | ||||
|  |  | |||
							
								
								
									
										26
									
								
								arch/s390/lib/ucmpdi2.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								arch/s390/lib/ucmpdi2.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,26 @@ | |||
| #include <linux/module.h> | ||||
| 
 | ||||
| union ull_union { | ||||
| 	unsigned long long ull; | ||||
| 	struct { | ||||
| 		unsigned int high; | ||||
| 		unsigned int low; | ||||
| 	} ui; | ||||
| }; | ||||
| 
 | ||||
| int __ucmpdi2(unsigned long long a, unsigned long long b) | ||||
| { | ||||
| 	union ull_union au = {.ull = a}; | ||||
| 	union ull_union bu = {.ull = b}; | ||||
| 
 | ||||
| 	if (au.ui.high < bu.ui.high) | ||||
| 		return 0; | ||||
| 	else if (au.ui.high > bu.ui.high) | ||||
| 		return 2; | ||||
| 	if (au.ui.low < bu.ui.low) | ||||
| 		return 0; | ||||
| 	else if (au.ui.low > bu.ui.low) | ||||
| 		return 2; | ||||
| 	return 1; | ||||
| } | ||||
| EXPORT_SYMBOL(__ucmpdi2); | ||||
|  | @ -22,7 +22,6 @@ | |||
| #include <linux/compat.h> | ||||
| #include <linux/smp.h> | ||||
| #include <linux/kdebug.h> | ||||
| #include <linux/smp_lock.h> | ||||
| #include <linux/init.h> | ||||
| #include <linux/console.h> | ||||
| #include <linux/module.h> | ||||
|  |  | |||
|  | @ -304,6 +304,7 @@ static struct platform_device sh_eth_device = { | |||
| }; | ||||
| 
 | ||||
| static struct r8a66597_platdata sh7724_usb0_host_data = { | ||||
| 	.on_chip = 1, | ||||
| }; | ||||
| 
 | ||||
| static struct resource sh7724_usb0_host_resources[] = { | ||||
|  |  | |||
|  | @ -4,6 +4,9 @@ | |||
| #include <asm/clock.h> | ||||
| #include <asm/io.h> | ||||
| 
 | ||||
| #define HWBLK_CNT_USAGE 0 | ||||
| #define HWBLK_CNT_NR 1 | ||||
| 
 | ||||
| #define HWBLK_AREA_FLAG_PARENT (1 << 0) /* valid parent */ | ||||
| 
 | ||||
| #define HWBLK_AREA(_flags, _parent)		\ | ||||
|  | @ -13,7 +16,7 @@ | |||
| } | ||||
| 
 | ||||
| struct hwblk_area { | ||||
| 	unsigned long cnt; | ||||
| 	int cnt[HWBLK_CNT_NR]; | ||||
| 	unsigned char parent; | ||||
| 	unsigned char flags; | ||||
| }; | ||||
|  | @ -29,7 +32,7 @@ struct hwblk { | |||
| 	void __iomem *mstp; | ||||
| 	unsigned char bit; | ||||
| 	unsigned char area; | ||||
| 	unsigned long cnt; | ||||
| 	int cnt[HWBLK_CNT_NR]; | ||||
| }; | ||||
| 
 | ||||
| struct hwblk_info { | ||||
|  | @ -46,6 +49,12 @@ int arch_hwblk_sleep_mode(void); | |||
| int hwblk_register(struct hwblk_info *info); | ||||
| int hwblk_init(void); | ||||
| 
 | ||||
| void hwblk_enable(struct hwblk_info *info, int hwblk); | ||||
| void hwblk_disable(struct hwblk_info *info, int hwblk); | ||||
| 
 | ||||
| void hwblk_cnt_inc(struct hwblk_info *info, int hwblk, int cnt); | ||||
| void hwblk_cnt_dec(struct hwblk_info *info, int hwblk, int cnt); | ||||
| 
 | ||||
| /* allow clocks to enable and disable hardware blocks */ | ||||
| #define SH_HWBLK_CLK(_name, _id, _parent, _hwblk, _flags)	\ | ||||
| {							\ | ||||
|  |  | |||
|  | @ -265,4 +265,21 @@ enum { | |||
| 	GPIO_FN_IDEA1, GPIO_FN_IDEA0, | ||||
| }; | ||||
| 
 | ||||
| enum { | ||||
| 	HWBLK_UNKNOWN = 0, | ||||
| 	HWBLK_TLB, HWBLK_IC, HWBLK_OC, HWBLK_L2C, HWBLK_ILMEM, HWBLK_FPU, | ||||
| 	HWBLK_INTC, HWBLK_DMAC0, HWBLK_SHYWAY, | ||||
| 	HWBLK_HUDI, HWBLK_DBG, HWBLK_UBC, HWBLK_SUBC, | ||||
| 	HWBLK_TMU0, HWBLK_CMT, HWBLK_RWDT, HWBLK_DMAC1, HWBLK_TMU1, | ||||
| 	HWBLK_FLCTL, | ||||
| 	HWBLK_SCIF0, HWBLK_SCIF1, HWBLK_SCIF2, | ||||
| 	HWBLK_SCIF3, HWBLK_SCIF4, HWBLK_SCIF5, | ||||
| 	HWBLK_MSIOF0, HWBLK_MSIOF1, HWBLK_MERAM, HWBLK_IIC, HWBLK_RTC, | ||||
| 	HWBLK_ATAPI, HWBLK_ADC, HWBLK_TPU, HWBLK_IRDA, HWBLK_TSIF, HWBLK_ICB, | ||||
| 	HWBLK_SDHI0, HWBLK_SDHI1, HWBLK_KEYSC, HWBLK_USB, | ||||
| 	HWBLK_2DG, HWBLK_SIU, HWBLK_VEU2H1, HWBLK_VOU, HWBLK_BEU, HWBLK_CEU, | ||||
| 	HWBLK_VEU2H0, HWBLK_VPU, HWBLK_LCDC, | ||||
| 	HWBLK_NR, | ||||
| }; | ||||
| 
 | ||||
| #endif /* __ASM_SH7723_H__ */ | ||||
|  |  | |||
|  | @ -9,38 +9,64 @@ | |||
| 
 | ||||
| static DEFINE_SPINLOCK(hwblk_lock); | ||||
| 
 | ||||
| static void hwblk_area_inc(struct hwblk_info *info, int area) | ||||
| static void hwblk_area_mod_cnt(struct hwblk_info *info, | ||||
| 			       int area, int counter, int value, int goal) | ||||
| { | ||||
| 	struct hwblk_area *hap = info->areas + area; | ||||
| 
 | ||||
| 	hap->cnt++; | ||||
| 	if (hap->cnt == 1) | ||||
| 		if (hap->flags & HWBLK_AREA_FLAG_PARENT) | ||||
| 			hwblk_area_inc(info, hap->parent); | ||||
| 	hap->cnt[counter] += value; | ||||
| 
 | ||||
| 	if (hap->cnt[counter] != goal) | ||||
| 		return; | ||||
| 
 | ||||
| 	if (hap->flags & HWBLK_AREA_FLAG_PARENT) | ||||
| 		hwblk_area_mod_cnt(info, hap->parent, counter, value, goal); | ||||
| } | ||||
| 
 | ||||
| static void hwblk_area_dec(struct hwblk_info *info, int area) | ||||
| 
 | ||||
| static int __hwblk_mod_cnt(struct hwblk_info *info, int hwblk, | ||||
| 			  int counter, int value, int goal) | ||||
| { | ||||
| 	struct hwblk_area *hap = info->areas + area; | ||||
| 	struct hwblk *hp = info->hwblks + hwblk; | ||||
| 
 | ||||
| 	if (hap->cnt == 1) | ||||
| 		if (hap->flags & HWBLK_AREA_FLAG_PARENT) | ||||
| 			hwblk_area_dec(info, hap->parent); | ||||
| 	hap->cnt--; | ||||
| 	hp->cnt[counter] += value; | ||||
| 	if (hp->cnt[counter] == goal) | ||||
| 		hwblk_area_mod_cnt(info, hp->area, counter, value, goal); | ||||
| 
 | ||||
| 	return hp->cnt[counter]; | ||||
| } | ||||
| 
 | ||||
| static void hwblk_enable(struct hwblk_info *info, int hwblk) | ||||
| static void hwblk_mod_cnt(struct hwblk_info *info, int hwblk, | ||||
| 			  int counter, int value, int goal) | ||||
| { | ||||
| 	unsigned long flags; | ||||
| 
 | ||||
| 	spin_lock_irqsave(&hwblk_lock, flags); | ||||
| 	__hwblk_mod_cnt(info, hwblk, counter, value, goal); | ||||
| 	spin_unlock_irqrestore(&hwblk_lock, flags); | ||||
| } | ||||
| 
 | ||||
| void hwblk_cnt_inc(struct hwblk_info *info, int hwblk, int counter) | ||||
| { | ||||
| 	hwblk_mod_cnt(info, hwblk, counter, 1, 1); | ||||
| } | ||||
| 
 | ||||
| void hwblk_cnt_dec(struct hwblk_info *info, int hwblk, int counter) | ||||
| { | ||||
| 	hwblk_mod_cnt(info, hwblk, counter, -1, 0); | ||||
| } | ||||
| 
 | ||||
| void hwblk_enable(struct hwblk_info *info, int hwblk) | ||||
| { | ||||
| 	struct hwblk *hp = info->hwblks + hwblk; | ||||
| 	unsigned long tmp; | ||||
| 	unsigned long flags; | ||||
| 	int ret; | ||||
| 
 | ||||
| 	spin_lock_irqsave(&hwblk_lock, flags); | ||||
| 
 | ||||
| 	hp->cnt++; | ||||
| 	if (hp->cnt == 1) { | ||||
| 		hwblk_area_inc(info, hp->area); | ||||
| 
 | ||||
| 	ret = __hwblk_mod_cnt(info, hwblk, HWBLK_CNT_USAGE, 1, 1); | ||||
| 	if (ret == 1) { | ||||
| 		tmp = __raw_readl(hp->mstp); | ||||
| 		tmp &= ~(1 << hp->bit); | ||||
| 		__raw_writel(tmp, hp->mstp); | ||||
|  | @ -49,27 +75,26 @@ static void hwblk_enable(struct hwblk_info *info, int hwblk) | |||
| 	spin_unlock_irqrestore(&hwblk_lock, flags); | ||||
| } | ||||
| 
 | ||||
| static void hwblk_disable(struct hwblk_info *info, int hwblk) | ||||
| void hwblk_disable(struct hwblk_info *info, int hwblk) | ||||
| { | ||||
| 	struct hwblk *hp = info->hwblks + hwblk; | ||||
| 	unsigned long tmp; | ||||
| 	unsigned long flags; | ||||
| 	int ret; | ||||
| 
 | ||||
| 	spin_lock_irqsave(&hwblk_lock, flags); | ||||
| 
 | ||||
| 	if (hp->cnt == 1) { | ||||
| 		hwblk_area_dec(info, hp->area); | ||||
| 
 | ||||
| 	ret = __hwblk_mod_cnt(info, hwblk, HWBLK_CNT_USAGE, -1, 0); | ||||
| 	if (ret == 0) { | ||||
| 		tmp = __raw_readl(hp->mstp); | ||||
| 		tmp |= 1 << hp->bit; | ||||
| 		__raw_writel(tmp, hp->mstp); | ||||
| 	} | ||||
| 	hp->cnt--; | ||||
| 
 | ||||
| 	spin_unlock_irqrestore(&hwblk_lock, flags); | ||||
| } | ||||
| 
 | ||||
| static struct hwblk_info *hwblk_info; | ||||
| struct hwblk_info *hwblk_info; | ||||
| 
 | ||||
| int __init hwblk_register(struct hwblk_info *info) | ||||
| { | ||||
|  |  | |||
|  | @ -26,7 +26,7 @@ clock-$(CONFIG_CPU_SUBTYPE_SH7785)	:= clock-sh7785.o | |||
| clock-$(CONFIG_CPU_SUBTYPE_SH7786)	:= clock-sh7786.o | ||||
| clock-$(CONFIG_CPU_SUBTYPE_SH7343)	:= clock-sh7343.o | ||||
| clock-$(CONFIG_CPU_SUBTYPE_SH7722)	:= clock-sh7722.o hwblk-sh7722.o | ||||
| clock-$(CONFIG_CPU_SUBTYPE_SH7723)	:= clock-sh7723.o | ||||
| clock-$(CONFIG_CPU_SUBTYPE_SH7723)	:= clock-sh7723.o hwblk-sh7723.o | ||||
| clock-$(CONFIG_CPU_SUBTYPE_SH7724)	:= clock-sh7724.o | ||||
| clock-$(CONFIG_CPU_SUBTYPE_SH7366)	:= clock-sh7366.o | ||||
| clock-$(CONFIG_CPU_SUBTYPE_SHX3)	:= clock-shx3.o | ||||
|  |  | |||
|  | @ -22,6 +22,8 @@ | |||
| #include <linux/kernel.h> | ||||
| #include <linux/io.h> | ||||
| #include <asm/clock.h> | ||||
| #include <asm/hwblk.h> | ||||
| #include <cpu/sh7723.h> | ||||
| 
 | ||||
| /* SH7723 registers */ | ||||
| #define FRQCR		0xa4150000 | ||||
|  | @ -140,60 +142,64 @@ struct clk div6_clks[] = { | |||
| 	SH_CLK_DIV6("video_clk", &pll_clk, VCLKCR, 0), | ||||
| }; | ||||
| 
 | ||||
| #define MSTP(_str, _parent, _reg, _bit, _force_on, _need_cpg, _need_ram) \ | ||||
|   SH_CLK_MSTP32(_str, -1, _parent, _reg, _bit, _force_on * CLK_ENABLE_ON_INIT) | ||||
| #define R_CLK (&r_clk) | ||||
| #define P_CLK (&div4_clks[DIV4_P]) | ||||
| #define B_CLK (&div4_clks[DIV4_B]) | ||||
| #define U_CLK (&div4_clks[DIV4_U]) | ||||
| #define I_CLK (&div4_clks[DIV4_I]) | ||||
| #define SH_CLK (&div4_clks[DIV4_SH]) | ||||
| 
 | ||||
| static struct clk mstp_clks[] = { | ||||
| 	/* See page 60 of Datasheet V1.0: Overview -> Block Diagram */ | ||||
| 	MSTP("tlb0", &div4_clks[DIV4_I], MSTPCR0, 31, 1, 1, 0), | ||||
| 	MSTP("ic0", &div4_clks[DIV4_I], MSTPCR0, 30, 1, 1, 0), | ||||
| 	MSTP("oc0", &div4_clks[DIV4_I], MSTPCR0, 29, 1, 1, 0), | ||||
| 	MSTP("l2c0", &div4_clks[DIV4_SH], MSTPCR0, 28, 1, 1, 0), | ||||
| 	MSTP("ilmem0", &div4_clks[DIV4_I], MSTPCR0, 27, 1, 1, 0), | ||||
| 	MSTP("fpu0", &div4_clks[DIV4_I], MSTPCR0, 24, 1, 1, 0), | ||||
| 	MSTP("intc0", &div4_clks[DIV4_I], MSTPCR0, 22, 1, 1, 0), | ||||
| 	MSTP("dmac0", &div4_clks[DIV4_B], MSTPCR0, 21, 0, 1, 1), | ||||
| 	MSTP("sh0", &div4_clks[DIV4_SH], MSTPCR0, 20, 0, 1, 0), | ||||
| 	MSTP("hudi0", &div4_clks[DIV4_P], MSTPCR0, 19, 0, 1, 0), | ||||
| 	MSTP("ubc0", &div4_clks[DIV4_I], MSTPCR0, 17, 0, 1, 0), | ||||
| 	MSTP("tmu0", &div4_clks[DIV4_P], MSTPCR0, 15, 0, 1, 0), | ||||
| 	MSTP("cmt0", &r_clk, MSTPCR0, 14, 0, 0, 0), | ||||
| 	MSTP("rwdt0", &r_clk, MSTPCR0, 13, 0, 0, 0), | ||||
| 	MSTP("dmac1", &div4_clks[DIV4_B], MSTPCR0, 12, 0, 1, 1), | ||||
| 	MSTP("tmu1", &div4_clks[DIV4_P], MSTPCR0, 11, 0, 1, 0), | ||||
| 	MSTP("flctl0", &div4_clks[DIV4_P], MSTPCR0, 10, 0, 1, 0), | ||||
| 	MSTP("scif0", &div4_clks[DIV4_P], MSTPCR0, 9, 0, 1, 0), | ||||
| 	MSTP("scif1", &div4_clks[DIV4_P], MSTPCR0, 8, 0, 1, 0), | ||||
| 	MSTP("scif2", &div4_clks[DIV4_P], MSTPCR0, 7, 0, 1, 0), | ||||
| 	MSTP("scif3", &div4_clks[DIV4_B], MSTPCR0, 6, 0, 1, 0), | ||||
| 	MSTP("scif4", &div4_clks[DIV4_B], MSTPCR0, 5, 0, 1, 0), | ||||
| 	MSTP("scif5", &div4_clks[DIV4_B], MSTPCR0, 4, 0, 1, 0), | ||||
| 	MSTP("msiof0", &div4_clks[DIV4_B], MSTPCR0, 2, 0, 1, 0), | ||||
| 	MSTP("msiof1", &div4_clks[DIV4_B], MSTPCR0, 1, 0, 1, 0), | ||||
| 	MSTP("meram0", &div4_clks[DIV4_SH], MSTPCR0, 0, 1, 1, 0), | ||||
| 	SH_HWBLK_CLK("tlb0", -1, I_CLK, HWBLK_TLB, CLK_ENABLE_ON_INIT), | ||||
| 	SH_HWBLK_CLK("ic0", -1, I_CLK, HWBLK_IC, CLK_ENABLE_ON_INIT), | ||||
| 	SH_HWBLK_CLK("oc0", -1, I_CLK, HWBLK_OC, CLK_ENABLE_ON_INIT), | ||||
| 	SH_HWBLK_CLK("l2c0", -1, SH_CLK, HWBLK_L2C, CLK_ENABLE_ON_INIT), | ||||
| 	SH_HWBLK_CLK("ilmem0", -1, I_CLK, HWBLK_ILMEM, CLK_ENABLE_ON_INIT), | ||||
| 	SH_HWBLK_CLK("fpu0", -1, I_CLK, HWBLK_FPU, CLK_ENABLE_ON_INIT), | ||||
| 	SH_HWBLK_CLK("intc0", -1, I_CLK, HWBLK_INTC, CLK_ENABLE_ON_INIT), | ||||
| 	SH_HWBLK_CLK("dmac0", -1, B_CLK, HWBLK_DMAC0, 0), | ||||
| 	SH_HWBLK_CLK("sh0", -1, SH_CLK, HWBLK_SHYWAY, CLK_ENABLE_ON_INIT), | ||||
| 	SH_HWBLK_CLK("hudi0", -1, P_CLK, HWBLK_HUDI, 0), | ||||
| 	SH_HWBLK_CLK("ubc0", -1, I_CLK, HWBLK_UBC, 0), | ||||
| 	SH_HWBLK_CLK("tmu0", -1, P_CLK, HWBLK_TMU0, 0), | ||||
| 	SH_HWBLK_CLK("cmt0", -1, R_CLK, HWBLK_CMT, 0), | ||||
| 	SH_HWBLK_CLK("rwdt0", -1, R_CLK, HWBLK_RWDT, 0), | ||||
| 	SH_HWBLK_CLK("dmac1", -1, B_CLK, HWBLK_DMAC1, 0), | ||||
| 	SH_HWBLK_CLK("tmu1", -1, P_CLK, HWBLK_TMU1, 0), | ||||
| 	SH_HWBLK_CLK("flctl0", -1, P_CLK, HWBLK_FLCTL, 0), | ||||
| 	SH_HWBLK_CLK("scif0", -1, P_CLK, HWBLK_SCIF0, 0), | ||||
| 	SH_HWBLK_CLK("scif1", -1, P_CLK, HWBLK_SCIF1, 0), | ||||
| 	SH_HWBLK_CLK("scif2", -1, P_CLK, HWBLK_SCIF2, 0), | ||||
| 	SH_HWBLK_CLK("scif3", -1, B_CLK, HWBLK_SCIF3, 0), | ||||
| 	SH_HWBLK_CLK("scif4", -1, B_CLK, HWBLK_SCIF4, 0), | ||||
| 	SH_HWBLK_CLK("scif5", -1, B_CLK, HWBLK_SCIF5, 0), | ||||
| 	SH_HWBLK_CLK("msiof0", -1, B_CLK, HWBLK_MSIOF0, 0), | ||||
| 	SH_HWBLK_CLK("msiof1", -1, B_CLK, HWBLK_MSIOF1, 0), | ||||
| 	SH_HWBLK_CLK("meram0", -1, SH_CLK, HWBLK_MERAM, 0), | ||||
| 
 | ||||
| 	MSTP("i2c0", &div4_clks[DIV4_P], MSTPCR1, 9, 0, 1, 0), | ||||
| 	MSTP("rtc0", &r_clk, MSTPCR1, 8, 0, 0, 0), | ||||
| 	SH_HWBLK_CLK("i2c0", -1, P_CLK, HWBLK_IIC, 0), | ||||
| 	SH_HWBLK_CLK("rtc0", -1, R_CLK, HWBLK_RTC, 0), | ||||
| 
 | ||||
| 	MSTP("atapi0", &div4_clks[DIV4_SH], MSTPCR2, 28, 0, 1, 0), | ||||
| 	MSTP("adc0", &div4_clks[DIV4_P], MSTPCR2, 27, 0, 1, 0), | ||||
| 	MSTP("tpu0", &div4_clks[DIV4_B], MSTPCR2, 25, 0, 1, 0), | ||||
| 	MSTP("irda0", &div4_clks[DIV4_P], MSTPCR2, 24, 0, 1, 0), | ||||
| 	MSTP("tsif0", &div4_clks[DIV4_B], MSTPCR2, 22, 0, 1, 0), | ||||
| 	MSTP("icb0", &div4_clks[DIV4_B], MSTPCR2, 21, 0, 1, 1), | ||||
| 	MSTP("sdhi0", &div4_clks[DIV4_B], MSTPCR2, 18, 0, 1, 0), | ||||
| 	MSTP("sdhi1", &div4_clks[DIV4_B], MSTPCR2, 17, 0, 1, 0), | ||||
| 	MSTP("keysc0", &r_clk, MSTPCR2, 14, 0, 0, 0), | ||||
| 	MSTP("usb0", &div4_clks[DIV4_B], MSTPCR2, 11, 0, 1, 0), | ||||
| 	MSTP("2dg0", &div4_clks[DIV4_B], MSTPCR2, 10, 0, 1, 1), | ||||
| 	MSTP("siu0", &div4_clks[DIV4_B], MSTPCR2, 8, 0, 1, 0), | ||||
| 	MSTP("veu1", &div4_clks[DIV4_B], MSTPCR2, 6, 1, 1, 1), | ||||
| 	MSTP("vou0", &div4_clks[DIV4_B], MSTPCR2, 5, 0, 1, 1), | ||||
| 	MSTP("beu0", &div4_clks[DIV4_B], MSTPCR2, 4, 0, 1, 1), | ||||
| 	MSTP("ceu0", &div4_clks[DIV4_B], MSTPCR2, 3, 0, 1, 1), | ||||
| 	MSTP("veu0", &div4_clks[DIV4_B], MSTPCR2, 2, 1, 1, 1), | ||||
| 	MSTP("vpu0", &div4_clks[DIV4_B], MSTPCR2, 1, 1, 1, 1), | ||||
| 	MSTP("lcdc0", &div4_clks[DIV4_B], MSTPCR2, 0, 0, 1, 1), | ||||
| 	SH_HWBLK_CLK("atapi0", -1, SH_CLK, HWBLK_ATAPI, 0), | ||||
| 	SH_HWBLK_CLK("adc0", -1, P_CLK, HWBLK_ADC, 0), | ||||
| 	SH_HWBLK_CLK("tpu0", -1, B_CLK, HWBLK_TPU, 0), | ||||
| 	SH_HWBLK_CLK("irda0", -1, P_CLK, HWBLK_IRDA, 0), | ||||
| 	SH_HWBLK_CLK("tsif0", -1, B_CLK, HWBLK_TSIF, 0), | ||||
| 	SH_HWBLK_CLK("icb0", -1, B_CLK, HWBLK_ICB, CLK_ENABLE_ON_INIT), | ||||
| 	SH_HWBLK_CLK("sdhi0", -1, B_CLK, HWBLK_SDHI0, 0), | ||||
| 	SH_HWBLK_CLK("sdhi1", -1, B_CLK, HWBLK_SDHI1, 0), | ||||
| 	SH_HWBLK_CLK("keysc0", -1, R_CLK, HWBLK_KEYSC, 0), | ||||
| 	SH_HWBLK_CLK("usb0", -1, B_CLK, HWBLK_USB, 0), | ||||
| 	SH_HWBLK_CLK("2dg0", -1, B_CLK, HWBLK_2DG, 0), | ||||
| 	SH_HWBLK_CLK("siu0", -1, B_CLK, HWBLK_SIU, 0), | ||||
| 	SH_HWBLK_CLK("veu1", -1, B_CLK, HWBLK_VEU2H1, CLK_ENABLE_ON_INIT), | ||||
| 	SH_HWBLK_CLK("vou0", -1, B_CLK, HWBLK_VOU, 0), | ||||
| 	SH_HWBLK_CLK("beu0", -1, B_CLK, HWBLK_BEU, 0), | ||||
| 	SH_HWBLK_CLK("ceu0", -1, B_CLK, HWBLK_CEU, 0), | ||||
| 	SH_HWBLK_CLK("veu0", -1, B_CLK, HWBLK_VEU2H0, CLK_ENABLE_ON_INIT), | ||||
| 	SH_HWBLK_CLK("vpu0", -1, B_CLK, HWBLK_VPU, CLK_ENABLE_ON_INIT), | ||||
| 	SH_HWBLK_CLK("lcdc0", -1, B_CLK, HWBLK_LCDC, 0), | ||||
| }; | ||||
| 
 | ||||
| int __init arch_clk_init(void) | ||||
|  | @ -216,7 +222,7 @@ int __init arch_clk_init(void) | |||
| 		ret = sh_clk_div6_register(div6_clks, ARRAY_SIZE(div6_clks)); | ||||
| 
 | ||||
| 	if (!ret) | ||||
| 		ret = sh_clk_mstp32_register(mstp_clks, ARRAY_SIZE(mstp_clks)); | ||||
| 		ret = sh_hwblk_clk_register(mstp_clks, ARRAY_SIZE(mstp_clks)); | ||||
| 
 | ||||
| 	return ret; | ||||
| } | ||||
|  |  | |||
|  | @ -91,10 +91,10 @@ static struct hwblk_info sh7722_hwblk_info = { | |||
| 
 | ||||
| int arch_hwblk_sleep_mode(void) | ||||
| { | ||||
| 	if (!sh7722_hwblk_area[CORE_AREA].cnt) | ||||
| 	if (!sh7722_hwblk_area[CORE_AREA].cnt[HWBLK_CNT_USAGE]) | ||||
| 		return SUSP_SH_STANDBY | SUSP_SH_SF; | ||||
| 
 | ||||
| 	if (!sh7722_hwblk_area[CORE_AREA_BM].cnt) | ||||
| 	if (!sh7722_hwblk_area[CORE_AREA_BM].cnt[HWBLK_CNT_USAGE]) | ||||
| 		return SUSP_SH_SLEEP | SUSP_SH_SF; | ||||
| 
 | ||||
| 	return SUSP_SH_SLEEP; | ||||
|  |  | |||
							
								
								
									
										117
									
								
								arch/sh/kernel/cpu/sh4a/hwblk-sh7723.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										117
									
								
								arch/sh/kernel/cpu/sh4a/hwblk-sh7723.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,117 @@ | |||
| /*
 | ||||
|  * arch/sh/kernel/cpu/sh4a/hwblk-sh7723.c | ||||
|  * | ||||
|  * SH7723 hardware block support | ||||
|  * | ||||
|  * Copyright (C) 2009 Magnus Damm | ||||
|  * | ||||
|  * 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 | ||||
|  * | ||||
|  * 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 <linux/init.h> | ||||
| #include <linux/kernel.h> | ||||
| #include <linux/io.h> | ||||
| #include <asm/suspend.h> | ||||
| #include <asm/hwblk.h> | ||||
| #include <cpu/sh7723.h> | ||||
| 
 | ||||
| /* SH7723 registers */ | ||||
| #define MSTPCR0		0xa4150030 | ||||
| #define MSTPCR1		0xa4150034 | ||||
| #define MSTPCR2		0xa4150038 | ||||
| 
 | ||||
| /* SH7723 Power Domains */ | ||||
| enum { CORE_AREA, SUB_AREA, CORE_AREA_BM }; | ||||
| static struct hwblk_area sh7723_hwblk_area[] = { | ||||
| 	[CORE_AREA] = HWBLK_AREA(0, 0), | ||||
| 	[CORE_AREA_BM] = HWBLK_AREA(HWBLK_AREA_FLAG_PARENT, CORE_AREA), | ||||
| 	[SUB_AREA] = HWBLK_AREA(0, 0), | ||||
| }; | ||||
| 
 | ||||
| /* Table mapping HWBLK to Module Stop Bit and Power Domain */ | ||||
| static struct hwblk sh7723_hwblk[HWBLK_NR] = { | ||||
| 	[HWBLK_TLB] = HWBLK(MSTPCR0, 31, CORE_AREA), | ||||
| 	[HWBLK_IC] = HWBLK(MSTPCR0, 30, CORE_AREA), | ||||
| 	[HWBLK_OC] = HWBLK(MSTPCR0, 29, CORE_AREA), | ||||
| 	[HWBLK_L2C] = HWBLK(MSTPCR0, 28, CORE_AREA), | ||||
| 	[HWBLK_ILMEM] = HWBLK(MSTPCR0, 27, CORE_AREA), | ||||
| 	[HWBLK_FPU] = HWBLK(MSTPCR0, 24, CORE_AREA), | ||||
| 	[HWBLK_INTC] = HWBLK(MSTPCR0, 22, CORE_AREA), | ||||
| 	[HWBLK_DMAC0] = HWBLK(MSTPCR0, 21, CORE_AREA_BM), | ||||
| 	[HWBLK_SHYWAY] = HWBLK(MSTPCR0, 20, CORE_AREA), | ||||
| 	[HWBLK_HUDI] = HWBLK(MSTPCR0, 19, CORE_AREA), | ||||
| 	[HWBLK_DBG] = HWBLK(MSTPCR0, 18, CORE_AREA), | ||||
| 	[HWBLK_UBC] = HWBLK(MSTPCR0, 17, CORE_AREA), | ||||
| 	[HWBLK_SUBC] = HWBLK(MSTPCR0, 16, CORE_AREA), | ||||
| 	[HWBLK_TMU0] = HWBLK(MSTPCR0, 15, CORE_AREA), | ||||
| 	[HWBLK_CMT] = HWBLK(MSTPCR0, 14, SUB_AREA), | ||||
| 	[HWBLK_RWDT] = HWBLK(MSTPCR0, 13, SUB_AREA), | ||||
| 	[HWBLK_DMAC1] = HWBLK(MSTPCR0, 12, CORE_AREA_BM), | ||||
| 	[HWBLK_TMU1] = HWBLK(MSTPCR0, 11, CORE_AREA), | ||||
| 	[HWBLK_FLCTL] = HWBLK(MSTPCR0, 10, CORE_AREA), | ||||
| 	[HWBLK_SCIF0] = HWBLK(MSTPCR0, 9, CORE_AREA), | ||||
| 	[HWBLK_SCIF1] = HWBLK(MSTPCR0, 8, CORE_AREA), | ||||
| 	[HWBLK_SCIF2] = HWBLK(MSTPCR0, 7, CORE_AREA), | ||||
| 	[HWBLK_SCIF3] = HWBLK(MSTPCR0, 6, CORE_AREA), | ||||
| 	[HWBLK_SCIF4] = HWBLK(MSTPCR0, 5, CORE_AREA), | ||||
| 	[HWBLK_SCIF5] = HWBLK(MSTPCR0, 4, CORE_AREA), | ||||
| 	[HWBLK_MSIOF0] = HWBLK(MSTPCR0, 2, CORE_AREA), | ||||
| 	[HWBLK_MSIOF1] = HWBLK(MSTPCR0, 1, CORE_AREA), | ||||
| 	[HWBLK_MERAM] = HWBLK(MSTPCR0, 0, CORE_AREA), | ||||
| 
 | ||||
| 	[HWBLK_IIC] = HWBLK(MSTPCR1, 9, CORE_AREA), | ||||
| 	[HWBLK_RTC] = HWBLK(MSTPCR1, 8, SUB_AREA), | ||||
| 
 | ||||
| 	[HWBLK_ATAPI] = HWBLK(MSTPCR2, 28, CORE_AREA_BM), | ||||
| 	[HWBLK_ADC] = HWBLK(MSTPCR2, 27, CORE_AREA), | ||||
| 	[HWBLK_TPU] = HWBLK(MSTPCR2, 25, CORE_AREA), | ||||
| 	[HWBLK_IRDA] = HWBLK(MSTPCR2, 24, CORE_AREA), | ||||
| 	[HWBLK_TSIF] = HWBLK(MSTPCR2, 22, CORE_AREA), | ||||
| 	[HWBLK_ICB] = HWBLK(MSTPCR2, 21, CORE_AREA_BM), | ||||
| 	[HWBLK_SDHI0] = HWBLK(MSTPCR2, 18, CORE_AREA), | ||||
| 	[HWBLK_SDHI1] = HWBLK(MSTPCR2, 17, CORE_AREA), | ||||
| 	[HWBLK_KEYSC] = HWBLK(MSTPCR2, 14, SUB_AREA), | ||||
| 	[HWBLK_USB] = HWBLK(MSTPCR2, 11, CORE_AREA), | ||||
| 	[HWBLK_2DG] = HWBLK(MSTPCR2, 10, CORE_AREA_BM), | ||||
| 	[HWBLK_SIU] = HWBLK(MSTPCR2, 8, CORE_AREA), | ||||
| 	[HWBLK_VEU2H1] = HWBLK(MSTPCR2, 6, CORE_AREA_BM), | ||||
| 	[HWBLK_VOU] = HWBLK(MSTPCR2, 5, CORE_AREA_BM), | ||||
| 	[HWBLK_BEU] = HWBLK(MSTPCR2, 4, CORE_AREA_BM), | ||||
| 	[HWBLK_CEU] = HWBLK(MSTPCR2, 3, CORE_AREA_BM), | ||||
| 	[HWBLK_VEU2H0] = HWBLK(MSTPCR2, 2, CORE_AREA_BM), | ||||
| 	[HWBLK_VPU] = HWBLK(MSTPCR2, 1, CORE_AREA_BM), | ||||
| 	[HWBLK_LCDC] = HWBLK(MSTPCR2, 0, CORE_AREA_BM), | ||||
| }; | ||||
| 
 | ||||
| static struct hwblk_info sh7723_hwblk_info = { | ||||
| 	.areas = sh7723_hwblk_area, | ||||
| 	.nr_areas = ARRAY_SIZE(sh7723_hwblk_area), | ||||
| 	.hwblks = sh7723_hwblk, | ||||
| 	.nr_hwblks = ARRAY_SIZE(sh7723_hwblk), | ||||
| }; | ||||
| 
 | ||||
| int arch_hwblk_sleep_mode(void) | ||||
| { | ||||
| 	if (!sh7723_hwblk_area[CORE_AREA].cnt[HWBLK_CNT_USAGE]) | ||||
| 		return SUSP_SH_STANDBY | SUSP_SH_SF; | ||||
| 
 | ||||
| 	if (!sh7723_hwblk_area[CORE_AREA_BM].cnt[HWBLK_CNT_USAGE]) | ||||
| 		return SUSP_SH_SLEEP | SUSP_SH_SF; | ||||
| 
 | ||||
| 	return SUSP_SH_SLEEP; | ||||
| } | ||||
| 
 | ||||
| int __init arch_hwblk_init(void) | ||||
| { | ||||
| 	return hwblk_register(&sh7723_hwblk_info); | ||||
| } | ||||
|  | @ -40,7 +40,7 @@ static struct platform_device iic_device = { | |||
| }; | ||||
| 
 | ||||
| static struct r8a66597_platdata r8a66597_data = { | ||||
| 	/* This set zero to all members */ | ||||
| 	.on_chip = 1, | ||||
| }; | ||||
| 
 | ||||
| static struct resource usb_host_resources[] = { | ||||
|  |  | |||
|  | @ -398,7 +398,7 @@ static struct platform_device rtc_device = { | |||
| }; | ||||
| 
 | ||||
| static struct r8a66597_platdata r8a66597_data = { | ||||
| 	/* This set zero to all members */ | ||||
| 	.on_chip = 1, | ||||
| }; | ||||
| 
 | ||||
| static struct resource sh7723_usb_host_resources[] = { | ||||
|  |  | |||
|  | @ -18,7 +18,6 @@ | |||
| #include <linux/mman.h> | ||||
| #include <linux/mm.h> | ||||
| #include <linux/smp.h> | ||||
| #include <linux/smp_lock.h> | ||||
| #include <linux/interrupt.h> | ||||
| 
 | ||||
| #include <asm/system.h> | ||||
|  |  | |||
|  | @ -16,7 +16,6 @@ | |||
| #include <linux/ptrace.h> | ||||
| #include <linux/user.h> | ||||
| #include <linux/smp.h> | ||||
| #include <linux/smp_lock.h> | ||||
| #include <linux/security.h> | ||||
| #include <linux/signal.h> | ||||
| #include <linux/regset.h> | ||||
|  |  | |||
|  | @ -17,7 +17,6 @@ | |||
| #include <linux/ptrace.h> | ||||
| #include <linux/user.h> | ||||
| #include <linux/smp.h> | ||||
| #include <linux/smp_lock.h> | ||||
| #include <linux/security.h> | ||||
| #include <linux/seccomp.h> | ||||
| #include <linux/audit.h> | ||||
|  |  | |||
|  | @ -11,7 +11,6 @@ | |||
| #include <linux/errno.h> | ||||
| #include <linux/module.h> | ||||
| #include <linux/sched.h> | ||||
| #include <linux/smp_lock.h> | ||||
| #include <linux/kernel.h> | ||||
| #include <linux/param.h> | ||||
| #include <linux/string.h> | ||||
|  |  | |||
|  | @ -13,7 +13,6 @@ | |||
| #include <linux/kernel.h> | ||||
| #include <linux/signal.h> | ||||
| #include <linux/smp.h> | ||||
| #include <linux/smp_lock.h> | ||||
| #include <linux/kdebug.h> | ||||
| 
 | ||||
| #include <asm/delay.h> | ||||
|  |  | |||
|  | @ -224,7 +224,12 @@ static struct vio_dev *vio_create_one(struct mdesc_handle *hp, u64 mp, | |||
| 	if (!strcmp(type, "domain-services-port")) | ||||
| 		bus_id_name = "ds"; | ||||
| 
 | ||||
| 	if (strlen(bus_id_name) >= BUS_ID_SIZE - 4) { | ||||
| 	/*
 | ||||
| 	 * 20 char is the old driver-core name size limit, which is no more. | ||||
| 	 * This check can probably be removed after review and possible | ||||
| 	 * adaption of the vio users name length handling. | ||||
| 	 */ | ||||
| 	if (strlen(bus_id_name) >= 20 - 4) { | ||||
| 		printk(KERN_ERR "VIO: bus_id_name [%s] is too long.\n", | ||||
| 		       bus_id_name); | ||||
| 		return NULL; | ||||
|  |  | |||
|  | @ -161,6 +161,7 @@ extern int io_apic_set_pci_routing(struct device *dev, int irq, | |||
| 		 struct io_apic_irq_attr *irq_attr); | ||||
| extern int (*ioapic_renumber_irq)(int ioapic, int irq); | ||||
| extern void ioapic_init_mappings(void); | ||||
| extern void ioapic_insert_resources(void); | ||||
| 
 | ||||
| extern struct IO_APIC_route_entry **alloc_ioapic_entries(void); | ||||
| extern void free_ioapic_entries(struct IO_APIC_route_entry **ioapic_entries); | ||||
|  | @ -180,6 +181,7 @@ extern void ioapic_write_entry(int apic, int pin, | |||
| #define io_apic_assign_pci_irqs 0 | ||||
| static const int timer_through_8259 = 0; | ||||
| static inline void ioapic_init_mappings(void)	{ } | ||||
| static inline void ioapic_insert_resources(void) { } | ||||
| 
 | ||||
| static inline void probe_nr_irqs_gsi(void)	{ } | ||||
| #endif | ||||
|  |  | |||
|  | @ -30,7 +30,7 @@ | |||
| #include <asm/hw_irq.h> | ||||
| #include <asm/kvm_para.h> | ||||
| 
 | ||||
| /*G:031 But first, how does our Guest contact the Host to ask for privileged
 | ||||
| /*G:030 But first, how does our Guest contact the Host to ask for privileged
 | ||||
|  * operations?  There are two ways: the direct way is to make a "hypercall", | ||||
|  * to make requests of the Host Itself. | ||||
|  * | ||||
|  |  | |||
|  | @ -652,7 +652,8 @@ static int es7000_mps_oem_check_cluster(struct mpc_table *mpc, char *oem, | |||
| 	return ret && es7000_apic_is_cluster(); | ||||
| } | ||||
| 
 | ||||
| struct apic apic_es7000_cluster = { | ||||
| /* We've been warned by a false positive warning.Use __refdata to keep calm. */ | ||||
| struct apic __refdata apic_es7000_cluster = { | ||||
| 
 | ||||
| 	.name				= "es7000", | ||||
| 	.probe				= probe_es7000, | ||||
|  |  | |||
|  | @ -4181,28 +4181,20 @@ fake_ioapic_page: | |||
| 	} | ||||
| } | ||||
| 
 | ||||
| static int __init ioapic_insert_resources(void) | ||||
| void __init ioapic_insert_resources(void) | ||||
| { | ||||
| 	int i; | ||||
| 	struct resource *r = ioapic_resources; | ||||
| 
 | ||||
| 	if (!r) { | ||||
| 		if (nr_ioapics > 0) { | ||||
| 		if (nr_ioapics > 0) | ||||
| 			printk(KERN_ERR | ||||
| 				"IO APIC resources couldn't be allocated.\n"); | ||||
| 			return -1; | ||||
| 		} | ||||
| 		return 0; | ||||
| 		return; | ||||
| 	} | ||||
| 
 | ||||
| 	for (i = 0; i < nr_ioapics; i++) { | ||||
| 		insert_resource(&iomem_resource, r); | ||||
| 		r++; | ||||
| 	} | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| /* Insert the IO APIC resources after PCI initialization has occured to handle
 | ||||
|  * IO APICS that are mapped in on a BAR in PCI space. */ | ||||
| late_initcall(ioapic_insert_resources); | ||||
|  |  | |||
|  | @ -493,7 +493,8 @@ static void numaq_setup_portio_remap(void) | |||
| 		(u_long) xquad_portio, (u_long) num_quads*XQUAD_PORTIO_QUAD); | ||||
| } | ||||
| 
 | ||||
| struct apic apic_numaq = { | ||||
| /* Use __refdata to keep false positive warning calm.	*/ | ||||
| struct apic __refdata apic_numaq = { | ||||
| 
 | ||||
| 	.name				= "NUMAQ", | ||||
| 	.probe				= probe_numaq, | ||||
|  |  | |||
|  | @ -60,7 +60,7 @@ static inline u64 scale_delta(u64 delta, u32 mul_frac, int shift) | |||
| 		"adc  %5,%%edx ; " | ||||
| 		: "=A" (product), "=r" (tmp1), "=r" (tmp2) | ||||
| 		: "a" ((u32)delta), "1" ((u32)(delta >> 32)), "2" (mul_frac) ); | ||||
| #elif __x86_64__ | ||||
| #elif defined(__x86_64__) | ||||
| 	__asm__ ( | ||||
| 		"mul %%rdx ; shrd $32,%%rdx,%%rax" | ||||
| 		: "=a" (product) : "0" (delta), "d" ((u64)mul_frac) ); | ||||
|  |  | |||
|  | @ -379,6 +379,11 @@ static void lguest_cpuid(unsigned int *ax, unsigned int *bx, | |||
| 
 | ||||
| 	native_cpuid(ax, bx, cx, dx); | ||||
| 	switch (function) { | ||||
| 	case 0: /* ID and highest CPUID.  Futureproof a little by sticking to
 | ||||
| 		 * older ones. */ | ||||
| 		if (*ax > 5) | ||||
| 			*ax = 5; | ||||
| 		break; | ||||
| 	case 1:	/* Basic feature request. */ | ||||
| 		/* We only allow kernel to see SSE3, CMPXCHG16B and SSSE3 */ | ||||
| 		*cx &= 0x00002201; | ||||
|  | @ -1079,7 +1084,7 @@ static unsigned lguest_patch(u8 type, u16 clobber, void *ibuf, | |||
| 	return insn_len; | ||||
| } | ||||
| 
 | ||||
| /*G:030 Once we get to lguest_init(), we know we're a Guest.  The various
 | ||||
| /*G:029 Once we get to lguest_init(), we know we're a Guest.  The various
 | ||||
|  * pv_ops structures in the kernel provide points for (almost) every routine we | ||||
|  * have to override to avoid privileged instructions. */ | ||||
| __init void lguest_init(void) | ||||
|  |  | |||
|  | @ -697,7 +697,7 @@ show_signal_msg(struct pt_regs *regs, unsigned long error_code, | |||
| 	if (!printk_ratelimit()) | ||||
| 		return; | ||||
| 
 | ||||
| 	printk(KERN_CONT "%s%s[%d]: segfault at %lx ip %p sp %p error %lx", | ||||
| 	printk("%s%s[%d]: segfault at %lx ip %p sp %p error %lx", | ||||
| 		task_pid_nr(tsk) > 1 ? KERN_INFO : KERN_EMERG, | ||||
| 		tsk->comm, task_pid_nr(tsk), address, | ||||
| 		(void *)regs->ip, (void *)regs->sp, error_code); | ||||
|  |  | |||
|  | @ -35,6 +35,7 @@ | |||
| #include <asm/pat.h> | ||||
| #include <asm/e820.h> | ||||
| #include <asm/pci_x86.h> | ||||
| #include <asm/io_apic.h> | ||||
| 
 | ||||
| 
 | ||||
| static int | ||||
|  | @ -227,6 +228,12 @@ void __init pcibios_resource_survey(void) | |||
| 	pcibios_allocate_resources(1); | ||||
| 
 | ||||
| 	e820_reserve_resources_late(); | ||||
| 	/*
 | ||||
| 	 * Insert the IO APIC resources after PCI initialization has | ||||
| 	 * occured to handle IO APICS that are mapped in on a BAR in | ||||
| 	 * PCI space, but before trying to assign unassigned pci res. | ||||
| 	 */ | ||||
| 	ioapic_insert_resources(); | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
|  |  | |||
|  | @ -513,6 +513,7 @@ static const struct pci_device_id ahci_pci_tbl[] = { | |||
| 	{ PCI_VDEVICE(INTEL, 0x502a), board_ahci }, /* Tolapai */ | ||||
| 	{ PCI_VDEVICE(INTEL, 0x502b), board_ahci }, /* Tolapai */ | ||||
| 	{ PCI_VDEVICE(INTEL, 0x3a05), board_ahci }, /* ICH10 */ | ||||
| 	{ PCI_VDEVICE(INTEL, 0x3a22), board_ahci }, /* ICH10 */ | ||||
| 	{ PCI_VDEVICE(INTEL, 0x3a25), board_ahci }, /* ICH10 */ | ||||
| 	{ PCI_VDEVICE(INTEL, 0x3b24), board_ahci }, /* PCH RAID */ | ||||
| 	{ PCI_VDEVICE(INTEL, 0x3b25), board_ahci }, /* PCH RAID */ | ||||
|  |  | |||
|  | @ -3392,17 +3392,27 @@ int ata_down_xfermask_limit(struct ata_device *dev, unsigned int sel) | |||
| 
 | ||||
| static int ata_dev_set_mode(struct ata_device *dev) | ||||
| { | ||||
| 	struct ata_port *ap = dev->link->ap; | ||||
| 	struct ata_eh_context *ehc = &dev->link->eh_context; | ||||
| 	const bool nosetxfer = dev->horkage & ATA_HORKAGE_NOSETXFER; | ||||
| 	const char *dev_err_whine = ""; | ||||
| 	int ign_dev_err = 0; | ||||
| 	unsigned int err_mask; | ||||
| 	unsigned int err_mask = 0; | ||||
| 	int rc; | ||||
| 
 | ||||
| 	dev->flags &= ~ATA_DFLAG_PIO; | ||||
| 	if (dev->xfer_shift == ATA_SHIFT_PIO) | ||||
| 		dev->flags |= ATA_DFLAG_PIO; | ||||
| 
 | ||||
| 	err_mask = ata_dev_set_xfermode(dev); | ||||
| 	if (nosetxfer && ap->flags & ATA_FLAG_SATA && ata_id_is_sata(dev->id)) | ||||
| 		dev_err_whine = " (SET_XFERMODE skipped)"; | ||||
| 	else { | ||||
| 		if (nosetxfer) | ||||
| 			ata_dev_printk(dev, KERN_WARNING, | ||||
| 				       "NOSETXFER but PATA detected - can't " | ||||
| 				       "skip SETXFER, might malfunction\n"); | ||||
| 		err_mask = ata_dev_set_xfermode(dev); | ||||
| 	} | ||||
| 
 | ||||
| 	if (err_mask & ~AC_ERR_DEV) | ||||
| 		goto fail; | ||||
|  | @ -4297,6 +4307,12 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = { | |||
| 	/* Devices which aren't very happy with higher link speeds */ | ||||
| 	{ "WD My Book",			NULL,	ATA_HORKAGE_1_5_GBPS, }, | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * Devices which choke on SETXFER.  Applies only if both the | ||||
| 	 * device and controller are SATA. | ||||
| 	 */ | ||||
| 	{ "PIONEER DVD-RW  DVRTD08",	"1.00",	ATA_HORKAGE_NOSETXFER }, | ||||
| 
 | ||||
| 	/* End Marker */ | ||||
| 	{ } | ||||
| }; | ||||
|  |  | |||
|  | @ -2517,6 +2517,10 @@ int ata_eh_reset(struct ata_link *link, int classify, | |||
| 
 | ||||
| 			ata_eh_about_to_do(link, NULL, ATA_EH_RESET); | ||||
| 			rc = ata_do_reset(link, reset, classes, deadline, true); | ||||
| 			if (rc) { | ||||
| 				failed_link = link; | ||||
| 				goto fail; | ||||
| 			} | ||||
| 		} | ||||
| 	} else { | ||||
| 		if (verbose) | ||||
|  |  | |||
|  | @ -312,11 +312,12 @@ err_ide_ioremap: | |||
| static int __devexit pata_at91_remove(struct platform_device *pdev) | ||||
| { | ||||
| 	struct ata_host *host = dev_get_drvdata(&pdev->dev); | ||||
| 	struct at91_ide_info *info = host->private_data; | ||||
| 	struct at91_ide_info *info; | ||||
| 	struct device *dev = &pdev->dev; | ||||
| 
 | ||||
| 	if (!host) | ||||
| 		return 0; | ||||
| 	info = host->private_data; | ||||
| 
 | ||||
| 	ata_host_detach(host); | ||||
| 
 | ||||
|  |  | |||
|  | @ -428,6 +428,9 @@ int devres_release_all(struct device *dev) | |||
| { | ||||
| 	unsigned long flags; | ||||
| 
 | ||||
| 	/* Looks like an uninitialized device structure */ | ||||
| 	if (WARN_ON(dev->devres_head.next == NULL)) | ||||
| 		return -ENODEV; | ||||
| 	spin_lock_irqsave(&dev->devres_lock, flags); | ||||
| 	return release_nodes(dev, dev->devres_head.next, &dev->devres_head, | ||||
| 			     flags); | ||||
|  |  | |||
|  | @ -217,8 +217,10 @@ firmware_data_read(struct kobject *kobj, struct bin_attribute *bin_attr, | |||
| 		ret_count = -ENODEV; | ||||
| 		goto out; | ||||
| 	} | ||||
| 	if (offset > fw->size) | ||||
| 		return 0; | ||||
| 	if (offset > fw->size) { | ||||
| 		ret_count = 0; | ||||
| 		goto out; | ||||
| 	} | ||||
| 	if (count > fw->size - offset) | ||||
| 		count = fw->size - offset; | ||||
| 
 | ||||
|  |  | |||
|  | @ -36,6 +36,7 @@ | |||
| #include <linux/ioport.h> | ||||
| #include <linux/mm.h> | ||||
| #include <linux/slab.h> | ||||
| #include <linux/smp_lock.h> | ||||
| #include <linux/proc_fs.h> | ||||
| #include <linux/reboot.h> | ||||
| #include <linux/spinlock.h> | ||||
|  |  | |||
|  | @ -298,6 +298,22 @@ config BLK_DEV_NBD | |||
| 
 | ||||
| 	  If unsure, say N. | ||||
| 
 | ||||
| config BLK_DEV_OSD | ||||
| 	tristate "OSD object-as-blkdev support" | ||||
| 	depends on SCSI_OSD_ULD | ||||
| 	---help--- | ||||
| 	  Saying Y or M here will allow the exporting of a single SCSI | ||||
| 	  OSD (object-based storage) object as a Linux block device. | ||||
| 
 | ||||
| 	  For example, if you create a 2G object on an OSD device, | ||||
| 	  you can then use this module to present that 2G object as | ||||
| 	  a Linux block device. | ||||
| 
 | ||||
| 	  To compile this driver as a module, choose M here: the | ||||
| 	  module will be called osdblk. | ||||
| 
 | ||||
| 	  If unsure, say N. | ||||
| 
 | ||||
| config BLK_DEV_SX8 | ||||
| 	tristate "Promise SATA SX8 support" | ||||
| 	depends on PCI | ||||
|  |  | |||
|  | @ -23,6 +23,7 @@ obj-$(CONFIG_XILINX_SYSACE)	+= xsysace.o | |||
| obj-$(CONFIG_CDROM_PKTCDVD)	+= pktcdvd.o | ||||
| obj-$(CONFIG_MG_DISK)		+= mg_disk.o | ||||
| obj-$(CONFIG_SUNVDC)		+= sunvdc.o | ||||
| obj-$(CONFIG_BLK_DEV_OSD)	+= osdblk.o | ||||
| 
 | ||||
| obj-$(CONFIG_BLK_DEV_UMEM)	+= umem.o | ||||
| obj-$(CONFIG_BLK_DEV_NBD)	+= nbd.o | ||||
|  |  | |||
|  | @ -26,6 +26,7 @@ | |||
| #include <linux/pci.h> | ||||
| #include <linux/kernel.h> | ||||
| #include <linux/slab.h> | ||||
| #include <linux/smp_lock.h> | ||||
| #include <linux/delay.h> | ||||
| #include <linux/major.h> | ||||
| #include <linux/fs.h> | ||||
|  |  | |||
|  | @ -61,7 +61,6 @@ | |||
| #include <linux/blkdev.h> | ||||
| #include <linux/blkpg.h> | ||||
| #include <linux/init.h> | ||||
| #include <linux/smp_lock.h> | ||||
| #include <linux/swap.h> | ||||
| #include <linux/slab.h> | ||||
| #include <linux/loop.h> | ||||
|  |  | |||
							
								
								
									
										701
									
								
								drivers/block/osdblk.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										701
									
								
								drivers/block/osdblk.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,701 @@ | |||
| 
 | ||||
| /*
 | ||||
|    osdblk.c -- Export a single SCSI OSD object as a Linux block device | ||||
| 
 | ||||
| 
 | ||||
|    Copyright 2009 Red Hat, 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. | ||||
| 
 | ||||
|    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; see the file COPYING.  If not, write to | ||||
|    the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. | ||||
| 
 | ||||
| 
 | ||||
|    Instructions for use | ||||
|    -------------------- | ||||
| 
 | ||||
|    1) Map a Linux block device to an existing OSD object. | ||||
| 
 | ||||
|       In this example, we will use partition id 1234, object id 5678, | ||||
|       OSD device /dev/osd1. | ||||
| 
 | ||||
|       $ echo "1234 5678 /dev/osd1" > /sys/class/osdblk/add | ||||
| 
 | ||||
| 
 | ||||
|    2) List all active blkdev<->object mappings. | ||||
| 
 | ||||
|       In this example, we have performed step #1 twice, creating two blkdevs, | ||||
|       mapped to two separate OSD objects. | ||||
| 
 | ||||
|       $ cat /sys/class/osdblk/list | ||||
|       0 174 1234 5678 /dev/osd1 | ||||
|       1 179 1994 897123 /dev/osd0 | ||||
| 
 | ||||
|       The columns, in order, are: | ||||
|       - blkdev unique id | ||||
|       - blkdev assigned major | ||||
|       - OSD object partition id | ||||
|       - OSD object id | ||||
|       - OSD device | ||||
| 
 | ||||
| 
 | ||||
|    3) Remove an active blkdev<->object mapping. | ||||
| 
 | ||||
|       In this example, we remove the mapping with blkdev unique id 1. | ||||
| 
 | ||||
|       $ echo 1 > /sys/class/osdblk/remove | ||||
| 
 | ||||
| 
 | ||||
|    NOTE:  The actual creation and deletion of OSD objects is outside the scope | ||||
|    of this driver. | ||||
| 
 | ||||
|  */ | ||||
| 
 | ||||
| #include <linux/kernel.h> | ||||
| #include <linux/device.h> | ||||
| #include <linux/module.h> | ||||
| #include <linux/fs.h> | ||||
| #include <scsi/osd_initiator.h> | ||||
| #include <scsi/osd_attributes.h> | ||||
| #include <scsi/osd_sec.h> | ||||
| #include <scsi/scsi_device.h> | ||||
| 
 | ||||
| #define DRV_NAME "osdblk" | ||||
| #define PFX DRV_NAME ": " | ||||
| 
 | ||||
| /* #define _OSDBLK_DEBUG */ | ||||
| #ifdef _OSDBLK_DEBUG | ||||
| #define OSDBLK_DEBUG(fmt, a...) \ | ||||
| 	printk(KERN_NOTICE "osdblk @%s:%d: " fmt, __func__, __LINE__, ##a) | ||||
| #else | ||||
| #define OSDBLK_DEBUG(fmt, a...) \ | ||||
| 	do { if (0) printk(fmt, ##a); } while (0) | ||||
| #endif | ||||
| 
 | ||||
| MODULE_AUTHOR("Jeff Garzik <jeff@garzik.org>"); | ||||
| MODULE_DESCRIPTION("block device inside an OSD object osdblk.ko"); | ||||
| MODULE_LICENSE("GPL"); | ||||
| 
 | ||||
| struct osdblk_device; | ||||
| 
 | ||||
| enum { | ||||
| 	OSDBLK_MINORS_PER_MAJOR	= 256,		/* max minors per blkdev */ | ||||
| 	OSDBLK_MAX_REQ		= 32,		/* max parallel requests */ | ||||
| 	OSDBLK_OP_TIMEOUT	= 4 * 60,	/* sync OSD req timeout */ | ||||
| }; | ||||
| 
 | ||||
| struct osdblk_request { | ||||
| 	struct request		*rq;		/* blk layer request */ | ||||
| 	struct bio		*bio;		/* cloned bio */ | ||||
| 	struct osdblk_device	*osdev;		/* associated blkdev */ | ||||
| }; | ||||
| 
 | ||||
| struct osdblk_device { | ||||
| 	int			id;		/* blkdev unique id */ | ||||
| 
 | ||||
| 	int			major;		/* blkdev assigned major */ | ||||
| 	struct gendisk		*disk;		/* blkdev's gendisk and rq */ | ||||
| 	struct request_queue	*q; | ||||
| 
 | ||||
| 	struct osd_dev		*osd;		/* associated OSD */ | ||||
| 
 | ||||
| 	char			name[32];	/* blkdev name, e.g. osdblk34 */ | ||||
| 
 | ||||
| 	spinlock_t		lock;		/* queue lock */ | ||||
| 
 | ||||
| 	struct osd_obj_id	obj;		/* OSD partition, obj id */ | ||||
| 	uint8_t			obj_cred[OSD_CAP_LEN]; /* OSD cred */ | ||||
| 
 | ||||
| 	struct osdblk_request	req[OSDBLK_MAX_REQ]; /* request table */ | ||||
| 
 | ||||
| 	struct list_head	node; | ||||
| 
 | ||||
| 	char			osd_path[0];	/* OSD device path */ | ||||
| }; | ||||
| 
 | ||||
| static struct class *class_osdblk;		/* /sys/class/osdblk */ | ||||
| static DEFINE_MUTEX(ctl_mutex);	/* Serialize open/close/setup/teardown */ | ||||
| static LIST_HEAD(osdblkdev_list); | ||||
| 
 | ||||
| static struct block_device_operations osdblk_bd_ops = { | ||||
| 	.owner		= THIS_MODULE, | ||||
| }; | ||||
| 
 | ||||
| static const struct osd_attr g_attr_logical_length = ATTR_DEF( | ||||
| 	OSD_APAGE_OBJECT_INFORMATION, OSD_ATTR_OI_LOGICAL_LENGTH, 8); | ||||
| 
 | ||||
| static void osdblk_make_credential(u8 cred_a[OSD_CAP_LEN], | ||||
| 				   const struct osd_obj_id *obj) | ||||
| { | ||||
| 	osd_sec_init_nosec_doall_caps(cred_a, obj, false, true); | ||||
| } | ||||
| 
 | ||||
| /* copied from exofs; move to libosd? */ | ||||
| /*
 | ||||
|  * Perform a synchronous OSD operation.  copied from exofs; move to libosd? | ||||
|  */ | ||||
| static int osd_sync_op(struct osd_request *or, int timeout, uint8_t *credential) | ||||
| { | ||||
| 	int ret; | ||||
| 
 | ||||
| 	or->timeout = timeout; | ||||
| 	ret = osd_finalize_request(or, 0, credential, NULL); | ||||
| 	if (ret) | ||||
| 		return ret; | ||||
| 
 | ||||
| 	ret = osd_execute_request(or); | ||||
| 
 | ||||
| 	/* osd_req_decode_sense(or, ret); */ | ||||
| 	return ret; | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * Perform an asynchronous OSD operation.  copied from exofs; move to libosd? | ||||
|  */ | ||||
| static int osd_async_op(struct osd_request *or, osd_req_done_fn *async_done, | ||||
| 		   void *caller_context, u8 *cred) | ||||
| { | ||||
| 	int ret; | ||||
| 
 | ||||
| 	ret = osd_finalize_request(or, 0, cred, NULL); | ||||
| 	if (ret) | ||||
| 		return ret; | ||||
| 
 | ||||
| 	ret = osd_execute_request_async(or, async_done, caller_context); | ||||
| 
 | ||||
| 	return ret; | ||||
| } | ||||
| 
 | ||||
| /* copied from exofs; move to libosd? */ | ||||
| static int extract_attr_from_req(struct osd_request *or, struct osd_attr *attr) | ||||
| { | ||||
| 	struct osd_attr cur_attr = {.attr_page = 0}; /* start with zeros */ | ||||
| 	void *iter = NULL; | ||||
| 	int nelem; | ||||
| 
 | ||||
| 	do { | ||||
| 		nelem = 1; | ||||
| 		osd_req_decode_get_attr_list(or, &cur_attr, &nelem, &iter); | ||||
| 		if ((cur_attr.attr_page == attr->attr_page) && | ||||
| 		    (cur_attr.attr_id == attr->attr_id)) { | ||||
| 			attr->len = cur_attr.len; | ||||
| 			attr->val_ptr = cur_attr.val_ptr; | ||||
| 			return 0; | ||||
| 		} | ||||
| 	} while (iter); | ||||
| 
 | ||||
| 	return -EIO; | ||||
| } | ||||
| 
 | ||||
| static int osdblk_get_obj_size(struct osdblk_device *osdev, u64 *size_out) | ||||
| { | ||||
| 	struct osd_request *or; | ||||
| 	struct osd_attr attr; | ||||
| 	int ret; | ||||
| 
 | ||||
| 	/* start request */ | ||||
| 	or = osd_start_request(osdev->osd, GFP_KERNEL); | ||||
| 	if (!or) | ||||
| 		return -ENOMEM; | ||||
| 
 | ||||
| 	/* create a get-attributes(length) request */ | ||||
| 	osd_req_get_attributes(or, &osdev->obj); | ||||
| 
 | ||||
| 	osd_req_add_get_attr_list(or, &g_attr_logical_length, 1); | ||||
| 
 | ||||
| 	/* execute op synchronously */ | ||||
| 	ret = osd_sync_op(or, OSDBLK_OP_TIMEOUT, osdev->obj_cred); | ||||
| 	if (ret) | ||||
| 		goto out; | ||||
| 
 | ||||
| 	/* extract length from returned attribute info */ | ||||
| 	attr = g_attr_logical_length; | ||||
| 	ret = extract_attr_from_req(or, &attr); | ||||
| 	if (ret) | ||||
| 		goto out; | ||||
| 
 | ||||
| 	*size_out = get_unaligned_be64(attr.val_ptr); | ||||
| 
 | ||||
| out: | ||||
| 	osd_end_request(or); | ||||
| 	return ret; | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| static void osdblk_osd_complete(struct osd_request *or, void *private) | ||||
| { | ||||
| 	struct osdblk_request *orq = private; | ||||
| 	struct osd_sense_info osi; | ||||
| 	int ret = osd_req_decode_sense(or, &osi); | ||||
| 
 | ||||
| 	if (ret) { | ||||
| 		ret = -EIO; | ||||
| 		OSDBLK_DEBUG("osdblk_osd_complete with err=%d\n", ret); | ||||
| 	} | ||||
| 
 | ||||
| 	/* complete OSD request */ | ||||
| 	osd_end_request(or); | ||||
| 
 | ||||
| 	/* complete request passed to osdblk by block layer */ | ||||
| 	__blk_end_request_all(orq->rq, ret); | ||||
| } | ||||
| 
 | ||||
| static void bio_chain_put(struct bio *chain) | ||||
| { | ||||
| 	struct bio *tmp; | ||||
| 
 | ||||
| 	while (chain) { | ||||
| 		tmp = chain; | ||||
| 		chain = chain->bi_next; | ||||
| 
 | ||||
| 		bio_put(tmp); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| static struct bio *bio_chain_clone(struct bio *old_chain, gfp_t gfpmask) | ||||
| { | ||||
| 	struct bio *tmp, *new_chain = NULL, *tail = NULL; | ||||
| 
 | ||||
| 	while (old_chain) { | ||||
| 		tmp = bio_kmalloc(gfpmask, old_chain->bi_max_vecs); | ||||
| 		if (!tmp) | ||||
| 			goto err_out; | ||||
| 
 | ||||
| 		__bio_clone(tmp, old_chain); | ||||
| 		tmp->bi_bdev = NULL; | ||||
| 		gfpmask &= ~__GFP_WAIT; | ||||
| 		tmp->bi_next = NULL; | ||||
| 
 | ||||
| 		if (!new_chain) | ||||
| 			new_chain = tail = tmp; | ||||
| 		else { | ||||
| 			tail->bi_next = tmp; | ||||
| 			tail = tmp; | ||||
| 		} | ||||
| 
 | ||||
| 		old_chain = old_chain->bi_next; | ||||
| 	} | ||||
| 
 | ||||
| 	return new_chain; | ||||
| 
 | ||||
| err_out: | ||||
| 	OSDBLK_DEBUG("bio_chain_clone with err\n"); | ||||
| 	bio_chain_put(new_chain); | ||||
| 	return NULL; | ||||
| } | ||||
| 
 | ||||
| static void osdblk_rq_fn(struct request_queue *q) | ||||
| { | ||||
| 	struct osdblk_device *osdev = q->queuedata; | ||||
| 
 | ||||
| 	while (1) { | ||||
| 		struct request *rq; | ||||
| 		struct osdblk_request *orq; | ||||
| 		struct osd_request *or; | ||||
| 		struct bio *bio; | ||||
| 		bool do_write, do_flush; | ||||
| 
 | ||||
| 		/* peek at request from block layer */ | ||||
| 		rq = blk_fetch_request(q); | ||||
| 		if (!rq) | ||||
| 			break; | ||||
| 
 | ||||
| 		/* filter out block requests we don't understand */ | ||||
| 		if (!blk_fs_request(rq) && !blk_barrier_rq(rq)) { | ||||
| 			blk_end_request_all(rq, 0); | ||||
| 			continue; | ||||
| 		} | ||||
| 
 | ||||
| 		/* deduce our operation (read, write, flush) */ | ||||
| 		/* I wish the block layer simplified cmd_type/cmd_flags/cmd[]
 | ||||
| 		 * into a clearly defined set of RPC commands: | ||||
| 		 * read, write, flush, scsi command, power mgmt req, | ||||
| 		 * driver-specific, etc. | ||||
| 		 */ | ||||
| 
 | ||||
| 		do_flush = (rq->special == (void *) 0xdeadbeefUL); | ||||
| 		do_write = (rq_data_dir(rq) == WRITE); | ||||
| 
 | ||||
| 		if (!do_flush) { /* osd_flush does not use a bio */ | ||||
| 			/* a bio clone to be passed down to OSD request */ | ||||
| 			bio = bio_chain_clone(rq->bio, GFP_ATOMIC); | ||||
| 			if (!bio) | ||||
| 				break; | ||||
| 		} else | ||||
| 			bio = NULL; | ||||
| 
 | ||||
| 		/* alloc internal OSD request, for OSD command execution */ | ||||
| 		or = osd_start_request(osdev->osd, GFP_ATOMIC); | ||||
| 		if (!or) { | ||||
| 			bio_chain_put(bio); | ||||
| 			OSDBLK_DEBUG("osd_start_request with err\n"); | ||||
| 			break; | ||||
| 		} | ||||
| 
 | ||||
| 		orq = &osdev->req[rq->tag]; | ||||
| 		orq->rq = rq; | ||||
| 		orq->bio = bio; | ||||
| 		orq->osdev = osdev; | ||||
| 
 | ||||
| 		/* init OSD command: flush, write or read */ | ||||
| 		if (do_flush) | ||||
| 			osd_req_flush_object(or, &osdev->obj, | ||||
| 					     OSD_CDB_FLUSH_ALL, 0, 0); | ||||
| 		else if (do_write) | ||||
| 			osd_req_write(or, &osdev->obj, blk_rq_pos(rq) * 512ULL, | ||||
| 				      bio, blk_rq_bytes(rq)); | ||||
| 		else | ||||
| 			osd_req_read(or, &osdev->obj, blk_rq_pos(rq) * 512ULL, | ||||
| 				     bio, blk_rq_bytes(rq)); | ||||
| 
 | ||||
| 		OSDBLK_DEBUG("%s 0x%x bytes at 0x%llx\n", | ||||
| 			do_flush ? "flush" : do_write ? | ||||
| 				"write" : "read", blk_rq_bytes(rq), | ||||
| 			blk_rq_pos(rq) * 512ULL); | ||||
| 
 | ||||
| 		/* begin OSD command execution */ | ||||
| 		if (osd_async_op(or, osdblk_osd_complete, orq, | ||||
| 				 osdev->obj_cred)) { | ||||
| 			osd_end_request(or); | ||||
| 			blk_requeue_request(q, rq); | ||||
| 			bio_chain_put(bio); | ||||
| 			OSDBLK_DEBUG("osd_execute_request_async with err\n"); | ||||
| 			break; | ||||
| 		} | ||||
| 
 | ||||
| 		/* remove the special 'flush' marker, now that the command
 | ||||
| 		 * is executing | ||||
| 		 */ | ||||
| 		rq->special = NULL; | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| static void osdblk_prepare_flush(struct request_queue *q, struct request *rq) | ||||
| { | ||||
| 	/* add driver-specific marker, to indicate that this request
 | ||||
| 	 * is a flush command | ||||
| 	 */ | ||||
| 	rq->special = (void *) 0xdeadbeefUL; | ||||
| } | ||||
| 
 | ||||
| static void osdblk_free_disk(struct osdblk_device *osdev) | ||||
| { | ||||
| 	struct gendisk *disk = osdev->disk; | ||||
| 
 | ||||
| 	if (!disk) | ||||
| 		return; | ||||
| 
 | ||||
| 	if (disk->flags & GENHD_FL_UP) | ||||
| 		del_gendisk(disk); | ||||
| 	if (disk->queue) | ||||
| 		blk_cleanup_queue(disk->queue); | ||||
| 	put_disk(disk); | ||||
| } | ||||
| 
 | ||||
| static int osdblk_init_disk(struct osdblk_device *osdev) | ||||
| { | ||||
| 	struct gendisk *disk; | ||||
| 	struct request_queue *q; | ||||
| 	int rc; | ||||
| 	u64 obj_size = 0; | ||||
| 
 | ||||
| 	/* contact OSD, request size info about the object being mapped */ | ||||
| 	rc = osdblk_get_obj_size(osdev, &obj_size); | ||||
| 	if (rc) | ||||
| 		return rc; | ||||
| 
 | ||||
| 	/* create gendisk info */ | ||||
| 	disk = alloc_disk(OSDBLK_MINORS_PER_MAJOR); | ||||
| 	if (!disk) | ||||
| 		return -ENOMEM; | ||||
| 
 | ||||
| 	sprintf(disk->disk_name, DRV_NAME "%d", osdev->id); | ||||
| 	disk->major = osdev->major; | ||||
| 	disk->first_minor = 0; | ||||
| 	disk->fops = &osdblk_bd_ops; | ||||
| 	disk->private_data = osdev; | ||||
| 
 | ||||
| 	/* init rq */ | ||||
| 	q = blk_init_queue(osdblk_rq_fn, &osdev->lock); | ||||
| 	if (!q) { | ||||
| 		put_disk(disk); | ||||
| 		return -ENOMEM; | ||||
| 	} | ||||
| 
 | ||||
| 	/* switch queue to TCQ mode; allocate tag map */ | ||||
| 	rc = blk_queue_init_tags(q, OSDBLK_MAX_REQ, NULL); | ||||
| 	if (rc) { | ||||
| 		blk_cleanup_queue(q); | ||||
| 		put_disk(disk); | ||||
| 		return rc; | ||||
| 	} | ||||
| 
 | ||||
| 	/* Set our limits to the lower device limits, because osdblk cannot
 | ||||
| 	 * sleep when allocating a lower-request and therefore cannot be | ||||
| 	 * bouncing. | ||||
| 	 */ | ||||
| 	blk_queue_stack_limits(q, osd_request_queue(osdev->osd)); | ||||
| 
 | ||||
| 	blk_queue_prep_rq(q, blk_queue_start_tag); | ||||
| 	blk_queue_ordered(q, QUEUE_ORDERED_DRAIN_FLUSH, osdblk_prepare_flush); | ||||
| 
 | ||||
| 	disk->queue = q; | ||||
| 
 | ||||
| 	q->queuedata = osdev; | ||||
| 
 | ||||
| 	osdev->disk = disk; | ||||
| 	osdev->q = q; | ||||
| 
 | ||||
| 	/* finally, announce the disk to the world */ | ||||
| 	set_capacity(disk, obj_size / 512ULL); | ||||
| 	add_disk(disk); | ||||
| 
 | ||||
| 	printk(KERN_INFO "%s: Added of size 0x%llx\n", | ||||
| 		disk->disk_name, (unsigned long long)obj_size); | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| /********************************************************************
 | ||||
|  * /sys/class/osdblk/ | ||||
|  *                   add	map OSD object to blkdev | ||||
|  *                   remove	unmap OSD object | ||||
|  *                   list	show mappings | ||||
|  *******************************************************************/ | ||||
| 
 | ||||
| static void class_osdblk_release(struct class *cls) | ||||
| { | ||||
| 	kfree(cls); | ||||
| } | ||||
| 
 | ||||
| static ssize_t class_osdblk_list(struct class *c, char *data) | ||||
| { | ||||
| 	int n = 0; | ||||
| 	struct list_head *tmp; | ||||
| 
 | ||||
| 	mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING); | ||||
| 
 | ||||
| 	list_for_each(tmp, &osdblkdev_list) { | ||||
| 		struct osdblk_device *osdev; | ||||
| 
 | ||||
| 		osdev = list_entry(tmp, struct osdblk_device, node); | ||||
| 
 | ||||
| 		n += sprintf(data+n, "%d %d %llu %llu %s\n", | ||||
| 			osdev->id, | ||||
| 			osdev->major, | ||||
| 			osdev->obj.partition, | ||||
| 			osdev->obj.id, | ||||
| 			osdev->osd_path); | ||||
| 	} | ||||
| 
 | ||||
| 	mutex_unlock(&ctl_mutex); | ||||
| 	return n; | ||||
| } | ||||
| 
 | ||||
| static ssize_t class_osdblk_add(struct class *c, const char *buf, size_t count) | ||||
| { | ||||
| 	struct osdblk_device *osdev; | ||||
| 	ssize_t rc; | ||||
| 	int irc, new_id = 0; | ||||
| 	struct list_head *tmp; | ||||
| 
 | ||||
| 	if (!try_module_get(THIS_MODULE)) | ||||
| 		return -ENODEV; | ||||
| 
 | ||||
| 	/* new osdblk_device object */ | ||||
| 	osdev = kzalloc(sizeof(*osdev) + strlen(buf) + 1, GFP_KERNEL); | ||||
| 	if (!osdev) { | ||||
| 		rc = -ENOMEM; | ||||
| 		goto err_out_mod; | ||||
| 	} | ||||
| 
 | ||||
| 	/* static osdblk_device initialization */ | ||||
| 	spin_lock_init(&osdev->lock); | ||||
| 	INIT_LIST_HEAD(&osdev->node); | ||||
| 
 | ||||
| 	/* generate unique id: find highest unique id, add one */ | ||||
| 
 | ||||
| 	mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING); | ||||
| 
 | ||||
| 	list_for_each(tmp, &osdblkdev_list) { | ||||
| 		struct osdblk_device *osdev; | ||||
| 
 | ||||
| 		osdev = list_entry(tmp, struct osdblk_device, node); | ||||
| 		if (osdev->id > new_id) | ||||
| 			new_id = osdev->id + 1; | ||||
| 	} | ||||
| 
 | ||||
| 	osdev->id = new_id; | ||||
| 
 | ||||
| 	/* add to global list */ | ||||
| 	list_add_tail(&osdev->node, &osdblkdev_list); | ||||
| 
 | ||||
| 	mutex_unlock(&ctl_mutex); | ||||
| 
 | ||||
| 	/* parse add command */ | ||||
| 	if (sscanf(buf, "%llu %llu %s", &osdev->obj.partition, &osdev->obj.id, | ||||
| 		   osdev->osd_path) != 3) { | ||||
| 		rc = -EINVAL; | ||||
| 		goto err_out_slot; | ||||
| 	} | ||||
| 
 | ||||
| 	/* initialize rest of new object */ | ||||
| 	sprintf(osdev->name, DRV_NAME "%d", osdev->id); | ||||
| 
 | ||||
| 	/* contact requested OSD */ | ||||
| 	osdev->osd = osduld_path_lookup(osdev->osd_path); | ||||
| 	if (IS_ERR(osdev->osd)) { | ||||
| 		rc = PTR_ERR(osdev->osd); | ||||
| 		goto err_out_slot; | ||||
| 	} | ||||
| 
 | ||||
| 	/* build OSD credential */ | ||||
| 	osdblk_make_credential(osdev->obj_cred, &osdev->obj); | ||||
| 
 | ||||
| 	/* register our block device */ | ||||
| 	irc = register_blkdev(0, osdev->name); | ||||
| 	if (irc < 0) { | ||||
| 		rc = irc; | ||||
| 		goto err_out_osd; | ||||
| 	} | ||||
| 
 | ||||
| 	osdev->major = irc; | ||||
| 
 | ||||
| 	/* set up and announce blkdev mapping */ | ||||
| 	rc = osdblk_init_disk(osdev); | ||||
| 	if (rc) | ||||
| 		goto err_out_blkdev; | ||||
| 
 | ||||
| 	return count; | ||||
| 
 | ||||
| err_out_blkdev: | ||||
| 	unregister_blkdev(osdev->major, osdev->name); | ||||
| err_out_osd: | ||||
| 	osduld_put_device(osdev->osd); | ||||
| err_out_slot: | ||||
| 	mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING); | ||||
| 	list_del_init(&osdev->node); | ||||
| 	mutex_unlock(&ctl_mutex); | ||||
| 
 | ||||
| 	kfree(osdev); | ||||
| err_out_mod: | ||||
| 	OSDBLK_DEBUG("Error adding device %s\n", buf); | ||||
| 	module_put(THIS_MODULE); | ||||
| 	return rc; | ||||
| } | ||||
| 
 | ||||
| static ssize_t class_osdblk_remove(struct class *c, const char *buf, | ||||
| 					size_t count) | ||||
| { | ||||
| 	struct osdblk_device *osdev = NULL; | ||||
| 	int target_id, rc; | ||||
| 	unsigned long ul; | ||||
| 	struct list_head *tmp; | ||||
| 
 | ||||
| 	rc = strict_strtoul(buf, 10, &ul); | ||||
| 	if (rc) | ||||
| 		return rc; | ||||
| 
 | ||||
| 	/* convert to int; abort if we lost anything in the conversion */ | ||||
| 	target_id = (int) ul; | ||||
| 	if (target_id != ul) | ||||
| 		return -EINVAL; | ||||
| 
 | ||||
| 	/* remove object from list immediately */ | ||||
| 	mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING); | ||||
| 
 | ||||
| 	list_for_each(tmp, &osdblkdev_list) { | ||||
| 		osdev = list_entry(tmp, struct osdblk_device, node); | ||||
| 		if (osdev->id == target_id) { | ||||
| 			list_del_init(&osdev->node); | ||||
| 			break; | ||||
| 		} | ||||
| 		osdev = NULL; | ||||
| 	} | ||||
| 
 | ||||
| 	mutex_unlock(&ctl_mutex); | ||||
| 
 | ||||
| 	if (!osdev) | ||||
| 		return -ENOENT; | ||||
| 
 | ||||
| 	/* clean up and free blkdev and associated OSD connection */ | ||||
| 	osdblk_free_disk(osdev); | ||||
| 	unregister_blkdev(osdev->major, osdev->name); | ||||
| 	osduld_put_device(osdev->osd); | ||||
| 	kfree(osdev); | ||||
| 
 | ||||
| 	/* release module ref */ | ||||
| 	module_put(THIS_MODULE); | ||||
| 
 | ||||
| 	return count; | ||||
| } | ||||
| 
 | ||||
| static struct class_attribute class_osdblk_attrs[] = { | ||||
| 	__ATTR(add,	0200, NULL, class_osdblk_add), | ||||
| 	__ATTR(remove,	0200, NULL, class_osdblk_remove), | ||||
| 	__ATTR(list,	0444, class_osdblk_list, NULL), | ||||
| 	__ATTR_NULL | ||||
| }; | ||||
| 
 | ||||
| static int osdblk_sysfs_init(void) | ||||
| { | ||||
| 	int ret = 0; | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * create control files in sysfs | ||||
| 	 * /sys/class/osdblk/... | ||||
| 	 */ | ||||
| 	class_osdblk = kzalloc(sizeof(*class_osdblk), GFP_KERNEL); | ||||
| 	if (!class_osdblk) | ||||
| 		return -ENOMEM; | ||||
| 
 | ||||
| 	class_osdblk->name = DRV_NAME; | ||||
| 	class_osdblk->owner = THIS_MODULE; | ||||
| 	class_osdblk->class_release = class_osdblk_release; | ||||
| 	class_osdblk->class_attrs = class_osdblk_attrs; | ||||
| 
 | ||||
| 	ret = class_register(class_osdblk); | ||||
| 	if (ret) { | ||||
| 		kfree(class_osdblk); | ||||
| 		class_osdblk = NULL; | ||||
| 		printk(PFX "failed to create class osdblk\n"); | ||||
| 		return ret; | ||||
| 	} | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static void osdblk_sysfs_cleanup(void) | ||||
| { | ||||
| 	if (class_osdblk) | ||||
| 		class_destroy(class_osdblk); | ||||
| 	class_osdblk = NULL; | ||||
| } | ||||
| 
 | ||||
| static int __init osdblk_init(void) | ||||
| { | ||||
| 	int rc; | ||||
| 
 | ||||
| 	rc = osdblk_sysfs_init(); | ||||
| 	if (rc) | ||||
| 		return rc; | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static void __exit osdblk_exit(void) | ||||
| { | ||||
| 	osdblk_sysfs_cleanup(); | ||||
| } | ||||
| 
 | ||||
| module_init(osdblk_init); | ||||
| module_exit(osdblk_exit); | ||||
| 
 | ||||
|  | @ -213,7 +213,7 @@ static int virtblk_ioctl(struct block_device *bdev, fmode_t mode, | |||
| 	 * Only allow the generic SCSI ioctls if the host can support it. | ||||
| 	 */ | ||||
| 	if (!virtio_has_feature(vblk->vdev, VIRTIO_BLK_F_SCSI)) | ||||
| 		return -ENOIOCTLCMD; | ||||
| 		return -ENOTTY; | ||||
| 
 | ||||
| 	return scsi_cmd_ioctl(disk->queue, disk, mode, cmd, argp); | ||||
| } | ||||
|  | @ -360,6 +360,9 @@ static int __devinit virtblk_probe(struct virtio_device *vdev) | |||
| 	blk_queue_max_phys_segments(vblk->disk->queue, vblk->sg_elems-2); | ||||
| 	blk_queue_max_hw_segments(vblk->disk->queue, vblk->sg_elems-2); | ||||
| 
 | ||||
| 	/* No need to bounce any requests */ | ||||
| 	blk_queue_bounce_limit(vblk->disk->queue, BLK_BOUNCE_ANY); | ||||
| 
 | ||||
| 	/* No real sector limit. */ | ||||
| 	blk_queue_max_sectors(vblk->disk->queue, -1U); | ||||
| 
 | ||||
|  |  | |||
|  | @ -28,7 +28,6 @@ | |||
| #include <linux/kernel.h> | ||||
| #include <linux/init.h> | ||||
| #include <linux/slab.h> | ||||
| #include <linux/smp_lock.h> | ||||
| #include <linux/types.h> | ||||
| #include <linux/errno.h> | ||||
| #include <linux/sched.h> | ||||
|  |  | |||
|  | @ -81,6 +81,7 @@ static char *serial_version = "4.30"; | |||
| #include <linux/mm.h> | ||||
| #include <linux/seq_file.h> | ||||
| #include <linux/slab.h> | ||||
| #include <linux/smp_lock.h> | ||||
| #include <linux/init.h> | ||||
| #include <linux/bitops.h> | ||||
| 
 | ||||
|  |  | |||
|  | @ -633,6 +633,7 @@ | |||
| #include <linux/tty.h> | ||||
| #include <linux/tty_flip.h> | ||||
| #include <linux/serial.h> | ||||
| #include <linux/smp_lock.h> | ||||
| #include <linux/major.h> | ||||
| #include <linux/string.h> | ||||
| #include <linux/fcntl.h> | ||||
|  |  | |||
|  | @ -36,6 +36,7 @@ | |||
| #include <linux/tty.h> | ||||
| #include <linux/tty_flip.h> | ||||
| #include <linux/slab.h> | ||||
| #include <linux/smp_lock.h> | ||||
| #include <linux/ioport.h> | ||||
| #include <linux/interrupt.h> | ||||
| #include <linux/uaccess.h> | ||||
|  |  | |||
|  | @ -122,6 +122,7 @@ | |||
| #include <linux/fs.h> | ||||
| #include <linux/sched.h> | ||||
| #include <linux/serial.h> | ||||
| #include <linux/smp_lock.h> | ||||
| #include <linux/mm.h> | ||||
| #include <linux/interrupt.h> | ||||
| #include <linux/timer.h> | ||||
|  |  | |||
|  | @ -20,6 +20,7 @@ | |||
| 
 | ||||
| #include <linux/module.h> | ||||
| #include <linux/slab.h> | ||||
| #include <linux/smp_lock.h> | ||||
| #include <linux/interrupt.h> | ||||
| #include <linux/tty.h> | ||||
| #include <linux/tty_flip.h> | ||||
|  |  | |||
|  | @ -34,6 +34,7 @@ | |||
| #include <linux/tty.h> | ||||
| #include <linux/tty_flip.h> | ||||
| #include <linux/major.h> | ||||
| #include <linux/smp_lock.h> | ||||
| #include <linux/string.h> | ||||
| #include <linux/fcntl.h> | ||||
| #include <linux/ptrace.h> | ||||
|  |  | |||
|  | @ -23,6 +23,7 @@ | |||
| #include <linux/errno.h> | ||||
| #include <linux/signal.h> | ||||
| #include <linux/sched.h> | ||||
| #include <linux/smp_lock.h> | ||||
| #include <linux/timer.h> | ||||
| #include <linux/interrupt.h> | ||||
| #include <linux/tty.h> | ||||
|  |  | |||
|  | @ -97,6 +97,7 @@ | |||
| #include <linux/slab.h> | ||||
| #include <linux/tty.h> | ||||
| #include <linux/errno.h> | ||||
| #include <linux/smp_lock.h> | ||||
| #include <linux/string.h>	/* used in new tty drivers */ | ||||
| #include <linux/signal.h>	/* used in new tty drivers */ | ||||
| #include <linux/if.h> | ||||
|  |  | |||
|  | @ -58,6 +58,7 @@ | |||
| #include <linux/ioport.h> | ||||
| #include <linux/in.h> | ||||
| #include <linux/slab.h> | ||||
| #include <linux/smp_lock.h> | ||||
| #include <linux/tty.h> | ||||
| #include <linux/errno.h> | ||||
| #include <linux/string.h>	/* used in new tty drivers */ | ||||
|  |  | |||
|  | @ -1331,9 +1331,6 @@ handle_newline: | |||
| 
 | ||||
| static void n_tty_write_wakeup(struct tty_struct *tty) | ||||
| { | ||||
| 	/* Write out any echoed characters that are still pending */ | ||||
| 	process_echoes(tty); | ||||
| 
 | ||||
| 	if (tty->fasync && test_and_clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags)) | ||||
| 		kill_fasync(&tty->fasync, SIGIO, POLL_OUT); | ||||
| } | ||||
|  |  | |||
|  | @ -828,7 +828,7 @@ static int receive_data(enum port_type index, struct nozomi *dc) | |||
| 	struct port *port = &dc->port[index]; | ||||
| 	void __iomem *addr = port->dl_addr[port->toggle_dl]; | ||||
| 	struct tty_struct *tty = tty_port_tty_get(&port->port); | ||||
| 	int i; | ||||
| 	int i, ret; | ||||
| 
 | ||||
| 	if (unlikely(!tty)) { | ||||
| 		DBG1("tty not open for port: %d?", index); | ||||
|  | @ -844,12 +844,14 @@ static int receive_data(enum port_type index, struct nozomi *dc) | |||
| 
 | ||||
| 		/* disable interrupt in downlink... */ | ||||
| 		disable_transmit_dl(index, dc); | ||||
| 		return 0; | ||||
| 		ret = 0; | ||||
| 		goto put; | ||||
| 	} | ||||
| 
 | ||||
| 	if (unlikely(size == 0)) { | ||||
| 		dev_err(&dc->pdev->dev, "size == 0?\n"); | ||||
| 		return 1; | ||||
| 		ret = 1; | ||||
| 		goto put; | ||||
| 	} | ||||
| 
 | ||||
| 	tty_buffer_request_room(tty, size); | ||||
|  | @ -871,8 +873,10 @@ static int receive_data(enum port_type index, struct nozomi *dc) | |||
| 	} | ||||
| 
 | ||||
| 	set_bit(index, &dc->flip); | ||||
| 	ret = 1; | ||||
| put: | ||||
| 	tty_kref_put(tty); | ||||
| 	return 1; | ||||
| 	return ret; | ||||
| } | ||||
| 
 | ||||
| /* Debug for interrupts */ | ||||
|  |  | |||
|  | @ -22,6 +22,7 @@ | |||
| #include <linux/major.h> | ||||
| #include <linux/mm.h> | ||||
| #include <linux/init.h> | ||||
| #include <linux/smp_lock.h> | ||||
| #include <linux/sysctl.h> | ||||
| #include <linux/device.h> | ||||
| #include <linux/uaccess.h> | ||||
|  |  | |||
|  | @ -44,6 +44,7 @@ | |||
| #include <linux/delay.h> | ||||
| #include <linux/pci.h> | ||||
| #include <linux/slab.h> | ||||
| #include <linux/smp_lock.h> | ||||
| #include <linux/miscdevice.h> | ||||
| #include <linux/init.h> | ||||
| 
 | ||||
|  |  | |||
|  | @ -47,6 +47,7 @@ | |||
| #include <linux/init.h> | ||||
| #include <linux/delay.h> | ||||
| #include <linux/tty_flip.h> | ||||
| #include <linux/smp_lock.h> | ||||
| #include <linux/spinlock.h> | ||||
| #include <linux/device.h> | ||||
| 
 | ||||
|  |  | |||
|  | @ -73,6 +73,7 @@ | |||
| #include <linux/tty_driver.h> | ||||
| #include <linux/tty_flip.h> | ||||
| #include <linux/serial.h> | ||||
| #include <linux/smp_lock.h> | ||||
| #include <linux/string.h> | ||||
| #include <linux/fcntl.h> | ||||
| #include <linux/ptrace.h> | ||||
|  |  | |||
|  | @ -52,6 +52,7 @@ | |||
| #include <linux/interrupt.h> | ||||
| #include <linux/serial.h> | ||||
| #include <linux/serialP.h> | ||||
| #include <linux/smp_lock.h> | ||||
| #include <linux/string.h> | ||||
| #include <linux/fcntl.h> | ||||
| #include <linux/ptrace.h> | ||||
|  |  | |||
|  | @ -87,6 +87,7 @@ | |||
| #include <linux/tty_flip.h> | ||||
| #include <linux/mm.h> | ||||
| #include <linux/serial.h> | ||||
| #include <linux/smp_lock.h> | ||||
| #include <linux/fcntl.h> | ||||
| #include <linux/major.h> | ||||
| #include <linux/delay.h> | ||||
|  |  | |||
|  | @ -216,6 +216,7 @@ | |||
| #include <linux/eisa.h> | ||||
| #include <linux/pci.h> | ||||
| #include <linux/slab.h> | ||||
| #include <linux/smp_lock.h> | ||||
| #include <linux/init.h> | ||||
| #include <linux/miscdevice.h> | ||||
| #include <linux/bitops.h> | ||||
|  |  | |||
|  | @ -81,6 +81,7 @@ | |||
| #include <linux/mm.h> | ||||
| #include <linux/seq_file.h> | ||||
| #include <linux/slab.h> | ||||
| #include <linux/smp_lock.h> | ||||
| #include <linux/delay.h> | ||||
| #include <linux/netdevice.h> | ||||
| #include <linux/vmalloc.h> | ||||
|  |  | |||
|  | @ -62,6 +62,7 @@ | |||
| #include <linux/mm.h> | ||||
| #include <linux/seq_file.h> | ||||
| #include <linux/slab.h> | ||||
| #include <linux/smp_lock.h> | ||||
| #include <linux/netdevice.h> | ||||
| #include <linux/vmalloc.h> | ||||
| #include <linux/init.h> | ||||
|  |  | |||
|  | @ -52,6 +52,7 @@ | |||
| #include <linux/mm.h> | ||||
| #include <linux/seq_file.h> | ||||
| #include <linux/slab.h> | ||||
| #include <linux/smp_lock.h> | ||||
| #include <linux/netdevice.h> | ||||
| #include <linux/vmalloc.h> | ||||
| #include <linux/init.h> | ||||
|  |  | |||
|  | @ -26,7 +26,6 @@ | |||
| #include <linux/poll.h> | ||||
| #include <linux/mutex.h> | ||||
| #include <linux/spinlock.h> | ||||
| #include <linux/smp_lock.h> | ||||
| 
 | ||||
| #include "tpm.h" | ||||
| 
 | ||||
|  |  | |||
Some files were not shown because too many files have changed in this diff Show more
		Loading…
	
	Add table
		
		Reference in a new issue
	
	 Paul Mundt
						Paul Mundt