diff options
284 files changed, 5783 insertions, 2542 deletions
diff --git a/Documentation/i386/boot.txt b/Documentation/i386/boot.txt index 2f75e750e4f..fc49b79bc1a 100644 --- a/Documentation/i386/boot.txt +++ b/Documentation/i386/boot.txt @@ -785,3 +785,41 @@ IMPORTANT: All the hooks are required to preserve %esp, %ebp, %esi and After completing your hook, you should jump to the address that was in this field before your boot loader overwrote it (relocated, if appropriate.) + + +**** 32-bit BOOT PROTOCOL + +For machine with some new BIOS other than legacy BIOS, such as EFI, +LinuxBIOS, etc, and kexec, the 16-bit real mode setup code in kernel +based on legacy BIOS can not be used, so a 32-bit boot protocol needs +to be defined. + +In 32-bit boot protocol, the first step in loading a Linux kernel +should be to setup the boot parameters (struct boot_params, +traditionally known as "zero page"). The memory for struct boot_params +should be allocated and initialized to all zero. Then the setup header +from offset 0x01f1 of kernel image on should be loaded into struct +boot_params and examined. The end of setup header can be calculated as +follow: + + 0x0202 + byte value at offset 0x0201 + +In addition to read/modify/write the setup header of the struct +boot_params as that of 16-bit boot protocol, the boot loader should +also fill the additional fields of the struct boot_params as that +described in zero-page.txt. + +After setupping the struct boot_params, the boot loader can load the +32/64-bit kernel in the same way as that of 16-bit boot protocol. + +In 32-bit boot protocol, the kernel is started by jumping to the +32-bit kernel entry point, which is the start address of loaded +32/64-bit kernel. + +At entry, the CPU must be in 32-bit protected mode with paging +disabled; a GDT must be loaded with the descriptors for selectors +__BOOT_CS(0x10) and __BOOT_DS(0x18); both descriptors must be 4G flat +segment; __BOOS_CS must have execute/read permission, and __BOOT_DS +must have read/write permission; CS must be __BOOT_CS and DS, ES, SS +must be __BOOT_DS; interrupt must be disabled; %esi must hold the base +address of the struct boot_params; %ebp, %edi and %ebx must be zero. diff --git a/Documentation/i386/zero-page.txt b/Documentation/i386/zero-page.txt index 6c0817c4568..169ad423a3d 100644 --- a/Documentation/i386/zero-page.txt +++ b/Documentation/i386/zero-page.txt @@ -1,99 +1,31 @@ ---------------------------------------------------------------------------- -!!!!!!!!!!!!!!!WARNING!!!!!!!! -The zero page is a kernel internal data structure, not a stable ABI. It might change -without warning and the kernel has no way to detect old version of it. -If you're writing some external code like a boot loader you should only use -the stable versioned real mode boot protocol described in boot.txt. Otherwise the kernel -might break you at any time. -!!!!!!!!!!!!!WARNING!!!!!!!!!!! ----------------------------------------------------------------------------- +The additional fields in struct boot_params as a part of 32-bit boot +protocol of kernel. These should be filled by bootloader or 16-bit +real-mode setup code of the kernel. References/settings to it mainly +are in: -Summary of boot_params layout (kernel point of view) - ( collected by Hans Lermen and Martin Mares ) - -The contents of boot_params are used to pass parameters from the -16-bit realmode code of the kernel to the 32-bit part. References/settings -to it mainly are in: + include/asm-x86/bootparam.h - arch/i386/boot/setup.S - arch/i386/boot/video.S - arch/i386/kernel/head.S - arch/i386/kernel/setup.c - -Offset Type Description ------- ---- ----------- - 0 32 bytes struct screen_info, SCREEN_INFO - ATTENTION, overlaps the following !!! - 2 unsigned short EXT_MEM_K, extended memory size in Kb (from int 0x15) - 0x20 unsigned short CL_MAGIC, commandline magic number (=0xA33F) - 0x22 unsigned short CL_OFFSET, commandline offset - Address of commandline is calculated: - 0x90000 + contents of CL_OFFSET - (only taken, when CL_MAGIC = 0xA33F) - 0x40 20 bytes struct apm_bios_info, APM_BIOS_INFO - 0x60 16 bytes Intel SpeedStep (IST) BIOS support information - 0x80 16 bytes hd0-disk-parameter from intvector 0x41 - 0x90 16 bytes hd1-disk-parameter from intvector 0x46 +Offset Proto Name Meaning +/Size - 0xa0 16 bytes System description table truncated to 16 bytes. - ( struct sys_desc_table_struct ) - 0xb0 - 0x13f Free. Add more parameters here if you really need them. - 0x140- 0x1be EDID_INFO Video mode setup - -0x1c4 unsigned long EFI system table pointer -0x1c8 unsigned long EFI memory descriptor size -0x1cc unsigned long EFI memory descriptor version -0x1d0 unsigned long EFI memory descriptor map pointer -0x1d4 unsigned long EFI memory descriptor map size -0x1e0 unsigned long ALT_MEM_K, alternative mem check, in Kb -0x1e4 unsigned long Scratch field for the kernel setup code -0x1e8 char number of entries in E820MAP (below) -0x1e9 unsigned char number of entries in EDDBUF (below) -0x1ea unsigned char number of entries in EDD_MBR_SIG_BUFFER (below) -0x1f1 char size of setup.S, number of sectors -0x1f2 unsigned short MOUNT_ROOT_RDONLY (if !=0) -0x1f4 unsigned short size of compressed kernel-part in the - (b)zImage-file (in 16 byte units, rounded up) -0x1f6 unsigned short swap_dev (unused AFAIK) -0x1f8 unsigned short RAMDISK_FLAGS -0x1fa unsigned short VGA-Mode (old one) -0x1fc unsigned short ORIG_ROOT_DEV (high=Major, low=minor) -0x1ff char AUX_DEVICE_INFO - -0x200 short jump to start of setup code aka "reserved" field. -0x202 4 bytes Signature for SETUP-header, ="HdrS" -0x206 unsigned short Version number of header format - Current version is 0x0201... -0x208 8 bytes (used by setup.S for communication with boot loaders, - look there) -0x210 char LOADER_TYPE, = 0, old one - else it is set by the loader: - 0xTV: T=0 for LILO - 1 for Loadlin - 2 for bootsect-loader - 3 for SYSLINUX - 4 for ETHERBOOT - 5 for ELILO - 7 for GRuB - 8 for U-BOOT - 9 for Xen - V = version -0x211 char loadflags: - bit0 = 1: kernel is loaded high (bzImage) - bit7 = 1: Heap and pointer (see below) set by boot - loader. -0x212 unsigned short (setup.S) -0x214 unsigned long KERNEL_START, where the loader started the kernel -0x218 unsigned long INITRD_START, address of loaded ramdisk image -0x21c unsigned long INITRD_SIZE, size in bytes of ramdisk image -0x220 4 bytes (setup.S) -0x224 unsigned short setup.S heap end pointer -0x226 unsigned short zero_pad -0x228 unsigned long cmd_line_ptr -0x22c unsigned long ramdisk_max -0x230 16 bytes trampoline -0x290 - 0x2cf EDD_MBR_SIG_BUFFER (edd.S) -0x2d0 - 0xd00 E820MAP -0xd00 - 0xeff EDDBUF (edd.S) for disk signature read sector -0xd00 - 0xeeb EDDBUF (edd.S) for edd data +000/040 ALL screen_info Text mode or frame buffer information + (struct screen_info) +040/014 ALL apm_bios_info APM BIOS information (struct apm_bios_info) +060/010 ALL ist_info Intel SpeedStep (IST) BIOS support information + (struct ist_info) +080/010 ALL hd0_info hd0 disk parameter, OBSOLETE!! +090/010 ALL hd1_info hd1 disk parameter, OBSOLETE!! +0A0/010 ALL sys_desc_table System description table (struct sys_desc_table) +140/080 ALL edid_info Video mode setup (struct edid_info) +1C0/020 ALL efi_info EFI 32 information (struct efi_info) +1E0/004 ALL alk_mem_k Alternative mem check, in KB +1E4/004 ALL scratch Scratch field for the kernel setup code +1E8/001 ALL e820_entries Number of entries in e820_map (below) +1E9/001 ALL eddbuf_entries Number of entries in eddbuf (below) +1EA/001 ALL edd_mbr_sig_buf_entries Number of entries in edd_mbr_sig_buffer + (below) +290/040 ALL edd_mbr_sig_buffer EDD MBR signatures +2D0/A00 ALL e820_map E820 memory map table + (array of struct e820entry) +D00/1EC ALL eddbuf EDD data (array of struct edd_info) diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index 8ae5fac08df..33121d6c827 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -586,11 +586,6 @@ and is between 256 and 4096 characters. It is defined in the file eata= [HW,SCSI] - ec_intr= [HW,ACPI] ACPI Embedded Controller interrupt mode - Format: <int> - 0: polling mode - non-0: interrupt mode (default) - edd= [EDD] Format: {"of[f]" | "sk[ipmbr]"} See comment in arch/i386/boot/edd.S diff --git a/Documentation/scsi/link_power_management_policy.txt b/Documentation/scsi/link_power_management_policy.txt new file mode 100644 index 00000000000..d18993d0188 --- /dev/null +++ b/Documentation/scsi/link_power_management_policy.txt @@ -0,0 +1,19 @@ +This parameter allows the user to set the link (interface) power management. +There are 3 possible options: + +Value Effect +---------------------------------------------------------------------------- +min_power Tell the controller to try to make the link use the + least possible power when possible. This may + sacrifice some performance due to increased latency + when coming out of lower power states. + +max_performance Generally, this means no power management. Tell + the controller to have performance be a priority + over power management. + +medium_power Tell the controller to enter a lower power state + when possible, but do not enter the lowest power + state, thus improving latency over min_power setting. + + diff --git a/MAINTAINERS b/MAINTAINERS index 231bda28c42..4a26f832b4b 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -216,7 +216,7 @@ P: Len Brown M: len.brown@intel.com M: lenb@kernel.org L: linux-acpi@vger.kernel.org -W: http://acpi.sourceforge.net/ +W: http://www.lesswatts.org/projects/acpi/ T: git kernel.org:/pub/scm/linux/kernel/git/lenb/linux-acpi-2.6.git S: Supported @@ -235,8 +235,8 @@ W: http://acpi.sourceforge.net/ S: Supported ACPI FAN DRIVER -P: Konstantin A. Karasyov -M: konstantin.a.karasyov@intel.com +P: Len Brown +M: len.brown@intel.com L: linux-acpi@vger.kernel.org W: http://acpi.sourceforge.net/ S: Supported @@ -248,15 +248,15 @@ L: pcihpd-discuss@lists.sourceforge.net S: Supported ACPI THERMAL DRIVER -P: Konstantin A. Karasyov -M: konstantin.a.karasyov@intel.com +P: Len Brown +M: len.brown@intel.com L: linux-acpi@vger.kernel.org W: http://acpi.sourceforge.net/ S: Supported ACPI VIDEO DRIVER -P: Luming Yu -M: luming.yu@intel.com +P: Rui Zhang +M: rui.zhang@intel.com L: linux-acpi@vger.kernel.org W: http://acpi.sourceforge.net/ S: Supported @@ -3472,12 +3472,14 @@ L: linux-pm@lists.linux-foundation.org S: Supported SUSPEND TO RAM: +P: Len Brown +M: len.brown@intel.com P: Pavel Machek M: pavel@suse.cz P: Rafael J. Wysocki M: rjw@sisk.pl L: linux-pm@lists.linux-foundation.org -S: Maintained +S: Supported SONIC NETWORK DRIVER P: Thomas Bogendoerfer diff --git a/arch/blackfin/Kconfig b/arch/blackfin/Kconfig index 7888551ed93..9f9de3e9582 100644 --- a/arch/blackfin/Kconfig +++ b/arch/blackfin/Kconfig @@ -295,6 +295,12 @@ config PNAV10 help PNAV 1.0 board Support. +config H8606_HVSISTEMAS + bool "HV Sistemas H8606" + depends on (BF532) + help + HV Sistemas H8606 board support. + config GENERIC_BOARD bool "Custom" depends on (BF537 || BF536 \ @@ -317,7 +323,8 @@ config MEM_MT48LC64M4A2FB_7E config MEM_MT48LC16M16A2TG_75 bool depends on (BFIN533_EZKIT || BFIN561_EZKIT \ - || BFIN533_BLUETECHNIX_CM || BFIN537_BLUETECHNIX_CM) + || BFIN533_BLUETECHNIX_CM || BFIN537_BLUETECHNIX_CM \ + || H8606_HVSISTEMAS) default y config MEM_MT48LC32M8A2_75 @@ -366,7 +373,7 @@ config CLKIN_HZ int "Crystal Frequency in Hz" default "11059200" if BFIN533_STAMP default "27000000" if BFIN533_EZKIT - default "25000000" if (BFIN537_STAMP || BFIN527_EZKIT) + default "25000000" if (BFIN537_STAMP || BFIN527_EZKIT || H8606_HVSISTEMAS) default "30000000" if BFIN561_EZKIT default "24576000" if PNAV10 help @@ -404,6 +411,7 @@ config VCO_MULT default "20" if BFIN537_BLUETECHNIX_CM default "20" if BFIN561_BLUETECHNIX_CM default "20" if BFIN561_EZKIT + default "16" if H8606_HVSISTEMAS help This controls the frequency of the on-chip PLL. This can be between 1 and 64. PLL Frequency = (Crystal Frequency) * (this setting) @@ -440,6 +448,7 @@ config SCLK_DIV default 4 if BFIN537_BLUETECHNIX_CM default 4 if BFIN561_BLUETECHNIX_CM default 5 if BFIN561_EZKIT + default 3 if H8606_HVSISTEMAS help This sets the frequency of the system clock (including SDRAM or DDR). This can be between 1 and 15 @@ -492,11 +501,13 @@ config MEM_SIZE default 64 if BFIN561_EZKIT default 128 if BFIN533_STAMP default 64 if PNAV10 + default 32 if H8606_HVSISTEMAS config MEM_ADD_WIDTH int "SDRAM Memory Address Width" default 9 if BFIN533_EZKIT default 9 if BFIN561_EZKIT + default 9 if H8606_HVSISTEMAS default 10 if BFIN527_EZKIT default 10 if BFIN537_STAMP default 11 if BFIN533_STAMP diff --git a/arch/blackfin/configs/BF527-EZKIT_defconfig b/arch/blackfin/configs/BF527-EZKIT_defconfig index df974e785ee..1f6a93df6b3 100644 --- a/arch/blackfin/configs/BF527-EZKIT_defconfig +++ b/arch/blackfin/configs/BF527-EZKIT_defconfig @@ -244,7 +244,7 @@ CONFIG_CLKIN_HZ=25000000 # CONFIG_BFIN_KERNEL_CLOCK is not set CONFIG_MAX_VCO_HZ=600000000 CONFIG_MIN_VCO_HZ=50000000 -CONFIG_MAX_SCLK_HZ=133000000 +CONFIG_MAX_SCLK_HZ=133333333 CONFIG_MIN_SCLK_HZ=27000000 # diff --git a/arch/blackfin/configs/BF533-EZKIT_defconfig b/arch/blackfin/configs/BF533-EZKIT_defconfig index 57f58d5cd47..9e9b420342d 100644 --- a/arch/blackfin/configs/BF533-EZKIT_defconfig +++ b/arch/blackfin/configs/BF533-EZKIT_defconfig @@ -198,7 +198,7 @@ CONFIG_CLKIN_HZ=27000000 # CONFIG_BFIN_KERNEL_CLOCK is not set CONFIG_MAX_VCO_HZ=750000000 CONFIG_MIN_VCO_HZ=50000000 -CONFIG_MAX_SCLK_HZ=133000000 +CONFIG_MAX_SCLK_HZ=133333333 CONFIG_MIN_SCLK_HZ=27000000 # diff --git a/arch/blackfin/configs/BF533-STAMP_defconfig b/arch/blackfin/configs/BF533-STAMP_defconfig index 306302baff0..f59ade98010 100644 --- a/arch/blackfin/configs/BF533-STAMP_defconfig +++ b/arch/blackfin/configs/BF533-STAMP_defconfig @@ -199,7 +199,7 @@ CONFIG_CLKIN_HZ=11059200 # CONFIG_BFIN_KERNEL_CLOCK is not set CONFIG_MAX_VCO_HZ=750000000 CONFIG_MIN_VCO_HZ=50000000 -CONFIG_MAX_SCLK_HZ=133000000 +CONFIG_MAX_SCLK_HZ=133333333 CONFIG_MIN_SCLK_HZ=27000000 # diff --git a/arch/blackfin/configs/BF537-STAMP_defconfig b/arch/blackfin/configs/BF537-STAMP_defconfig index 828b604438e..07eb63dc25e 100644 --- a/arch/blackfin/configs/BF537-STAMP_defconfig +++ b/arch/blackfin/configs/BF537-STAMP_defconfig @@ -206,7 +206,7 @@ CONFIG_CLKIN_HZ=25000000 # CONFIG_BFIN_KERNEL_CLOCK is not set CONFIG_MAX_VCO_HZ=600000000 CONFIG_MIN_VCO_HZ=50000000 -CONFIG_MAX_SCLK_HZ=133000000 +CONFIG_MAX_SCLK_HZ=133333333 CONFIG_MIN_SCLK_HZ=27000000 # diff --git a/arch/blackfin/configs/BF548-EZKIT_defconfig b/arch/blackfin/configs/BF548-EZKIT_defconfig index d8569888a1c..0dd3d2253dc 100644 --- a/arch/blackfin/configs/BF548-EZKIT_defconfig +++ b/arch/blackfin/configs/BF548-EZKIT_defconfig @@ -1,6 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.22.6 +# Linux kernel version: 2.6.22.10 +# Sat Oct 27 02:34:07 2007 # # CONFIG_MMU is not set # CONFIG_FPU is not set @@ -64,7 +65,6 @@ CONFIG_FUTEX=y CONFIG_ANON_INODES=y CONFIG_EPOLL=y CONFIG_SIGNALFD=y -CONFIG_TIMERFD=y CONFIG_EVENTFD=y CONFIG_VM_EVENT_COUNTERS=y CONFIG_BIG_ORDER_ALLOC_NOFAIL_MAGIC=3 @@ -117,6 +117,9 @@ CONFIG_PREEMPT_VOLUNTARY=y # # Processor and Board Settings # +# CONFIG_BF522 is not set +# CONFIG_BF525 is not set +# CONFIG_BF527 is not set # CONFIG_BF531 is not set # CONFIG_BF532 is not set # CONFIG_BF533 is not set @@ -129,6 +132,7 @@ CONFIG_PREEMPT_VOLUNTARY=y CONFIG_BF549=y # CONFIG_BF561 is not set CONFIG_BF_REV_0_0=y +# CONFIG_BF_REV_0_1 is not set # CONFIG_BF_REV_0_2 is not set # CONFIG_BF_REV_0_3 is not set # CONFIG_BF_REV_0_4 is not set @@ -137,6 +141,7 @@ CONFIG_BF_REV_0_0=y # CONFIG_BF_REV_NONE is not set CONFIG_BF54x=y CONFIG_BFIN_SINGLE_CORE=y +# CONFIG_BFIN527_EZKIT is not set # CONFIG_BFIN533_EZKIT is not set # CONFIG_BFIN533_STAMP is not set # CONFIG_BFIN537_STAMP is not set @@ -147,8 +152,23 @@ CONFIG_BFIN548_EZKIT=y # CONFIG_BFIN561_EZKIT is not set # CONFIG_BFIN561_TEPLA is not set # CONFIG_PNAV10 is not set +# CONFIG_H8606_HVSISTEMAS is not set # CONFIG_GENERIC_BOARD is not set CONFIG_IRQ_PLL_WAKEUP=7 +CONFIG_IRQ_RTC=8 +CONFIG_IRQ_SPORT0_RX=9 +CONFIG_IRQ_SPORT0_TX=9 +CONFIG_IRQ_SPORT1_RX=9 +CONFIG_IRQ_SPORT1_TX=9 +CONFIG_IRQ_UART0_RX=10 +CONFIG_IRQ_UART0_TX=10 +CONFIG_IRQ_UART1_RX=10 +CONFIG_IRQ_UART1_TX=10 +CONFIG_IRQ_CNT=8 +CONFIG_IRQ_USB_INT0=11 +CONFIG_IRQ_USB_INT1=11 +CONFIG_IRQ_USB_INT2=11 +CONFIG_IRQ_USB_DMA=11 CONFIG_IRQ_TIMER0=11 CONFIG_IRQ_TIMER1=11 CONFIG_IRQ_TIMER2=11 @@ -160,15 +180,6 @@ CONFIG_IRQ_TIMER7=11 CONFIG_IRQ_TIMER8=11 CONFIG_IRQ_TIMER9=11 CONFIG_IRQ_TIMER10=11 -CONFIG_IRQ_RTC=8 -CONFIG_IRQ_SPORT0_RX=9 -CONFIG_IRQ_SPORT0_TX=9 -CONFIG_IRQ_SPORT1_RX=9 -CONFIG_IRQ_SPORT1_TX=9 -CONFIG_IRQ_UART0_RX=10 -CONFIG_IRQ_UART0_TX=10 -CONFIG_IRQ_UART1_RX=10 -CONFIG_IRQ_UART1_TX=10 # # BF548 Specific Configuration @@ -236,16 +247,11 @@ CONFIG_IRQ_PIXC_IN0=8 CONFIG_IRQ_PIXC_IN1=8 CONFIG_IRQ_PIXC_OUT=8 CONFIG_IRQ_SDH=8 -CONFIG_IRQ_CNT=8 CONFIG_IRQ_KEY=8 CONFIG_IRQ_CAN1_RX=11 CONFIG_IRQ_CAN1_TX=11 CONFIG_IRQ_SDH_MASK0=11 CONFIG_IRQ_SDH_MASK1=11 -CONFIG_IRQ_USB_INT0=11 -CONFIG_IRQ_USB_INT1=11 -CONFIG_IRQ_USB_INT2=11 -CONFIG_IRQ_USB_DMA=11 CONFIG_IRQ_OTPSEC=11 CONFIG_IRQ_PINT2=11 CONFIG_IRQ_PINT3=11 @@ -273,9 +279,9 @@ CONFIG_PINT3_ASSIGN=0x02020303 # CONFIG_CLKIN_HZ=25000000 # CONFIG_BFIN_KERNEL_CLOCK is not set -CONFIG_MAX_VCO_HZ=533000000 +CONFIG_MAX_VCO_HZ=533333333 CONFIG_MIN_VCO_HZ=50000000 -CONFIG_MAX_SCLK_HZ=133000000 +CONFIG_MAX_SCLK_HZ=133333333 CONFIG_MIN_SCLK_HZ=27000000 # @@ -332,9 +338,10 @@ CONFIG_SPLIT_PTLOCK_CPUS=4 # CONFIG_RESOURCES_64BIT is not set CONFIG_ZONE_DMA_FLAG=1 CONFIG_LARGE_ALLOCS=y +# CONFIG_BFIN_GPTIMERS is not set CONFIG_BFIN_DMA_5XX=y -# CONFIG_DMA_UNCACHED_2M is not set -CONFIG_DMA_UNCACHED_1M=y +CONFIG_DMA_UNCACHED_2M=y +# CONFIG_DMA_UNCACHED_1M is not set # CONFIG_DMA_UNCACHED_NONE is not set # @@ -353,7 +360,7 @@ CONFIG_L1_MAX_PIECE=16 # # -# EBIU_AMBCTL Global Control +# EBIU_AMGCTL Global Control # CONFIG_C_AMCKEN=y # CONFIG_C_AMBEN is not set @@ -722,7 +729,7 @@ CONFIG_NETDEV_10000=y # # Input device support # -CONFIG_INPUT=y +CONFIG_INPUT=m # CONFIG_INPUT_FF_MEMLESS is not set # CONFIG_INPUT_POLLDEV is not set @@ -731,18 +738,39 @@ CONFIG_INPUT=y # # CONFIG_INPUT_MOUSEDEV is not set # CONFIG_INPUT_JOYDEV is not set -# CONFIG_INPUT_TSDEV is not set -# CONFIG_INPUT_EVDEV is not set -# CONFIG_INPUT_EVBUG is not set +CONFIG_INPUT_TSDEV=m +CONFIG_INPUT_TSDEV_SCREEN_X=240 +CONFIG_INPUT_TSDEV_SCREEN_Y=320 +CONFIG_INPUT_EVDEV=m +CONFIG_INPUT_EVBUG=m # # Input Device Drivers # -# CONFIG_INPUT_KEYBOARD is not set +CONFIG_INPUT_KEYBOARD=y +# CONFIG_KEYBOARD_ATKBD is not set +# CONFIG_KEYBOARD_SUNKBD is not set +# CONFIG_KEYBOARD_LKKBD is not set +# CONFIG_KEYBOARD_XTKBD is not set +# CONFIG_KEYBOARD_NEWTON is not set +# CONFIG_KEYBOARD_STOWAWAY is not set +# CONFIG_KEYBOARD_GPIO is not set +CONFIG_KEYBOARD_BFIN=m # CONFIG_INPUT_MOUSE is not set # CONFIG_INPUT_JOYSTICK is not set # CONFIG_INPUT_TABLET is not set -# CONFIG_INPUT_TOUCHSCREEN is not set +CONFIG_INPUT_TOUCHSCREEN=y +# CONFIG_TOUCHSCREEN_ADS7846 is not set +CONFIG_TOUCHSCREEN_AD7877=m +# CONFIG_TOUCHSCREEN_GUNZE is not set +# CONFIG_TOUCHSCREEN_ELO is not set +# CONFIG_TOUCHSCREEN_MTOUCH is not set +# CONFIG_TOUCHSCREEN_MK712 is not set +# CONFIG_TOUCHSCREEN_PENMOUNT is not set +# CONFIG_TOUCHSCREEN_TOUCHRIGHT is not set +# CONFIG_TOUCHSCREEN_TOUCHWIN is not set +# CONFIG_TOUCHSCREEN_UCB1400 is not set +# CONFIG_TOUCHSCREEN_USB_COMPOSITE is not set CONFIG_INPUT_MISC=y # CONFIG_INPUT_ATI_REMOTE is not set # CONFIG_INPUT_ATI_REMOTE2 is not set @@ -764,9 +792,9 @@ CONFIG_INPUT_MISC=y # # CONFIG_AD9960 is not set # CONFIG_SPI_ADC_BF533 is not set -# CONFIG_BFIN_PFLAGS is not set +# CONFIG_BF5xx_PFLAGS is not set # CONFIG_BF5xx_PPIFCD is not set -# CONFIG_BF5xx_TIMERS is not set +# CONFIG_BFIN_SIMPLE_TIMER is not set # CONFIG_BF5xx_PPI is not set # CONFIG_BFIN_SPORT is not set # CONFIG_BFIN_TIMER_LATENCY is not set @@ -958,17 +986,92 @@ CONFIG_DAB=y # # CONFIG_DISPLAY_SUPPORT is not set # CONFIG_VGASTATE is not set -# CONFIG_FB is not set +CONFIG_FB=m +CONFIG_FIRMWARE_EDID=y +# CONFIG_FB_DDC is not set +CONFIG_FB_CFB_FILLRECT=m +CONFIG_FB_CFB_COPYAREA=m +CONFIG_FB_CFB_IMAGEBLIT=m +# CONFIG_FB_SYS_FILLRECT is not set +# CONFIG_FB_SYS_COPYAREA is not set +# CONFIG_FB_SYS_IMAGEBLIT is not set +# CONFIG_FB_SYS_FOPS is not set +CONFIG_FB_DEFERRED_IO=y +# CONFIG_FB_SVGALIB is not set +# CONFIG_FB_MACMODES is not set +# CONFIG_FB_BACKLIGHT is not set +# CONFIG_FB_MODE_HELPERS is not set +# CONFIG_FB_TILEBLITTING is not set + +# +# Frame buffer hardware drivers +# +# CONFIG_FB_BFIN_7171 is not set +# CONFIG_FB_BFIN_7393 is not set +CONFIG_FB_BF54X_LQ043=m +# CONFIG_FB_BFIN_T350MCQB is not set +# CONFIG_FB_S1D13XXX is not set +# CONFIG_FB_VIRTUAL is not set +# CONFIG_LOGO is not set # # Sound # -# CONFIG_SOUND is not set +CONFIG_SOUND=y + +# +# Advanced Linux Sound Architecture +# +CONFIG_SND=y +CONFIG_SND_TIMER=y +CONFIG_SND_PCM=y +# CONFIG_SND_SEQUENCER is not set +CONFIG_SND_OSSEMUL=y +CONFIG_SND_MIXER_OSS=y +CONFIG_SND_PCM_OSS=y +CONFIG_SND_PCM_OSS_PLUGINS=y +# CONFIG_SND_DYNAMIC_MINORS is not set +CONFIG_SND_SUPPORT_OLD_API=y +CONFIG_SND_VERBOSE_PROCFS=y +# CONFIG_SND_VERBOSE_PRINTK is not set +# CONFIG_SND_DEBUG is not set + +# +# Generic devices +# +# CONFIG_SND_DUMMY is not set +# CONFIG_SND_MTPAV is not set +# CONFIG_SND_SERIAL_U16550 is not set +# CONFIG_SND_MPU401 is not set + +# +# ALSA Blackfin devices +# +# CONFIG_SND_BLACKFIN_AD1836 is not set +# CONFIG_SND_BFIN_AD73311 is not set + +# +# System on Chip audio support +# +CONFIG_SND_SOC_AC97_BUS=y +CONFIG_SND_SOC=y +CONFIG_SND_BF5XX_SOC=y +CONFIG_SND_BF5XX_SOC_AC97=y +CONFIG_SND_BF5XX_SOC_BF548_EZKIT=y +CONFIG_SND_BF5XX_SPORT_NUM=0 +# CONFIG_SND_BF5XX_HAVE_COLD_RESET is not set +CONFIG_SND_SOC_AD1980=y + +# +# Open Sound System +# +# CONFIG_SOUND_PRIME is not set +CONFIG_AC97_BUS=y # # HID Devices # -CONFIG_HID=y +CONFIG_HID=m # CONFIG_HID_DEBUG is not set # @@ -1101,8 +1204,13 @@ CONFIG_EXT2_FS=y CONFIG_EXT2_FS_XATTR=y # CONFIG_EXT2_FS_POSIX_ACL is not set # CONFIG_EXT2_FS_SECURITY is not set -# CONFIG_EXT3_FS is not set +CONFIG_EXT3_FS=y +CONFIG_EXT3_FS_XATTR=y +# CONFIG_EXT3_FS_POSIX_ACL is not set +# CONFIG_EXT3_FS_SECURITY is not set # CONFIG_EXT4DEV_FS is not set +CONFIG_JBD=y +# CONFIG_JBD_DEBUG is not set CONFIG_FS_MBCACHE=y # CONFIG_REISERFS_FS is not set # CONFIG_JFS_FS is not set @@ -1123,15 +1231,22 @@ CONFIG_DNOTIFY=y # # CD-ROM/DVD Filesystems # -# CONFIG_ISO9660_FS is not set +CONFIG_ISO9660_FS=m +CONFIG_JOLIET=y +CONFIG_ZISOFS=y # CONFIG_UDF_FS is not set # # DOS/FAT/NT Filesystems # -# CONFIG_MSDOS_FS is not set -# CONFIG_VFAT_FS is not set -# CONFIG_NTFS_FS is not set +CONFIG_FAT_FS=m +CONFIG_MSDOS_FS=m +CONFIG_VFAT_FS=m +CONFIG_FAT_DEFAULT_CODEPAGE=437 +CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" +CONFIG_NTFS_FS=m +# CONFIG_NTFS_DEBUG is not set +CONFIG_NTFS_RW=y # # Pseudo filesystems @@ -1183,10 +1298,33 @@ CONFIG_JFFS2_RTIME=y # # Network File Systems # -# CONFIG_NFS_FS is not set -# CONFIG_NFSD is not set -# CONFIG_SMB_FS is not set -# CONFIG_CIFS is not set +CONFIG_NFS_FS=m +CONFIG_NFS_V3=y +# CONFIG_NFS_V3_ACL is not set +# CONFIG_NFS_V4 is not set +# CONFIG_NFS_DIRECTIO is not set +CONFIG_NFSD=m +CONFIG_NFSD_V3=y +# CONFIG_NFSD_V3_ACL is not set +# CONFIG_NFSD_V4 is not set +CONFIG_NFSD_TCP=y +CONFIG_LOCKD=m +CONFIG_LOCKD_V4=y +CONFIG_EXPORTFS=m +CONFIG_NFS_COMMON=y +CONFIG_SUNRPC=m +# CONFIG_SUNRPC_BIND34 is not set +# CONFIG_RPCSEC_GSS_KRB5 is not set +# CONFIG_RPCSEC_GSS_SPKM3 is not set +CONFIG_SMB_FS=m +CONFIG_SMB_NLS_DEFAULT=y +CONFIG_SMB_NLS_REMOTE="cp437" +CONFIG_CIFS=y +# CONFIG_CIFS_STATS is not set +# CONFIG_CIFS_WEAK_PW_HASH is not set +# CONFIG_CIFS_XATTR is not set +# CONFIG_CIFS_DEBUG2 is not set +# CONFIG_CIFS_EXPERIMENTAL is not set # CONFIG_NCP_FS is not set # CONFIG_CODA_FS is not set # CONFIG_AFS_FS is not set @@ -1195,13 +1333,68 @@ CONFIG_JFFS2_RTIME=y # # Partition Types # -# CONFIG_PARTITION_ADVANCED is not set +CONFIG_PARTITION_ADVANCED=y +# CONFIG_ACORN_PARTITION is not set +# CONFIG_OSF_PARTITION is not set +# CONFIG_AMIGA_PARTITION is not set +# CONFIG_ATARI_PARTITION is not set +# CONFIG_MAC_PARTITION is not set CONFIG_MSDOS_PARTITION=y +# CONFIG_BSD_DISKLABEL is not set +# CONFIG_MINIX_SUBPARTITION is not set +# CONFIG_SOLARIS_X86_PARTITION is not set +# CONFIG_UNIXWARE_DISKLABEL is not set +# CONFIG_LDM_PARTITION is not set +# CONFIG_SGI_PARTITION is not set +# CONFIG_ULTRIX_PARTITION is not set +# CONFIG_SUN_PARTITION is not set +# CONFIG_KARMA_PARTITION is not set +# CONFIG_EFI_PARTITION is not set +# CONFIG_SYSV68_PARTITION is not set # # Native Language Support # -# CONFIG_NLS is not set +CONFIG_NLS=y +CONFIG_NLS_DEFAULT="iso8859-1" +CONFIG_NLS_CODEPAGE_437=m +CONFIG_NLS_CODEPAGE_737=m +CONFIG_NLS_CODEPAGE_775=m +CONFIG_NLS_CODEPAGE_850=m +CONFIG_NLS_CODEPAGE_852=m +CONFIG_NLS_CODEPAGE_855=m +CONFIG_NLS_CODEPAGE_857=m +CONFIG_NLS_CODEPAGE_860=m +CONFIG_NLS_CODEPAGE_861=m +CONFIG_NLS_CODEPAGE_862=m +CONFIG_NLS_CODEPAGE_863=m +CONFIG_NLS_CODEPAGE_864=m +CONFIG_NLS_CODEPAGE_865=m +CONFIG_NLS_CODEPAGE_866=m +CONFIG_NLS_CODEPAGE_869=m +CONFIG_NLS_CODEPAGE_936=m +CONFIG_NLS_CODEPAGE_950=m +CONFIG_NLS_CODEPAGE_932=m +CONFIG_NLS_CODEPAGE_949=m +CONFIG_NLS_CODEPAGE_874=m +CONFIG_NLS_ISO8859_8=m +CONFIG_NLS_CODEPAGE_1250=m +CONFIG_NLS_CODEPAGE_1251=m +CONFIG_NLS_ASCII=m +CONFIG_NLS_ISO8859_1=m +CONFIG_NLS_ISO8859_2=m +CONFIG_NLS_ISO8859_3=m +CONFIG_NLS_ISO8859_4=m +CONFIG_NLS_ISO8859_5=m +CONFIG_NLS_ISO8859_6=m +CONFIG_NLS_ISO8859_7=m +CONFIG_NLS_ISO8859_9=m +CONFIG_NLS_ISO8859_13=m +CONFIG_NLS_ISO8859_14=m +CONFIG_NLS_ISO8859_15=m +CONFIG_NLS_KOI8_R=m +CONFIG_NLS_KOI8_U=m +CONFIG_NLS_UTF8=m # # Distributed Lock Manager diff --git a/arch/blackfin/configs/BF561-EZKIT_defconfig b/arch/blackfin/configs/BF561-EZKIT_defconfig index 85e647f8775..277d72dac0f 100644 --- a/arch/blackfin/configs/BF561-EZKIT_defconfig +++ b/arch/blackfin/configs/BF561-EZKIT_defconfig @@ -243,7 +243,7 @@ CONFIG_CLKIN_HZ=30000000 # CONFIG_BFIN_KERNEL_CLOCK is not set CONFIG_MAX_VCO_HZ=600000000 CONFIG_MIN_VCO_HZ=50000000 -CONFIG_MAX_SCLK_HZ=133000000 +CONFIG_MAX_SCLK_HZ=133333333 CONFIG_MIN_SCLK_HZ=27000000 # diff --git a/arch/blackfin/configs/PNAV-10_defconfig b/arch/blackfin/configs/PNAV-10_defconfig index 15e36aaf218..3d403e0b82c 100644 --- a/arch/blackfin/configs/PNAV-10_defconfig +++ b/arch/blackfin/configs/PNAV-10_defconfig @@ -204,7 +204,7 @@ CONFIG_CLKIN_HZ=24576000 # CONFIG_BFIN_KERNEL_CLOCK is not set CONFIG_MAX_VCO_HZ=600000000 CONFIG_MIN_VCO_HZ=50000000 -CONFIG_MAX_SCLK_HZ=133000000 +CONFIG_MAX_SCLK_HZ=133333333 CONFIG_MIN_SCLK_HZ=27000000 # diff --git a/arch/blackfin/kernel/entry.S b/arch/blackfin/kernel/entry.S index 65c5ba4260b..65f4e67a65c 100644 --- a/arch/blackfin/kernel/entry.S +++ b/arch/blackfin/kernel/entry.S @@ -54,9 +54,11 @@ ENTRY(_ret_from_fork) [sp + PT_IPEND] = r0; /* do a 'fake' RTI by jumping to [RETI] * to avoid clearing supervisor mode in child - */ + */ + r0 = [sp + PT_PC]; + [sp + PT_P0] = r0; + RESTORE_ALL_SYS - p0 = reti; jump (p0); ENDPROC(_ret_from_fork) diff --git a/arch/blackfin/kernel/fixed_code.S b/arch/blackfin/kernel/fixed_code.S index d8b1ebc7099..90262691b11 100644 --- a/arch/blackfin/kernel/fixed_code.S +++ b/arch/blackfin/kernel/fixed_code.S @@ -129,4 +129,18 @@ ENTRY(_atomic_xor32) rts; ENDPROC (_atomic_ior32) +.align 16 + /* + * safe_user_instruction + * Four NOPS are enough to allow the pipeline to speculativily load + * execute anything it wants. After that, things have gone bad, and + * we are stuck - so panic. Since we might be in user space, we can't + * call panic, so just cause a unhandled exception, this should cause + * a dump of the trace buffer so we can tell were we are, and a reboot + */ +ENTRY(_safe_user_instruction) + NOP; NOP; NOP; NOP; + EXCPT 0x4; +ENDPROC(_safe_user_instruction) + ENTRY(_fixed_code_end) diff --git a/arch/blackfin/kernel/gptimers.c b/arch/blackfin/kernel/gptimers.c index cb7ba9bfc79..5cf4bdb1df3 100644 --- a/arch/blackfin/kernel/gptimers.c +++ b/arch/blackfin/kernel/gptimers.c @@ -20,8 +20,7 @@ #else # define tassert(expr) \ if (!(expr)) \ - printk(KERN_DEBUG "%s:%s:%i: Assertion failed: " #expr "\n", \ - __FILE__, __func__, __LINE__); + printk(KERN_DEBUG "%s:%s:%i: Assertion failed: " #expr "\n", __FILE__, __func__, __LINE__); #endif #define BFIN_TIMER_NUM_GROUP (BFIN_TIMER_OCTET(MAX_BLACKFIN_GPTIMERS - 1) + 1) @@ -70,7 +69,7 @@ static volatile GPTIMER_group_regs *const group_regs[BFIN_TIMER_NUM_GROUP] = #endif }; -static uint32_t const dis_mask[MAX_BLACKFIN_GPTIMERS] = +static uint32_t const trun_mask[MAX_BLACKFIN_GPTIMERS] = { TIMER_STATUS_TRUN0, TIMER_STATUS_TRUN1, @@ -90,7 +89,27 @@ static uint32_t const dis_mask[MAX_BLACKFIN_GPTIMERS] = #endif }; -static uint32_t const irq_mask[MAX_BLACKFIN_GPTIMERS] = +static uint32_t const tovf_mask[MAX_BLACKFIN_GPTIMERS] = +{ + TIMER_STATUS_TOVF0, + TIMER_STATUS_TOVF1, + TIMER_STATUS_TOVF2, +#if (MAX_BLACKFIN_GPTIMERS > 3) + TIMER_STATUS_TOVF3, + TIMER_STATUS_TOVF4, + TIMER_STATUS_TOVF5, + TIMER_STATUS_TOVF6, + TIMER_STATUS_TOVF7, +#endif +#if (MAX_BLACKFIN_GPTIMERS > 8) + TIMER_STATUS_TOVF8, + TIMER_STATUS_TOVF9, + TIMER_STATUS_TOVF10, + TIMER_STATUS_TOVF11, +#endif +}; + +static uint32_t const timil_mask[MAX_BLACKFIN_GPTIMERS] = { TIMER_STATUS_TIMIL0, TIMER_STATUS_TIMIL1, @@ -165,17 +184,31 @@ EXPORT_SYMBOL(set_gptimer_status); uint16_t get_gptimer_intr(int timer_id) { tassert(timer_id < MAX_BLACKFIN_GPTIMERS); - return (group_regs[BFIN_TIMER_OCTET(timer_id)]->status & irq_mask[timer_id]) ? 1 : 0; + return (group_regs[BFIN_TIMER_OCTET(timer_id)]->status & timil_mask[timer_id]) ? 1 : 0; } EXPORT_SYMBOL(get_gptimer_intr); void clear_gptimer_intr(int timer_id) { tassert(timer_id < MAX_BLACKFIN_GPTIMERS); - group_regs[BFIN_TIMER_OCTET(timer_id)]->status = irq_mask[timer_id]; + group_regs[BFIN_TIMER_OCTET(timer_id)]->status = timil_mask[timer_id]; } EXPORT_SYMBOL(clear_gptimer_intr); +uint16_t get_gptimer_over(int timer_id) +{ + tassert(timer_id < MAX_BLACKFIN_GPTIMERS); + return (group_regs[BFIN_TIMER_OCTET(timer_id)]->status & tovf_mask[timer_id]) ? 1 : 0; +} +EXPORT_SYMBOL(get_gptimer_over); + +void clear_gptimer_over(int timer_id) +{ + tassert(timer_id < MAX_BLACKFIN_GPTIMERS); + group_regs[BFIN_TIMER_OCTET(timer_id)]->status = tovf_mask[timer_id]; +} +EXPORT_SYMBOL(clear_gptimer_over); + void set_gptimer_config(int timer_id, uint16_t config) { tassert(timer_id < MAX_BLACKFIN_GPTIMERS); @@ -214,7 +247,7 @@ void disable_gptimers(uint16_t mask) } for (i = 0; i < MAX_BLACKFIN_GPTIMERS; ++i) if (mask & (1 << i)) - group_regs[BFIN_TIMER_OCTET(i)]->status |= dis_mask[i]; + group_regs[BFIN_TIMER_OCTET(i)]->status |= trun_mask[i]; SSYNC(); } EXPORT_SYMBOL(disable_gptimers); diff --git a/arch/blackfin/kernel/setup.c b/arch/blackfin/kernel/setup.c index f1b059e5a06..934234f4383 100644 --- a/arch/blackfin/kernel/setup.c +++ b/arch/blackfin/kernel/setup.c @@ -316,6 +316,15 @@ void __init setup_arch(char **cmdline_p) init_leds(); + _bfin_swrst = bfin_read_SWRST(); + + if (_bfin_swrst & RESET_DOUBLE) + printk(KERN_INFO "Recovering from Double Fault event\n"); + else if (_bfin_swrst & RESET_WDOG) + printk(KERN_INFO "Recovering from Watchdog event\n"); + else if (_bfin_swrst & RESET_SOFTWARE) + printk(KERN_NOTICE "Reset caused by Software reset\n"); + printk(KERN_INFO "Blackfin support (C) 2004-2007 Analog Devices, Inc.\n"); if (bfin_compiled_revid() == 0xffff) printk(KERN_INFO "Compiled for ADSP-%s Rev any\n", CPU); @@ -402,8 +411,6 @@ void __init setup_arch(char **cmdline_p) if (l1_length > L1_DATA_A_LENGTH) panic("L1 data memory overflow\n"); - _bfin_swrst = bfin_read_SWRST(); - /* Copy atomic sequences to their fixed location, and sanity check that these locations are the ones that we advertise to userspace. */ memcpy((void *)FIXED_CODE_START, &fixed_code_start, @@ -424,6 +431,8 @@ void __init setup_arch(char **cmdline_p) != ATOMIC_AND32 - FIXED_CODE_START); BUG_ON((char *)&atomic_xor32 - (char *)&fixed_code_start != ATOMIC_XOR32 - FIXED_CODE_START); + BUG_ON((char *)&safe_user_instruction - (char *)&fixed_code_start + != SAFE_USER_INSTRUCTION - FIXED_CODE_START); init_exception_vectors(); bf53x_cache_init(); diff --git a/arch/blackfin/kernel/traps.c b/arch/blackfin/kernel/traps.c index afd044e78af..cfa05436c97 100644 --- a/arch/blackfin/kernel/traps.c +++ b/arch/blackfin/kernel/traps.c @@ -37,10 +37,24 @@ #include <asm/blackfin.h> #include <asm/irq_handler.h> #include <asm/trace.h> +#include <asm/fixed_code.h> #ifdef CONFIG_KGDB # include <linux/debugger.h> # include <linux/kgdb.h> + +# define CHK_DEBUGGER_TRAP() \ + do { \ + CHK_DEBUGGER(trapnr, sig, info.si_code, fp, ); \ + } while (0) +# define CHK_DEBUGGER_TRAP_MAYBE() \ + do { \ + if (kgdb_connected) \ + CHK_DEBUGGER_TRAP(); \ + } while (0) +#else +# define CHK_DEBUGGER_TRAP() do { } while (0) +# define CHK_DEBUGGER_TRAP_MAYBE() do { } while (0) #endif /* Initiate the event table handler */ @@ -53,13 +67,13 @@ void __init trap_init(void) int kstack_depth_to_print = 48; -#ifdef CONFIG_DEBUG_BFIN_HWTRACE_ON -static int printk_address(unsigned long address) +static void decode_address(char *buf, unsigned long address) { struct vm_list_struct *vml; struct task_struct *p; struct mm_struct *mm; - unsigned long offset; + unsigned long flags, offset; + unsigned int in_exception = bfin_read_IPEND() & 0x10; #ifdef CONFIG_KALLSYMS unsigned long symsize; @@ -75,20 +89,33 @@ static int printk_address(unsigned long address) /* yeah! kernel space! */ if (!modname) modname = delim = ""; - return printk("<0x%p> { %s%s%s%s + 0x%lx }", + sprintf(buf, "<0x%p> { %s%s%s%s + 0x%lx }", (void *)address, delim, modname, delim, symname, (unsigned long)offset); + return; } #endif + /* Problem in fixed code section? */ + if (address >= FIXED_CODE_START && address < FIXED_CODE_END) { + sprintf(buf, "<0x%p> /* Maybe fixed code section */", (void *)address); + return; + } + + /* Problem somewhere before the kernel start address */ + if (address < CONFIG_BOOT_LOAD) { + sprintf(buf, "<0x%p> /* Maybe null pointer? */", (void *)address); + return; + } + /* looks like we're off in user-land, so let's walk all the * mappings of all our processes and see if we can't be a whee * bit more specific */ - write_lock_irq(&tasklist_lock); + write_lock_irqsave(&tasklist_lock, flags); for_each_process(p) { - mm = get_task_mm(p); + mm = (in_exception ? p->mm : get_task_mm(p)); if (!mm) continue; @@ -117,25 +144,30 @@ static int printk_address(unsigned long address) else offset = (address - vma->vm_start) + (vma->vm_pgoff << PAGE_SHIFT); - write_unlock_irq(&tasklist_lock); - mmput(mm); - return printk("<0x%p> [ %s + 0x%lx ]", - (void *)address, name, offset); + sprintf(buf, "<0x%p> [ %s + 0x%lx ]", + (void *)address, name, offset); + if (!in_exception) + mmput(mm); + goto done; } vml = vml->next; } - mmput(mm); + if (!in_exception) + mmput(mm); } - write_unlock_irq(&tasklist_lock); /* we were unable to find this address anywhere */ - return printk("[<0x%p>]", (void *)address); + sprintf(buf, "[<0x%p>]", (void *)address); + +done: + write_unlock_irqrestore(&tasklist_lock, flags); } -#endif asmlinkage void double_fault_c(struct pt_regs *fp) { + console_verbose(); + oops_in_progress = 1; printk(KERN_EMERG "\n" KERN_EMERG "Double Fault\n"); dump_bfin_regs(fp, (void *)fp->retx); panic("Double Fault - unrecoverable event\n"); @@ -151,22 +183,29 @@ asmlinkage void trap_c(struct pt_regs *fp) siginfo_t info; unsigned long trapnr = fp->seqstat & SEQSTAT_EXCAUSE; + trace_buffer_save(j); + + /* Important - be very careful dereferncing pointers - will lead to + * double faults if the stack has become corrupt + */ + + /* If the fault was caused by a kernel thread, or interrupt handler + * we will kernel panic, so the system reboots. + * If KGDB is enabled, don't set this for kernel breakpoints + */ + if ((bfin_read_IPEND() & 0xFFC0) #ifdef CONFIG_KGDB -# define CHK_DEBUGGER_TRAP() \ - do { \ - CHK_DEBUGGER(trapnr, sig, info.si_code, fp, ); \ - } while (0) -# define CHK_DEBUGGER_TRAP_MAYBE() \ - do { \ - if (kgdb_connected) \ - CHK_DEBUGGER_TRAP(); \ - } while (0) -#else -# define CHK_DEBUGGER_TRAP() do { } while (0) -# define CHK_DEBUGGER_TRAP_MAYBE() do { } while (0) + && trapnr != VEC_EXCPT02 #endif - - trace_buffer_save(j); + ){ + console_verbose(); + oops_in_progress = 1; + } else if (current) { + if (current->mm == NULL) { + console_verbose(); + oops_in_progress = 1; + } + } /* trap_c() will be called for exceptions. During exceptions * processing, the pc value should be set with retx value. @@ -211,7 +250,7 @@ asmlinkage void trap_c(struct pt_regs *fp) case VEC_EXCPT03: info.si_code = SEGV_STACKFLOW; sig = SIGSEGV; - printk(KERN_EMERG EXC_0x03); + printk(KERN_NOTICE EXC_0x03); CHK_DEBUGGER_TRAP(); break; /* 0x04 - User Defined, Caught by default */ @@ -240,7 +279,7 @@ asmlinkage void trap_c(struct pt_regs *fp) case VEC_OVFLOW: info.si_code = TRAP_TRACEFLOW; sig = SIGTRAP; - printk(KERN_EMERG EXC_0x11); + printk(KERN_NOTICE EXC_0x11); CHK_DEBUGGER_TRAP(); break; /* 0x12 - Reserved, Caught by default */ @@ -262,14 +301,14 @@ asmlinkage void trap_c(struct pt_regs *fp) case VEC_UNDEF_I: info.si_code = ILL_ILLOPC; sig = SIGILL; - printk(KERN_EMERG EXC_0x21); + printk(KERN_NOTICE EXC_0x21); CHK_DEBUGGER_TRAP(); break; /* 0x22 - Illegal Instruction Combination, handled here */ case VEC_ILGAL_I: info.si_code = ILL_ILLPARAOP; sig = SIGILL; - printk(KERN_EMERG EXC_0x22); + printk(KERN_NOTICE EXC_0x22); CHK_DEBUGGER_TRAP(); break; /* 0x23 - Data CPLB Protection Violation, @@ -277,21 +316,21 @@ asmlinkage void trap_c(struct pt_regs *fp) case VEC_CPLB_VL: info.si_code = ILL_CPLB_VI; sig = SIGILL; - printk(KERN_EMERG EXC_0x23); + printk(KERN_NOTICE EXC_0x23); CHK_DEBUGGER_TRAP(); break; /* 0x24 - Data access misaligned, handled here */ case VEC_MISALI_D: info.si_code = BUS_ADRALN; sig = SIGBUS; - printk(KERN_EMERG EXC_0x24); + printk(KERN_NOTICE EXC_0x24); CHK_DEBUGGER_TRAP(); break; /* 0x25 - Unrecoverable Event, handled here */ case VEC_UNCOV: info.si_code = ILL_ILLEXCPT; sig = SIGILL; - printk(KERN_EMERG EXC_0x25); + printk(KERN_NOTICE EXC_0x25); CHK_DEBUGGER_TRAP(); break; /* 0x26 - Data CPLB Miss, normal case is handled in _cplb_hdr, @@ -299,7 +338,7 @@ asmlinkage void trap_c(struct pt_regs *fp) case VEC_CPLB_M: info.si_code = BUS_ADRALN; sig = SIGBUS; - printk(KERN_EMERG EXC_0x26); + printk(KERN_NOTICE EXC_0x26); CHK_DEBUGGER_TRAP(); break; /* 0x27 - Data CPLB Multiple Hits - Linux Trap Zero, handled here */ @@ -307,11 +346,10 @@ asmlinkage void trap_c(struct pt_regs *fp) info.si_code = ILL_CPLB_MULHIT; #ifdef CONFIG_DEBUG_HUNT_FOR_ZERO sig = SIGSEGV; - printk(KERN_EMERG "\n" - KERN_EMERG "NULL pointer access (probably)\n"); + printk(KERN_NOTICE "NULL pointer access (probably)\n"); #else sig = SIGILL; - printk(KERN_EMERG EXC_0x27); + printk(KERN_NOTICE EXC_0x27); #endif CHK_DEBUGGER_TRAP(); break; @@ -331,7 +369,7 @@ asmlinkage void trap_c(struct pt_regs *fp) case VEC_ISTRU_VL: /* ADSP-BF535 only (MH) */ info.si_code = BUS_OPFETCH; sig = SIGBUS; - printk(KERN_EMERG "BF535: VEC_ISTRU_VL\n"); + printk(KERN_NOTICE "BF535: VEC_ISTRU_VL\n"); CHK_DEBUGGER_TRAP(); break; #else @@ -341,7 +379,7 @@ asmlinkage void trap_c(struct pt_regs *fp) case VEC_MISALI_I: info.si_code = BUS_ADRALN; sig = SIGBUS; - printk(KERN_EMERG EXC_0x2A); + printk(KERN_NOTICE EXC_0x2A); CHK_DEBUGGER_TRAP(); break; /* 0x2B - Instruction CPLB protection Violation, @@ -349,14 +387,14 @@ asmlinkage void trap_c(struct pt_regs *fp) case VEC_CPLB_I_VL: info.si_code = ILL_CPLB_VI; sig = SIGILL; - printk(KERN_EMERG EXC_0x2B); + printk(KERN_NOTICE EXC_0x2B); CHK_DEBUGGER_TRAP(); break; /* 0x2C - Instruction CPLB miss, handled in _cplb_hdr */ case VEC_CPLB_I_M: info.si_code = ILL_CPLB_MISS; sig = SIGBUS; - printk(KERN_EMERG EXC_0x2C); + printk(KERN_NOTICE EXC_0x2C); CHK_DEBUGGER_TRAP(); break; /* 0x2D - Instruction CPLB Multiple Hits, handled here */ @@ -364,10 +402,10 @@ asmlinkage void trap_c(struct pt_regs *fp) info.si_code = ILL_CPLB_MULHIT; #ifdef CONFIG_DEBUG_HUNT_FOR_ZERO sig = SIGSEGV; - printk(KERN_EMERG "\n\nJump to address 0 - 0x0fff\n"); + printk(KERN_NOTICE "Jump to address 0 - 0x0fff\n"); #else sig = SIGILL; - printk(KERN_EMERG EXC_0x2D); + printk(KERN_NOTICE EXC_0x2D); #endif CHK_DEBUGGER_TRAP(); break; @@ -375,7 +413,7 @@ asmlinkage void trap_c(struct pt_regs *fp) case VEC_ILL_RES: info.si_code = ILL_PRVOPC; sig = SIGILL; - printk(KERN_EMERG EXC_0x2E); + printk(KERN_NOTICE EXC_0x2E); CHK_DEBUGGER_TRAP(); break; /* 0x2F - Reserved, Caught by default */ @@ -404,38 +442,40 @@ asmlinkage void trap_c(struct pt_regs *fp) break; } - if (sig != 0 && sig != SIGTRAP) { + BUG_ON(sig == 0); + + if (sig != SIGTRAP) { unsigned long stack; dump_bfin_regs(fp, (void *)fp->retx); - dump_bfin_trace_buffer(); + + /* Print out the trace buffer if it makes sense */ +#ifndef CONFIG_DEBUG_BFIN_NO_KERN_HWTRACE + if (trapnr == VEC_CPLB_I_M || trapnr == VEC_CPLB_M) + printk(KERN_NOTICE "No trace since you do not have " + "CONFIG_DEBUG_BFIN_NO_KERN_HWTRACE enabled\n" + KERN_NOTICE "\n"); + else +#endif + dump_bfin_trace_buffer(); show_stack(current, &stack); - if (current->mm == NULL) + if (oops_in_progress) { +#ifndef CONFIG_ACCESS_CHECK + printk(KERN_EMERG "Hey - dork - please turn on " + "CONFIG_ACCESS_CHECK\n"); +#endif panic("Kernel exception"); + } + + /* Ensure that bad return addresses don't end up in an infinite + * loop, due to speculative loads/reads + */ + fp->pc = SAFE_USER_INSTRUCTION; } info.si_signo = sig; info.si_errno = 0; info.si_addr = (void *)fp->pc; force_sig_info(sig, &info, current); - /* if the address that we are about to return to is not valid, set it - * to a valid address, if we have a current application or panic - */ - if (!(fp->pc <= physical_mem_end -#if L1_CODE_LENGTH != 0 - || (fp->pc >= L1_CODE_START && - fp->pc <= (L1_CODE_START + L1_CODE_LENGTH)) -#endif - )) { - if (current->mm) { - fp->pc = current->mm->start_code; - } else { - printk(KERN_EMERG - "I can't return to memory that doesn't exist" - " - bad things happen\n"); - panic("Help - I've fallen and can't get up\n"); - } - } - trace_buffer_restore(j); return; } @@ -448,21 +488,21 @@ void dump_bfin_trace_buffer(void) { #ifdef CONFIG_DEBUG_BFIN_HWTRACE_ON int tflags, i = 0; + char buf[150]; #ifdef CONFIG_DEBUG_BFIN_HWTRACE_EXPAND int j, index; #endif trace_buffer_save(tflags); - printk(KERN_EMERG "Hardware Trace:\n"); + printk(KERN_NOTICE "Hardware Trace:\n"); if (likely(bfin_read_TBUFSTAT() & TBUFCNT)) { for (; bfin_read_TBUFSTAT() & TBUFCNT; i++) { - printk(KERN_EMERG "%4i Target : ", i); - printk_address((unsigned long)bfin_read_TBUF()); - printk("\n" KERN_EMERG " Source : "); - printk_address((unsigned long)bfin_read_TBUF()); - printk("\n"); + decode_address(buf, (unsigned long)bfin_read_TBUF()); + printk(KERN_NOTICE "%4i Target : %s\n", i, buf); + decode_address(buf, (unsigned long)bfin_read_TBUF()); + printk(KERN_NOTICE " Source : %s\n", buf); } } @@ -474,17 +514,16 @@ void dump_bfin_trace_buffer(void) j = (1 << CONFIG_DEBUG_BFIN_HWTRACE_EXPAND_LEN) * 128; while (j) { - printk(KERN_EMERG "%4i Target : ", i); - printk_address(software_trace_buff[index]); + decode_address(buf, software_trace_buff[index]); + printk(KERN_NOTICE "%4i Target : %s\n", i, buf); index -= 1; if (index < 0 ) index = EXPAND_LEN; - printk("\n" KERN_EMERG " Source : "); - printk_address(software_trace_buff[index]); + decode_address(buf, software_trace_buff[index]); + printk(KERN_NOTICE " Source : %s\n", buf); index -= 1; if (index < 0) index = EXPAND_LEN; - printk("\n"); j--; i++; } @@ -499,10 +538,7 @@ static void show_trace(struct task_struct *tsk, unsigned long *sp) { unsigned long addr; - printk("\nCall Trace:"); -#ifdef CONFIG_KALLSYMS - printk("\n"); -#endif + printk(KERN_NOTICE "\n" KERN_NOTICE "Call Trace:\n"); while (!kstack_end(sp)) { addr = *sp++; @@ -518,7 +554,7 @@ static void show_trace(struct task_struct *tsk, unsigned long *sp) print_ip_sym(addr); } - printk("\n"); + printk(KERN_NOTICE "\n"); } void show_stack(struct task_struct *task, unsigned long *stack) @@ -540,14 +576,15 @@ void show_stack(struct task_struct *task, unsigned long *stack) addr = (unsigned long)stack; endstack = (unsigned long *)PAGE_ALIGN(addr); - printk(KERN_EMERG "Stack from %08lx:", (unsigned long)stack); + printk(KERN_NOTICE "Stack from %08lx:", (unsigned long)stack); for (i = 0; i < kstack_depth_to_print; i++) { if (stack + 1 > endstack) break; if (i % 8 == 0) - printk("\n" KERN_EMERG " "); + printk("\n" KERN_NOTICE " "); printk(" %08lx", *stack++); } + printk("\n"); show_trace(task, stack); } @@ -568,33 +605,34 @@ EXPORT_SYMBOL(dump_stack); void dump_bfin_regs(struct pt_regs *fp, void *retaddr) { - if (current->pid) { - printk(KERN_EMERG "\n" KERN_EMERG "CURRENT PROCESS:\n" - KERN_EMERG "\n"); - printk(KERN_EMERG "COMM=%s PID=%d\n", - current->comm, current->pid); + char buf [150]; + + if (!oops_in_progress) { + if (current->pid && current->mm) { + printk(KERN_NOTICE "\n" KERN_NOTICE "CURRENT PROCESS:\n"); + printk(KERN_NOTICE "COMM=%s PID=%d\n", + current->comm, current->pid); + + printk(KERN_NOTICE "TEXT = 0x%p-0x%p DATA = 0x%p-0x%p\n" + KERN_NOTICE "BSS = 0x%p-0x%p USER-STACK = 0x%p\n" + KERN_NOTICE "\n", + (void *)current->mm->start_code, + (void *)current->mm->end_code, + (void *)current->mm->start_data, + (void *)current->mm->end_data, + (void *)current->mm->end_data, + (void *)current->mm->brk, + (void *)current->mm->start_stack); + } else { + printk (KERN_NOTICE "\n" KERN_NOTICE + "No Valid pid - Either things are really messed up," + " or you are in the kernel\n"); + } } else { - printk - (KERN_EMERG "\n" KERN_EMERG - "No Valid pid - Either things are really messed up," - " or you are in the kernel\n"); - } - - if (current->mm) { - printk(KERN_EMERG "TEXT = 0x%p-0x%p DATA = 0x%p-0x%p\n" - KERN_EMERG "BSS = 0x%p-0x%p USER-STACK = 0x%p\n" - KERN_EMERG "\n", - (void *)current->mm->start_code, - (void *)current->mm->end_code, - (void *)current->mm->start_data, - (void *)current->mm->end_data, - (void *)current->mm->end_data, - (void *)current->mm->brk, - (void *)current->mm->start_stack); + printk(KERN_NOTICE "Kernel or interrupt exception\n"); } - printk(KERN_EMERG "return address: [0x%p]; contents of:", retaddr); - if (retaddr != 0 && retaddr <= (void *)physical_mem_end + if (retaddr >= (void *)FIXED_CODE_START && retaddr < (void *)physical_mem_end #if L1_CODE_LENGTH != 0 /* FIXME: Copy the code out of L1 Instruction SRAM through dma memcpy. */ @@ -604,18 +642,20 @@ void dump_bfin_regs(struct pt_regs *fp, void *retaddr) ) { int i = ((unsigned int)retaddr & 0xFFFFFFF0) - 32; unsigned short x = 0; + printk(KERN_NOTICE "return address: [0x%p]; contents of:", retaddr); for (; i < ((unsigned int)retaddr & 0xFFFFFFF0) + 32; i += 2) { if (!(i & 0xF)) - printk("\n" KERN_EMERG "0x%08x: ", i); + printk("\n" KERN_NOTICE "0x%08x: ", i); if (get_user(x, (unsigned short *)i)) break; #ifndef CONFIG_DEBUG_HWERR /* If one of the last few instructions was a STI * it is likely that the error occured awhile ago - * and we just noticed + * and we just noticed. This only happens in kernel + * context, which should mean an oops is happening */ - if (x >= 0x0040 && x <= 0x0047 && i <= 0) + if (oops_in_progress && x >= 0x0040 && x <= 0x0047 && i <= 0) panic("\n\nWARNING : You should reconfigure" " the kernel to turn on\n" " 'Hardware error interrupt" @@ -628,56 +668,60 @@ void dump_bfin_regs(struct pt_regs *fp, void *retaddr) else printk(" %04x ", x); } - printk("\n" KERN_EMERG "\n"); + printk("\n"); } else - printk(KERN_EMERG + printk("\n" KERN_NOTICE "Cannot look at the [PC] for it is" - "in unreadable L1 SRAM - sorry\n"); + " in unreadable memory - sorry\n"); + + printk(KERN_NOTICE "\n" KERN_NOTICE "SEQUENCER STATUS:\n"); + printk(KERN_NOTICE " SEQSTAT: %08lx IPEND: %04lx SYSCFG: %04lx\n", + (long)fp->seqstat, fp->ipend, fp->syscfg); + decode_address(buf, fp->rete); + printk(KERN_NOTICE " RETE: %s\n", buf); + decode_address(buf, fp->retn); + printk(KERN_NOTICE " RETN: %s\n", buf); + decode_address(buf, fp->retx); + printk(KERN_NOTICE " RETX: %s\n", buf); + decode_address(buf, fp->rets); + printk(KERN_NOTICE " RETS: %s\n", buf); - printk(KERN_EMERG - "RETE: %08lx RETN: %08lx RETX: %08lx RETS: %08lx\n", - fp->rete, fp->retn, fp->retx, fp->rets); - printk(KERN_EMERG "IPEND: %04lx SYSCFG: %04lx\n", - fp->ipend, fp->syscfg); - printk(KERN_EMERG "SEQSTAT: %08lx SP: %08lx\n", - (long)fp->seqstat, (long)fp); - printk(KERN_EMERG "R0: %08lx R1: %08lx R2: %08lx R3: %08lx\n", + if ((long)fp->seqstat & SEQSTAT_EXCAUSE) { + decode_address(buf, bfin_read_DCPLB_FAULT_ADDR()); + printk(KERN_NOTICE "DCPLB_FAULT_ADDR: %s\n", buf); + decode_address(buf, bfin_read_ICPLB_FAULT_ADDR()); + printk(KERN_NOTICE "ICPLB_FAULT_ADDR: %s\n", buf); + } + + printk(KERN_NOTICE "\n" KERN_NOTICE "PROCESSOR STATE:\n"); + printk(KERN_NOTICE " R0 : %08lx R1 : %08lx R2 : %08lx R3 : %08lx\n", fp->r0, fp->r1, fp->r2, fp->r3); - printk(KERN_EMERG "R4: %08lx R5: %08lx R6: %08lx R7: %08lx\n", + printk(KERN_NOTICE " R4 : %08lx R5 : %08lx R6 : %08lx R7 : %08lx\n", fp->r4, fp->r5, fp->r6, fp->r7); - printk(KERN_EMERG "P0: %08lx P1: %08lx P2: %08lx P3: %08lx\n", + printk(KERN_NOTICE " P0 : %08lx P1 : %08lx P2 : %08lx P3 : %08lx\n", fp->p0, fp->p1, fp->p2, fp->p3); - printk(KERN_EMERG - "P4: %08lx P5: %08lx FP: %08lx\n", - fp->p4, fp->p5, fp->fp); - printk(KERN_EMERG - "A0.w: %08lx A0.x: %08lx A1.w: %08lx A1.x: %08lx\n", - fp->a0w, fp->a0x, fp->a1w, fp->a1x); - - printk(KERN_EMERG "LB0: %08lx LT0: %08lx LC0: %08lx\n", + printk(KERN_NOTICE " P4 : %08lx P5 : %08lx FP : %08lx SP : %08lx\n", + fp->p4, fp->p5, fp->fp, (long)fp); + printk(KERN_NOTICE " LB0: %08lx LT0: %08lx LC0: %08lx\n", fp->lb0, fp->lt0, fp->lc0); - printk(KERN_EMERG "LB1: %08lx LT1: %08lx LC1: %08lx\n", + printk(KERN_NOTICE " LB1: %08lx LT1: %08lx LC1: %08lx\n", fp->lb1, fp->lt1, fp->lc1); - printk(KERN_EMERG "B0: %08lx L0: %08lx M0: %08lx I0: %08lx\n", + printk(KERN_NOTICE " B0 : %08lx L0 : %08lx M0 : %08lx I0 : %08lx\n", fp->b0, fp->l0, fp->m0, fp->i0); - printk(KERN_EMERG "B1: %08lx L1: %08lx M1: %08lx I1: %08lx\n", + printk(KERN_NOTICE " B1 : %08lx L1 : %08lx M1 : %08lx I1 : %08lx\n", fp->b1, fp->l1, fp->m1, fp->i1); - printk(KERN_EMERG "B2: %08lx L2: %08lx M2: %08lx I2: %08lx\n", + printk(KERN_NOTICE " B2 : %08lx L2 : %08lx M2 : %08lx I2 : %08lx\n", fp->b2, fp->l2, fp->m2, fp->i2); - printk(KERN_EMERG "B3: %08lx L3: %08lx M3: %08lx I3: %08lx\n", + printk(KERN_NOTICE " B3 : %08lx L3 : %08lx M3 : %08lx I3 : %08lx\n", fp->b3, fp->l3, fp->m3, fp->i3); + printk(KERN_NOTICE "A0.w: %08lx A0.x: %08lx A1.w: %08lx A1.x: %08lx\n", + fp->a0w, fp->a0x, fp->a1w, fp->a1x); - printk(KERN_EMERG "\n" KERN_EMERG "USP: %08lx ASTAT: %08lx\n", + printk(KERN_NOTICE "USP : %08lx ASTAT: %08lx\n", rdusp(), fp->astat); - if ((long)fp->seqstat & SEQSTAT_EXCAUSE) { - printk(KERN_EMERG "DCPLB_FAULT_ADDR=%p\n", - (void *)bfin_read_DCPLB_FAULT_ADDR()); - printk(KERN_EMERG "ICPLB_FAULT_ADDR=%p\n", - (void *)bfin_read_ICPLB_FAULT_ADDR()); - } - printk("\n\n"); + printk(KERN_NOTICE "\n"); } #ifdef CONFIG_SYS_BFIN_SPINLOCK_L1 @@ -752,6 +796,8 @@ void panic_cplb_error(int cplb_panic, struct pt_regs *fp) break; } + oops_in_progress = 1; + printk(KERN_EMERG "DCPLB_FAULT_ADDR=%p\n", (void *)bfin_read_DCPLB_FAULT_ADDR()); printk(KERN_EMERG "ICPLB_FAULT_ADDR=%p\n", (void *)bfin_read_ICPLB_FAULT_ADDR()); dump_bfin_regs(fp, (void *)fp->retx); diff --git a/arch/blackfin/kernel/vmlinux.lds.S b/arch/blackfin/kernel/vmlinux.lds.S index eec43674a46..9b75bc83c71 100644 --- a/arch/blackfin/kernel/vmlinux.lds.S +++ b/arch/blackfin/kernel/vmlinux.lds.S @@ -172,9 +172,14 @@ SECTIONS __ebss_b_l1 = .; } - ___init_end = LOADADDR(.data_b_l1) + SIZEOF(.data_b_l1); - - .bss LOADADDR(.data_b_l1) + SIZEOF(.data_b_l1) : + /* Force trailing alignment of our init section so that when we + * free our init memory, we don't leave behind a partial page. + */ + . = LOADADDR(.data_b_l1) + SIZEOF(.data_b_l1); + . = ALIGN(PAGE_SIZE); + ___init_end = .; + + .bss : { . = ALIGN(4); ___bss_start = .; diff --git a/arch/blackfin/mach-bf527/boards/ezkit.c b/arch/blackfin/mach-bf527/boards/ezkit.c index 3e884f3a818..bf1bedcc886 100644 --- a/arch/blackfin/mach-bf527/boards/ezkit.c +++ b/arch/blackfin/mach-bf527/boards/ezkit.c @@ -41,9 +41,11 @@ #include <linux/irq.h> #include <linux/interrupt.h> #include <linux/usb_sl811.h> +#include <asm/cplb.h> #include <asm/dma.h> #include <asm/bfin5xx_spi.h> #include <asm/reboot.h> +#include <asm/nand.h> #include <linux/spi/ad7877.h> /* @@ -102,6 +104,53 @@ void __exit bfin_isp1761_exit(void) arch_initcall(bfin_isp1761_init); #endif +#if defined(CONFIG_MTD_NAND_BF5XX) || defined(CONFIG_MTD_NAND_BF5XX_MODULE) +static struct mtd_partition partition_info[] = { + { + .name = "Linux Kernel", + .offset = 0, + .size = 4 * SIZE_1M, + }, + { + .name = "File System", + .offset = 4 * SIZE_1M, + .size = (256 - 4) * SIZE_1M, + }, +}; + +static struct bf5xx_nand_platform bf5xx_nand_platform = { + .page_size = NFC_PG_SIZE_256, + .data_width = NFC_NWIDTH_8, + .partitions = partition_info, + .nr_partitions = ARRAY_SIZE(partition_info), + .rd_dly = 3, + .wr_dly = 3, +}; + +static struct resource bf5xx_nand_resources[] = { + { + .start = NFC_CTL, + .end = NFC_DATA_RD + 2, + .flags = IORESOURCE_MEM, + }, + { + .start = CH_NFC, + .end = CH_NFC, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device bf5xx_nand_device = { + .name = "bf5xx-nand", + .id = 0, + .num_resources = ARRAY_SIZE(bf5xx_nand_resources), + .resource = bf5xx_nand_resources, + .dev = { + .platform_data = &bf5xx_nand_platform, + }, +}; +#endif + #if defined(CONFIG_BFIN_CFPCMCIA) || defined(CONFIG_BFIN_CFPCMCIA_MODULE) static struct resource bfin_pcmcia_cf_resources[] = { { @@ -650,6 +699,10 @@ static struct platform_device bfin_pata_device = { #endif static struct platform_device *stamp_devices[] __initdata = { +#if defined(CONFIG_MTD_NAND_BF5XX) || defined(CONFIG_MTD_NAND_BF5XX_MODULE) + &bf5xx_nand_device, +#endif + #if defined(CONFIG_BFIN_CFPCMCIA) || defined(CONFIG_BFIN_CFPCMCIA_MODULE) &bfin_pcmcia_cf_device, #endif diff --git a/arch/blackfin/mach-bf533/boards/H8606.c b/arch/blackfin/mach-bf533/boards/H8606.c new file mode 100644 index 00000000000..b941550f956 --- /dev/null +++ b/arch/blackfin/mach-bf533/boards/H8606.c @@ -0,0 +1,345 @@ +/* + * File: arch/blackfin/mach-bf533/H8606.c + * Based on: arch/blackfin/mach-bf533/stamp.c + * Author: Javier Herrero <jherrero@hvsistemas.es> + * + * Created: 2007 + * Description: Board Info File for the HV Sistemas H8606 board + * + * Modified: + * Copyright 2005 National ICT Australia (NICTA) + * Copyright 2004-2006 Analog Devices Inc + * Copyright 2007 HV Sistemas S.L. + * + * Bugs: Enter bugs at http://blackfin.uclinux.org/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see the file COPYING, or write + * to the Free Software Foundation, Inc., + * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include <linux/device.h> +#include <linux/platform_device.h> +#include <linux/mtd/mtd.h> +#include <linux/mtd/partitions.h> +#include <linux/spi/spi.h> +#include <linux/spi/flash.h> +#if defined(CONFIG_USB_ISP1362_HCD) || defined(CONFIG_USB_ISP1362_HCD_MODULE) +#include <linux/usb_isp1362.h> +#endif +#include <linux/pata_platform.h> +#include <linux/irq.h> +#include <asm/dma.h> +#include <asm/bfin5xx_spi.h> +#include <asm/reboot.h> + +/* + * Name the Board for the /proc/cpuinfo + */ +const char bfin_board_name[] = "HV Sistemas H8606"; + +#if defined(CONFIG_RTC_DRV_BFIN) || defined(CONFIG_RTC_BFIN_MODULE) +static struct platform_device rtc_device = { + .name = "rtc-bfin", + .id = -1, +}; +#endif + +/* +* Driver needs to know address, irq and flag pin. + */ + #if defined(CONFIG_DM9000) || defined(CONFIG_DM9000_MODULE) +static struct resource dm9000_resources[] = { + [0] = { + .start = 0x20300000, + .end = 0x20300000 + 8, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = IRQ_PF10, + .end = IRQ_PF10, + .flags = (IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE), + }, +}; + +static struct platform_device dm9000_device = { + .id = 0, + .name = "dm9000", + .resource = dm9000_resources, + .num_resources = ARRAY_SIZE(dm9000_resources), +}; +#endif + +#if defined(CONFIG_SMC91X) || defined(CONFIG_SMC91X_MODULE) +static struct resource smc91x_resources[] = { + { + .name = "smc91x-regs", + .start = 0x20300300, + .end = 0x20300300 + 16, + .flags = IORESOURCE_MEM, + }, { + .start = IRQ_PROG_INTB, + .end = IRQ_PROG_INTB, + .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL, + }, { + /* + * denotes the flag pin and is used directly if + * CONFIG_IRQCHIP_DEMUX_GPIO is defined. + */ + .start = IRQ_PF7, + .end = IRQ_PF7, + .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL, + }, +}; + +static struct platform_device smc91x_device = { + .name = "smc91x", + .id = 0, + .num_resources = ARRAY_SIZE(smc91x_resources), + .resource = smc91x_resources, +}; +#endif + +#if defined(CONFIG_USB_NET2272) || defined(CONFIG_USB_NET2272_MODULE) +static struct resource net2272_bfin_resources[] = { + { + .start = 0x20300000, + .end = 0x20300000 + 0x100, + .flags = IORESOURCE_MEM, + }, { + .start = IRQ_PF10, + .end = IRQ_PF10, + .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL, + }, +}; + +static struct platform_device net2272_bfin_device = { + .name = "net2272", + .id = -1, + .num_resources = ARRAY_SIZE(net2272_bfin_resources), + .resource = net2272_bfin_resources, +}; +#endif + +#if defined(CONFIG_SPI_BFIN) || defined(CONFIG_SPI_BFIN_MODULE) +/* all SPI peripherals info goes here */ + +#if defined(CONFIG_MTD_M25P80) || defined(CONFIG_MTD_M25P80_MODULE) +static struct mtd_partition bfin_spi_flash_partitions[] = { + { + .name = "bootloader", + .size = 0x00060000, + .offset = 0, + .mask_flags = MTD_CAP_ROM + }, { + .name = "kernel", + .size = 0x100000, + .offset = 0x60000 + }, { + .name = "file system", + .size = 0x6a0000, + .offset = 0x00160000, + } +}; + +static struct flash_platform_data bfin_spi_flash_data = { + .name = "m25p80", + .parts = bfin_spi_flash_partitions, + .nr_parts = ARRAY_SIZE(bfin_spi_flash_partitions), + .type = "m25p64", +}; + +/* SPI flash chip (m25p64) */ +static struct bfin5xx_spi_chip spi_flash_chip_info = { + .enable_dma = 0, /* use dma transfer with this chip*/ + .bits_per_word = 8, +}; +#endif + +#if defined(CONFIG_SPI_ADC_BF533) || defined(CONFIG_SPI_ADC_BF533_MODULE) +/* SPI ADC chip */ +static struct bfin5xx_spi_chip spi_adc_chip_info = { + .ctl_reg = 0x1000, + .enable_dma = 1, /* use dma transfer with this chip*/ + .bits_per_word = 16, +}; +#endif + +#if defined(CONFIG_SND_BLACKFIN_AD1836) || defined(CONFIG_SND_BLACKFIN_AD1836_MODULE) +static struct bfin5xx_spi_chip ad1836_spi_chip_info = { + .ctl_reg = 0x1000, + .enable_dma = 0, + .bits_per_word = 16, +}; +#endif + +#if defined(CONFIG_PBX) +static struct bfin5xx_spi_chip spi_si3xxx_chip_info = { + .ctl_reg = 0x1c04, + .enable_dma = 0, + .bits_per_word = 8, + .cs_change_per_word = 1, +}; +#endif + +/* Notice: for blackfin, the speed_hz is the value of register + * SPI_BAUD, not the real baudrate */ +static struct spi_board_info bfin_spi_board_info[] __initdata = { +#if defined(CONFIG_MTD_M25P80) || defined(CONFIG_MTD_M25P80_MODULE) + { + /* the modalias must be the same as spi device driver name */ + .modalias = "m25p80", /* Name of spi_driver for this device */ + /* this value is the baudrate divisor */ + .max_speed_hz = 50000000, /* actual baudrate is SCLK/(2xspeed_hz) */ + .bus_num = 0, /* Framework bus number */ + .chip_select = 2, /* Framework chip select. On STAMP537 it is SPISSEL2*/ + .platform_data = &bfin_spi_flash_data, + .controller_data = &spi_flash_chip_info, + .mode = SPI_MODE_3, + }, +#endif + +#if defined(CONFIG_SPI_ADC_BF533) || defined(CONFIG_SPI_ADC_BF533_MODULE) + { + .modalias = "bfin_spi_adc", /* Name of spi_driver for this device */ + .max_speed_hz = 4, /* actual baudrate is SCLK/(2xspeed_hz) */ + .bus_num = 1, /* Framework bus number */ + .chip_select = 1, /* Framework chip select. */ + .platform_data = NULL, /* No spi_driver specific config */ + .controller_data = &spi_adc_chip_info, + }, +#endif + +#if defined(CONFIG_SND_BLACKFIN_AD1836) || defined(CONFIG_SND_BLACKFIN_AD1836_MODULE) + { + .modalias = "ad1836-spi", + .max_speed_hz = 16, + .bus_num = 1, + .chip_select = CONFIG_SND_BLACKFIN_SPI_PFBIT, + .controller_data = &ad1836_spi_chip_info, + }, +#endif + +#if defined(CONFIG_PBX) + { + .modalias = "fxs-spi", + .max_speed_hz = 4, + .bus_num = 1, + .chip_select = 3, + .controller_data = &spi_si3xxx_chip_info, + }, + + { + .modalias = "fxo-spi", + .max_speed_hz = 4, + .bus_num = 1, + .chip_select = 2, + .controller_data = &spi_si3xxx_chip_info, + }, +#endif +}; + +/* SPI (0) */ +static struct resource bfin_spi0_resource[] = { + [0] = { + .start = SPI0_REGBASE, + .end = SPI0_REGBASE + 0xFF, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = CH_SPI, + .end = CH_SPI, + .flags = IORESOURCE_IRQ, + } +}; + + +/* SPI controller data */ +static struct bfin5xx_spi_master bfin_spi0_info = { + .num_chipselect = 8, + .enable_dma = 1, /* master has the ability to do dma transfer */ +}; + +static struct platform_device bfin_spi0_device = { + .name = "bfin-spi", + .id = 0, /* Bus number */ + .num_resources = ARRAY_SIZE(bfin_spi0_resource), + .resource = bfin_spi0_resource, + .dev = { + .platform_data = &bfin_spi0_info, /* Passed to driver */ + }, +}; +#endif /* spi master and devices */ + +#if defined(CONFIG_FB_BF537_LQ035) || defined(CONFIG_FB_BF537_LQ035_MODULE) +static struct platform_device bfin_fb_device = { + .name = "bf537-fb", +}; +#endif + +#if defined(CONFIG_SERIAL_BFIN) || defined(CONFIG_SERIAL_BFIN_MODULE) +static struct resource bfin_uart_resources[] = { + { + .start = 0xFFC00400, + .end = 0xFFC004FF, + .flags = IORESOURCE_MEM, + }, +}; + +static struct platform_device bfin_uart_device = { + .name = "bfin-uart", + .id = 1, + .num_resources = ARRAY_SIZE(bfin_uart_resources), + .resource = bfin_uart_resources, +}; +#endif + +static struct platform_device *stamp_devices[] __initdata = { +#if defined(CONFIG_RTC_DRV_BFIN) || defined(CONFIG_RTC_DRV_BFIN_MODULE) + &rtc_device, +#endif + +#if defined(CONFIG_DM9000) || defined(CONFIG_DM9000_MODULE) + &dm9000_device, +#endif + +#if defined(CONFIG_SMC91X) || defined(CONFIG_SMC91X_MODULE) + &smc91x_device, +#endif + +#if defined(CONFIG_USB_NET2272) || defined(CONFIG_USB_NET2272_MODULE) + &net2272_bfin_device, +#endif + +#if defined(CONFIG_SPI_BFIN) || defined(CONFIG_SPI_BFIN_MODULE) + &bfin_spi0_device, +#endif + +#if defined(CONFIG_SERIAL_BFIN) || defined(CONFIG_SERIAL_BFIN_MODULE) + &bfin_uart_device, +#endif +}; + +static int __init H8606_init(void) +{ + printk(KERN_INFO "HV Sistemas H8606 board support by http://www.hvsistemas.com\n"); + printk(KERN_INFO "%s(): registering device resources\n", __FUNCTION__); + platform_add_devices(stamp_devices, ARRAY_SIZE(stamp_devices)); +#if defined(CONFIG_SPI_BFIN) || defined(CONFIG_SPI_BFIN_MODULE) + spi_register_board_info(bfin_spi_board_info, ARRAY_SIZE(bfin_spi_board_info)); +#endif + return 0; +} + +arch_initcall(H8606_init);
\ No newline at end of file diff --git a/arch/blackfin/mach-bf533/boards/Makefile b/arch/blackfin/mach-bf533/boards/Makefile index 12a631ab389..2452b456ccb 100644 --- a/arch/blackfin/mach-bf533/boards/Makefile +++ b/arch/blackfin/mach-bf533/boards/Makefile @@ -6,3 +6,4 @@ obj-$(CONFIG_GENERIC_BOARD) += generic_board.o obj-$(CONFIG_BFIN533_STAMP) += stamp.o obj-$(CONFIG_BFIN533_EZKIT) += ezkit.o obj-$(CONFIG_BFIN533_BLUETECHNIX_CM) += cm_bf533.o +obj-$(CONFIG_H8606_HVSISTEMAS) += H8606.o diff --git a/arch/blackfin/mach-bf533/boards/cm_bf533.c b/arch/blackfin/mach-bf533/boards/cm_bf533.c index 1c5a86adfab..a863522a446 100644 --- a/arch/blackfin/mach-bf533/boards/cm_bf533.c +++ b/arch/blackfin/mach-bf533/boards/cm_bf533.c @@ -46,7 +46,7 @@ const char bfin_board_name[] = "Bluetechnix CM BF533"; #if defined(CONFIG_SPI_BFIN) || defined(CONFIG_SPI_BFIN_MODULE) /* all SPI peripherals info goes here */ - +#if defined(CONFIG_MTD_M25P80) || defined(CONFIG_MTD_M25P80_MODULE) static struct mtd_partition bfin_spi_flash_partitions[] = { { .name = "bootloader", @@ -76,12 +76,15 @@ static struct bfin5xx_spi_chip spi_flash_chip_info = { .enable_dma = 0, /* use dma transfer with this chip*/ .bits_per_word = 8, }; +#endif /* SPI ADC chip */ +#if defined(CONFIG_SPI_ADC_BF533) || defined(CONFIG_SPI_ADC_BF533_MODULE) static struct bfin5xx_spi_chip spi_adc_chip_info = { .enable_dma = 1, /* use dma transfer with this chip*/ .bits_per_word = 16, }; +#endif #if defined(CONFIG_SND_BLACKFIN_AD1836) || defined(CONFIG_SND_BLACKFIN_AD1836_MODULE) static struct bfin5xx_spi_chip ad1836_spi_chip_info = { @@ -90,7 +93,15 @@ static struct bfin5xx_spi_chip ad1836_spi_chip_info = { }; #endif +#if defined(CONFIG_SPI_MMC) || defined(CONFIG_SPI_MMC_MODULE) +static struct bfin5xx_spi_chip spi_mmc_chip_info = { + .enable_dma = 1, + .bits_per_word = 8, +}; +#endif + static struct spi_board_info bfin_spi_board_info[] __initdata = { +#if defined(CONFIG_MTD_M25P80) || defined(CONFIG_MTD_M25P80_MODULE) { /* the modalias must be the same as spi device driver name */ .modalias = "m25p80", /* Name of spi_driver for this device */ @@ -100,7 +111,11 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = { .platform_data = &bfin_spi_flash_data, .controller_data = &spi_flash_chip_info, .mode = SPI_MODE_3, - }, { + }, +#endif + +#if defined(CONFIG_SPI_ADC_BF533) || defined(CONFIG_SPI_ADC_BF533_MODULE) + { .modalias = "bfin_spi_adc", /* Name of spi_driver for this device */ .max_speed_hz = 6250000, /* max spi clock (SCK) speed in HZ */ .bus_num = 0, /* Framework bus number */ @@ -108,6 +123,8 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = { .platform_data = NULL, /* No spi_driver specific config */ .controller_data = &spi_adc_chip_info, }, +#endif + #if defined(CONFIG_SND_BLACKFIN_AD1836) || defined(CONFIG_SND_BLACKFIN_AD1836_MODULE) { .modalias = "ad1836-spi", @@ -117,6 +134,27 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = { .controller_data = &ad1836_spi_chip_info, }, #endif + +#if defined(CONFIG_SPI_MMC) || defined(CONFIG_SPI_MMC_MODULE) + { + .modalias = "spi_mmc_dummy", + .max_speed_hz = 25000000, /* max spi clock (SCK) speed in HZ */ + .bus_num = 0, + .chip_select = 0, + .platform_data = NULL, + .controller_data = &spi_mmc_chip_info, + .mode = SPI_MODE_3, + }, + { + .modalias = "spi_mmc", + .max_speed_hz = 25000000, /* max spi clock (SCK) speed in HZ */ + .bus_num = 0, + .chip_select = CONFIG_SPI_MMC_CS_CHAN, + .platform_data = NULL, + .controller_data = &spi_mmc_chip_info, + .mode = SPI_MODE_3, + }, +#endif }; /* SPI (0) */ diff --git a/arch/blackfin/mach-bf533/boards/stamp.c b/arch/blackfin/mach-bf533/boards/stamp.c index f84be4eabfd..62ffa500420 100644 --- a/arch/blackfin/mach-bf533/boards/stamp.c +++ b/arch/blackfin/mach-bf533/boards/stamp.c @@ -218,7 +218,7 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = { #if defined(CONFIG_SPI_MMC) || defined(CONFIG_SPI_MMC_MODULE) { .modalias = "spi_mmc_dummy", - .max_speed_hz = 25000000, /* max spi clock (SCK) speed in HZ */ + .max_speed_hz = 20000000, /* max spi clock (SCK) speed in HZ */ .bus_num = 0, .chip_select = 0, .platform_data = NULL, @@ -227,7 +227,7 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = { }, { .modalias = "spi_mmc", - .max_speed_hz = 25000000, /* max spi clock (SCK) speed in HZ */ + .max_speed_hz = 20000000, /* max spi clock (SCK) speed in HZ */ .bus_num = 0, .chip_select = CONFIG_SPI_MMC_CS_CHAN, .platform_data = NULL, diff --git a/arch/blackfin/mach-bf537/boards/cm_bf537.c b/arch/blackfin/mach-bf537/boards/cm_bf537.c index 52e2320307d..2915931045e 100644 --- a/arch/blackfin/mach-bf537/boards/cm_bf537.c +++ b/arch/blackfin/mach-bf537/boards/cm_bf537.c @@ -281,8 +281,8 @@ static struct resource net2272_bfin_resources[] = { .end = 0x20200000 + 0x100, .flags = IORESOURCE_MEM, }, { - .start = IRQ_PF7, - .end = IRQ_PF7, + .start = IRQ_PH14, + .end = IRQ_PH14, .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL, }, }; diff --git a/arch/blackfin/mach-bf537/boards/stamp.c b/arch/blackfin/mach-bf537/boards/stamp.c index cc41f6c2ef4..5f7b91fbafe 100644 --- a/arch/blackfin/mach-bf537/boards/stamp.c +++ b/arch/blackfin/mach-bf537/boards/stamp.c @@ -450,7 +450,7 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = { #if defined(CONFIG_SPI_MMC) || defined(CONFIG_SPI_MMC_MODULE) { .modalias = "spi_mmc_dummy", - .max_speed_hz = 25000000, /* max spi clock (SCK) speed in HZ */ + .max_speed_hz = 20000000, /* max spi clock (SCK) speed in HZ */ .bus_num = 0, .chip_select = 0, .platform_data = NULL, @@ -459,7 +459,7 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = { }, { .modalias = "spi_mmc", - .max_speed_hz = 25000000, /* max spi clock (SCK) speed in HZ */ + .max_speed_hz = 20000000, /* max spi clock (SCK) speed in HZ */ .bus_num = 0, .chip_select = CONFIG_SPI_MMC_CS_CHAN, .platform_data = NULL, @@ -612,7 +612,7 @@ static struct platform_device bfin_sport1_uart_device = { static struct pata_platform_info bfin_pata_platform_data = { .ioport_shift = 1, - .irq_type = IRQF_TRIGGER_HIGH | IRQF_DISABLED, + .irq_flags = IRQF_TRIGGER_HIGH | IRQF_DISABLED, }; static struct resource bfin_pata_resources[] = { diff --git a/arch/blackfin/mach-common/entry.S b/arch/blackfin/mach-common/entry.S index e3ad5802868..1b13fa47097 100644 --- a/arch/blackfin/mach-common/entry.S +++ b/arch/blackfin/mach-common/entry.S @@ -917,7 +917,7 @@ ENTRY(_ex_table) .long _ex_soft_bp /* 0x01 - User Defined - Software breakpoint */ .long _ex_replaceable /* 0x02 - User Defined */ .long _ex_trap_c /* 0x03 - User Defined - userspace stack overflow */ - .long _ex_replaceable /* 0x04 - User Defined */ + .long _ex_trap_c /* 0x04 - User Defined - dump trace buffer */ .long _ex_replaceable /* 0x05 - User Defined */ .long _ex_replaceable /* 0x06 - User Defined */ .long _ex_replaceable /* 0x07 - User Defined */ diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 61262c5f9c6..97da953eb5d 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -583,6 +583,7 @@ config SNI_RM config TOSHIBA_JMR3927 bool "Toshiba JMR-TX3927 board" + select CEVT_TXX9 select DMA_NONCOHERENT select HW_HAS_PCI select MIPS_TX3927 @@ -597,6 +598,7 @@ config TOSHIBA_JMR3927 config TOSHIBA_RBTX4927 bool "Toshiba RBTX49[23]7 board" select CEVT_R4K + select CEVT_TXX9 select DMA_NONCOHERENT select HAS_TXX9_SERIAL select HW_HAS_PCI @@ -618,6 +620,7 @@ config TOSHIBA_RBTX4927 config TOSHIBA_RBTX4938 bool "Toshiba RBTX4938 board" select CEVT_R4K + select CEVT_TXX9 select DMA_NONCOHERENT select HAS_TXX9_SERIAL select HW_HAS_PCI @@ -736,6 +739,9 @@ config CEVT_GT641XX config CEVT_R4K bool +config CEVT_TXX9 + bool + config CFE bool diff --git a/arch/mips/au1000/common/irq.c b/arch/mips/au1000/common/irq.c index 59e932a928d..ddfb7f0a17a 100644 --- a/arch/mips/au1000/common/irq.c +++ b/arch/mips/au1000/common/irq.c @@ -318,38 +318,6 @@ static struct irq_chip level_irq_type = { .end = end_irq, }; -#ifdef CONFIG_PM -void startup_match20_interrupt(irq_handler_t handler) -{ - struct irq_desc *desc = &irq_desc[AU1000_TOY_MATCH2_INT]; - - static struct irqaction action; - memset(&action, 0, sizeof(struct irqaction)); - - /* - * This is a big problem.... since we didn't use request_irq - * when kernel/irq.c calls probe_irq_xxx this interrupt will - * be probed for usage. This will end up disabling the device :( - * Give it a bogus "action" pointer -- this will keep it from - * getting auto-probed! - * - * By setting the status to match that of request_irq() we - * can avoid it. --cgray - */ - action.dev_id = handler; - action.flags = IRQF_DISABLED; - cpus_clear(action.mask); - action.name = "Au1xxx TOY"; - action.handler = handler; - action.next = NULL; - - desc->action = &action; - desc->status &= ~(IRQ_DISABLED | IRQ_AUTODETECT | IRQ_WAITING | IRQ_INPROGRESS); - - local_enable_irq(AU1000_TOY_MATCH2_INT); -} -#endif - static void __init setup_local_irq(unsigned int irq_nr, int type, int int_req) { unsigned int bit = irq_nr - AU1000_INTC0_INT_BASE; diff --git a/arch/mips/au1000/common/time.c b/arch/mips/au1000/common/time.c index 2556399708b..f113b512d7b 100644 --- a/arch/mips/au1000/common/time.c +++ b/arch/mips/au1000/common/time.c @@ -67,7 +67,7 @@ static DEFINE_SPINLOCK(time_lock); unsigned long wtimer; #ifdef CONFIG_PM -irqreturn_t counter0_irq(int irq, void *dev_id) +static irqreturn_t counter0_irq(int irq, void *dev_id) { unsigned long pc0; int time_elapsed; @@ -117,6 +117,13 @@ irqreturn_t counter0_irq(int irq, void *dev_id) return IRQ_HANDLED; } +struct irqaction counter0_action = { + .handler = counter0_irq, + .flags = IRQF_DISABLED, + .name = "alchemy-toy", + .dev_id = NULL, +}; + /* When we wakeup from sleep, we have to "catch up" on all of the * timer ticks we have missed. */ @@ -221,7 +228,7 @@ unsigned long cal_r4koff(void) return (cpu_speed / HZ); } -void __init plat_timer_setup(struct irqaction *irq) +void __init plat_time_init(void) { unsigned int est_freq; @@ -255,15 +262,10 @@ void __init plat_timer_setup(struct irqaction *irq) * we do this. */ if (no_au1xxx_32khz) { - unsigned int c0_status; - printk("WARNING: no 32KHz clock found.\n"); - /* Ensure we get CPO_COUNTER interrupts. - */ - c0_status = read_c0_status(); - c0_status |= IE_IRQ5; - write_c0_status(c0_status); + /* Ensure we get CPO_COUNTER interrupts. */ + set_c0_status(IE_IRQ5); } else { while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_C0S); @@ -280,7 +282,7 @@ void __init plat_timer_setup(struct irqaction *irq) au_writel(last_match20 + MATCH20_INC, SYS_TOYMATCH2); au_sync(); while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_M20); - startup_match20_interrupt(counter0_irq); + setup_irq(AU1000_TOY_MATCH2_INT, &counter0_action); /* We can use the real 'wait' instruction. */ diff --git a/arch/mips/au1000/mtx-1/Makefile b/arch/mips/au1000/mtx-1/Makefile index 764bf9f7e28..afa7007d67f 100644 --- a/arch/mips/au1000/mtx-1/Makefile +++ b/arch/mips/au1000/mtx-1/Makefile @@ -8,3 +8,4 @@ # lib-y := init.o board_setup.o irqmap.o +obj-y := platform.o diff --git a/arch/mips/au1000/mtx-1/platform.c b/arch/mips/au1000/mtx-1/platform.c new file mode 100644 index 00000000000..01ebff67797 --- /dev/null +++ b/arch/mips/au1000/mtx-1/platform.c @@ -0,0 +1,86 @@ +/* + * MTX-1 platform devices registration + * + * Copyright (C) 2007, Florian Fainelli <florian@openwrt.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include <linux/init.h> +#include <linux/types.h> +#include <linux/platform_device.h> +#include <linux/leds.h> + +#include <asm/gpio.h> + +static struct resource mtx1_wdt_res[] = { + [0] = { + .start = 15, + .end = 15, + .name = "mtx1-wdt-gpio", + .flags = IORESOURCE_IRQ, + } +}; + +static struct resource mtx1_sys_btn[] = { + [0] = { + .start = 7, + .end = 7, + .name = "mtx1-sys-btn-gpio", + .flags = IORESOURCE_IRQ, + } +}; + +static struct platform_device mtx1_wdt = { + .name = "mtx1-wdt", + .id = 0, + .num_resources = ARRAY_SIZE(mtx1_wdt_res), + .resource = mtx1_wdt_res, +}; + +static struct gpio_led default_leds[] = { + { + .name = "mtx1:green", + .gpio = 211, + }, { + .name = "mtx1:red", + .gpio = 212, + }, +}; + +static struct gpio_led_platform_data mtx1_led_data = { + .num_leds = ARRAY_SIZE(default_leds), + .leds = default_leds, +}; + +static struct platform_device mtx1_gpio_leds = { + .name = "leds-gpio", + .id = -1, + .dev = { + .platform_data = &mtx1_led_data, + } +}; + +static struct __initdata platform_device * mtx1_devs[] = { + &mtx1_gpio_leds, + &mtx1_wdt +}; + +static int __init mtx1_register_devices(void) +{ + return platform_add_devices(mtx1_devs, ARRAY_SIZE(mtx1_devs)); +} + +arch_initcall(mtx1_register_devices); diff --git a/arch/mips/basler/excite/excite_setup.c b/arch/mips/basler/excite/excite_setup.c index 404ca9284b3..24378b9223f 100644 --- a/arch/mips/basler/excite/excite_setup.c +++ b/arch/mips/basler/excite/excite_setup.c @@ -68,24 +68,23 @@ DEFINE_SPINLOCK(titan_lock); int titan_irqflags; +/* + * The eXcite platform uses the alternate timer interrupt + * + * Fixme: At the time of this writing cevt-r4k.c doesn't yet know about how + * to handle the alternate timer interrupt of the RM9000. + */ void __init plat_time_init(void) { const u32 modebit5 = ocd_readl(0x00e4); - unsigned int - mult = ((modebit5 >> 11) & 0x1f) + 2, - div = ((modebit5 >> 16) & 0x1f) + 2; + unsigned int mult = ((modebit5 >> 11) & 0x1f) + 2, + unsigned int div = ((modebit5 >> 16) & 0x1f) + 2; - if (div == 33) div = 1; + if (div == 33) + div = 1; mips_hpt_frequency = EXCITE_CPU_EXT_CLOCK * mult / div / 2; } -void __init plat_timer_setup(struct irqaction *irq) -{ - /* The eXcite platform uses the alternate timer interrupt */ - set_c0_intcontrol(0x80); - setup_irq(TIMER_IRQ, irq); -} - static int __init excite_init_console(void) { #if defined(CONFIG_SERIAL_8250) diff --git a/arch/mips/configs/db1000_defconfig b/arch/mips/configs/db1000_defconfig index 885b633647e..5a8b7acb7dd 100644 --- a/arch/mips/configs/db1000_defconfig +++ b/arch/mips/configs/db1000_defconfig @@ -738,7 +738,6 @@ CONFIG_HW_CONSOLE=y CONFIG_VT_HW_CONSOLE_BINDING=y # CONFIG_SERIAL_NONSTANDARD is not set # CONFIG_AU1X00_GPIO is not set -# CONFIG_TS_AU1X00_ADS7846 is not set # # Serial drivers diff --git a/arch/mips/configs/db1100_defconfig b/arch/mips/configs/db1100_defconfig index e3c3a07e8a7..d4ed90bca26 100644 --- a/arch/mips/configs/db1100_defconfig +++ b/arch/mips/configs/db1100_defconfig @@ -714,7 +714,6 @@ CONFIG_HW_CONSOLE=y CONFIG_VT_HW_CONSOLE_BINDING=y # CONFIG_SERIAL_NONSTANDARD is not set # CONFIG_AU1X00_GPIO is not set -# CONFIG_TS_AU1X00_ADS7846 is not set # # Serial drivers diff --git a/arch/mips/configs/db1200_defconfig b/arch/mips/configs/db1200_defconfig index 9aa7c3ebfa3..a055657e698 100644 --- a/arch/mips/configs/db1200_defconfig +++ b/arch/mips/configs/db1200_defconfig @@ -775,7 +775,6 @@ CONFIG_HW_CONSOLE=y CONFIG_VT_HW_CONSOLE_BINDING=y # CONFIG_SERIAL_NONSTANDARD is not set # CONFIG_AU1X00_GPIO is not set -# CONFIG_TS_AU1X00_ADS7846 is not set # # Serial drivers diff --git a/arch/mips/configs/db1500_defconfig b/arch/mips/configs/db1500_defconfig index 99240668bca..0ad08cf446e 100644 --- a/arch/mips/configs/db1500_defconfig +++ b/arch/mips/configs/db1500_defconfig @@ -811,7 +811,6 @@ CONFIG_SERIO_RAW=m # CONFIG_VT is not set # CONFIG_SERIAL_NONSTANDARD is not set # CONFIG_AU1X00_GPIO is not set -# CONFIG_TS_AU1X00_ADS7846 is not set # # Serial drivers diff --git a/arch/mips/configs/db1550_defconfig b/arch/mips/configs/db1550_defconfig index 19992f76c60..057c7d429c8 100644 --- a/arch/mips/configs/db1550_defconfig +++ b/arch/mips/configs/db1550_defconfig @@ -856,7 +856,6 @@ CONFIG_SERIO_RAW=m # CONFIG_VT is not set # CONFIG_SERIAL_NONSTANDARD is not set # CONFIG_AU1X00_GPIO is not set -# CONFIG_TS_AU1X00_ADS7846 is not set # # Serial drivers diff --git a/arch/mips/configs/pb1100_defconfig b/arch/mips/configs/pb1100_defconfig index d53fa8f8e09..703d28db05b 100644 --- a/arch/mips/configs/pb1100_defconfig +++ b/arch/mips/configs/pb1100_defconfig @@ -731,7 +731,6 @@ CONFIG_HW_CONSOLE=y CONFIG_VT_HW_CONSOLE_BINDING=y # CONFIG_SERIAL_NONSTANDARD is not set # CONFIG_AU1X00_GPIO is not set -# CONFIG_TS_AU1X00_ADS7846 is not set # # Serial drivers diff --git a/arch/mips/configs/pb1500_defconfig b/arch/mips/configs/pb1500_defconfig index dc4aa0c6684..82f0c5cee0d 100644 --- a/arch/mips/configs/pb1500_defconfig +++ b/arch/mips/configs/pb1500_defconfig @@ -849,7 +849,6 @@ CONFIG_SERIO_RAW=m # CONFIG_VT is not set # CONFIG_SERIAL_NONSTANDARD is not set # CONFIG_AU1X00_GPIO is not set -# CONFIG_TS_AU1X00_ADS7846 is not set # # Serial drivers diff --git a/arch/mips/configs/pb1550_defconfig b/arch/mips/configs/pb1550_defconfig index 24428e13002..147a4fc7fdd 100644 --- a/arch/mips/configs/pb1550_defconfig +++ b/arch/mips/configs/pb1550_defconfig @@ -842,7 +842,6 @@ CONFIG_SERIO_RAW=m # CONFIG_VT is not set # CONFIG_SERIAL_NONSTANDARD is not set # CONFIG_AU1X00_GPIO is not set -# CONFIG_TS_AU1X00_ADS7846 is not set # # Serial drivers diff --git a/arch/mips/configs/sb1250-swarm_defconfig b/arch/mips/configs/sb1250-swarm_defconfig index 49dfcef2518..c2798229cbf 100644 --- a/arch/mips/configs/sb1250-swarm_defconfig +++ b/arch/mips/configs/sb1250-swarm_defconfig @@ -468,7 +468,7 @@ CONFIG_BLK_DEV_IDEFLOPPY=y # CONFIG_IDE_GENERIC=y # CONFIG_BLK_DEV_IDEPCI is not set -# CONFIG_BLK_DEV_IDE_SWARM is not set +CONFIG_BLK_DEV_IDE_SWARM=y # CONFIG_IDE_ARM is not set # CONFIG_BLK_DEV_IDEDMA is not set # CONFIG_IDEDMA_AUTO is not set diff --git a/arch/mips/gt64120/wrppmc/time.c b/arch/mips/gt64120/wrppmc/time.c index b207e7f1417..668dbd5f12c 100644 --- a/arch/mips/gt64120/wrppmc/time.c +++ b/arch/mips/gt64120/wrppmc/time.c @@ -19,12 +19,6 @@ #define WRPPMC_CPU_CLK_FREQ 40000000 /* 40MHZ */ -void __init plat_timer_setup(struct irqaction *irq) -{ - /* Install ISR for timer interrupt */ - setup_irq(WRPPMC_MIPS_TIMER_IRQ, irq); -} - /* * Estimate CPU frequency. Sets mips_hpt_frequency as a side-effect * diff --git a/arch/mips/jmr3927/rbhma3100/setup.c b/arch/mips/jmr3927/rbhma3100/setup.c index edb9e59248e..06e01c8f4e3 100644 --- a/arch/mips/jmr3927/rbhma3100/setup.c +++ b/arch/mips/jmr3927/rbhma3100/setup.c @@ -27,17 +27,13 @@ * Copyright (C) 2007 Ralf Baechle (ralf@linux-mips.org) */ -#include <linux/clockchips.h> #include <linux/init.h> #include <linux/kernel.h> #include <linux/kdev_t.h> #include <linux/types.h> -#include <linux/sched.h> #include <linux/pci.h> #include <linux/ide.h> -#include <linux/irq.h> #include <linux/ioport.h> -#include <linux/param.h> /* for HZ */ #include <linux/delay.h> #include <linux/pm.h> #include <linux/platform_device.h> @@ -48,17 +44,13 @@ #endif #include <asm/addrspace.h> -#include <asm/time.h> +#include <asm/txx9tmr.h> #include <asm/reboot.h> #include <asm/jmr3927/jmr3927.h> #include <asm/mipsregs.h> extern void puts(const char *cp); -/* Tick Timer divider */ -#define JMR3927_TIMER_CCD 0 /* 1/2 */ -#define JMR3927_TIMER_CLK (JMR3927_IMCLK / (2 << JMR3927_TIMER_CCD)) - /* don't enable - see errata */ static int jmr3927_ccfg_toeon; @@ -93,66 +85,12 @@ static void jmr3927_machine_power_off(void) while (1); } -static cycle_t jmr3927_hpt_read(void) -{ - /* We assume this function is called xtime_lock held. */ - return jiffies * (JMR3927_TIMER_CLK / HZ) + jmr3927_tmrptr->trr; -} - -static void jmr3927_set_mode(enum clock_event_mode mode, - struct clock_event_device *evt) -{ - /* Nothing to do here */ -} - -struct clock_event_device jmr3927_clock_event_device = { - .name = "MIPS", - .features = CLOCK_EVT_FEAT_PERIODIC, - .shift = 32, - .rating = 300, - .cpumask = CPU_MASK_CPU0, - .irq = JMR3927_IRQ_TICK, - .set_mode = jmr3927_set_mode, -}; - -static irqreturn_t jmr3927_timer_interrupt(int irq, void *dev_id) -{ - struct clock_event_device *cd = &jmr3927_clock_event_device; - - jmr3927_tmrptr->tisr = 0; /* ack interrupt */ - - cd->event_handler(cd); - - return IRQ_HANDLED; -} - -static struct irqaction jmr3927_timer_irqaction = { - .handler = jmr3927_timer_interrupt, - .flags = IRQF_DISABLED | IRQF_PERCPU, - .name = "jmr3927-timer", -}; - void __init plat_time_init(void) { - struct clock_event_device *cd; - - clocksource_mips.read = jmr3927_hpt_read; - mips_hpt_frequency = JMR3927_TIMER_CLK; - - jmr3927_tmrptr->cpra = JMR3927_TIMER_CLK / HZ; - jmr3927_tmrptr->itmr = TXx927_TMTITMR_TIIE | TXx927_TMTITMR_TZCE; - jmr3927_tmrptr->ccdr = JMR3927_TIMER_CCD; - jmr3927_tmrptr->tcr = - TXx927_TMTCR_TCE | TXx927_TMTCR_CCDE | TXx927_TMTCR_TMODE_ITVL; - - cd = &jmr3927_clock_event_device; - /* Calculate the min / max delta */ - cd->mult = div_sc((unsigned long) JMR3927_IMCLK, NSEC_PER_SEC, 32); - cd->max_delta_ns = clockevent_delta2ns(0x7fffffff, cd); - cd->min_delta_ns = clockevent_delta2ns(0x300, cd); - clockevents_register_device(cd); - - setup_irq(JMR3927_IRQ_TICK, &jmr3927_timer_irqaction); + txx9_clockevent_init(TX3927_TMR_REG(0), + TXX9_IRQ_BASE + JMR3927_IRQ_IRC_TMR(0), + JMR3927_IMCLK); + txx9_clocksource_init(TX3927_TMR_REG(1), JMR3927_IMCLK); } #define DO_WRITE_THROUGH @@ -317,15 +255,8 @@ static void __init tx3927_setup(void) tx3927_ccfgptr->ccfg, tx3927_ccfgptr->pcfg); /* TMR */ - /* disable all timers */ - for (i = 0; i < TX3927_NR_TMR; i++) { - tx3927_tmrptr(i)->tcr = TXx927_TMTCR_CRE; - tx3927_tmrptr(i)->tisr = 0; - tx3927_tmrptr(i)->cpra = 0xffffffff; - tx3927_tmrptr(i)->itmr = 0; - tx3927_tmrptr(i)->ccdr = 0; - tx3927_tmrptr(i)->pgmr = 0; - } + for (i = 0; i < TX3927_NR_TMR; i++) + txx9_tmr_init(TX3927_TMR_REG(i)); /* DMA */ tx3927_dmaptr->mcr = 0; diff --git a/arch/mips/kernel/Makefile b/arch/mips/kernel/Makefile index d7745c8976f..3196509a28d 100644 --- a/arch/mips/kernel/Makefile +++ b/arch/mips/kernel/Makefile @@ -10,6 +10,7 @@ obj-y += cpu-probe.o branch.o entry.o genex.o irq.o process.o \ obj-$(CONFIG_CEVT_R4K) += cevt-r4k.o obj-$(CONFIG_CEVT_GT641XX) += cevt-gt641xx.o +obj-$(CONFIG_CEVT_TXX9) += cevt-txx9.o binfmt_irix-objs := irixelf.o irixinv.o irixioctl.o irixsig.o \ irix5sys.o sysirix.o diff --git a/arch/mips/kernel/cevt-gt641xx.c b/arch/mips/kernel/cevt-gt641xx.c index 4c651b2680f..c36772631fe 100644 --- a/arch/mips/kernel/cevt-gt641xx.c +++ b/arch/mips/kernel/cevt-gt641xx.c @@ -49,10 +49,9 @@ int gt641xx_timer0_state(void) static int gt641xx_timer0_set_next_event(unsigned long delta, struct clock_event_device *evt) { - unsigned long flags; u32 ctrl; - spin_lock_irqsave(>641xx_timer_lock, flags); + spin_lock(>641xx_timer_lock); ctrl = GT_READ(GT_TC_CONTROL_OFS); ctrl &= ~(GT_TC_CONTROL_ENTC0_MSK | GT_TC_CONTROL_SELTC0_MSK); @@ -61,7 +60,7 @@ static int gt641xx_timer0_set_next_event(unsigned long delta, GT_WRITE(GT_TC0_OFS, delta); GT_WRITE(GT_TC_CONTROL_OFS, ctrl); - spin_unlock_irqrestore(>641xx_timer_lock, flags); + spin_unlock(>641xx_timer_lock); return 0; } @@ -69,10 +68,9 @@ static int gt641xx_timer0_set_next_event(unsigned long delta, static void gt641xx_timer0_set_mode(enum clock_event_mode mode, struct clock_event_device *evt) { - unsigned long flags; u32 ctrl; - spin_lock_irqsave(>641xx_timer_lock, flags); + spin_lock(>641xx_timer_lock); ctrl = GT_READ(GT_TC_CONTROL_OFS); ctrl &= ~(GT_TC_CONTROL_ENTC0_MSK | GT_TC_CONTROL_SELTC0_MSK); @@ -90,7 +88,7 @@ static void gt641xx_timer0_set_mode(enum clock_event_mode mode, GT_WRITE(GT_TC_CONTROL_OFS, ctrl); - spin_unlock_irqrestore(>641xx_timer_lock, flags); + spin_unlock(>641xx_timer_lock); } static void gt641xx_timer0_event_handler(struct clock_event_device *dev) @@ -133,9 +131,9 @@ static int __init gt641xx_timer0_clockevent_init(void) cd = >641xx_timer0_clockevent; cd->rating = 200 + gt641xx_base_clock / 10000000; + clockevent_set_clock(cd, gt641xx_base_clock); cd->max_delta_ns = clockevent_delta2ns(0x7fffffff, cd); cd->min_delta_ns = clockevent_delta2ns(0x300, cd); - clockevent_set_clock(cd, gt641xx_base_clock); clockevents_register_device(>641xx_timer0_clockevent); diff --git a/arch/mips/kernel/cevt-r4k.c b/arch/mips/kernel/cevt-r4k.c index ae2984fff58..bab935a3d74 100644 --- a/arch/mips/kernel/cevt-r4k.c +++ b/arch/mips/kernel/cevt-r4k.c @@ -28,7 +28,7 @@ static int mips_next_event(unsigned long delta, cnt = read_c0_count(); cnt += delta; write_c0_compare(cnt); - res = ((long)(read_c0_count() - cnt ) > 0) ? -ETIME : 0; + res = ((int)(read_c0_count() - cnt) > 0) ? -ETIME : 0; #ifdef CONFIG_MIPS_MT_SMTC evpe(vpflags); local_irq_restore(flags); @@ -179,7 +179,7 @@ static int c0_compare_int_pending(void) static int c0_compare_int_usable(void) { - const unsigned int delta = 0x300000; + unsigned int delta; unsigned int cnt; /* @@ -192,11 +192,17 @@ static int c0_compare_int_usable(void) return 0; } - cnt = read_c0_count(); - cnt += delta; - write_c0_compare(cnt); + for (delta = 0x10; delta <= 0x400000; delta <<= 1) { + cnt = read_c0_count(); + cnt += delta; + write_c0_compare(cnt); + irq_disable_hazard(); + if ((int)(read_c0_count() - cnt) < 0) + break; + /* increase delta if the timer was already expired */ + } - while ((long)(read_c0_count() - cnt) <= 0) + while ((int)(read_c0_count() - cnt) <= 0) ; /* Wait for expiry */ if (!c0_compare_int_pending()) @@ -218,9 +224,9 @@ void __cpuinit mips_clockevent_init(void) uint64_t mips_freq = mips_hpt_frequency; unsigned int cpu = smp_processor_id(); struct clock_event_device *cd; - unsigned int irq = MIPS_CPU_IRQ_BASE + 7; + unsigned int irq; - if (!cpu_has_counter) + if (!cpu_has_counter || !mips_hpt_frequency) return; #ifdef CONFIG_MIPS_MT_SMTC @@ -237,6 +243,15 @@ void __cpuinit mips_clockevent_init(void) if (!c0_compare_int_usable()) return; + /* + * With vectored interrupts things are getting platform specific. + * get_c0_compare_int is a hook to allow a platform to return the + * interrupt number of it's liking. + */ + irq = MIPS_CPU_IRQ_BASE + cp0_compare_irq; + if (get_c0_compare_int) + irq = get_c0_compare_int(); + cd = &per_cpu(mips_clockevent_device, cpu); cd->name = "MIPS"; @@ -261,13 +276,15 @@ void __cpuinit mips_clockevent_init(void) clockevents_register_device(cd); - if (!cp0_timer_irq_installed) { + if (!cp0_timer_irq_installed) + return; + + cp0_timer_irq_installed = 1; + #ifdef CONFIG_MIPS_MT_SMTC #define CPUCTR_IMASKBIT (0x100 << cp0_compare_irq) - setup_irq_smtc(irq, &c0_compare_irqaction, CPUCTR_IMASKBIT); + setup_irq_smtc(irq, &c0_compare_irqaction, CPUCTR_IMASKBIT); #else - setup_irq(irq, &c0_compare_irqaction); -#endif /* CONFIG_MIPS_MT_SMTC */ - cp0_timer_irq_installed = 1; - } + setup_irq(irq, &c0_compare_irqaction); +#endif } diff --git a/arch/mips/kernel/cevt-txx9.c b/arch/mips/kernel/cevt-txx9.c new file mode 100644 index 00000000000..795cb8fb0d7 --- /dev/null +++ b/arch/mips/kernel/cevt-txx9.c @@ -0,0 +1,171 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Based on linux/arch/mips/kernel/cevt-r4k.c, + * linux/arch/mips/jmr3927/rbhma3100/setup.c + * + * Copyright 2001 MontaVista Software Inc. + * Copyright (C) 2000-2001 Toshiba Corporation + * Copyright (C) 2007 MIPS Technologies, Inc. + * Copyright (C) 2007 Ralf Baechle <ralf@linux-mips.org> + */ +#include <linux/init.h> +#include <linux/interrupt.h> +#include <asm/time.h> +#include <asm/txx9tmr.h> + +#define TCR_BASE (TXx9_TMTCR_CCDE | TXx9_TMTCR_CRE | TXx9_TMTCR_TMODE_ITVL) +#define TIMER_CCD 0 /* 1/2 */ +#define TIMER_CLK(imclk) ((imclk) / (2 << TIMER_CCD)) + +static struct txx9_tmr_reg __iomem *txx9_cs_tmrptr; + +static cycle_t txx9_cs_read(void) +{ + return __raw_readl(&txx9_cs_tmrptr->trr); +} + +/* Use 1 bit smaller width to use full bits in that width */ +#define TXX9_CLOCKSOURCE_BITS (TXX9_TIMER_BITS - 1) + +static struct clocksource txx9_clocksource = { + .name = "TXx9", + .rating = 200, + .read = txx9_cs_read, + .mask = CLOCKSOURCE_MASK(TXX9_CLOCKSOURCE_BITS), + .flags = CLOCK_SOURCE_IS_CONTINUOUS, +}; + +void __init txx9_clocksource_init(unsigned long baseaddr, + unsigned int imbusclk) +{ + struct txx9_tmr_reg __iomem *tmrptr; + + clocksource_set_clock(&txx9_clocksource, TIMER_CLK(imbusclk)); + clocksource_register(&txx9_clocksource); + + tmrptr = ioremap(baseaddr, sizeof(struct txx9_tmr_reg)); + __raw_writel(TCR_BASE, &tmrptr->tcr); + __raw_writel(0, &tmrptr->tisr); + __raw_writel(TIMER_CCD, &tmrptr->ccdr); + __raw_writel(TXx9_TMITMR_TZCE, &tmrptr->itmr); + __raw_writel(1 << TXX9_CLOCKSOURCE_BITS, &tmrptr->cpra); + __raw_writel(TCR_BASE | TXx9_TMTCR_TCE, &tmrptr->tcr); + txx9_cs_tmrptr = tmrptr; +} + +static struct txx9_tmr_reg __iomem *txx9_tmrptr; + +static void txx9tmr_stop_and_clear(struct txx9_tmr_reg __iomem *tmrptr) +{ + /* stop and reset counter */ + __raw_writel(TCR_BASE, &tmrptr->tcr); + /* clear pending interrupt */ + __raw_writel(0, &tmrptr->tisr); +} + +static void txx9tmr_set_mode(enum clock_event_mode mode, + struct clock_event_device *evt) +{ + struct txx9_tmr_reg __iomem *tmrptr = txx9_tmrptr; + + txx9tmr_stop_and_clear(tmrptr); + switch (mode) { + case CLOCK_EVT_MODE_PERIODIC: + __raw_writel(TXx9_TMITMR_TIIE | TXx9_TMITMR_TZCE, + &tmrptr->itmr); + /* start timer */ + __raw_writel(((u64)(NSEC_PER_SEC / HZ) * evt->mult) >> + evt->shift, + &tmrptr->cpra); + __raw_writel(TCR_BASE | TXx9_TMTCR_TCE, &tmrptr->tcr); + break; + case CLOCK_EVT_MODE_SHUTDOWN: + case CLOCK_EVT_MODE_UNUSED: + __raw_writel(0, &tmrptr->itmr); + break; + case CLOCK_EVT_MODE_ONESHOT: + __raw_writel(TXx9_TMITMR_TIIE, &tmrptr->itmr); + break; + case CLOCK_EVT_MODE_RESUME: + __raw_writel(TIMER_CCD, &tmrptr->ccdr); + __raw_writel(0, &tmrptr->itmr); + break; + } +} + +static int txx9tmr_set_next_event(unsigned long delta, + struct clock_event_device *evt) +{ + struct txx9_tmr_reg __iomem *tmrptr = txx9_tmrptr; + + txx9tmr_stop_and_clear(tmrptr); + /* start timer */ + __raw_writel(delta, &tmrptr->cpra); + __raw_writel(TCR_BASE | TXx9_TMTCR_TCE, &tmrptr->tcr); + return 0; +} + +static struct clock_event_device txx9tmr_clock_event_device = { + .name = "TXx9", + .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, + .rating = 200, + .cpumask = CPU_MASK_CPU0, + .set_mode = txx9tmr_set_mode, + .set_next_event = txx9tmr_set_next_event, +}; + +static irqreturn_t txx9tmr_interrupt(int irq, void *dev_id) +{ + struct clock_event_device *cd = &txx9tmr_clock_event_device; + struct txx9_tmr_reg __iomem *tmrptr = txx9_tmrptr; + + __raw_writel(0, &tmrptr->tisr); /* ack interrupt */ + cd->event_handler(cd); + return IRQ_HANDLED; +} + +static struct irqaction txx9tmr_irq = { + .handler = txx9tmr_interrupt, + .flags = IRQF_DISABLED | IRQF_PERCPU, + .name = "txx9tmr", +}; + +void __init txx9_clockevent_init(unsigned long baseaddr, int irq, + unsigned int imbusclk) +{ + struct clock_event_device *cd = &txx9tmr_clock_event_device; + struct txx9_tmr_reg __iomem *tmrptr; + + tmrptr = ioremap(baseaddr, sizeof(struct txx9_tmr_reg)); + txx9tmr_stop_and_clear(tmrptr); + __raw_writel(TIMER_CCD, &tmrptr->ccdr); + __raw_writel(0, &tmrptr->itmr); + txx9_tmrptr = tmrptr; + + clockevent_set_clock(cd, TIMER_CLK(imbusclk)); + cd->max_delta_ns = + clockevent_delta2ns(0xffffffff >> (32 - TXX9_TIMER_BITS), cd); + cd->min_delta_ns = clockevent_delta2ns(0xf, cd); + cd->irq = irq; + clockevents_register_device(cd); + setup_irq(irq, &txx9tmr_irq); + printk(KERN_INFO "TXx9: clockevent device at 0x%lx, irq %d\n", + baseaddr, irq); +} + +void __init txx9_tmr_init(unsigned long baseaddr) +{ + struct txx9_tmr_reg __iomem *tmrptr; + + tmrptr = ioremap(baseaddr, sizeof(struct txx9_tmr_reg)); + __raw_writel(TXx9_TMTCR_CRE, &tmrptr->tcr); + __raw_writel(0, &tmrptr->tisr); + __raw_writel(0xffffffff, &tmrptr->cpra); + __raw_writel(0, &tmrptr->itmr); + __raw_writel(0, &tmrptr->ccdr); + __raw_writel(0, &tmrptr->pgmr); + iounmap(tmrptr); +} diff --git a/arch/mips/kernel/irixsig.c b/arch/mips/kernel/irixsig.c index a0a91056fda..33506ff2591 100644 --- a/arch/mips/kernel/irixsig.c +++ b/arch/mips/kernel/irixsig.c @@ -24,8 +24,12 @@ #define _BLOCKABLE (~(_S(SIGKILL) | _S(SIGSTOP))) +#define _IRIX_NSIG 128 +#define _IRIX_NSIG_BPW BITS_PER_LONG +#define _IRIX_NSIG_WORDS (_IRIX_NSIG / _IRIX_NSIG_BPW) + typedef struct { - unsigned long sig[4]; + unsigned long sig[_IRIX_NSIG_WORDS]; } irix_sigset_t; struct sigctx_irix5 { @@ -527,7 +531,7 @@ asmlinkage int irix_sigpoll_sys(unsigned long __user *set, expire = schedule_timeout_interruptible(expire); - for (i=0; i<=4; i++) + for (i=0; i < _IRIX_NSIG_WORDS; i++) tmp |= (current->pending.signal.sig[i] & kset.sig[i]); if (tmp) diff --git a/arch/mips/kernel/ptrace.c b/arch/mips/kernel/ptrace.c index 999f7853de2..35234b92b9a 100644 --- a/arch/mips/kernel/ptrace.c +++ b/arch/mips/kernel/ptrace.c @@ -65,13 +65,13 @@ int ptrace_getregs(struct task_struct *child, __s64 __user *data) regs = task_pt_regs(child); for (i = 0; i < 32; i++) - __put_user(regs->regs[i], data + i); - __put_user(regs->lo, data + EF_LO - EF_R0); - __put_user(regs->hi, data + EF_HI - EF_R0); - __put_user(regs->cp0_epc, data + EF_CP0_EPC - EF_R0); - __put_user(regs->cp0_badvaddr, data + EF_CP0_BADVADDR - EF_R0); - __put_user(regs->cp0_status, data + EF_CP0_STATUS - EF_R0); - __put_user(regs->cp0_cause, data + EF_CP0_CAUSE - EF_R0); + __put_user((long)regs->regs[i], data + i); + __put_user((long)regs->lo, data + EF_LO - EF_R0); + __put_user((long)regs->hi, data + EF_HI - EF_R0); + __put_user((long)regs->cp0_epc, data + EF_CP0_EPC - EF_R0); + __put_user((long)regs->cp0_badvaddr, data + EF_CP0_BADVADDR - EF_R0); + __put_user((long)regs->cp0_status, data + EF_CP0_STATUS - EF_R0); + __put_user((long)regs->cp0_cause, data + EF_CP0_CAUSE - EF_R0); return 0; } @@ -390,11 +390,11 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) } case PTRACE_GETREGS: - ret = ptrace_getregs(child, (__u64 __user *) data); + ret = ptrace_getregs(child, (__s64 __user *) data); break; case PTRACE_SETREGS: - ret = ptrace_setregs(child, (__u64 __user *) data); + ret = ptrace_setregs(child, (__s64 __user *) data); break; case PTRACE_GETFPREGS: diff --git a/arch/mips/kernel/ptrace32.c b/arch/mips/kernel/ptrace32.c index f2bffed94fa..76818be6ba7 100644 --- a/arch/mips/kernel/ptrace32.c +++ b/arch/mips/kernel/ptrace32.c @@ -346,11 +346,11 @@ asmlinkage int sys32_ptrace(int request, int pid, int addr, int data) } case PTRACE_GETREGS: - ret = ptrace_getregs(child, (__u64 __user *) (__u64) data); + ret = ptrace_getregs(child, (__s64 __user *) (__u64) data); break; case PTRACE_SETREGS: - ret = ptrace_setregs(child, (__u64 __user *) (__u64) data); + ret = ptrace_setregs(child, (__s64 __user *) (__u64) data); break; case PTRACE_GETFPREGS: diff --git a/arch/mips/kernel/smtc.c b/arch/mips/kernel/smtc.c index a8c1a698d58..9c92d42996c 100644 --- a/arch/mips/kernel/smtc.c +++ b/arch/mips/kernel/smtc.c @@ -88,11 +88,19 @@ unsigned int smtc_status = 0; /* Boot command line configuration overrides */ +static int vpe0limit; static int ipibuffers = 0; static int nostlb = 0; static int asidmask = 0; unsigned long smtc_asid_mask = 0xff; +static int __init vpe0tcs(char *str) +{ + get_option(&str, &vpe0limit); + + return 1; +} + static int __init ipibufs(char *str) { get_option(&str, &ipibuffers); @@ -125,6 +133,7 @@ static int __init asidmask_set(char *str) return 1; } +__setup("vpe0tcs=", vpe0tcs); __setup("ipibufs=", ipibufs); __setup("nostlb", stlb_disable); __setup("asidmask=", asidmask_set); @@ -340,7 +349,7 @@ static void smtc_tc_setup(int vpe, int tc, int cpu) void mipsmt_prepare_cpus(void) { - int i, vpe, tc, ntc, nvpe, tcpervpe, slop, cpu; + int i, vpe, tc, ntc, nvpe, tcpervpe[NR_CPUS], slop, cpu; unsigned long flags; unsigned long val; int nipi; @@ -401,8 +410,39 @@ void mipsmt_prepare_cpus(void) ntc = NR_CPUS; if (tclimit > 0 && ntc > tclimit) ntc = tclimit; - tcpervpe = ntc / nvpe; - slop = ntc % nvpe; /* Residual TCs, < NVPE */ + slop = ntc % nvpe; + for (i = 0; i < nvpe; i++) { + tcpervpe[i] = ntc / nvpe; + if (slop) { + if((slop - i) > 0) tcpervpe[i]++; + } + } + /* Handle command line override for VPE0 */ + if (vpe0limit > ntc) vpe0limit = ntc; + if (vpe0limit > 0) { + int slopslop; + if (vpe0limit < tcpervpe[0]) { + /* Reducing TC count - distribute to others */ + slop = tcpervpe[0] - vpe0limit; + slopslop = slop % (nvpe - 1); + tcpervpe[0] = vpe0limit; + for (i = 1; i < nvpe; i++) { + tcpervpe[i] += slop / (nvpe - 1); + if(slopslop && ((slopslop - (i - 1) > 0))) + tcpervpe[i]++; + } + } else if (vpe0limit > tcpervpe[0]) { + /* Increasing TC count - steal from others */ + slop = vpe0limit - tcpervpe[0]; + slopslop = slop % (nvpe - 1); + tcpervpe[0] = vpe0limit; + for (i = 1; i < nvpe; i++) { + tcpervpe[i] -= slop / (nvpe - 1); + if(slopslop && ((slopslop - (i - 1) > 0))) + tcpervpe[i]--; + } + } + } /* Set up shared TLB */ smtc_configure_tlb(); @@ -416,7 +456,7 @@ void mipsmt_prepare_cpus(void) if (vpe != 0) printk(", "); printk("VPE %d: TC", vpe); - for (i = 0; i < tcpervpe; i++) { + for (i = 0; i < tcpervpe[vpe]; i++) { /* * TC 0 is bound to VPE 0 at reset, * and is presumably executing this @@ -429,15 +469,6 @@ void mipsmt_prepare_cpus(void) printk(" %d", tc); tc++; } - if (slop) { - if (tc != 0) { - smtc_tc_setup(vpe, tc, cpu); - cpu++; - } - printk(" %d", tc); - tc++; - slop--; - } if (vpe != 0) { /* * Clear any stale software interrupts from VPE's Cause diff --git a/arch/mips/kernel/syscall.c b/arch/mips/kernel/syscall.c index b95fe93dd64..af1bdc89748 100644 --- a/arch/mips/kernel/syscall.c +++ b/arch/mips/kernel/syscall.c @@ -73,7 +73,14 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, task_size = STACK_TOP; + if (len > task_size) + return -ENOMEM; + if (flags & MAP_FIXED) { + /* Even MAP_FIXED mappings must reside within task_size. */ + if (task_size - len < addr) + return -EINVAL; + /* * We do not accept a shared mapping if it would violate * cache aliasing constraints. @@ -83,8 +90,6 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, return addr; } - if (len > task_size) - return -ENOMEM; do_color_align = 0; if (filp || (flags & MAP_SHARED)) do_color_align = 1; diff --git a/arch/mips/kernel/time.c b/arch/mips/kernel/time.c index 6c6849a8f13..27228f583da 100644 --- a/arch/mips/kernel/time.c +++ b/arch/mips/kernel/time.c @@ -11,6 +11,7 @@ * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. */ +#include <linux/bug.h> #include <linux/clockchips.h> #include <linux/types.h> #include <linux/kernel.h> @@ -115,10 +116,6 @@ EXPORT_SYMBOL(perf_irq); * (only needed if you intended to use cpu counter as timer interrupt * source) * 2) calculate a couple of cached variables for later usage - * 3) plat_timer_setup() - - * a) (optional) over-write any choices made above by time_init(). - * b) machine specific code should setup the timer irqaction. - * c) enable the timer interrupt */ unsigned int mips_hpt_frequency; @@ -221,8 +218,18 @@ void __init __weak plat_time_init(void) { } -void __init __weak plat_timer_setup(struct irqaction *irq) +/* + * This function exists in order to cause an error due to a duplicate + * definition if platform code should have its own implementation. The hook + * to use instead is plat_time_init. plat_time_init does not receive the + * irqaction pointer argument anymore. This is because any function which + * initializes an interrupt timer now takes care of its own request_irq rsp. + * setup_irq calls and each clock_event_device should use its own + * struct irqrequest. + */ +void __init plat_timer_setup(struct irqaction *irq) { + BUG(); } void __init time_init(void) diff --git a/arch/mips/kernel/vmlinux.lds.S b/arch/mips/kernel/vmlinux.lds.S index 2781cff1485..5fc2398bdb7 100644 --- a/arch/mips/kernel/vmlinux.lds.S +++ b/arch/mips/kernel/vmlinux.lds.S @@ -63,21 +63,23 @@ SECTIONS /* writeable */ .data : { /* Data */ - . = . + DATAOFFSET; /* for CONFIG_MAPPED_KERNEL */ - /* - * This ALIGN is needed as a workaround for a bug a gcc bug upto 4.1 which - * limits the maximum alignment to at most 32kB and results in the following - * warning: - * - * CC arch/mips/kernel/init_task.o - * arch/mips/kernel/init_task.c:30: warning: alignment of ‘init_thread_union’ - * is greater than maximum object file alignment. Using 32768 - */ - . = ALIGN(_PAGE_SIZE); - *(.data.init_task) - - DATA_DATA - CONSTRUCTORS + . = . + DATAOFFSET; /* for CONFIG_MAPPED_KERNEL */ + /* + * This ALIGN is needed as a workaround for a bug a + * gcc bug upto 4.1 which limits the maximum alignment + * to at most 32kB and results in the following + * warning: + * + * CC arch/mips/kernel/init_task.o + * arch/mips/kernel/init_task.c:30: warning: alignment + * of ‘init_thread_union’ is greater than maximum + * object file alignment. Using 32768 + */ + . = ALIGN(_PAGE_SIZE); + *(.data.init_task) + + DATA_DATA + CONSTRUCTORS } _gp = . + 0x8000; .lit8 : { diff --git a/arch/mips/kernel/vpe.c b/arch/mips/kernel/vpe.c index df8cbe4c7c0..436a64ff398 100644 --- a/arch/mips/kernel/vpe.c +++ b/arch/mips/kernel/vpe.c @@ -942,8 +942,8 @@ static int vpe_elfload(struct vpe * v) if (phdr->p_type != PT_LOAD) continue; - memcpy((void *)phdr->p_vaddr, (char *)hdr + phdr->p_offset, phdr->p_filesz); - memset((void *)phdr->p_vaddr + phdr->p_filesz, 0, phdr->p_memsz - phdr->p_filesz); + memcpy((void *)phdr->p_paddr, (char *)hdr + phdr->p_offset, phdr->p_filesz); + memset((void *)phdr->p_paddr + phdr->p_filesz, 0, phdr->p_memsz - phdr->p_filesz); phdr++; } diff --git a/arch/mips/lasat/setup.c b/arch/mips/lasat/setup.c index 54827d0174b..e072da4ff3b 100644 --- a/arch/mips/lasat/setup.c +++ b/arch/mips/lasat/setup.c @@ -117,14 +117,11 @@ static struct notifier_block lasat_panic_block[] = } }; -void plat_time_init(void) +void __init plat_time_init(void) { mips_hpt_frequency = lasat_board_info.li_cpu_hz / 2; -} -void __init plat_timer_setup(struct irqaction *irq) -{ - change_c0_status(ST0_IM, IE_IRQ0 | IE_IRQ5); + change_c0_status(ST0_IM, IE_IRQ0); } void __init plat_mem_setup(void) diff --git a/arch/mips/mips-boards/generic/time.c b/arch/mips/mips-boards/generic/time.c index 9d6243a8c15..f02ce6308e5 100644 --- a/arch/mips/mips-boards/generic/time.c +++ b/arch/mips/mips-boards/generic/time.c @@ -127,26 +127,6 @@ unsigned long read_persistent_clock(void) return mc146818_get_cmos_time(); } -void __init plat_time_init(void) -{ - unsigned int est_freq; - - /* Set Data mode - binary. */ - CMOS_WRITE(CMOS_READ(RTC_CONTROL) | RTC_DM_BINARY, RTC_CONTROL); - - est_freq = estimate_cpu_frequency(); - - printk("CPU frequency %d.%02d MHz\n", est_freq/1000000, - (est_freq%1000000)*100/1000000); - - cpu_khz = est_freq / 1000; - - mips_scroll_message(); -#ifdef CONFIG_I8253 /* Only Malta has a PIT */ - setup_pit_timer(); -#endif -} - void __init plat_perf_setup(void) { cp0_perfcount_irq = -1; @@ -166,14 +146,13 @@ void __init plat_perf_setup(void) } } -void __init plat_timer_setup(struct irqaction *irq) +unsigned int __init get_c0_compare_int(void) { #ifdef MSC01E_INT_BASE if (cpu_has_veic) { set_vi_handler(MSC01E_INT_CPUCTR, mips_timer_dispatch); mips_cpu_timer_irq = MSC01E_INT_BASE + MSC01E_INT_CPUCTR; - } - else + } else #endif { if (cpu_has_vint) @@ -181,13 +160,26 @@ void __init plat_timer_setup(struct irqaction *irq) mips_cpu_timer_irq = MIPS_CPU_IRQ_BASE + cp0_compare_irq; } -#ifdef CONFIG_MIPS_MT_SMTC - setup_irq_smtc(mips_cpu_timer_irq, irq, 0x100 << cp0_compare_irq); -#else - setup_irq(mips_cpu_timer_irq, irq); -#endif /* CONFIG_MIPS_MT_SMTC */ -#ifdef CONFIG_SMP - set_irq_handler(mips_cpu_timer_irq, handle_percpu_irq); + return mips_cpu_timer_irq; +} + +void __init plat_time_init(void) +{ + unsigned int est_freq; + + /* Set Data mode - binary. */ + CMOS_WRITE(CMOS_READ(RTC_CONTROL) | RTC_DM_BINARY, RTC_CONTROL); + + est_freq = estimate_cpu_frequency(); + + printk("CPU frequency %d.%02d MHz\n", est_freq/1000000, + (est_freq%1000000)*100/1000000); + + cpu_khz = est_freq / 1000; + + mips_scroll_message(); +#ifdef CONFIG_I8253 /* Only Malta has a PIT */ + setup_pit_timer(); #endif plat_perf_setup(); diff --git a/arch/mips/mipssim/sim_time.c b/arch/mips/mipssim/sim_time.c index e7fa0d1078a..bfaafa38846 100644 --- a/arch/mips/mipssim/sim_time.c +++ b/arch/mips/mipssim/sim_time.c @@ -75,25 +75,6 @@ static unsigned int __init estimate_cpu_frequency(void) return count; } -void __init plat_time_init(void) -{ - unsigned int est_freq, flags; - - local_irq_save(flags); - - /* Set Data mode - binary. */ - CMOS_WRITE(CMOS_READ(RTC_CONTROL) | RTC_DM_BINARY, RTC_CONTROL); - - est_freq = estimate_cpu_frequency(); - - printk(KERN_INFO "CPU frequency %d.%02d MHz\n", est_freq / 1000000, - (est_freq % 1000000) * 100 / 1000000); - - cpu_khz = est_freq / 1000; - - local_irq_restore(flags); -} - static int mips_cpu_timer_irq; static void mips_timer_dispatch(void) @@ -102,26 +83,37 @@ static void mips_timer_dispatch(void) } -void __init plat_timer_setup(struct irqaction *irq) +unsigned __init get_c0_compare_int(void) { +#ifdef MSC01E_INT_BASE if (cpu_has_veic) { set_vi_handler(MSC01E_INT_CPUCTR, mips_timer_dispatch); mips_cpu_timer_irq = MSC01E_INT_BASE + MSC01E_INT_CPUCTR; } else { +#endif if (cpu_has_vint) set_vi_handler(cp0_compare_irq, mips_timer_dispatch); mips_cpu_timer_irq = MIPS_CPU_IRQ_BASE + cp0_compare_irq; } - /* we are using the cpu counter for timer interrupts */ - setup_irq(mips_cpu_timer_irq, irq); + return mips_cpu_timer_irq; +} -#ifdef CONFIG_SMP - /* irq_desc(riptor) is a global resource, when the interrupt overlaps - on seperate cpu's the first one tries to handle the second interrupt. - The effect is that the int remains disabled on the second cpu. - Mark the interrupt with IRQ_PER_CPU to avoid any confusion */ - irq_desc[mips_cpu_timer_irq].flags |= IRQ_PER_CPU; - set_irq_handler(mips_cpu_timer_irq, handle_percpu_irq); -#endif +void __init plat_time_init(void) +{ + unsigned int est_freq, flags; + + local_irq_save(flags); + + /* Set Data mode - binary. */ + CMOS_WRITE(CMOS_READ(RTC_CONTROL) | RTC_DM_BINARY, RTC_CONTROL); + + est_freq = estimate_cpu_frequency(); + + printk(KERN_INFO "CPU frequency %d.%02d MHz\n", est_freq / 1000000, + (est_freq % 1000000) * 100 / 1000000); + + cpu_khz = est_freq / 1000; + + local_irq_restore(flags); } diff --git a/arch/mips/mm/c-r3k.c b/arch/mips/mm/c-r3k.c index c55312f6fd3..562abb77d1d 100644 --- a/arch/mips/mm/c-r3k.c +++ b/arch/mips/mm/c-r3k.c @@ -7,7 +7,7 @@ * Tx39XX R4k style caches added. HK * Copyright (C) 1998, 1999, 2000 Harald Koerfgen * Copyright (C) 1998 Gleb Raiko & Vladimir Roganov - * Copyright (C) 2001, 2004 Maciej W. Rozycki + * Copyright (C) 2001, 2004, 2007 Maciej W. Rozycki */ #include <linux/init.h> #include <linux/kernel.h> @@ -26,8 +26,6 @@ static unsigned long icache_size, dcache_size; /* Size in bytes */ static unsigned long icache_lsize, dcache_lsize; /* Size in bytes */ -#undef DEBUG_CACHE - unsigned long __init r3k_cache_size(unsigned long ca_flags) { unsigned long flags, status, dummy, size; @@ -217,26 +215,6 @@ static void r3k_flush_dcache_range(unsigned long start, unsigned long end) write_c0_status(flags); } -static inline unsigned long get_phys_page(unsigned long addr, - struct mm_struct *mm) -{ - pgd_t *pgd; - pud_t *pud; - pmd_t *pmd; - pte_t *pte; - unsigned long physpage; - - pgd = pgd_offset(mm, addr); - pud = pud_offset(pgd, addr); - pmd = pmd_offset(pud, addr); - pte = pte_offset(pmd, addr); - - if ((physpage = pte_val(*pte)) & _PAGE_VALID) - return KSEG0ADDR(physpage & PAGE_MASK); - - return 0; -} - static inline void r3k_flush_cache_all(void) { } @@ -252,12 +230,40 @@ static void r3k_flush_cache_mm(struct mm_struct *mm) } static void r3k_flush_cache_range(struct vm_area_struct *vma, - unsigned long start, unsigned long end) + unsigned long start, unsigned long end) { } -static void r3k_flush_cache_page(struct vm_area_struct *vma, unsigned long page, unsigned long pfn) +static void r3k_flush_cache_page(struct vm_area_struct *vma, + unsigned long addr, unsigned long pfn) { + unsigned long kaddr = KSEG0ADDR(pfn << PAGE_SHIFT); + int exec = vma->vm_flags & VM_EXEC; + struct mm_struct *mm = vma->vm_mm; + pgd_t *pgdp; + pud_t *pudp; + pmd_t *pmdp; + pte_t *ptep; + + pr_debug("cpage[%08lx,%08lx]\n", + cpu_context(smp_processor_id(), mm), addr); + + /* No ASID => no such page in the cache. */ + if (cpu_context(smp_processor_id(), mm) == 0) + return; + + pgdp = pgd_offset(mm, addr); + pudp = pud_offset(pgdp, addr); + pmdp = pmd_offset(pudp, addr); + ptep = pte_offset(pmdp, addr); + + /* Invalid => no such page in the cache. */ + if (!(pte_val(*ptep) & _PAGE_PRESENT)) + return; + + r3k_flush_dcache_range(kaddr, kaddr + PAGE_SIZE); + if (exec) + r3k_flush_icache_range(kaddr, kaddr + PAGE_SIZE); } static void local_r3k_flush_data_cache_page(void *addr) @@ -272,9 +278,7 @@ static void r3k_flush_cache_sigtramp(unsigned long addr) { unsigned long flags; -#ifdef DEBUG_CACHE - printk("csigtramp[%08lx]", addr); -#endif + pr_debug("csigtramp[%08lx]\n", addr); flags = read_c0_status(); diff --git a/arch/mips/mm/c-r4k.c b/arch/mips/mm/c-r4k.c index d7088331fb0..6806d58211b 100644 --- a/arch/mips/mm/c-r4k.c +++ b/arch/mips/mm/c-r4k.c @@ -345,11 +345,26 @@ static void r4k___flush_cache_all(void) r4k_on_each_cpu(local_r4k___flush_cache_all, NULL, 1, 1); } +static inline int has_valid_asid(const struct mm_struct *mm) +{ +#if defined(CONFIG_MIPS_MT_SMP) || defined(CONFIG_MIPS_MT_SMTC) + int i; + + for_each_online_cpu(i) + if (cpu_context(i, mm)) + return 1; + + return 0; +#else + return cpu_context(smp_processor_id(), mm); +#endif +} + static inline void local_r4k_flush_cache_range(void * args) { struct vm_area_struct *vma = args; - if (!(cpu_context(smp_processor_id(), vma->vm_mm))) + if (!(has_valid_asid(vma->vm_mm))) return; r4k_blast_dcache(); @@ -368,7 +383,7 @@ static inline void local_r4k_flush_cache_mm(void * args) { struct mm_struct *mm = args; - if (!cpu_context(smp_processor_id(), mm)) + if (!has_valid_asid(mm)) return; /* @@ -420,7 +435,7 @@ static inline void local_r4k_flush_cache_page(void *args) * If ownes no valid ASID yet, cannot possibly have gotten * this page into the cache. */ - if (cpu_context(smp_processor_id(), mm) == 0) + if (!has_valid_asid(mm)) return; addr &= PAGE_MASK; diff --git a/arch/mips/mm/dma-default.c b/arch/mips/mm/dma-default.c index b1b40527658..33519ce4954 100644 --- a/arch/mips/mm/dma-default.c +++ b/arch/mips/mm/dma-default.c @@ -12,8 +12,8 @@ #include <linux/dma-mapping.h> #include <linux/mm.h> #include <linux/module.h> -#include <linux/string.h> #include <linux/scatterlist.h> +#include <linux/string.h> #include <asm/cache.h> #include <asm/io.h> diff --git a/arch/mips/pci/fixup-pmcmsp.c b/arch/mips/pci/fixup-pmcmsp.c index 00261211dbf..65735b1b766 100644 --- a/arch/mips/pci/fixup-pmcmsp.c +++ b/arch/mips/pci/fixup-pmcmsp.c @@ -202,7 +202,7 @@ int pcibios_plat_dev_init(struct pci_dev *dev) * RETURNS: IRQ number * ****************************************************************************/ -int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin) +int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) { #if !defined(CONFIG_PMC_MSP7120_GW) && !defined(CONFIG_PMC_MSP7120_EVAL) printk(KERN_WARNING "PCI: unknown board, no PCI IRQs assigned.\n"); diff --git a/arch/mips/pci/fixup-tb0219.c b/arch/mips/pci/fixup-tb0219.c index 720a2b720c5..ed87733f679 100644 --- a/arch/mips/pci/fixup-tb0219.c +++ b/arch/mips/pci/fixup-tb0219.c @@ -2,7 +2,7 @@ * fixup-tb0219.c, The TANBAC TB0219 specific PCI fixups. * * Copyright (C) 2003 Megasolution Inc. <matsu@megasolution.jp> - * Copyright (C) 2004 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> + * Copyright (C) 2004-2005 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> * * 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 diff --git a/arch/mips/pci/ops-pmcmsp.c b/arch/mips/pci/ops-pmcmsp.c index 059eade96f2..109c95ca698 100644 --- a/arch/mips/pci/ops-pmcmsp.c +++ b/arch/mips/pci/ops-pmcmsp.c @@ -404,7 +404,7 @@ int msp_pcibios_config_access(unsigned char access_type, if (pciirqflag == 0) { request_irq(MSP_INT_PCI,/* Hardcoded internal MSP7120 wiring */ bpci_interrupt, - SA_SHIRQ | SA_INTERRUPT, + IRQF_SHARED | IRQF_DISABLED, "PMC MSP PCI Host", preg); pciirqflag = ~0; diff --git a/arch/mips/pmc-sierra/msp71xx/msp_serial.c b/arch/mips/pmc-sierra/msp71xx/msp_serial.c index 15e7b8000b4..9de34302e5f 100644 --- a/arch/mips/pmc-sierra/msp71xx/msp_serial.c +++ b/arch/mips/pmc-sierra/msp71xx/msp_serial.c @@ -122,7 +122,7 @@ void __init msp_serial_setup(void) up.uartclk = uartclk; up.regshift = 2; up.iotype = UPIO_DWAPB; /* UPIO_MEM like */ - up.flags = STD_COM_FLAGS; + up.flags = ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST; up.type = PORT_16550A; up.line = 0; up.private_data = (void*)UART0_STATUS_REG; diff --git a/arch/mips/sgi-ip27/ip27-timer.c b/arch/mips/sgi-ip27/ip27-timer.c index f5dccf01da1..dc59c3b708e 100644 --- a/arch/mips/sgi-ip27/ip27-timer.c +++ b/arch/mips/sgi-ip27/ip27-timer.c @@ -131,12 +131,12 @@ static struct irq_chip rt_irq_type = { static int rt_next_event(unsigned long delta, struct clock_event_device *evt) { unsigned int cpu = smp_processor_id(); - int slice = cputoslice(cpu) == 0; + int slice putoslice(cpu); unsigned long cnt; cnt = LOCAL_HUB_L(PI_RT_COUNT); cnt += delta; - LOCAL_HUB_S(slice ? PI_RT_COMPARE_A : PI_RT_COMPARE_B, cnt); + LOCAL_HUB_S(PI_RT_COMPARE_A + PI_COUNT_OFFSET * slice, cnt); return LOCAL_HUB_L(PI_RT_COUNT) >= cnt ? -ETIME : 0; } @@ -164,9 +164,12 @@ static irqreturn_t hub_rt_counter_handler(int irq, void *dev_id) { struct clock_event_device *cd = dev_id; unsigned int cpu = smp_processor_id(); - int slice = cputoslice(cpu) == 0; + int slice = cputoslice(cpu); - LOCAL_HUB_S(slice ? PI_RT_PEND_A : PI_RT_PEND_B, 0); /* Ack */ + /* + * Ack + */ + LOCAL_HUB_S(PI_RT_PEND_A + PI_COUNT_OFFSET * slice, cnt); cd->event_handler(cd); return IRQ_HANDLED; diff --git a/arch/mips/sgi-ip32/ip32-irq.c b/arch/mips/sgi-ip32/ip32-irq.c index 7e8094f617b..aab17ddd2f3 100644 --- a/arch/mips/sgi-ip32/ip32-irq.c +++ b/arch/mips/sgi-ip32/ip32-irq.c @@ -40,13 +40,6 @@ static void inline flush_mace_bus(void) mace->perif.ctrl.misc; } -#undef DEBUG_IRQ -#ifdef DEBUG_IRQ -#define DBG(x...) printk(x) -#else -#define DBG(x...) -#endif - /* * O2 irq map * @@ -125,6 +118,7 @@ struct irqaction memerr_irq = { .mask = CPU_MASK_NONE, .name = "CRIME memory error", }; + struct irqaction cpuerr_irq = { .handler = crime_cpuerr_intr, .flags = IRQF_DISABLED, @@ -139,46 +133,70 @@ struct irqaction cpuerr_irq = { static uint64_t crime_mask; -static void enable_crime_irq(unsigned int irq) +static inline void crime_enable_irq(unsigned int irq) { - crime_mask |= 1 << (irq - 1); + unsigned int bit = irq - CRIME_IRQ_BASE; + + crime_mask |= 1 << bit; crime->imask = crime_mask; } -static void disable_crime_irq(unsigned int irq) +static inline void crime_disable_irq(unsigned int irq) { - crime_mask &= ~(1 << (irq - 1)); + unsigned int bit = irq - CRIME_IRQ_BASE; + + crime_mask &= ~(1 << bit); crime->imask = crime_mask; flush_crime_bus(); } -static void mask_and_ack_crime_irq(unsigned int irq) +static void crime_level_mask_and_ack_irq(unsigned int irq) +{ + crime_disable_irq(irq); +} + +static void crime_level_end_irq(unsigned int irq) +{ + if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) + crime_enable_irq(irq); +} + +static struct irq_chip crime_level_interrupt = { + .name = "IP32 CRIME", + .ack = crime_level_mask_and_ack_irq, + .mask = crime_disable_irq, + .mask_ack = crime_level_mask_and_ack_irq, + .unmask = crime_enable_irq, + .end = crime_level_end_irq, +}; + +static void crime_edge_mask_and_ack_irq(unsigned int irq) { + unsigned int bit = irq - CRIME_IRQ_BASE; + uint64_t crime_int; + /* Edge triggered interrupts must be cleared. */ - if ((irq >= CRIME_GBE0_IRQ && irq <= CRIME_GBE3_IRQ) - || (irq >= CRIME_RE_EMPTY_E_IRQ && irq <= CRIME_RE_IDLE_E_IRQ) - || (irq >= CRIME_SOFT0_IRQ && irq <= CRIME_SOFT2_IRQ)) { - uint64_t crime_int; - crime_int = crime->hard_int; - crime_int &= ~(1 << (irq - 1)); - crime->hard_int = crime_int; - } - disable_crime_irq(irq); + + crime_int = crime->hard_int; + crime_int &= ~(1 << bit); + crime->hard_int = crime_int; + + crime_disable_irq(irq); } -static void end_crime_irq(unsigned int irq) +static void crime_edge_end_irq(unsigned int irq) { if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) - enable_crime_irq(irq); + crime_enable_irq(irq); } -static struct irq_chip ip32_crime_interrupt = { - .name = "IP32 CRIME", - .ack = mask_and_ack_crime_irq, - .mask = disable_crime_irq, - .mask_ack = mask_and_ack_crime_irq, - .unmask = enable_crime_irq, - .end = end_crime_irq, +static struct irq_chip crime_edge_interrupt = { + .name = "IP32 CRIME", + .ack = crime_edge_mask_and_ack_irq, + .mask = crime_disable_irq, + .mask_ack = crime_edge_mask_and_ack_irq, + .unmask = crime_enable_irq, + .end = crime_edge_end_irq, }; /* @@ -265,7 +283,7 @@ static void enable_maceisa_irq(unsigned int irq) { unsigned int crime_int = 0; - DBG("maceisa enable: %u\n", irq); + pr_debug("maceisa enable: %u\n", irq); switch (irq) { case MACEISA_AUDIO_SW_IRQ ... MACEISA_AUDIO3_MERR_IRQ: @@ -278,7 +296,7 @@ static void enable_maceisa_irq(unsigned int irq) crime_int = MACE_SUPERIO_INT; break; } - DBG("crime_int %08x enabled\n", crime_int); + pr_debug("crime_int %08x enabled\n", crime_int); crime_mask |= crime_int; crime->imask = crime_mask; maceisa_mask |= 1 << (irq - 33); @@ -290,11 +308,11 @@ static void disable_maceisa_irq(unsigned int irq) unsigned int crime_int = 0; maceisa_mask &= ~(1 << (irq - 33)); - if(!(maceisa_mask & MACEISA_AUDIO_INT)) + if (!(maceisa_mask & MACEISA_AUDIO_INT)) crime_int |= MACE_AUDIO_INT; - if(!(maceisa_mask & MACEISA_MISC_INT)) + if (!(maceisa_mask & MACEISA_MISC_INT)) crime_int |= MACE_MISC_INT; - if(!(maceisa_mask & MACEISA_SUPERIO_INT)) + if (!(maceisa_mask & MACEISA_SUPERIO_INT)) crime_int |= MACE_SUPERIO_INT; crime_mask &= ~crime_int; crime->imask = crime_mask; @@ -327,12 +345,12 @@ static void end_maceisa_irq(unsigned irq) } static struct irq_chip ip32_maceisa_interrupt = { - .name = "IP32 MACE ISA", - .ack = mask_and_ack_maceisa_irq, - .mask = disable_maceisa_irq, - .mask_ack = mask_and_ack_maceisa_irq, - .unmask = enable_maceisa_irq, - .end = end_maceisa_irq, + .name = "IP32 MACE ISA", + .ack = mask_and_ack_maceisa_irq, + .mask = disable_maceisa_irq, + .mask_ack = mask_and_ack_maceisa_irq, + .unmask = enable_maceisa_irq, + .end = end_maceisa_irq, }; /* This is used for regular non-ISA, non-PCI MACE interrupts. That means @@ -411,7 +429,7 @@ static void ip32_irq0(void) irq = __ffs(mace_int & maceisa_mask) + MACEISA_AUDIO_SW_IRQ; } - DBG("*irq %u*\n", irq); + pr_debug("*irq %u*\n", irq); do_IRQ(irq); } @@ -472,23 +490,31 @@ void __init arch_init_irq(void) mips_cpu_irq_init(); for (irq = MIPS_CPU_IRQ_BASE + 8; irq <= IP32_IRQ_MAX; irq++) { - struct irq_chip *chip; - switch (irq) { case MACE_VID_IN1_IRQ ... MACE_PCI_BRIDGE_IRQ: - chip = &ip32_mace_interrupt; + set_irq_chip(irq, &ip32_mace_interrupt); break; case MACEPCI_SCSI0_IRQ ... MACEPCI_SHARED2_IRQ: - chip = &ip32_macepci_interrupt; + set_irq_chip(irq, &ip32_macepci_interrupt); + break; + case CRIME_GBE0_IRQ ... CRIME_GBE3_IRQ: + set_irq_chip(irq, &crime_edge_interrupt); + break; + case CRIME_CPUERR_IRQ: + case CRIME_MEMERR_IRQ: + set_irq_chip(irq, &crime_level_interrupt); break; - case CRIME_GBE0_IRQ ... CRIME_VICE_IRQ: - chip = &ip32_crime_interrupt; + case CRIME_RE_EMPTY_E_IRQ ... CRIME_RE_IDLE_E_IRQ: + case CRIME_SOFT0_IRQ ... CRIME_SOFT2_IRQ: + set_irq_chip(irq, &crime_edge_interrupt); + break; + case CRIME_VICE_IRQ: + set_irq_chip(irq, &crime_edge_interrupt); break; default: - chip = &ip32_maceisa_interrupt; + set_irq_chip(irq, &ip32_maceisa_interrupt); + break; } - - set_irq_chip(irq, chip); } setup_irq(CRIME_MEMERR_IRQ, &memerr_irq); setup_irq(CRIME_CPUERR_IRQ, &cpuerr_irq); diff --git a/arch/mips/sibyte/bcm1480/irq.c b/arch/mips/sibyte/bcm1480/irq.c index 10299bafeab..61790c4bfb6 100644 --- a/arch/mips/sibyte/bcm1480/irq.c +++ b/arch/mips/sibyte/bcm1480/irq.c @@ -280,27 +280,6 @@ static struct irqaction bcm1480_dummy_action = { .dev_id = 0 }; -int bcm1480_steal_irq(int irq) -{ - struct irq_desc *desc = irq_desc + irq; - unsigned long flags; - int retval = 0; - - if (irq >= BCM1480_NR_IRQS) - return -EINVAL; - - spin_lock_irqsave(&desc->lock, flags); - /* Don't allow sharing at all for these */ - if (desc->action != NULL) - retval = -EBUSY; - else { - desc->action = &bcm1480_dummy_action; - desc->depth = 0; - } - spin_unlock_irqrestore(&desc->lock, flags); - return 0; -} - /* * init_IRQ is called early in the boot sequence from init/main.c. It * is responsible for setting up the interrupt mapper and installing the @@ -386,8 +365,6 @@ void __init arch_init_irq(void) __raw_writeq(tmp, IOADDR(A_BCM1480_IMR_REGISTER(cpu, R_BCM1480_IMR_INTERRUPT_MASK_L))); } - bcm1480_steal_irq(K_BCM1480_INT_MBOX_0_0); - /* * Note that the timer interrupts are also mapped, but this is * done in bcm1480_time_init(). Also, the profiling driver @@ -411,7 +388,6 @@ void __init arch_init_irq(void) /* QQQ FIXME */ __raw_writeq(M_DUART_IMR_BRK, IO_SPACE_BASE + A_DUART_IMRREG(kgdb_port)); - bcm1480_steal_irq(kgdb_irq); __raw_writeq(IMR_IP6_VAL, IO_SPACE_BASE + A_BCM1480_IMR_REGISTER(0, R_BCM1480_IMR_INTERRUPT_MAP_BASE_H) + (kgdb_irq<<3)); diff --git a/arch/mips/sibyte/bcm1480/time.c b/arch/mips/sibyte/bcm1480/time.c index 610f0253954..bbf19bfabcc 100644 --- a/arch/mips/sibyte/bcm1480/time.c +++ b/arch/mips/sibyte/bcm1480/time.c @@ -37,8 +37,6 @@ #define IMR_IP3_VAL K_BCM1480_INT_MAP_I1 #define IMR_IP4_VAL K_BCM1480_INT_MAP_I2 -extern int bcm1480_steal_irq(int irq); - /* * The general purpose timer ticks at 1MHz independent if * the rest of the system @@ -121,7 +119,7 @@ void __cpuinit sb1480_clockevent_init(void) sprintf(name, "bcm1480-counter %d", cpu); cd->name = name; cd->features = CLOCK_EVT_FEAT_PERIODIC | - CLOCK_EVT_MODE_ONESHOT; + CLOCK_EVT_FEAT_ONESHOT; clockevent_set_clock(cd, V_SCD_TIMER_FREQ); cd->max_delta_ns = clockevent_delta2ns(0x7fffff, cd); cd->min_delta_ns = clockevent_delta2ns(1, cd); @@ -142,7 +140,6 @@ void __cpuinit sb1480_clockevent_init(void) R_BCM1480_IMR_INTERRUPT_MAP_BASE_H) + (irq << 3))); bcm1480_unmask_irq(cpu, irq); - bcm1480_steal_irq(irq); action->handler = sibyte_counter_handler; action->flags = IRQF_DISABLED | IRQF_PERCPU; diff --git a/arch/mips/sibyte/sb1250/irq.c b/arch/mips/sibyte/sb1250/irq.c index 53780a179d1..52d18fc91f3 100644 --- a/arch/mips/sibyte/sb1250/irq.c +++ b/arch/mips/sibyte/sb1250/irq.c @@ -250,27 +250,6 @@ static struct irqaction sb1250_dummy_action = { .dev_id = 0 }; -int sb1250_steal_irq(int irq) -{ - struct irq_desc *desc = irq_desc + irq; - unsigned long flags; - int retval = 0; - - if (irq >= SB1250_NR_IRQS) - return -EINVAL; - - spin_lock_irqsave(&desc->lock, flags); - /* Don't allow sharing at all for these */ - if (desc->action != NULL) - retval = -EBUSY; - else { - desc->action = &sb1250_dummy_action; - desc->depth = 0; - } - spin_unlock_irqrestore(&desc->lock, flags); - return 0; -} - /* * arch_init_irq is called early in the boot sequence from init/main.c via * init_IRQ. It is responsible for setting up the interrupt mapper and @@ -342,8 +321,6 @@ void __init arch_init_irq(void) __raw_writeq(tmp, IOADDR(A_IMR_REGISTER(0, R_IMR_INTERRUPT_MASK))); __raw_writeq(tmp, IOADDR(A_IMR_REGISTER(1, R_IMR_INTERRUPT_MASK))); - sb1250_steal_irq(K_INT_MBOX_0); - /* * Note that the timer interrupts are also mapped, but this is * done in sb1250_time_init(). Also, the profiling driver @@ -367,7 +344,6 @@ void __init arch_init_irq(void) __raw_writeq(M_DUART_IMR_BRK, IOADDR(A_DUART_IMRREG(kgdb_port))); - sb1250_steal_irq(kgdb_irq); __raw_writeq(IMR_IP6_VAL, IOADDR(A_IMR_REGISTER(0, R_IMR_INTERRUPT_MAP_BASE) + diff --git a/arch/mips/sibyte/sb1250/time.c b/arch/mips/sibyte/sb1250/time.c index a41e908bc21..95ad34e3fba 100644 --- a/arch/mips/sibyte/sb1250/time.c +++ b/arch/mips/sibyte/sb1250/time.c @@ -50,8 +50,6 @@ #define SB1250_HPT_VALUE M_SCD_TIMER_CNT /* max value */ -extern int sb1250_steal_irq(int irq); - /* * The general purpose timer ticks at 1 Mhz independent if * the rest of the system @@ -139,7 +137,7 @@ void __cpuinit sb1250_clockevent_init(void) sprintf(name, "bcm1480-counter %d", cpu); cd->name = name; cd->features = CLOCK_EVT_FEAT_PERIODIC | - CLOCK_EVT_MODE_ONESHOT; + CLOCK_EVT_FEAT_ONESHOT; clockevent_set_clock(cd, V_SCD_TIMER_FREQ); cd->max_delta_ns = clockevent_delta2ns(0x7fffff, cd); cd->min_delta_ns = clockevent_delta2ns(1, cd); @@ -159,7 +157,6 @@ void __cpuinit sb1250_clockevent_init(void) cd->cpumask = cpumask_of_cpu(0); sb1250_unmask_irq(cpu, irq); - sb1250_steal_irq(irq); action->handler = sibyte_counter_handler; action->flags = IRQF_DISABLED | IRQF_PERCPU; diff --git a/arch/mips/sni/time.c b/arch/mips/sni/time.c index 0910b35cb71..60bc62ef093 100644 --- a/arch/mips/sni/time.c +++ b/arch/mips/sni/time.c @@ -11,27 +11,78 @@ #define SNI_COUNTER2_DIV 64 #define SNI_COUNTER0_DIV ((SNI_CLOCK_TICK_RATE / SNI_COUNTER2_DIV) / HZ) -static void sni_a20r_timer_ack(void) +static void a20r_set_mode(enum clock_event_mode mode, + struct clock_event_device *evt) { - *(volatile u8 *)A20R_PT_TIM0_ACK = 0x0; wmb(); + switch (mode) { + case CLOCK_EVT_MODE_PERIODIC: + *(volatile u8 *)(A20R_PT_CLOCK_BASE + 12) = 0x34; + wmb(); + *(volatile u8 *)(A20R_PT_CLOCK_BASE + 0) = SNI_COUNTER0_DIV; + wmb(); + *(volatile u8 *)(A20R_PT_CLOCK_BASE + 0) = SNI_COUNTER0_DIV >> 8; + wmb(); + + *(volatile u8 *)(A20R_PT_CLOCK_BASE + 12) = 0xb4; + wmb(); + *(volatile u8 *)(A20R_PT_CLOCK_BASE + 8) = SNI_COUNTER2_DIV; + wmb(); + *(volatile u8 *)(A20R_PT_CLOCK_BASE + 8) = SNI_COUNTER2_DIV >> 8; + wmb(); + + break; + case CLOCK_EVT_MODE_ONESHOT: + case CLOCK_EVT_MODE_UNUSED: + case CLOCK_EVT_MODE_SHUTDOWN: + break; + case CLOCK_EVT_MODE_RESUME: + break; + } } +static struct clock_event_device a20r_clockevent_device = { + .name = "a20r-timer", + .features = CLOCK_EVT_FEAT_PERIODIC, + + /* .mult, .shift, .max_delta_ns and .min_delta_ns left uninitialized */ + + .rating = 300, + .irq = SNI_A20R_IRQ_TIMER, + .set_mode = a20r_set_mode, +}; + +static irqreturn_t a20r_interrupt(int irq, void *dev_id) +{ + struct clock_event_device *cd = dev_id; + + *(volatile u8 *)A20R_PT_TIM0_ACK = 0; + wmb(); + + cd->event_handler(cd); + + return IRQ_HANDLED; +} + +static struct irqaction a20r_irqaction = { + .handler = a20r_interrupt, + .flags = IRQF_DISABLED | IRQF_PERCPU, + .name = "a20r-timer", +}; + /* * a20r platform uses 2 counters to divide the input frequency. * Counter 2 output is connected to Counter 0 & 1 input. */ -static void __init sni_a20r_timer_setup(struct irqaction *irq) +static void __init sni_a20r_timer_setup(void) { - *(volatile u8 *)(A20R_PT_CLOCK_BASE + 12) = 0x34; wmb(); - *(volatile u8 *)(A20R_PT_CLOCK_BASE + 0) = (SNI_COUNTER0_DIV) & 0xff; wmb(); - *(volatile u8 *)(A20R_PT_CLOCK_BASE + 0) = (SNI_COUNTER0_DIV >> 8) & 0xff; wmb(); + struct clock_event_device *cd = &a20r_clockevent_device; + struct irqaction *action = &a20r_irqaction; + unsigned int cpu = smp_processor_id(); - *(volatile u8 *)(A20R_PT_CLOCK_BASE + 12) = 0xb4; wmb(); - *(volatile u8 *)(A20R_PT_CLOCK_BASE + 8) = (SNI_COUNTER2_DIV) & 0xff; wmb(); - *(volatile u8 *)(A20R_PT_CLOCK_BASE + 8) = (SNI_COUNTER2_DIV >> 8) & 0xff; wmb(); + cd->cpumask = cpumask_of_cpu(cpu); - setup_irq(SNI_A20R_IRQ_TIMER, irq); - mips_timer_ack = sni_a20r_timer_ack; + action->dev_id = cd; + setup_irq(SNI_A20R_IRQ_TIMER, &a20r_irqaction); } #define SNI_8254_TICK_RATE 1193182UL @@ -119,17 +170,14 @@ void __init plat_time_init(void) mips_hpt_frequency = r4k_tick * HZ; setup_pit_timer(); -} -void __init plat_timer_setup(struct irqaction *irq) -{ switch (sni_brd_type) { case SNI_BRD_10: case SNI_BRD_10NEW: case SNI_BRD_TOWER_OASIC: case SNI_BRD_MINITOWER: - sni_a20r_timer_setup(irq); - break; + sni_a20r_timer_setup(); + break; } } diff --git a/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_setup.c b/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_setup.c index c7470fba618..0299595ce1c 100644 --- a/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_setup.c +++ b/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_setup.c @@ -63,6 +63,7 @@ #include <asm/processor.h> #include <asm/reboot.h> #include <asm/time.h> +#include <asm/txx9tmr.h> #include <linux/bootmem.h> #include <linux/blkdev.h> #ifdef CONFIG_TOSHIBA_FPCIB0 @@ -93,7 +94,6 @@ #define TOSHIBA_RBTX4927_SETUP_EFWFU ( 1 << 3 ) #define TOSHIBA_RBTX4927_SETUP_SETUP ( 1 << 4 ) -#define TOSHIBA_RBTX4927_SETUP_TIME_INIT ( 1 << 5 ) #define TOSHIBA_RBTX4927_SETUP_PCIBIOS ( 1 << 7 ) #define TOSHIBA_RBTX4927_SETUP_PCI1 ( 1 << 8 ) #define TOSHIBA_RBTX4927_SETUP_PCI2 ( 1 << 9 ) @@ -130,7 +130,6 @@ extern void toshiba_rbtx4927_power_off(void); int tx4927_using_backplane = 0; -extern void gt64120_time_init(void); extern void toshiba_rbtx4927_irq_setup(void); char *prom_getcmdline(void); @@ -721,6 +720,7 @@ void toshiba_rbtx4927_power_off(void) void __init toshiba_rbtx4927_setup(void) { + int i; u32 cp0_config; char *argptr; @@ -764,6 +764,9 @@ void __init toshiba_rbtx4927_setup(void) _machine_halt = toshiba_rbtx4927_halt; pm_power_off = toshiba_rbtx4927_power_off; + for (i = 0; i < TX4927_NR_TMR; i++) + txx9_tmr_init(TX4927_TMR_REG(0) & 0xfffffffffULL); + #ifdef CONFIG_PCI /* PCIC */ @@ -892,7 +895,6 @@ void __init toshiba_rbtx4927_setup(void) #ifdef CONFIG_SERIAL_TXX9 { extern int early_serial_txx9_setup(struct uart_port *port); - int i; struct uart_port req; for(i = 0; i < 2; i++) { memset(&req, 0, sizeof(req)); @@ -937,12 +939,11 @@ void __init toshiba_rbtx4927_setup(void) void __init toshiba_rbtx4927_time_init(void) { - TOSHIBA_RBTX4927_SETUP_DPRINTK(TOSHIBA_RBTX4927_SETUP_TIME_INIT, "-\n"); - mips_hpt_frequency = tx4927_cpu_clock / 2; - - TOSHIBA_RBTX4927_SETUP_DPRINTK(TOSHIBA_RBTX4927_SETUP_TIME_INIT, "+\n"); - + if (tx4927_ccfgptr->ccfg & TX4927_CCFG_TINTDIS) + txx9_clockevent_init(TX4927_TMR_REG(0) & 0xfffffffffULL, + TXX9_IRQ_BASE + 17, + 50000000); } static int __init toshiba_rbtx4927_rtc_init(void) diff --git a/arch/mips/tx4938/toshiba_rbtx4938/setup.c b/arch/mips/tx4938/toshiba_rbtx4938/setup.c index ceecaf49895..4a8152375ef 100644 --- a/arch/mips/tx4938/toshiba_rbtx4938/setup.c +++ b/arch/mips/tx4938/toshiba_rbtx4938/setup.c @@ -26,6 +26,7 @@ #include <asm/reboot.h> #include <asm/irq.h> #include <asm/time.h> +#include <asm/txx9tmr.h> #include <asm/uaccess.h> #include <asm/io.h> #include <asm/bootinfo.h> @@ -773,15 +774,8 @@ void __init tx4938_board_setup(void) } /* TMR */ - /* disable all timers */ - for (i = 0; i < TX4938_NR_TMR; i++) { - tx4938_tmrptr(i)->tcr = 0x00000020; - tx4938_tmrptr(i)->tisr = 0; - tx4938_tmrptr(i)->cpra = 0xffffffff; - tx4938_tmrptr(i)->itmr = 0; - tx4938_tmrptr(i)->ccdr = 0; - tx4938_tmrptr(i)->pgmr = 0; - } + for (i = 0; i < TX4938_NR_TMR; i++) + txx9_tmr_init(TX4938_TMR_REG(i) & 0xfffffffffULL); /* enable DMA */ TX4938_WR64(0xff1fb150, TX4938_DMA_MCR_MSTEN); @@ -852,12 +846,13 @@ void tx4938_report_pcic_status(void) #endif /* CONFIG_PCI */ -/* We use onchip r4k counter or TMR timer as our system wide timer - * interrupt running at 100HZ. */ - void __init plat_time_init(void) { mips_hpt_frequency = txx9_cpu_clock / 2; + if (tx4938_ccfgptr->ccfg & TX4938_CCFG_TINTDIS) + txx9_clockevent_init(TX4938_TMR_REG(0) & 0xfffffffffULL, + TXX9_IRQ_BASE + TX4938_IR_TMR(0), + txx9_gbus_clock / 2); } void __init toshiba_rbtx4938_setup(void) diff --git a/arch/um/Kconfig.i386 b/arch/um/Kconfig.i386 index 9876d80d85d..e0ac74e5d4c 100644 --- a/arch/um/Kconfig.i386 +++ b/arch/um/Kconfig.i386 @@ -1,6 +1,6 @@ menu "Host processor type and features" -source "arch/i386/Kconfig.cpu" +source "arch/x86/Kconfig.cpu" endmenu diff --git a/arch/um/Makefile-i386 b/arch/um/Makefile-i386 index 0178df30693..b01dfb00e5f 100644 --- a/arch/um/Makefile-i386 +++ b/arch/um/Makefile-i386 @@ -9,6 +9,7 @@ ELF_ARCH := $(SUBARCH) ELF_FORMAT := elf32-$(SUBARCH) OBJCOPYFLAGS := -O binary -R .note -R .comment -S HEADER_ARCH := x86 +CHECKFLAGS += -D__i386__ ifeq ("$(origin SUBARCH)", "command line") ifneq ("$(shell uname -m | sed -e s/i.86/i386/)", "$(SUBARCH)") @@ -26,10 +27,8 @@ AFLAGS += -DCONFIG_X86_32 CONFIG_X86_32 := y export CONFIG_X86_32 -ARCH_KERNEL_DEFINES += -U__$(SUBARCH)__ -U$(SUBARCH) - # First of all, tune CFLAGS for the specific CPU. This actually sets cflags-y. -include $(srctree)/arch/i386/Makefile.cpu +include $(srctree)/arch/x86/Makefile_32.cpu # prevent gcc from keeping the stack 16 byte aligned. Taken from i386. cflags-y += $(call cc-option,-mpreferred-stack-boundary=2) diff --git a/arch/um/Makefile-x86_64 b/arch/um/Makefile-x86_64 index fe5316f0c6a..8ed362f9358 100644 --- a/arch/um/Makefile-x86_64 +++ b/arch/um/Makefile-x86_64 @@ -6,12 +6,9 @@ START := 0x60000000 _extra_flags_ = -fno-builtin -m64 -#We #undef __x86_64__ for kernelspace, not for userspace where -#it's needed for headers to work! -ARCH_KERNEL_DEFINES = -U__$(SUBARCH)__ KBUILD_CFLAGS += $(_extra_flags_) -CHECKFLAGS += -m64 +CHECKFLAGS += -m64 -D__x86_64__ KBUILD_AFLAGS += -m64 LDFLAGS += -m elf_x86_64 KBUILD_CPPFLAGS += -m64 diff --git a/arch/um/kernel/mem.c b/arch/um/kernel/mem.c index 8456397f5f4..59822dee438 100644 --- a/arch/um/kernel/mem.c +++ b/arch/um/kernel/mem.c @@ -165,7 +165,7 @@ static void __init kmap_init(void) kmap_prot = PAGE_KERNEL; } -static void init_highmem(void) +static void __init init_highmem(void) { pgd_t *pgd; pud_t *pud; diff --git a/arch/um/sys-i386/ptrace.c b/arch/um/sys-i386/ptrace.c index 9657c89fdf3..bd3da8a61f6 100644 --- a/arch/um/sys-i386/ptrace.c +++ b/arch/um/sys-i386/ptrace.c @@ -155,7 +155,7 @@ int get_fpregs(struct user_i387_struct __user *buf, struct task_struct *child) if (err) return err; - n = copy_to_user((void *) buf, fpregs, sizeof(fpregs)); + n = copy_to_user(buf, fpregs, sizeof(fpregs)); if(n > 0) return -EFAULT; @@ -168,7 +168,7 @@ int set_fpregs(struct user_i387_struct __user *buf, struct task_struct *child) long fpregs[HOST_FP_SIZE]; BUG_ON(sizeof(*buf) != sizeof(fpregs)); - n = copy_from_user(fpregs, (void *) buf, sizeof(fpregs)); + n = copy_from_user(fpregs, buf, sizeof(fpregs)); if (n > 0) return -EFAULT; @@ -185,7 +185,7 @@ int get_fpxregs(struct user_fxsr_struct __user *buf, struct task_struct *child) if (err) return err; - n = copy_to_user((void *) buf, fpregs, sizeof(fpregs)); + n = copy_to_user(buf, fpregs, sizeof(fpregs)); if(n > 0) return -EFAULT; @@ -198,7 +198,7 @@ int set_fpxregs(struct user_fxsr_struct __user *buf, struct task_struct *child) long fpregs[HOST_XFP_SIZE]; BUG_ON(sizeof(*buf) != sizeof(fpregs)); - n = copy_from_user(fpregs, (void *) buf, sizeof(fpregs)); + n = copy_from_user(fpregs, buf, sizeof(fpregs)); if (n > 0) return -EFAULT; diff --git a/arch/um/sys-x86_64/ptrace.c b/arch/um/sys-x86_64/ptrace.c index a3cfeed17af..b7631b0e9dd 100644 --- a/arch/um/sys-x86_64/ptrace.c +++ b/arch/um/sys-x86_64/ptrace.c @@ -154,7 +154,7 @@ int get_fpregs(struct user_i387_struct __user *buf, struct task_struct *child) if (err) return err; - n = copy_to_user((void *) buf, fpregs, sizeof(fpregs)); + n = copy_to_user(buf, fpregs, sizeof(fpregs)); if(n > 0) return -EFAULT; @@ -167,7 +167,7 @@ int set_fpregs(struct user_i387_struct __user *buf, struct task_struct *child) long fpregs[HOST_FP_SIZE]; BUG_ON(sizeof(*buf) != sizeof(fpregs)); - n = copy_from_user(fpregs, (void *) buf, sizeof(fpregs)); + n = copy_from_user(fpregs, buf, sizeof(fpregs)); if (n > 0) return -EFAULT; diff --git a/arch/x86/Kconfig.debug b/arch/x86/Kconfig.debug index 970b2defe7d..761ca7b5f12 100644 --- a/arch/x86/Kconfig.debug +++ b/arch/x86/Kconfig.debug @@ -6,9 +6,8 @@ config TRACE_IRQFLAGS_SUPPORT source "lib/Kconfig.debug" config EARLY_PRINTK - bool "Early printk" if EMBEDDED && DEBUG_KERNEL + bool "Early printk" if EMBEDDED && DEBUG_KERNEL && X86_32 default y - depends on X86_32 help Write kernel log output directly into the VGA buffer or to a serial port. @@ -91,7 +90,7 @@ config DOUBLEFAULT config IOMMU_DEBUG bool "Enable IOMMU debugging" - depends on IOMMU && DEBUG_KERNEL + depends on GART_IOMMU && DEBUG_KERNEL depends on X86_64 help Force the IOMMU to on even when you have less than 4GB of @@ -113,7 +112,4 @@ config IOMMU_LEAK Add a simple leak tracer to the IOMMU code. This is useful when you are debugging a buggy device driver that leaks IOMMU mappings. -#config X86_REMOTE_DEBUG -# bool "kgdb debugging stub" - endmenu diff --git a/arch/x86/Kconfig.x86_64 b/arch/x86/Kconfig.x86_64 index e2542e5b536..cc468ea6124 100644 --- a/arch/x86/Kconfig.x86_64 +++ b/arch/x86/Kconfig.x86_64 @@ -97,10 +97,6 @@ config X86_CMPXCHG bool default y -config EARLY_PRINTK - bool - default y - config GENERIC_ISA_DMA bool default y @@ -479,8 +475,8 @@ config HPET_EMULATE_RTC # Mark as embedded because too many people got it wrong. # The code disables itself when not needed. -config IOMMU - bool "IOMMU support" if EMBEDDED +config GART_IOMMU + bool "GART IOMMU support" if EMBEDDED default y select SWIOTLB select AGP @@ -687,7 +683,7 @@ source kernel/Kconfig.hz config K8_NB def_bool y - depends on AGP_AMD64 || IOMMU || (PCI && NUMA) + depends on AGP_AMD64 || GART_IOMMU || (PCI && NUMA) endmenu @@ -753,7 +749,6 @@ config PCI_DOMAINS config DMAR bool "Support for DMA Remapping Devices (EXPERIMENTAL)" depends on PCI_MSI && ACPI && EXPERIMENTAL - default y help DMA remapping (DMAR) devices support enables independent address translations for Direct Memory Access (DMA) from devices. diff --git a/arch/x86/configs/x86_64_defconfig b/arch/x86/configs/x86_64_defconfig index b091c5e3555..38a83f9c966 100644 --- a/arch/x86/configs/x86_64_defconfig +++ b/arch/x86/configs/x86_64_defconfig @@ -170,7 +170,7 @@ CONFIG_HOTPLUG_CPU=y CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y CONFIG_HPET_TIMER=y CONFIG_HPET_EMULATE_RTC=y -CONFIG_IOMMU=y +CONFIG_GART_IOMMU=y # CONFIG_CALGARY_IOMMU is not set CONFIG_SWIOTLB=y CONFIG_X86_MCE=y diff --git a/arch/x86/kernel/Makefile_64 b/arch/x86/kernel/Makefile_64 index 466337ae9a1..24671c3838b 100644 --- a/arch/x86/kernel/Makefile_64 +++ b/arch/x86/kernel/Makefile_64 @@ -25,7 +25,7 @@ obj-$(CONFIG_CRASH_DUMP) += crash_dump_64.o obj-$(CONFIG_PM) += suspend_64.o obj-$(CONFIG_HIBERNATION) += suspend_asm_64.o obj-$(CONFIG_EARLY_PRINTK) += early_printk.o -obj-$(CONFIG_IOMMU) += pci-gart_64.o aperture_64.o +obj-$(CONFIG_GART_IOMMU) += pci-gart_64.o aperture_64.o obj-$(CONFIG_CALGARY_IOMMU) += pci-calgary_64.o tce_64.o obj-$(CONFIG_SWIOTLB) += pci-swiotlb_64.o obj-$(CONFIG_KPROBES) += kprobes_64.o diff --git a/arch/x86/kernel/aperture_64.c b/arch/x86/kernel/aperture_64.c index 8f681cae7bf..5b6992799c9 100644 --- a/arch/x86/kernel/aperture_64.c +++ b/arch/x86/kernel/aperture_64.c @@ -20,14 +20,14 @@ #include <linux/ioport.h> #include <asm/e820.h> #include <asm/io.h> -#include <asm/iommu.h> +#include <asm/gart.h> #include <asm/pci-direct.h> #include <asm/dma.h> #include <asm/k8.h> -int iommu_aperture; -int iommu_aperture_disabled __initdata = 0; -int iommu_aperture_allowed __initdata = 0; +int gart_iommu_aperture; +int gart_iommu_aperture_disabled __initdata = 0; +int gart_iommu_aperture_allowed __initdata = 0; int fallback_aper_order __initdata = 1; /* 64MB */ int fallback_aper_force __initdata = 0; @@ -204,14 +204,15 @@ static __u32 __init search_agp_bridge(u32 *order, int *valid_agp) return 0; } -void __init iommu_hole_init(void) +void __init gart_iommu_hole_init(void) { int fix, num; u32 aper_size, aper_alloc = 0, aper_order = 0, last_aper_order = 0; u64 aper_base, last_aper_base = 0; int valid_agp = 0; - if (iommu_aperture_disabled || !fix_aperture || !early_pci_allowed()) + if (gart_iommu_aperture_disabled || !fix_aperture || + !early_pci_allowed()) return; printk(KERN_INFO "Checking aperture...\n"); @@ -222,7 +223,7 @@ void __init iommu_hole_init(void) continue; iommu_detected = 1; - iommu_aperture = 1; + gart_iommu_aperture = 1; aper_order = (read_pci_config(0, num, 3, 0x90) >> 1) & 7; aper_size = (32 * 1024 * 1024) << aper_order; diff --git a/arch/x86/kernel/cpu/proc.c b/arch/x86/kernel/cpu/proc.c index 2d42b414b77..066f8c6af4d 100644 --- a/arch/x86/kernel/cpu/proc.c +++ b/arch/x86/kernel/cpu/proc.c @@ -49,7 +49,7 @@ static int show_cpuinfo(struct seq_file *m, void *v) /* Intel-defined (#2) */ "pni", NULL, NULL, "monitor", "ds_cpl", "vmx", "smx", "est", "tm2", "ssse3", "cid", NULL, NULL, "cx16", "xtpr", NULL, - NULL, NULL, "dca", NULL, NULL, NULL, NULL, "popcnt", + NULL, NULL, "dca", "sse4_1", "sse4_2", NULL, NULL, "popcnt", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* VIA/Cyrix/Centaur-defined */ @@ -59,10 +59,10 @@ static int show_cpuinfo(struct seq_file *m, void *v) NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* AMD-defined (#2) */ - "lahf_lm", "cmp_legacy", "svm", "extapic", "cr8_legacy", - "altmovcr8", "abm", "sse4a", - "misalignsse", "3dnowprefetch", - "osvw", "ibs", NULL, NULL, NULL, NULL, + "lahf_lm", "cmp_legacy", "svm", "extapic", + "cr8_legacy", "abm", "sse4a", "misalignsse", + "3dnowprefetch", "osvw", "ibs", "sse5", + "skinit", "wdt", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, diff --git a/arch/x86/kernel/early-quirks.c b/arch/x86/kernel/early-quirks.c index 639e6320518..88bb83ec895 100644 --- a/arch/x86/kernel/early-quirks.c +++ b/arch/x86/kernel/early-quirks.c @@ -17,19 +17,19 @@ #include <asm/io_apic.h> #include <asm/apic.h> -#ifdef CONFIG_IOMMU -#include <asm/iommu.h> +#ifdef CONFIG_GART_IOMMU +#include <asm/gart.h> #endif static void __init via_bugs(void) { -#ifdef CONFIG_IOMMU +#ifdef CONFIG_GART_IOMMU if ((end_pfn > MAX_DMA32_PFN || force_iommu) && - !iommu_aperture_allowed) { + !gart_iommu_aperture_allowed) { printk(KERN_INFO "Looks like a VIA chipset. Disabling IOMMU." " Override with iommu=allowed\n"); - iommu_aperture_disabled = 1; + gart_iommu_aperture_disabled = 1; } #endif } diff --git a/arch/x86/kernel/pci-calgary_64.c b/arch/x86/kernel/pci-calgary_64.c index 1a20fe31338..6bf1f716909 100644 --- a/arch/x86/kernel/pci-calgary_64.c +++ b/arch/x86/kernel/pci-calgary_64.c @@ -36,7 +36,7 @@ #include <linux/pci.h> #include <linux/delay.h> #include <linux/scatterlist.h> -#include <asm/iommu.h> +#include <asm/gart.h> #include <asm/calgary.h> #include <asm/tce.h> #include <asm/pci-direct.h> diff --git a/arch/x86/kernel/pci-dma_64.c b/arch/x86/kernel/pci-dma_64.c index 393e2725a6e..aa805b11b24 100644 --- a/arch/x86/kernel/pci-dma_64.c +++ b/arch/x86/kernel/pci-dma_64.c @@ -9,7 +9,7 @@ #include <linux/module.h> #include <linux/dmar.h> #include <asm/io.h> -#include <asm/iommu.h> +#include <asm/gart.h> #include <asm/calgary.h> int iommu_merge __read_mostly = 1; @@ -275,7 +275,7 @@ __init int iommu_setup(char *p) swiotlb = 1; #endif -#ifdef CONFIG_IOMMU +#ifdef CONFIG_GART_IOMMU gart_parse_options(p); #endif @@ -298,8 +298,8 @@ void __init pci_iommu_alloc(void) * The order of these functions is important for * fall-back/fail-over reasons */ -#ifdef CONFIG_IOMMU - iommu_hole_init(); +#ifdef CONFIG_GART_IOMMU + gart_iommu_hole_init(); #endif #ifdef CONFIG_CALGARY_IOMMU @@ -321,7 +321,7 @@ static int __init pci_iommu_init(void) intel_iommu_init(); -#ifdef CONFIG_IOMMU +#ifdef CONFIG_GART_IOMMU gart_iommu_init(); #endif diff --git a/arch/x86/kernel/pci-gart_64.c b/arch/x86/kernel/pci-gart_64.c index ae7e0161ce4..06bcba53604 100644 --- a/arch/x86/kernel/pci-gart_64.c +++ b/arch/x86/kernel/pci-gart_64.c @@ -30,17 +30,17 @@ #include <asm/mtrr.h> #include <asm/pgtable.h> #include <asm/proto.h> -#include <asm/iommu.h> +#include <asm/gart.h> #include <asm/cacheflush.h> #include <asm/swiotlb.h> #include <asm/dma.h> #include <asm/k8.h> -unsigned long iommu_bus_base; /* GART remapping area (physical) */ +static unsigned long iommu_bus_base; /* GART remapping area (physical) */ static unsigned long iommu_size; /* size of remapping area bytes */ static unsigned long iommu_pages; /* .. and in pages */ -u32 *iommu_gatt_base; /* Remapping table */ +static u32 *iommu_gatt_base; /* Remapping table */ /* If this is disabled the IOMMU will use an optimized flushing strategy of only flushing when an mapping is reused. With it true the GART is flushed @@ -135,8 +135,8 @@ static void flush_gart(void) /* Debugging aid for drivers that don't free their IOMMU tables */ static void **iommu_leak_tab; static int leak_trace; -int iommu_leak_pages = 20; -void dump_leak(void) +static int iommu_leak_pages = 20; +static void dump_leak(void) { int i; static int dump; @@ -435,7 +435,7 @@ static int gart_map_sg(struct device *dev, struct scatterlist *sg, int nents, error: flush_gart(); - gart_unmap_sg(dev, sg, nents, dir); + gart_unmap_sg(dev, sg, out, dir); /* When it was forced or merged try again in a dumb way */ if (force_iommu || iommu_merge) { out = dma_map_sg_nonforce(dev, sg, nents, dir); @@ -627,12 +627,12 @@ void __init gart_iommu_init(void) return; /* Did we detect a different HW IOMMU? */ - if (iommu_detected && !iommu_aperture) + if (iommu_detected && !gart_iommu_aperture) return; if (no_iommu || (!force_iommu && end_pfn <= MAX_DMA32_PFN) || - !iommu_aperture || + !gart_iommu_aperture || (no_agp && init_k8_gatt(&info) < 0)) { if (end_pfn > MAX_DMA32_PFN) { printk(KERN_ERR "WARNING more than 4GB of memory " @@ -733,9 +733,9 @@ void __init gart_parse_options(char *p) fix_aperture = 0; /* duplicated from pci-dma.c */ if (!strncmp(p,"force",5)) - iommu_aperture_allowed = 1; + gart_iommu_aperture_allowed = 1; if (!strncmp(p,"allowed",7)) - iommu_aperture_allowed = 1; + gart_iommu_aperture_allowed = 1; if (!strncmp(p, "memaper", 7)) { fallback_aper_force = 1; p += 7; diff --git a/arch/x86/kernel/pci-nommu_64.c b/arch/x86/kernel/pci-nommu_64.c index faf70bdca33..ab08e183222 100644 --- a/arch/x86/kernel/pci-nommu_64.c +++ b/arch/x86/kernel/pci-nommu_64.c @@ -7,7 +7,7 @@ #include <linux/dma-mapping.h> #include <linux/scatterlist.h> -#include <asm/iommu.h> +#include <asm/gart.h> #include <asm/processor.h> #include <asm/dma.h> diff --git a/arch/x86/kernel/pci-swiotlb_64.c b/arch/x86/kernel/pci-swiotlb_64.c index b2f405ea7c8..102866d729a 100644 --- a/arch/x86/kernel/pci-swiotlb_64.c +++ b/arch/x86/kernel/pci-swiotlb_64.c @@ -5,7 +5,7 @@ #include <linux/module.h> #include <linux/dma-mapping.h> -#include <asm/iommu.h> +#include <asm/gart.h> #include <asm/swiotlb.h> #include <asm/dma.h> diff --git a/arch/x86/kernel/reboot_64.c b/arch/x86/kernel/reboot_64.c index 776eb06b651..71b13c5f581 100644 --- a/arch/x86/kernel/reboot_64.c +++ b/arch/x86/kernel/reboot_64.c @@ -17,7 +17,7 @@ #include <asm/pgtable.h> #include <asm/tlbflush.h> #include <asm/apic.h> -#include <asm/iommu.h> +#include <asm/gart.h> /* * Power off function, if any diff --git a/arch/x86/kernel/setup_32.c b/arch/x86/kernel/setup_32.c index cc0e91447b7..e1e18c34c82 100644 --- a/arch/x86/kernel/setup_32.c +++ b/arch/x86/kernel/setup_32.c @@ -86,9 +86,6 @@ unsigned long mmu_cr4_features; /* for MCA, but anyone else can use it if they want */ unsigned int machine_id; -#ifdef CONFIG_MCA -EXPORT_SYMBOL(machine_id); -#endif unsigned int machine_submodel_id; unsigned int BIOS_revision; unsigned int mca_pentium_flag; diff --git a/arch/x86/kernel/setup_64.c b/arch/x86/kernel/setup_64.c index e7a9e36bd52..238633d3d09 100644 --- a/arch/x86/kernel/setup_64.c +++ b/arch/x86/kernel/setup_64.c @@ -1040,7 +1040,7 @@ static int show_cpuinfo(struct seq_file *m, void *v) /* Intel-defined (#2) */ "pni", NULL, NULL, "monitor", "ds_cpl", "vmx", "smx", "est", "tm2", "ssse3", "cid", NULL, NULL, "cx16", "xtpr", NULL, - NULL, NULL, "dca", NULL, NULL, NULL, NULL, "popcnt", + NULL, NULL, "dca", "sse4_1", "sse4_2", NULL, NULL, "popcnt", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* VIA/Cyrix/Centaur-defined */ @@ -1050,10 +1050,10 @@ static int show_cpuinfo(struct seq_file *m, void *v) NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* AMD-defined (#2) */ - "lahf_lm", "cmp_legacy", "svm", "extapic", "cr8_legacy", - "altmovcr8", "abm", "sse4a", - "misalignsse", "3dnowprefetch", - "osvw", "ibs", NULL, NULL, NULL, NULL, + "lahf_lm", "cmp_legacy", "svm", "extapic", + "cr8_legacy", "abm", "sse4a", "misalignsse", + "3dnowprefetch", "osvw", "ibs", "sse5", + "skinit", "wdt", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, diff --git a/arch/x86/mm/discontig_32.c b/arch/x86/mm/discontig_32.c index fe608a45ffb..13a474d3c6e 100644 --- a/arch/x86/mm/discontig_32.c +++ b/arch/x86/mm/discontig_32.c @@ -40,7 +40,7 @@ struct pglist_data *node_data[MAX_NUMNODES] __read_mostly; EXPORT_SYMBOL(node_data); -bootmem_data_t node0_bdata; +static bootmem_data_t node0_bdata; /* * numa interface - we expect the numa architecture specific code to have @@ -404,7 +404,7 @@ void __init set_highmem_pages_init(int bad_ppro) } #ifdef CONFIG_MEMORY_HOTPLUG -int paddr_to_nid(u64 addr) +static int paddr_to_nid(u64 addr) { int nid; unsigned long pfn = PFN_DOWN(addr); diff --git a/arch/x86/mm/init_64.c b/arch/x86/mm/init_64.c index 1e3862e4106..a7308b2cd05 100644 --- a/arch/x86/mm/init_64.c +++ b/arch/x86/mm/init_64.c @@ -728,12 +728,6 @@ int in_gate_area_no_task(unsigned long addr) return (addr >= VSYSCALL_START) && (addr < VSYSCALL_END); } -void * __init alloc_bootmem_high_node(pg_data_t *pgdat, unsigned long size) -{ - return __alloc_bootmem_core(pgdat->bdata, size, - SMP_CACHE_BYTES, (4UL*1024*1024*1024), 0); -} - const char *arch_vma_name(struct vm_area_struct *vma) { if (vma->vm_mm && vma->vm_start == (long)vma->vm_mm->context.vdso) diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c index 54dc0543900..e47a9309eb4 100644 --- a/block/cfq-iosched.c +++ b/block/cfq-iosched.c @@ -1443,8 +1443,11 @@ cfq_get_queue(struct cfq_data *cfqd, int is_sync, struct task_struct *tsk, cfqq = *async_cfqq; } - if (!cfqq) + if (!cfqq) { cfqq = cfq_find_alloc_queue(cfqd, is_sync, tsk, gfp_mask); + if (!cfqq) + return NULL; + } /* * pin the queue now that it's allocated, scheduler exit will prune it @@ -2053,7 +2056,7 @@ static void cfq_shutdown_timer_wq(struct cfq_data *cfqd) { del_timer_sync(&cfqd->idle_slice_timer); del_timer_sync(&cfqd->idle_class_timer); - blk_sync_queue(cfqd->queue); + kblockd_flush_work(&cfqd->unplug_work); } static void cfq_put_async_queues(struct cfq_data *cfqd) diff --git a/block/compat_ioctl.c b/block/compat_ioctl.c index f84093b97f7..cae0a852619 100644 --- a/block/compat_ioctl.c +++ b/block/compat_ioctl.c @@ -581,7 +581,7 @@ static int compat_blkdev_driver_ioctl(struct inode *inode, struct file *file, { int ret; - switch (arg) { + switch (cmd) { case HDIO_GET_UNMASKINTR: case HDIO_GET_MULTCOUNT: case HDIO_GET_KEEPSETTINGS: diff --git a/block/ll_rw_blk.c b/block/ll_rw_blk.c index b01dee3ae7f..56f2646612e 100644 --- a/block/ll_rw_blk.c +++ b/block/ll_rw_blk.c @@ -39,7 +39,7 @@ static void blk_unplug_work(struct work_struct *work); static void blk_unplug_timeout(unsigned long data); -static void drive_stat_acct(struct request *rq, int nr_sectors, int new_io); +static void drive_stat_acct(struct request *rq, int new_io); static void init_request_from_bio(struct request *req, struct bio *bio); static int __make_request(struct request_queue *q, struct bio *bio); static struct io_context *current_io_context(gfp_t gfp_flags, int node); @@ -791,7 +791,6 @@ static int __blk_free_tags(struct blk_queue_tag *bqt) retval = atomic_dec_and_test(&bqt->refcnt); if (retval) { BUG_ON(bqt->busy); - BUG_ON(!list_empty(&bqt->busy_list)); kfree(bqt->tag_index); bqt->tag_index = NULL; @@ -903,7 +902,6 @@ static struct blk_queue_tag *__blk_queue_init_tags(struct request_queue *q, if (init_tag_map(q, tags, depth)) goto fail; - INIT_LIST_HEAD(&tags->busy_list); tags->busy = 0; atomic_set(&tags->refcnt, 1); return tags; @@ -954,6 +952,7 @@ int blk_queue_init_tags(struct request_queue *q, int depth, */ q->queue_tags = tags; q->queue_flags |= (1 << QUEUE_FLAG_QUEUED); + INIT_LIST_HEAD(&q->tag_busy_list); return 0; fail: kfree(tags); @@ -1057,18 +1056,16 @@ void blk_queue_end_tag(struct request_queue *q, struct request *rq) bqt->tag_index[tag] = NULL; - /* - * We use test_and_clear_bit's memory ordering properties here. - * The tag_map bit acts as a lock for tag_index[bit], so we need - * a barrer before clearing the bit (precisely: release semantics). - * Could use clear_bit_unlock when it is merged. - */ - if (unlikely(!test_and_clear_bit(tag, bqt->tag_map))) { + if (unlikely(!test_bit(tag, bqt->tag_map))) { printk(KERN_ERR "%s: attempt to clear non-busy tag (%d)\n", __FUNCTION__, tag); return; } - + /* + * The tag_map bit acts as a lock for tag_index[bit], so we need + * unlock memory barrier semantics. + */ + clear_bit_unlock(tag, bqt->tag_map); bqt->busy--; } @@ -1114,17 +1111,17 @@ int blk_queue_start_tag(struct request_queue *q, struct request *rq) if (tag >= bqt->max_depth) return 1; - } while (test_and_set_bit(tag, bqt->tag_map)); + } while (test_and_set_bit_lock(tag, bqt->tag_map)); /* - * We rely on test_and_set_bit providing lock memory ordering semantics - * (could use test_and_set_bit_lock when it is merged). + * We need lock ordering semantics given by test_and_set_bit_lock. + * See blk_queue_end_tag for details. */ rq->cmd_flags |= REQ_QUEUED; rq->tag = tag; bqt->tag_index[tag] = rq; blkdev_dequeue_request(rq); - list_add(&rq->queuelist, &bqt->busy_list); + list_add(&rq->queuelist, &q->tag_busy_list); bqt->busy++; return 0; } @@ -1145,11 +1142,10 @@ EXPORT_SYMBOL(blk_queue_start_tag); **/ void blk_queue_invalidate_tags(struct request_queue *q) { - struct blk_queue_tag *bqt = q->queue_tags; struct list_head *tmp, *n; struct request *rq; - list_for_each_safe(tmp, n, &bqt->busy_list) { + list_for_each_safe(tmp, n, &q->tag_busy_list) { rq = list_entry_rq(tmp); if (rq->tag == -1) { @@ -1738,6 +1734,7 @@ EXPORT_SYMBOL(blk_stop_queue); void blk_sync_queue(struct request_queue *q) { del_timer_sync(&q->unplug_timer); + kblockd_flush_work(&q->unplug_work); } EXPORT_SYMBOL(blk_sync_queue); @@ -2341,7 +2338,7 @@ void blk_insert_request(struct request_queue *q, struct request *rq, if (blk_rq_tagged(rq)) blk_queue_end_tag(q, rq); - drive_stat_acct(rq, rq->nr_sectors, 1); + drive_stat_acct(rq, 1); __elv_add_request(q, rq, where, 0); blk_start_queueing(q); spin_unlock_irqrestore(q->queue_lock, flags); @@ -2736,7 +2733,7 @@ int blkdev_issue_flush(struct block_device *bdev, sector_t *error_sector) EXPORT_SYMBOL(blkdev_issue_flush); -static void drive_stat_acct(struct request *rq, int nr_sectors, int new_io) +static void drive_stat_acct(struct request *rq, int new_io) { int rw = rq_data_dir(rq); @@ -2758,7 +2755,7 @@ static void drive_stat_acct(struct request *rq, int nr_sectors, int new_io) */ static inline void add_request(struct request_queue * q, struct request * req) { - drive_stat_acct(req, req->nr_sectors, 1); + drive_stat_acct(req, 1); /* * elevator indicated where it wants this request to be @@ -3015,7 +3012,7 @@ static int __make_request(struct request_queue *q, struct bio *bio) req->biotail = bio; req->nr_sectors = req->hard_nr_sectors += nr_sectors; req->ioprio = ioprio_best(req->ioprio, prio); - drive_stat_acct(req, nr_sectors, 0); + drive_stat_acct(req, 0); if (!attempt_back_merge(q, req)) elv_merged_request(q, req, el_ret); goto out; @@ -3042,7 +3039,7 @@ static int __make_request(struct request_queue *q, struct bio *bio) req->sector = req->hard_sector = bio->bi_sector; req->nr_sectors = req->hard_nr_sectors += nr_sectors; req->ioprio = ioprio_best(req->ioprio, prio); - drive_stat_acct(req, nr_sectors, 0); + drive_stat_acct(req, 0); if (!attempt_front_merge(q, req)) elv_merged_request(q, req, el_ret); goto out; diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig index 5d0e26a5c34..da3a08fa9e4 100644 --- a/drivers/acpi/Kconfig +++ b/drivers/acpi/Kconfig @@ -3,7 +3,7 @@ # menuconfig ACPI - bool "ACPI Support (Advanced Configuration and Power Interface) Support" + bool "ACPI (Advanced Configuration and Power Interface) Support" depends on !X86_NUMAQ depends on !X86_VISWS depends on !IA64_HP_SIM @@ -88,7 +88,8 @@ config ACPI_PROC_EVENT config ACPI_AC tristate "AC Adapter" - depends on X86 && POWER_SUPPLY + depends on X86 + select POWER_SUPPLY default y help This driver adds support for the AC Adapter object, which indicates @@ -97,7 +98,8 @@ config ACPI_AC config ACPI_BATTERY tristate "Battery" - depends on X86 && POWER_SUPPLY + depends on X86 + select POWER_SUPPLY default y help This driver adds support for battery information through @@ -352,7 +354,7 @@ config ACPI_HOTPLUG_MEMORY config ACPI_SBS tristate "Smart Battery System" depends on X86 - depends on POWER_SUPPLY + select POWER_SUPPLY help This driver adds support for the Smart Battery System, another type of access to battery information, found on some laptops. diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c index 681e26b56b1..c2ce0ad2169 100644 --- a/drivers/acpi/battery.c +++ b/drivers/acpi/battery.c @@ -125,11 +125,15 @@ static int acpi_battery_technology(struct acpi_battery *battery) return POWER_SUPPLY_TECHNOLOGY_NiMH; if (!strcasecmp("LION", battery->type)) return POWER_SUPPLY_TECHNOLOGY_LION; + if (!strcasecmp("LI-ION", battery->type)) + return POWER_SUPPLY_TECHNOLOGY_LION; if (!strcasecmp("LiP", battery->type)) return POWER_SUPPLY_TECHNOLOGY_LIPO; return POWER_SUPPLY_TECHNOLOGY_UNKNOWN; } +static int acpi_battery_update(struct acpi_battery *battery); + static int acpi_battery_get_property(struct power_supply *psy, enum power_supply_property psp, union power_supply_propval *val) @@ -139,6 +143,7 @@ static int acpi_battery_get_property(struct power_supply *psy, if ((!acpi_battery_present(battery)) && psp != POWER_SUPPLY_PROP_PRESENT) return -ENODEV; + acpi_battery_update(battery); switch (psp) { case POWER_SUPPLY_PROP_STATUS: if (battery->state & 0x01) @@ -257,7 +262,7 @@ static int extract_package(struct acpi_battery *battery, union acpi_object *package, struct acpi_offsets *offsets, int num) { - int i, *x; + int i; union acpi_object *element; if (package->type != ACPI_TYPE_PACKAGE) return -EFAULT; @@ -266,16 +271,21 @@ static int extract_package(struct acpi_battery *battery, return -EFAULT; element = &package->package.elements[i]; if (offsets[i].mode) { - if (element->type != ACPI_TYPE_STRING && - element->type != ACPI_TYPE_BUFFER) - return -EFAULT; - strncpy((u8 *)battery + offsets[i].offset, - element->string.pointer, 32); + u8 *ptr = (u8 *)battery + offsets[i].offset; + if (element->type == ACPI_TYPE_STRING || + element->type == ACPI_TYPE_BUFFER) + strncpy(ptr, element->string.pointer, 32); + else if (element->type == ACPI_TYPE_INTEGER) { + strncpy(ptr, (u8 *)&element->integer.value, + sizeof(acpi_integer)); + ptr[sizeof(acpi_integer)] = 0; + } else return -EFAULT; } else { - if (element->type != ACPI_TYPE_INTEGER) - return -EFAULT; - x = (int *)((u8 *)battery + offsets[i].offset); - *x = element->integer.value; + if (element->type == ACPI_TYPE_INTEGER) { + int *x = (int *)((u8 *)battery + + offsets[i].offset); + *x = element->integer.value; + } else return -EFAULT; } } return 0; @@ -385,29 +395,81 @@ static int acpi_battery_init_alarm(struct acpi_battery *battery) return acpi_battery_set_alarm(battery); } +static ssize_t acpi_battery_alarm_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct acpi_battery *battery = to_acpi_battery(dev_get_drvdata(dev)); + return sprintf(buf, "%d\n", battery->alarm * 1000); +} + +static ssize_t acpi_battery_alarm_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + unsigned long x; + struct acpi_battery *battery = to_acpi_battery(dev_get_drvdata(dev)); + if (sscanf(buf, "%ld\n", &x) == 1) + battery->alarm = x/1000; + if (acpi_battery_present(battery)) + acpi_battery_set_alarm(battery); + return count; +} + +static struct device_attribute alarm_attr = { + .attr = {.name = "alarm", .mode = 0644, .owner = THIS_MODULE}, + .show = acpi_battery_alarm_show, + .store = acpi_battery_alarm_store, +}; + +static int sysfs_add_battery(struct acpi_battery *battery) +{ + int result; + + battery->update_time = 0; + result = acpi_battery_get_info(battery); + acpi_battery_init_alarm(battery); + if (result) + return result; + if (battery->power_unit) { + battery->bat.properties = charge_battery_props; + battery->bat.num_properties = + ARRAY_SIZE(charge_battery_props); + } else { + battery->bat.properties = energy_battery_props; + battery->bat.num_properties = + ARRAY_SIZE(energy_battery_props); + } + + battery->bat.name = acpi_device_bid(battery->device); + battery->bat.type = POWER_SUPPLY_TYPE_BATTERY; + battery->bat.get_property = acpi_battery_get_property; + + result = power_supply_register(&battery->device->dev, &battery->bat); + if (result) + return result; + return device_create_file(battery->bat.dev, &alarm_attr); +} + +static void sysfs_remove_battery(struct acpi_battery *battery) +{ + if (!battery->bat.dev) + return; + device_remove_file(battery->bat.dev, &alarm_attr); + power_supply_unregister(&battery->bat); +} + static int acpi_battery_update(struct acpi_battery *battery) { - int saved_present = acpi_battery_present(battery); int result = acpi_battery_get_status(battery); - if (result || !acpi_battery_present(battery)) + if (result) return result; - if (saved_present != acpi_battery_present(battery) || - !battery->update_time) { - battery->update_time = 0; - result = acpi_battery_get_info(battery); - if (result) - return result; - if (battery->power_unit) { - battery->bat.properties = charge_battery_props; - battery->bat.num_properties = - ARRAY_SIZE(charge_battery_props); - } else { - battery->bat.properties = energy_battery_props; - battery->bat.num_properties = - ARRAY_SIZE(energy_battery_props); - } - acpi_battery_init_alarm(battery); + if (!acpi_battery_present(battery)) { + sysfs_remove_battery(battery); + return 0; } + if (!battery->bat.dev) + sysfs_add_battery(battery); return acpi_battery_get_state(battery); } @@ -554,10 +616,6 @@ static ssize_t acpi_battery_write_alarm(struct file *file, if (!battery || (count > sizeof(alarm_string) - 1)) return -EINVAL; - if (result) { - result = -ENODEV; - goto end; - } if (!acpi_battery_present(battery)) { result = -ENODEV; goto end; @@ -688,33 +746,6 @@ static void acpi_battery_remove_fs(struct acpi_device *device) #endif -static ssize_t acpi_battery_alarm_show(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct acpi_battery *battery = to_acpi_battery(dev_get_drvdata(dev)); - return sprintf(buf, "%d\n", battery->alarm * 1000); -} - -static ssize_t acpi_battery_alarm_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - unsigned long x; - struct acpi_battery *battery = to_acpi_battery(dev_get_drvdata(dev)); - if (sscanf(buf, "%ld\n", &x) == 1) - battery->alarm = x/1000; - if (acpi_battery_present(battery)) - acpi_battery_set_alarm(battery); - return count; -} - -static struct device_attribute alarm_attr = { - .attr = {.name = "alarm", .mode = 0644, .owner = THIS_MODULE}, - .show = acpi_battery_alarm_show, - .store = acpi_battery_alarm_store, -}; - /* -------------------------------------------------------------------------- Driver Interface -------------------------------------------------------------------------- */ @@ -732,7 +763,9 @@ static void acpi_battery_notify(acpi_handle handle, u32 event, void *data) acpi_bus_generate_netlink_event(device->pnp.device_class, device->dev.bus_id, event, acpi_battery_present(battery)); - kobject_uevent(&battery->bat.dev->kobj, KOBJ_CHANGE); + /* acpi_batter_update could remove power_supply object */ + if (battery->bat.dev) + kobject_uevent(&battery->bat.dev->kobj, KOBJ_CHANGE); } static int acpi_battery_add(struct acpi_device *device) @@ -756,11 +789,6 @@ static int acpi_battery_add(struct acpi_device *device) if (result) goto end; #endif - battery->bat.name = acpi_device_bid(device); - battery->bat.type = POWER_SUPPLY_TYPE_BATTERY; - battery->bat.get_property = acpi_battery_get_property; - result = power_supply_register(&battery->device->dev, &battery->bat); - result = device_create_file(battery->bat.dev, &alarm_attr); status = acpi_install_notify_handler(device->handle, ACPI_ALL_NOTIFY, acpi_battery_notify, battery); @@ -796,10 +824,7 @@ static int acpi_battery_remove(struct acpi_device *device, int type) #ifdef CONFIG_ACPI_PROCFS acpi_battery_remove_fs(device); #endif - if (battery->bat.dev) { - device_remove_file(battery->bat.dev, &alarm_attr); - power_supply_unregister(&battery->bat); - } + sysfs_remove_battery(battery); mutex_destroy(&battery->lock); kfree(battery); return 0; @@ -813,6 +838,7 @@ static int acpi_battery_resume(struct acpi_device *device) return -EINVAL; battery = acpi_driver_data(device); battery->update_time = 0; + acpi_battery_update(battery); return 0; } diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index fb2cff9a2d2..49d432d0a12 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c @@ -198,12 +198,10 @@ int acpi_bus_set_power(acpi_handle handle, int state) return -ENODEV; } /* - * Get device's current power state if it's unknown - * This means device power state isn't initialized or previous setting failed + * Get device's current power state */ - if ((device->power.state == ACPI_STATE_UNKNOWN) || device->flags.force_power_state) - acpi_bus_get_power(device->handle, &device->power.state); - if ((state == device->power.state) && !device->flags.force_power_state) { + acpi_bus_get_power(device->handle, &device->power.state); + if (state == device->power.state) { ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device is already at D%d\n", state)); return 0; diff --git a/drivers/acpi/button.c b/drivers/acpi/button.c index 301e832e696..24a7865a57c 100644 --- a/drivers/acpi/button.c +++ b/drivers/acpi/button.c @@ -78,6 +78,7 @@ MODULE_DEVICE_TABLE(acpi, button_device_ids); static int acpi_button_add(struct acpi_device *device); static int acpi_button_remove(struct acpi_device *device, int type); +static int acpi_button_resume(struct acpi_device *device); static int acpi_button_info_open_fs(struct inode *inode, struct file *file); static int acpi_button_state_open_fs(struct inode *inode, struct file *file); @@ -87,6 +88,7 @@ static struct acpi_driver acpi_button_driver = { .ids = button_device_ids, .ops = { .add = acpi_button_add, + .resume = acpi_button_resume, .remove = acpi_button_remove, }, }; @@ -253,6 +255,19 @@ static int acpi_button_remove_fs(struct acpi_device *device) /* -------------------------------------------------------------------------- Driver Interface -------------------------------------------------------------------------- */ +static int acpi_lid_send_state(struct acpi_button *button) +{ + unsigned long state; + acpi_status status; + + status = acpi_evaluate_integer(button->device->handle, "_LID", NULL, + &state); + if (ACPI_FAILURE(status)) + return -ENODEV; + /* input layer checks if event is redundant */ + input_report_switch(button->input, SW_LID, !state); + return 0; +} static void acpi_button_notify(acpi_handle handle, u32 event, void *data) { @@ -265,15 +280,8 @@ static void acpi_button_notify(acpi_handle handle, u32 event, void *data) switch (event) { case ACPI_BUTTON_NOTIFY_STATUS: input = button->input; - if (button->type == ACPI_BUTTON_TYPE_LID) { - struct acpi_handle *handle = button->device->handle; - unsigned long state; - - if (!ACPI_FAILURE(acpi_evaluate_integer(handle, "_LID", - NULL, &state))) - input_report_switch(input, SW_LID, !state); - + acpi_lid_send_state(button); } else { int keycode = test_bit(KEY_SLEEP, input->keybit) ? KEY_SLEEP : KEY_POWER; @@ -336,6 +344,17 @@ static int acpi_button_install_notify_handlers(struct acpi_button *button) return ACPI_FAILURE(status) ? -ENODEV : 0; } +static int acpi_button_resume(struct acpi_device *device) +{ + struct acpi_button *button; + if (!device) + return -EINVAL; + button = acpi_driver_data(device); + if (button && button->type == ACPI_BUTTON_TYPE_LID) + return acpi_lid_send_state(button); + return 0; +} + static void acpi_button_remove_notify_handlers(struct acpi_button *button) { switch (button->type) { @@ -453,6 +472,8 @@ static int acpi_button_add(struct acpi_device *device) error = input_register_device(input); if (error) goto err_remove_handlers; + if (button->type == ACPI_BUTTON_TYPE_LID) + acpi_lid_send_state(button); if (device->wakeup.flags.valid) { /* Button's GPE is run-wake GPE */ diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index 7b4178393e3..06b78e5e33a 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c @@ -65,16 +65,18 @@ enum ec_command { /* EC events */ enum ec_event { ACPI_EC_EVENT_OBF_1 = 1, /* Output buffer full */ - ACPI_EC_EVENT_IBF_0, /* Input buffer empty */ + ACPI_EC_EVENT_IBF_0, /* Input buffer empty */ }; #define ACPI_EC_DELAY 500 /* Wait 500ms max. during EC ops */ #define ACPI_EC_UDELAY_GLK 1000 /* Wait 1ms max. to get global lock */ -static enum ec_mode { - EC_INTR = 1, /* Output buffer full */ - EC_POLL, /* Input buffer empty */ -} acpi_ec_mode = EC_INTR; +enum { + EC_FLAGS_WAIT_GPE = 0, /* Don't check status until GPE arrives */ + EC_FLAGS_QUERY_PENDING, /* Query is pending */ + EC_FLAGS_GPE_MODE, /* Expect GPE to be sent for status change */ + EC_FLAGS_ONLY_IBF_GPE, /* Expect GPE only for IBF = 0 event */ +}; static int acpi_ec_remove(struct acpi_device *device, int type); static int acpi_ec_start(struct acpi_device *device); @@ -116,9 +118,8 @@ static struct acpi_ec { unsigned long command_addr; unsigned long data_addr; unsigned long global_lock; + unsigned long flags; struct mutex lock; - atomic_t query_pending; - atomic_t event_count; wait_queue_head_t wait; struct list_head list; u8 handlers_installed; @@ -148,45 +149,54 @@ static inline void acpi_ec_write_data(struct acpi_ec *ec, u8 data) outb(data, ec->data_addr); } -static inline int acpi_ec_check_status(struct acpi_ec *ec, enum ec_event event, - unsigned old_count) +static inline int acpi_ec_check_status(struct acpi_ec *ec, enum ec_event event) { - u8 status = acpi_ec_read_status(ec); - if (old_count == atomic_read(&ec->event_count)) + if (test_bit(EC_FLAGS_WAIT_GPE, &ec->flags)) return 0; if (event == ACPI_EC_EVENT_OBF_1) { - if (status & ACPI_EC_FLAG_OBF) + if (acpi_ec_read_status(ec) & ACPI_EC_FLAG_OBF) return 1; } else if (event == ACPI_EC_EVENT_IBF_0) { - if (!(status & ACPI_EC_FLAG_IBF)) + if (!(acpi_ec_read_status(ec) & ACPI_EC_FLAG_IBF)) return 1; } return 0; } -static int acpi_ec_wait(struct acpi_ec *ec, enum ec_event event, - unsigned count, int force_poll) +static int acpi_ec_wait(struct acpi_ec *ec, enum ec_event event, int force_poll) { - if (unlikely(force_poll) || acpi_ec_mode == EC_POLL) { + if (likely(test_bit(EC_FLAGS_GPE_MODE, &ec->flags)) && + likely(!force_poll)) { + if (wait_event_timeout(ec->wait, acpi_ec_check_status(ec, event), + msecs_to_jiffies(ACPI_EC_DELAY))) + return 0; + clear_bit(EC_FLAGS_WAIT_GPE, &ec->flags); + if (acpi_ec_check_status(ec, event)) { + if (event == ACPI_EC_EVENT_OBF_1) { + /* miss OBF = 1 GPE, don't expect it anymore */ + printk(KERN_INFO PREFIX "missing OBF_1 confirmation," + "switching to degraded mode.\n"); + set_bit(EC_FLAGS_ONLY_IBF_GPE, &ec->flags); + } else { + /* missing GPEs, switch back to poll mode */ + printk(KERN_INFO PREFIX "missing IBF_1 confirmations," + "switch off interrupt mode.\n"); + clear_bit(EC_FLAGS_GPE_MODE, &ec->flags); + } + return 0; + } + } else { unsigned long delay = jiffies + msecs_to_jiffies(ACPI_EC_DELAY); + clear_bit(EC_FLAGS_WAIT_GPE, &ec->flags); while (time_before(jiffies, delay)) { - if (acpi_ec_check_status(ec, event, 0)) + if (acpi_ec_check_status(ec, event)) return 0; } - } else { - if (wait_event_timeout(ec->wait, - acpi_ec_check_status(ec, event, count), - msecs_to_jiffies(ACPI_EC_DELAY)) || - acpi_ec_check_status(ec, event, 0)) { - return 0; - } else { - printk(KERN_ERR PREFIX "acpi_ec_wait timeout," + } + printk(KERN_ERR PREFIX "acpi_ec_wait timeout," " status = %d, expect_event = %d\n", acpi_ec_read_status(ec), event); - } - } - return -ETIME; } @@ -196,39 +206,42 @@ static int acpi_ec_transaction_unlocked(struct acpi_ec *ec, u8 command, int force_poll) { int result = 0; - unsigned count = atomic_read(&ec->event_count); + set_bit(EC_FLAGS_WAIT_GPE, &ec->flags); acpi_ec_write_cmd(ec, command); for (; wdata_len > 0; --wdata_len) { - result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0, count, force_poll); + result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0, force_poll); if (result) { printk(KERN_ERR PREFIX "write_cmd timeout, command = %d\n", command); goto end; } - count = atomic_read(&ec->event_count); + set_bit(EC_FLAGS_WAIT_GPE, &ec->flags); acpi_ec_write_data(ec, *(wdata++)); } if (!rdata_len) { - result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0, count, force_poll); + result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0, force_poll); if (result) { printk(KERN_ERR PREFIX "finish-write timeout, command = %d\n", command); goto end; } - } else if (command == ACPI_EC_COMMAND_QUERY) { - atomic_set(&ec->query_pending, 0); - } + } else if (command == ACPI_EC_COMMAND_QUERY) + clear_bit(EC_FLAGS_QUERY_PENDING, &ec->flags); for (; rdata_len > 0; --rdata_len) { - result = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF_1, count, force_poll); + if (test_bit(EC_FLAGS_ONLY_IBF_GPE, &ec->flags)) + force_poll = 1; + result = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF_1, force_poll); if (result) { printk(KERN_ERR PREFIX "read timeout, command = %d\n", command); goto end; } - count = atomic_read(&ec->event_count); + /* Don't expect GPE after last read */ + if (rdata_len > 1) + set_bit(EC_FLAGS_WAIT_GPE, &ec->flags); *(rdata++) = acpi_ec_read_data(ec); } end: @@ -258,10 +271,7 @@ static int acpi_ec_transaction(struct acpi_ec *ec, u8 command, } } - /* Make sure GPE is enabled before doing transaction */ - acpi_enable_gpe(NULL, ec->gpe, ACPI_NOT_ISR); - - status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0, 0, 0); + status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0, 0); if (status) { printk(KERN_ERR PREFIX "input buffer is not empty, aborting transaction\n"); @@ -435,9 +445,9 @@ EXPORT_SYMBOL_GPL(acpi_ec_add_query_handler); void acpi_ec_remove_query_handler(struct acpi_ec *ec, u8 query_bit) { - struct acpi_ec_query_handler *handler; + struct acpi_ec_query_handler *handler, *tmp; mutex_lock(&ec->lock); - list_for_each_entry(handler, &ec->list, node) { + list_for_each_entry_safe(handler, tmp, &ec->list, node) { if (query_bit == handler->query_bit) { list_del(&handler->node); kfree(handler); @@ -476,23 +486,24 @@ static void acpi_ec_gpe_query(void *ec_cxt) static u32 acpi_ec_gpe_handler(void *data) { acpi_status status = AE_OK; - u8 value; struct acpi_ec *ec = data; - atomic_inc(&ec->event_count); - - if (acpi_ec_mode == EC_INTR) { + clear_bit(EC_FLAGS_WAIT_GPE, &ec->flags); + if (test_bit(EC_FLAGS_GPE_MODE, &ec->flags)) wake_up(&ec->wait); - } - value = acpi_ec_read_status(ec); - if ((value & ACPI_EC_FLAG_SCI) && !atomic_read(&ec->query_pending)) { - atomic_set(&ec->query_pending, 1); - status = - acpi_os_execute(OSL_EC_BURST_HANDLER, acpi_ec_gpe_query, ec); + if (acpi_ec_read_status(ec) & ACPI_EC_FLAG_SCI) { + if (!test_and_set_bit(EC_FLAGS_QUERY_PENDING, &ec->flags)) + status = acpi_os_execute(OSL_EC_BURST_HANDLER, + acpi_ec_gpe_query, ec); + } else if (unlikely(!test_bit(EC_FLAGS_GPE_MODE, &ec->flags))) { + /* this is non-query, must be confirmation */ + printk(KERN_INFO PREFIX "non-query interrupt received," + " switching to interrupt mode\n"); + set_bit(EC_FLAGS_GPE_MODE, &ec->flags); } - return status == AE_OK ? + return ACPI_SUCCESS(status) ? ACPI_INTERRUPT_HANDLED : ACPI_INTERRUPT_NOT_HANDLED; } @@ -641,13 +652,10 @@ static struct acpi_ec *make_acpi_ec(void) struct acpi_ec *ec = kzalloc(sizeof(struct acpi_ec), GFP_KERNEL); if (!ec) return NULL; - - atomic_set(&ec->query_pending, 1); - atomic_set(&ec->event_count, 1); + ec->flags = 1 << EC_FLAGS_QUERY_PENDING; mutex_init(&ec->lock); init_waitqueue_head(&ec->wait); INIT_LIST_HEAD(&ec->list); - return ec; } @@ -741,6 +749,8 @@ static int acpi_ec_add(struct acpi_device *device) acpi_ec_add_fs(device); printk(KERN_INFO PREFIX "GPE = 0x%lx, I/O: command/status = 0x%lx, data = 0x%lx\n", ec->gpe, ec->command_addr, ec->data_addr); + printk(KERN_INFO PREFIX "driver started in %s mode\n", + (test_bit(EC_FLAGS_GPE_MODE, &ec->flags))?"interrupt":"poll"); return 0; } @@ -833,7 +843,7 @@ static int acpi_ec_start(struct acpi_device *device) ret = ec_install_handlers(ec); /* EC is fully operational, allow queries */ - atomic_set(&ec->query_pending, 0); + clear_bit(EC_FLAGS_QUERY_PENDING, &ec->flags); return ret; } @@ -924,20 +934,4 @@ static void __exit acpi_ec_exit(void) return; } -#endif /* 0 */ - -static int __init acpi_ec_set_intr_mode(char *str) -{ - int intr; - - if (!get_option(&str, &intr)) - return 0; - - acpi_ec_mode = (intr) ? EC_INTR : EC_POLL; - - printk(KERN_NOTICE PREFIX "%s mode.\n", intr ? "interrupt" : "polling"); - - return 1; -} - -__setup("ec_intr=", acpi_ec_set_intr_mode); +#endif /* 0 */ diff --git a/drivers/acpi/fan.c b/drivers/acpi/fan.c index c81f6bdb68b..a5a5532db26 100644 --- a/drivers/acpi/fan.c +++ b/drivers/acpi/fan.c @@ -47,8 +47,6 @@ MODULE_LICENSE("GPL"); static int acpi_fan_add(struct acpi_device *device); static int acpi_fan_remove(struct acpi_device *device, int type); -static int acpi_fan_suspend(struct acpi_device *device, pm_message_t state); -static int acpi_fan_resume(struct acpi_device *device); static const struct acpi_device_id fan_device_ids[] = { {"PNP0C0B", 0}, @@ -63,15 +61,9 @@ static struct acpi_driver acpi_fan_driver = { .ops = { .add = acpi_fan_add, .remove = acpi_fan_remove, - .suspend = acpi_fan_suspend, - .resume = acpi_fan_resume, }, }; -struct acpi_fan { - struct acpi_device * device; -}; - /* -------------------------------------------------------------------------- FS Interface (/proc) -------------------------------------------------------------------------- */ @@ -80,12 +72,12 @@ static struct proc_dir_entry *acpi_fan_dir; static int acpi_fan_read_state(struct seq_file *seq, void *offset) { - struct acpi_fan *fan = seq->private; + struct acpi_device *device = seq->private; int state = 0; - if (fan) { - if (acpi_bus_get_power(fan->device->handle, &state)) + if (device) { + if (acpi_bus_get_power(device->handle, &state)) seq_printf(seq, "status: ERROR\n"); else seq_printf(seq, "status: %s\n", @@ -105,11 +97,10 @@ acpi_fan_write_state(struct file *file, const char __user * buffer, { int result = 0; struct seq_file *m = file->private_data; - struct acpi_fan *fan = m->private; + struct acpi_device *device = m->private; char state_string[12] = { '\0' }; - - if (!fan || (count > sizeof(state_string) - 1)) + if (count > sizeof(state_string) - 1) return -EINVAL; if (copy_from_user(state_string, buffer, count)) @@ -117,7 +108,7 @@ acpi_fan_write_state(struct file *file, const char __user * buffer, state_string[count] = '\0'; - result = acpi_bus_set_power(fan->device->handle, + result = acpi_bus_set_power(device->handle, simple_strtoul(state_string, NULL, 0)); if (result) return result; @@ -158,7 +149,7 @@ static int acpi_fan_add_fs(struct acpi_device *device) return -ENODEV; else { entry->proc_fops = &acpi_fan_state_ops; - entry->data = acpi_driver_data(device); + entry->data = device; entry->owner = THIS_MODULE; } @@ -191,14 +182,8 @@ static int acpi_fan_add(struct acpi_device *device) if (!device) return -EINVAL; - fan = kzalloc(sizeof(struct acpi_fan), GFP_KERNEL); - if (!fan) - return -ENOMEM; - - fan->device = device; strcpy(acpi_device_name(device), "Fan"); strcpy(acpi_device_class(device), ACPI_FAN_CLASS); - acpi_driver_data(device) = fan; result = acpi_bus_get_power(device->handle, &state); if (result) { @@ -206,10 +191,6 @@ static int acpi_fan_add(struct acpi_device *device) goto end; } - device->flags.force_power_state = 1; - acpi_bus_set_power(device->handle, state); - device->flags.force_power_state = 0; - result = acpi_fan_add_fs(device); if (result) goto end; @@ -227,53 +208,14 @@ static int acpi_fan_add(struct acpi_device *device) static int acpi_fan_remove(struct acpi_device *device, int type) { - struct acpi_fan *fan = NULL; - - if (!device || !acpi_driver_data(device)) return -EINVAL; - fan = acpi_driver_data(device); - acpi_fan_remove_fs(device); - kfree(fan); - return 0; } -static int acpi_fan_suspend(struct acpi_device *device, pm_message_t state) -{ - if (!device) - return -EINVAL; - - acpi_bus_set_power(device->handle, ACPI_STATE_D0); - - return AE_OK; -} - -static int acpi_fan_resume(struct acpi_device *device) -{ - int result = 0; - int power_state = 0; - - if (!device) - return -EINVAL; - - result = acpi_bus_get_power(device->handle, &power_state); - if (result) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Error reading fan power state\n")); - return result; - } - - device->flags.force_power_state = 1; - acpi_bus_set_power(device->handle, power_state); - device->flags.force_power_state = 0; - - return result; -} - static int __init acpi_fan_init(void) { int result = 0; diff --git a/drivers/acpi/power.c b/drivers/acpi/power.c index 57b9a2998fd..af1769a20c7 100644 --- a/drivers/acpi/power.c +++ b/drivers/acpi/power.c @@ -86,7 +86,6 @@ struct acpi_power_resource { acpi_bus_id name; u32 system_level; u32 order; - int state; struct mutex resource_lock; struct list_head reference; }; @@ -128,33 +127,31 @@ acpi_power_get_context(acpi_handle handle, return 0; } -static int acpi_power_get_state(struct acpi_power_resource *resource) +static int acpi_power_get_state(struct acpi_power_resource *resource, int *state) { acpi_status status = AE_OK; unsigned long sta = 0; - if (!resource) + if (!resource || !state) return -EINVAL; status = acpi_evaluate_integer(resource->device->handle, "_STA", NULL, &sta); if (ACPI_FAILURE(status)) return -ENODEV; - if (sta & 0x01) - resource->state = ACPI_POWER_RESOURCE_STATE_ON; - else - resource->state = ACPI_POWER_RESOURCE_STATE_OFF; + *state = (sta & 0x01)?ACPI_POWER_RESOURCE_STATE_ON: + ACPI_POWER_RESOURCE_STATE_OFF; ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Resource [%s] is %s\n", - resource->name, resource->state ? "on" : "off")); + resource->name, state ? "on" : "off")); return 0; } static int acpi_power_get_list_state(struct acpi_handle_list *list, int *state) { - int result = 0; + int result = 0, state1; struct acpi_power_resource *resource = NULL; u32 i = 0; @@ -168,11 +165,11 @@ static int acpi_power_get_list_state(struct acpi_handle_list *list, int *state) result = acpi_power_get_context(list->handles[i], &resource); if (result) return result; - result = acpi_power_get_state(resource); + result = acpi_power_get_state(resource, &state1); if (result) return result; - *state = resource->state; + *state = state1; if (*state != ACPI_POWER_RESOURCE_STATE_ON) break; @@ -186,7 +183,7 @@ static int acpi_power_get_list_state(struct acpi_handle_list *list, int *state) static int acpi_power_on(acpi_handle handle, struct acpi_device *dev) { - int result = 0; + int result = 0, state; int found = 0; acpi_status status = AE_OK; struct acpi_power_resource *resource = NULL; @@ -224,20 +221,14 @@ static int acpi_power_on(acpi_handle handle, struct acpi_device *dev) } mutex_unlock(&resource->resource_lock); - if (resource->state == ACPI_POWER_RESOURCE_STATE_ON) { - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Resource [%s] already on\n", - resource->name)); - return 0; - } - status = acpi_evaluate_object(resource->device->handle, "_ON", NULL, NULL); if (ACPI_FAILURE(status)) return -ENODEV; - result = acpi_power_get_state(resource); + result = acpi_power_get_state(resource, &state); if (result) return result; - if (resource->state != ACPI_POWER_RESOURCE_STATE_ON) + if (state != ACPI_POWER_RESOURCE_STATE_ON) return -ENOEXEC; /* Update the power resource's _device_ power state */ @@ -250,7 +241,7 @@ static int acpi_power_on(acpi_handle handle, struct acpi_device *dev) static int acpi_power_off_device(acpi_handle handle, struct acpi_device *dev) { - int result = 0; + int result = 0, state; acpi_status status = AE_OK; struct acpi_power_resource *resource = NULL; struct list_head *node, *next; @@ -281,20 +272,14 @@ static int acpi_power_off_device(acpi_handle handle, struct acpi_device *dev) } mutex_unlock(&resource->resource_lock); - if (resource->state == ACPI_POWER_RESOURCE_STATE_OFF) { - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Resource [%s] already off\n", - resource->name)); - return 0; - } - status = acpi_evaluate_object(resource->device->handle, "_OFF", NULL, NULL); if (ACPI_FAILURE(status)) return -ENODEV; - result = acpi_power_get_state(resource); + result = acpi_power_get_state(resource, &state); if (result) return result; - if (resource->state != ACPI_POWER_RESOURCE_STATE_OFF) + if (state != ACPI_POWER_RESOURCE_STATE_OFF) return -ENOEXEC; /* Update the power resource's _device_ power state */ @@ -494,7 +479,7 @@ static struct proc_dir_entry *acpi_power_dir; static int acpi_power_seq_show(struct seq_file *seq, void *offset) { int count = 0; - int result = 0; + int result = 0, state; struct acpi_power_resource *resource = NULL; struct list_head *node, *next; struct acpi_power_reference *ref; @@ -505,12 +490,12 @@ static int acpi_power_seq_show(struct seq_file *seq, void *offset) if (!resource) goto end; - result = acpi_power_get_state(resource); + result = acpi_power_get_state(resource, &state); if (result) goto end; seq_puts(seq, "state: "); - switch (resource->state) { + switch (state) { case ACPI_POWER_RESOURCE_STATE_ON: seq_puts(seq, "on\n"); break; @@ -591,7 +576,7 @@ static int acpi_power_remove_fs(struct acpi_device *device) static int acpi_power_add(struct acpi_device *device) { - int result = 0; + int result = 0, state; acpi_status status = AE_OK; struct acpi_power_resource *resource = NULL; union acpi_object acpi_object; @@ -622,11 +607,11 @@ static int acpi_power_add(struct acpi_device *device) resource->system_level = acpi_object.power_resource.system_level; resource->order = acpi_object.power_resource.resource_order; - result = acpi_power_get_state(resource); + result = acpi_power_get_state(resource, &state); if (result) goto end; - switch (resource->state) { + switch (state) { case ACPI_POWER_RESOURCE_STATE_ON: device->power.state = ACPI_STATE_D0; break; @@ -643,7 +628,7 @@ static int acpi_power_add(struct acpi_device *device) goto end; printk(KERN_INFO PREFIX "%s [%s] (%s)\n", acpi_device_name(device), - acpi_device_bid(device), resource->state ? "on" : "off"); + acpi_device_bid(device), state ? "on" : "off"); end: if (result) @@ -680,7 +665,7 @@ static int acpi_power_remove(struct acpi_device *device, int type) static int acpi_power_resume(struct acpi_device *device) { - int result = 0; + int result = 0, state; struct acpi_power_resource *resource = NULL; struct acpi_power_reference *ref; @@ -689,12 +674,12 @@ static int acpi_power_resume(struct acpi_device *device) resource = (struct acpi_power_resource *)acpi_driver_data(device); - result = acpi_power_get_state(resource); + result = acpi_power_get_state(resource, &state); if (result) return result; mutex_lock(&resource->resource_lock); - if ((resource->state == ACPI_POWER_RESOURCE_STATE_OFF) && + if (state == ACPI_POWER_RESOURCE_STATE_OFF && !list_empty(&resource->reference)) { ref = container_of(resource->reference.next, struct acpi_power_reference, node); mutex_unlock(&resource->resource_lock); diff --git a/drivers/acpi/sleep/main.c b/drivers/acpi/sleep/main.c index f3d3867303e..2c0b6630f8b 100644 --- a/drivers/acpi/sleep/main.c +++ b/drivers/acpi/sleep/main.c @@ -167,8 +167,8 @@ static void acpi_pm_finish(void) { u32 acpi_state = acpi_target_sleep_state; - acpi_leave_sleep_state(acpi_state); acpi_disable_wakeup_device(acpi_state); + acpi_leave_sleep_state(acpi_state); /* reset firmware waking vector */ acpi_set_firmware_waking_vector((acpi_physical_address) 0); @@ -272,8 +272,8 @@ static void acpi_hibernation_finish(void) * enable it here. */ acpi_enable(); - acpi_leave_sleep_state(ACPI_STATE_S4); acpi_disable_wakeup_device(ACPI_STATE_S4); + acpi_leave_sleep_state(ACPI_STATE_S4); /* reset firmware waking vector */ acpi_set_firmware_waking_vector((acpi_physical_address) 0); @@ -410,6 +410,7 @@ static void acpi_power_off(void) /* acpi_sleep_prepare(ACPI_STATE_S5) should have already been called */ printk("%s called\n", __FUNCTION__); local_irq_disable(); + acpi_enable_wakeup_device(ACPI_STATE_S5); acpi_enter_sleep_state(ACPI_STATE_S5); } diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index 49cf4cf1a5a..ed9b407e42d 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c @@ -49,6 +49,9 @@ #define DRV_NAME "ahci" #define DRV_VERSION "3.0" +static int ahci_enable_alpm(struct ata_port *ap, + enum link_pm policy); +static void ahci_disable_alpm(struct ata_port *ap); enum { AHCI_PCI_BAR = 5, @@ -99,6 +102,7 @@ enum { HOST_CAP_SSC = (1 << 14), /* Slumber capable */ HOST_CAP_PMP = (1 << 17), /* Port Multiplier support */ HOST_CAP_CLO = (1 << 24), /* Command List Override support */ + HOST_CAP_ALPM = (1 << 26), /* Aggressive Link PM support */ HOST_CAP_SSS = (1 << 27), /* Staggered Spin-up */ HOST_CAP_SNTF = (1 << 29), /* SNotification register */ HOST_CAP_NCQ = (1 << 30), /* Native Command Queueing */ @@ -155,6 +159,8 @@ enum { PORT_IRQ_PIOS_FIS | PORT_IRQ_D2H_REG_FIS, /* PORT_CMD bits */ + PORT_CMD_ASP = (1 << 27), /* Aggressive Slumber/Partial */ + PORT_CMD_ALPE = (1 << 26), /* Aggressive Link PM enable */ PORT_CMD_ATAPI = (1 << 24), /* Device is ATAPI */ PORT_CMD_PMP = (1 << 17), /* PMP attached */ PORT_CMD_LIST_ON = (1 << 15), /* cmd list DMA engine running */ @@ -178,13 +184,14 @@ enum { AHCI_HFLAG_MV_PATA = (1 << 4), /* PATA port */ AHCI_HFLAG_NO_MSI = (1 << 5), /* no PCI MSI */ AHCI_HFLAG_NO_PMP = (1 << 6), /* no PMP */ + AHCI_HFLAG_NO_HOTPLUG = (1 << 7), /* ignore PxSERR.DIAG.N */ /* ap->flags bits */ - AHCI_FLAG_NO_HOTPLUG = (1 << 24), /* ignore PxSERR.DIAG.N */ AHCI_FLAG_COMMON = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA | - ATA_FLAG_ACPI_SATA | ATA_FLAG_AN, + ATA_FLAG_ACPI_SATA | ATA_FLAG_AN | + ATA_FLAG_IPM, AHCI_LFLAG_COMMON = ATA_LFLAG_SKIP_D2H_BSY, }; @@ -254,6 +261,11 @@ static int ahci_pci_device_suspend(struct pci_dev *pdev, pm_message_t mesg); static int ahci_pci_device_resume(struct pci_dev *pdev); #endif +static struct class_device_attribute *ahci_shost_attrs[] = { + &class_device_attr_link_power_management_policy, + NULL +}; + static struct scsi_host_template ahci_sht = { .module = THIS_MODULE, .name = DRV_NAME, @@ -271,6 +283,7 @@ static struct scsi_host_template ahci_sht = { .slave_configure = ata_scsi_slave_config, .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, + .shost_attrs = ahci_shost_attrs, }; static const struct ata_port_operations ahci_ops = { @@ -302,6 +315,8 @@ static const struct ata_port_operations ahci_ops = { .port_suspend = ahci_port_suspend, .port_resume = ahci_port_resume, #endif + .enable_pm = ahci_enable_alpm, + .disable_pm = ahci_disable_alpm, .port_start = ahci_port_start, .port_stop = ahci_port_stop, @@ -836,6 +851,130 @@ static void ahci_power_up(struct ata_port *ap) writel(cmd | PORT_CMD_ICC_ACTIVE, port_mmio + PORT_CMD); } +static void ahci_disable_alpm(struct ata_port *ap) +{ + struct ahci_host_priv *hpriv = ap->host->private_data; + void __iomem *port_mmio = ahci_port_base(ap); + u32 cmd; + struct ahci_port_priv *pp = ap->private_data; + + /* IPM bits should be disabled by libata-core */ + /* get the existing command bits */ + cmd = readl(port_mmio + PORT_CMD); + + /* disable ALPM and ASP */ + cmd &= ~PORT_CMD_ASP; + cmd &= ~PORT_CMD_ALPE; + + /* force the interface back to active */ + cmd |= PORT_CMD_ICC_ACTIVE; + + /* write out new cmd value */ + writel(cmd, port_mmio + PORT_CMD); + cmd = readl(port_mmio + PORT_CMD); + + /* wait 10ms to be sure we've come out of any low power state */ + msleep(10); + + /* clear out any PhyRdy stuff from interrupt status */ + writel(PORT_IRQ_PHYRDY, port_mmio + PORT_IRQ_STAT); + + /* go ahead and clean out PhyRdy Change from Serror too */ + ahci_scr_write(ap, SCR_ERROR, ((1 << 16) | (1 << 18))); + + /* + * Clear flag to indicate that we should ignore all PhyRdy + * state changes + */ + hpriv->flags &= ~AHCI_HFLAG_NO_HOTPLUG; + + /* + * Enable interrupts on Phy Ready. + */ + pp->intr_mask |= PORT_IRQ_PHYRDY; + writel(pp->intr_mask, port_mmio + PORT_IRQ_MASK); + + /* + * don't change the link pm policy - we can be called + * just to turn of link pm temporarily + */ +} + +static int ahci_enable_alpm(struct ata_port *ap, + enum link_pm policy) +{ + struct ahci_host_priv *hpriv = ap->host->private_data; + void __iomem *port_mmio = ahci_port_base(ap); + u32 cmd; + struct ahci_port_priv *pp = ap->private_data; + u32 asp; + + /* Make sure the host is capable of link power management */ + if (!(hpriv->cap & HOST_CAP_ALPM)) + return -EINVAL; + + switch (policy) { + case MAX_PERFORMANCE: + case NOT_AVAILABLE: + /* + * if we came here with NOT_AVAILABLE, + * it just means this is the first time we + * have tried to enable - default to max performance, + * and let the user go to lower power modes on request. + */ + ahci_disable_alpm(ap); + return 0; + case MIN_POWER: + /* configure HBA to enter SLUMBER */ + asp = PORT_CMD_ASP; + break; + case MEDIUM_POWER: + /* configure HBA to enter PARTIAL */ + asp = 0; + break; + default: + return -EINVAL; + } + + /* + * Disable interrupts on Phy Ready. This keeps us from + * getting woken up due to spurious phy ready interrupts + * TBD - Hot plug should be done via polling now, is + * that even supported? + */ + pp->intr_mask &= ~PORT_IRQ_PHYRDY; + writel(pp->intr_mask, port_mmio + PORT_IRQ_MASK); + + /* + * Set a flag to indicate that we should ignore all PhyRdy + * state changes since these can happen now whenever we + * change link state + */ + hpriv->flags |= AHCI_HFLAG_NO_HOTPLUG; + + /* get the existing command bits */ + cmd = readl(port_mmio + PORT_CMD); + + /* + * Set ASP based on Policy + */ + cmd |= asp; + + /* + * Setting this bit will instruct the HBA to aggressively + * enter a lower power link state when it's appropriate and + * based on the value set above for ASP + */ + cmd |= PORT_CMD_ALPE; + + /* write out new cmd value */ + writel(cmd, port_mmio + PORT_CMD); + cmd = readl(port_mmio + PORT_CMD); + + /* IPM bits should be set by libata-core */ + return 0; +} + #ifdef CONFIG_PM static void ahci_power_down(struct ata_port *ap) { @@ -898,8 +1037,10 @@ static int ahci_reset_controller(struct ata_host *host) * AHCI-specific, such as HOST_RESET. */ tmp = readl(mmio + HOST_CTL); - if (!(tmp & HOST_AHCI_EN)) - writel(tmp | HOST_AHCI_EN, mmio + HOST_CTL); + if (!(tmp & HOST_AHCI_EN)) { + tmp |= HOST_AHCI_EN; + writel(tmp, mmio + HOST_CTL); + } /* global controller reset */ if ((tmp & HOST_RESET) == 0) { @@ -1153,15 +1294,8 @@ static int ahci_do_softreset(struct ata_link *link, unsigned int *class, tf.ctl &= ~ATA_SRST; ahci_exec_polled_cmd(ap, pmp, &tf, 0, 0, 0); - /* spec mandates ">= 2ms" before checking status. - * We wait 150ms, because that was the magic delay used for - * ATAPI devices in Hale Landis's ATADRVR, for the period of time - * between when the ATA command register is written, and then - * status is checked. Because waiting for "a while" before - * checking status is fine, post SRST, we perform this magic - * delay here as well. - */ - msleep(150); + /* wait a while before checking status */ + ata_wait_after_reset(ap, deadline); rc = ata_wait_ready(ap, deadline); /* link occupied, -ENODEV too is an error */ @@ -1509,6 +1643,17 @@ static void ahci_port_intr(struct ata_port *ap) if (unlikely(resetting)) status &= ~PORT_IRQ_BAD_PMP; + /* If we are getting PhyRdy, this is + * just a power state change, we should + * clear out this, plus the PhyRdy/Comm + * Wake bits from Serror + */ + if ((hpriv->flags & AHCI_HFLAG_NO_HOTPLUG) && + (status & PORT_IRQ_PHYRDY)) { + status &= ~PORT_IRQ_PHYRDY; + ahci_scr_write(ap, SCR_ERROR, ((1 << 16) | (1 << 18))); + } + if (unlikely(status & PORT_IRQ_ERROR)) { ahci_error_intr(ap, status); return; @@ -2156,6 +2301,9 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) ata_port_pbar_desc(ap, AHCI_PCI_BAR, 0x100 + ap->port_no * 0x80, "port"); + /* set initial link pm policy */ + ap->pm_policy = NOT_AVAILABLE; + /* standard SATA port setup */ if (hpriv->port_map & (1 << i)) ap->ioaddr.cmd_addr = port_mmio; diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index 081e3dfb64d..63035d71a61 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -620,6 +620,177 @@ void ata_dev_disable(struct ata_device *dev) } } +static int ata_dev_set_dipm(struct ata_device *dev, enum link_pm policy) +{ + struct ata_link *link = dev->link; + struct ata_port *ap = link->ap; + u32 scontrol; + unsigned int err_mask; + int rc; + + /* + * disallow DIPM for drivers which haven't set + * ATA_FLAG_IPM. This is because when DIPM is enabled, + * phy ready will be set in the interrupt status on + * state changes, which will cause some drivers to + * think there are errors - additionally drivers will + * need to disable hot plug. + */ + if (!(ap->flags & ATA_FLAG_IPM) || !ata_dev_enabled(dev)) { + ap->pm_policy = NOT_AVAILABLE; + return -EINVAL; + } + + /* + * For DIPM, we will only enable it for the + * min_power setting. + * + * Why? Because Disks are too stupid to know that + * If the host rejects a request to go to SLUMBER + * they should retry at PARTIAL, and instead it + * just would give up. So, for medium_power to + * work at all, we need to only allow HIPM. + */ + rc = sata_scr_read(link, SCR_CONTROL, &scontrol); + if (rc) + return rc; + + switch (policy) { + case MIN_POWER: + /* no restrictions on IPM transitions */ + scontrol &= ~(0x3 << 8); + rc = sata_scr_write(link, SCR_CONTROL, scontrol); + if (rc) + return rc; + + /* enable DIPM */ + if (dev->flags & ATA_DFLAG_DIPM) + err_mask = ata_dev_set_feature(dev, + SETFEATURES_SATA_ENABLE, SATA_DIPM); + break; + case MEDIUM_POWER: + /* allow IPM to PARTIAL */ + scontrol &= ~(0x1 << 8); + scontrol |= (0x2 << 8); + rc = sata_scr_write(link, SCR_CONTROL, scontrol); + if (rc) + return rc; + + /* disable DIPM */ + if (ata_dev_enabled(dev) && (dev->flags & ATA_DFLAG_DIPM)) + err_mask = ata_dev_set_feature(dev, + SETFEATURES_SATA_DISABLE, SATA_DIPM); + break; + case NOT_AVAILABLE: + case MAX_PERFORMANCE: + /* disable all IPM transitions */ + scontrol |= (0x3 << 8); + rc = sata_scr_write(link, SCR_CONTROL, scontrol); + if (rc) + return rc; + + /* disable DIPM */ + if (ata_dev_enabled(dev) && (dev->flags & ATA_DFLAG_DIPM)) + err_mask = ata_dev_set_feature(dev, + SETFEATURES_SATA_DISABLE, SATA_DIPM); + break; + } + + /* FIXME: handle SET FEATURES failure */ + (void) err_mask; + + return 0; +} + +/** + * ata_dev_enable_pm - enable SATA interface power management + * @device - device to enable ipm for + * @policy - the link power management policy + * + * Enable SATA Interface power management. This will enable + * Device Interface Power Management (DIPM) for min_power + * policy, and then call driver specific callbacks for + * enabling Host Initiated Power management. + * + * Locking: Caller. + * Returns: -EINVAL if IPM is not supported, 0 otherwise. + */ +void ata_dev_enable_pm(struct ata_device *dev, enum link_pm policy) +{ + int rc = 0; + struct ata_port *ap = dev->link->ap; + + /* set HIPM first, then DIPM */ + if (ap->ops->enable_pm) + rc = ap->ops->enable_pm(ap, policy); + if (rc) + goto enable_pm_out; + rc = ata_dev_set_dipm(dev, policy); + +enable_pm_out: + if (rc) + ap->pm_policy = MAX_PERFORMANCE; + else + ap->pm_policy = policy; + return /* rc */; /* hopefully we can use 'rc' eventually */ +} + +/** + * ata_dev_disable_pm - disable SATA interface power management + * @device - device to enable ipm for + * + * Disable SATA Interface power management. This will disable + * Device Interface Power Management (DIPM) without changing + * policy, call driver specific callbacks for disabling Host + * Initiated Power management. + * + * Locking: Caller. + * Returns: void + */ +static void ata_dev_disable_pm(struct ata_device *dev) +{ + struct ata_port *ap = dev->link->ap; + + ata_dev_set_dipm(dev, MAX_PERFORMANCE); + if (ap->ops->disable_pm) + ap->ops->disable_pm(ap); +} + +void ata_lpm_schedule(struct ata_port *ap, enum link_pm policy) +{ + ap->pm_policy = policy; + ap->link.eh_info.action |= ATA_EHI_LPM; + ap->link.eh_info.flags |= ATA_EHI_NO_AUTOPSY; + ata_port_schedule_eh(ap); +} + +static void ata_lpm_enable(struct ata_host *host) +{ + struct ata_link *link; + struct ata_port *ap; + struct ata_device *dev; + int i; + + for (i = 0; i < host->n_ports; i++) { + ap = host->ports[i]; + ata_port_for_each_link(link, ap) { + ata_link_for_each_dev(dev, link) + ata_dev_disable_pm(dev); + } + } +} + +static void ata_lpm_disable(struct ata_host *host) +{ + int i; + + for (i = 0; i < host->n_ports; i++) { + struct ata_port *ap = host->ports[i]; + ata_lpm_schedule(ap, ap->pm_policy); + } +} + + /** * ata_devchk - PATA device presence detection * @ap: ATA channel to examine @@ -2101,6 +2272,13 @@ int ata_dev_configure(struct ata_device *dev) if (dev->flags & ATA_DFLAG_LBA48) dev->max_sectors = ATA_MAX_SECTORS_LBA48; + if (!(dev->horkage & ATA_HORKAGE_IPM)) { + if (ata_id_has_hipm(dev->id)) + dev->flags |= ATA_DFLAG_HIPM; + if (ata_id_has_dipm(dev->id)) + dev->flags |= ATA_DFLAG_DIPM; + } + if (dev->horkage & ATA_HORKAGE_DIAGNOSTIC) { /* Let the user know. We don't want to disallow opens for rescue purposes, or in case the vendor is just a blithering @@ -2126,6 +2304,13 @@ int ata_dev_configure(struct ata_device *dev) dev->max_sectors = min_t(unsigned int, ATA_MAX_SECTORS_128, dev->max_sectors); + if (ata_dev_blacklisted(dev) & ATA_HORKAGE_IPM) { + dev->horkage |= ATA_HORKAGE_IPM; + + /* reset link pm_policy for this port to no pm */ + ap->pm_policy = MAX_PERFORMANCE; + } + if (ap->ops->dev_config) ap->ops->dev_config(dev); @@ -2219,6 +2404,25 @@ int ata_bus_probe(struct ata_port *ap) tries[dev->devno] = ATA_PROBE_MAX_TRIES; retry: + ata_link_for_each_dev(dev, &ap->link) { + /* If we issue an SRST then an ATA drive (not ATAPI) + * may change configuration and be in PIO0 timing. If + * we do a hard reset (or are coming from power on) + * this is true for ATA or ATAPI. Until we've set a + * suitable controller mode we should not touch the + * bus as we may be talking too fast. + */ + dev->pio_mode = XFER_PIO_0; + + /* If the controller has a pio mode setup function + * then use it to set the chipset to rights. Don't + * touch the DMA setup as that will be dealt with when + * configuring devices. + */ + if (ap->ops->set_piomode) + ap->ops->set_piomode(ap, dev); + } + /* reset and determine device classes */ ap->ops->phy_reset(ap); @@ -2234,12 +2438,6 @@ int ata_bus_probe(struct ata_port *ap) ata_port_probe(ap); - /* after the reset the device state is PIO 0 and the controller - state is undefined. Record the mode */ - - ata_link_for_each_dev(dev, &ap->link) - dev->pio_mode = XFER_PIO_0; - /* read IDENTIFY page and configure devices. We have to do the identify specific sequence bass-ackwards so that PDIAG- is released by the slave device */ @@ -3118,6 +3316,55 @@ int ata_busy_sleep(struct ata_port *ap, } /** + * ata_wait_after_reset - wait before checking status after reset + * @ap: port containing status register to be polled + * @deadline: deadline jiffies for the operation + * + * After reset, we need to pause a while before reading status. + * Also, certain combination of controller and device report 0xff + * for some duration (e.g. until SATA PHY is up and running) + * which is interpreted as empty port in ATA world. This + * function also waits for such devices to get out of 0xff + * status. + * + * LOCKING: + * Kernel thread context (may sleep). + */ +void ata_wait_after_reset(struct ata_port *ap, unsigned long deadline) +{ + unsigned long until = jiffies + ATA_TMOUT_FF_WAIT; + + if (time_before(until, deadline)) + deadline = until; + + /* Spec mandates ">= 2ms" before checking status. We wait + * 150ms, because that was the magic delay used for ATAPI + * devices in Hale Landis's ATADRVR, for the period of time + * between when the ATA command register is written, and then + * status is checked. Because waiting for "a while" before + * checking status is fine, post SRST, we perform this magic + * delay here as well. + * + * Old drivers/ide uses the 2mS rule and then waits for ready. + */ + msleep(150); + + /* Wait for 0xff to clear. Some SATA devices take a long time + * to clear 0xff after reset. For example, HHD424020F7SV00 + * iVDR needs >= 800ms while. Quantum GoVault needs even more + * than that. + */ + while (1) { + u8 status = ata_chk_status(ap); + + if (status != 0xff || time_after(jiffies, deadline)) + return; + + msleep(50); + } +} + +/** * ata_wait_ready - sleep until BSY clears, or timeout * @ap: port containing status register to be polled * @deadline: deadline jiffies for the operation @@ -3223,8 +3470,6 @@ static int ata_bus_softreset(struct ata_port *ap, unsigned int devmask, unsigned long deadline) { struct ata_ioports *ioaddr = &ap->ioaddr; - struct ata_device *dev; - int i = 0; DPRINTK("ata%u: bus reset via SRST\n", ap->print_id); @@ -3235,36 +3480,8 @@ static int ata_bus_softreset(struct ata_port *ap, unsigned int devmask, udelay(20); /* FIXME: flush */ iowrite8(ap->ctl, ioaddr->ctl_addr); - /* If we issued an SRST then an ATA drive (not ATAPI) - * may have changed configuration and be in PIO0 timing. If - * we did a hard reset (or are coming from power on) this is - * true for ATA or ATAPI. Until we've set a suitable controller - * mode we should not touch the bus as we may be talking too fast. - */ - - ata_link_for_each_dev(dev, &ap->link) - dev->pio_mode = XFER_PIO_0; - - /* If the controller has a pio mode setup function then use - it to set the chipset to rights. Don't touch the DMA setup - as that will be dealt with when revalidating */ - if (ap->ops->set_piomode) { - ata_link_for_each_dev(dev, &ap->link) - if (devmask & (1 << i++)) - ap->ops->set_piomode(ap, dev); - } - - /* spec mandates ">= 2ms" before checking status. - * We wait 150ms, because that was the magic delay used for - * ATAPI devices in Hale Landis's ATADRVR, for the period of time - * between when the ATA command register is written, and then - * status is checked. Because waiting for "a while" before - * checking status is fine, post SRST, we perform this magic - * delay here as well. - * - * Old drivers/ide uses the 2mS rule and then waits for ready - */ - msleep(150); + /* wait a while before checking status */ + ata_wait_after_reset(ap, deadline); /* Before we perform post reset processing we want to see if * the bus shows 0xFF because the odd clown forgets the D7 @@ -3691,8 +3908,8 @@ int sata_std_hardreset(struct ata_link *link, unsigned int *class, return 0; } - /* wait a while before checking status, see SRST for more info */ - msleep(150); + /* wait a while before checking status */ + ata_wait_after_reset(ap, deadline); /* If PMP is supported, we have to do follow-up SRST. Note * that some PMPs don't send D2H Reg FIS after hardreset at @@ -3992,6 +4209,7 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = { { "ST3160812AS", "3.ADJ", ATA_HORKAGE_NONCQ, }, { "ST980813AS", "3.ADB", ATA_HORKAGE_NONCQ, }, { "SAMSUNG HD401LJ", "ZZ100-15", ATA_HORKAGE_NONCQ, }, + { "Maxtor 7V300F0", "VA111900", ATA_HORKAGE_NONCQ, }, /* devices which puke on READ_NATIVE_MAX */ { "HDS724040KLSA80", "KFAOA20N", ATA_HORKAGE_BROKEN_HPA, }, @@ -4689,6 +4907,7 @@ static int ata_sg_setup(struct ata_queued_cmd *qc) * data in this function or read data in ata_sg_clean. */ offset = lsg->offset + lsg->length - qc->pad_len; + sg_init_table(psg, 1); sg_set_page(psg, nth_page(sg_page(lsg), offset >> PAGE_SHIFT), qc->pad_len, offset_in_page(offset)); @@ -5594,6 +5813,9 @@ void ata_qc_complete(struct ata_queued_cmd *qc) * taken care of. */ if (ap->ops->error_handler) { + struct ata_device *dev = qc->dev; + struct ata_eh_info *ehi = &dev->link->eh_info; + WARN_ON(ap->pflags & ATA_PFLAG_FROZEN); if (unlikely(qc->err_mask)) @@ -5612,6 +5834,27 @@ void ata_qc_complete(struct ata_queued_cmd *qc) if (qc->flags & ATA_QCFLAG_RESULT_TF) fill_result_tf(qc); + /* Some commands need post-processing after successful + * completion. + */ + switch (qc->tf.command) { + case ATA_CMD_SET_FEATURES: + if (qc->tf.feature != SETFEATURES_WC_ON && + qc->tf.feature != SETFEATURES_WC_OFF) + break; + /* fall through */ + case ATA_CMD_INIT_DEV_PARAMS: /* CHS translation changed */ + case ATA_CMD_SET_MULTI: /* multi_count changed */ + /* revalidate device */ + ehi->dev_action[dev->devno] |= ATA_EH_REVALIDATE; + ata_port_schedule_eh(ap); + break; + + case ATA_CMD_SLEEP: + dev->flags |= ATA_DFLAG_SLEEPING; + break; + } + __ata_qc_complete(qc); } else { if (qc->flags & ATA_QCFLAG_EH_SCHEDULED) @@ -5749,6 +5992,14 @@ void ata_qc_issue(struct ata_queued_cmd *qc) qc->flags &= ~ATA_QCFLAG_DMAMAP; } + /* if device is sleeping, schedule softreset and abort the link */ + if (unlikely(qc->dev->flags & ATA_DFLAG_SLEEPING)) { + link->eh_info.action |= ATA_EH_SOFTRESET; + ata_ehi_push_desc(&link->eh_info, "waking up from sleep"); + ata_link_abort(link); + return; + } + ap->ops->qc_prep(qc); qc->err_mask |= ap->ops->qc_issue(qc); @@ -6296,6 +6547,12 @@ int ata_host_suspend(struct ata_host *host, pm_message_t mesg) { int rc; + /* + * disable link pm on all ports before requesting + * any pm activity + */ + ata_lpm_enable(host); + rc = ata_host_request_pm(host, mesg, 0, ATA_EHI_QUIET, 1); if (rc == 0) host->dev->power.power_state = mesg; @@ -6318,6 +6575,9 @@ void ata_host_resume(struct ata_host *host) ata_host_request_pm(host, PMSG_ON, ATA_EH_SOFTRESET, ATA_EHI_NO_AUTOPSY | ATA_EHI_QUIET, 0); host->dev->power.power_state = PMSG_ON; + + /* reenable link pm */ + ata_lpm_disable(host); } #endif @@ -6860,6 +7120,7 @@ int ata_host_register(struct ata_host *host, struct scsi_host_template *sht) struct ata_port *ap = host->ports[i]; ata_scsi_scan_host(ap, 1); + ata_lpm_schedule(ap, ap->pm_policy); } return 0; @@ -7256,7 +7517,6 @@ const struct ata_port_info ata_dummy_port_info = { * likely to change as new drivers are added and updated. * Do not depend on ABI/API stability. */ - EXPORT_SYMBOL_GPL(sata_deb_timing_normal); EXPORT_SYMBOL_GPL(sata_deb_timing_hotplug); EXPORT_SYMBOL_GPL(sata_deb_timing_long); @@ -7326,6 +7586,7 @@ EXPORT_SYMBOL_GPL(ata_port_disable); EXPORT_SYMBOL_GPL(ata_ratelimit); EXPORT_SYMBOL_GPL(ata_wait_register); EXPORT_SYMBOL_GPL(ata_busy_sleep); +EXPORT_SYMBOL_GPL(ata_wait_after_reset); EXPORT_SYMBOL_GPL(ata_wait_ready); EXPORT_SYMBOL_GPL(ata_port_queue_task); EXPORT_SYMBOL_GPL(ata_scsi_ioctl); diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c index 8cb35bb8760..8d64f8fd8f1 100644 --- a/drivers/ata/libata-eh.c +++ b/drivers/ata/libata-eh.c @@ -1800,10 +1800,8 @@ static void ata_eh_link_autopsy(struct ata_link *link) qc->err_mask &= ~AC_ERR_OTHER; /* SENSE_VALID trumps dev/unknown error and revalidation */ - if (qc->flags & ATA_QCFLAG_SENSE_VALID) { + if (qc->flags & ATA_QCFLAG_SENSE_VALID) qc->err_mask &= ~(AC_ERR_DEV | AC_ERR_OTHER); - ehc->i.action &= ~ATA_EH_REVALIDATE; - } /* accumulate error info */ ehc->i.dev = qc->dev; @@ -1816,7 +1814,8 @@ static void ata_eh_link_autopsy(struct ata_link *link) if (ap->pflags & ATA_PFLAG_FROZEN || all_err_mask & (AC_ERR_HSM | AC_ERR_TIMEOUT)) ehc->i.action |= ATA_EH_SOFTRESET; - else if (all_err_mask) + else if ((is_io && all_err_mask) || + (!is_io && (all_err_mask & ~AC_ERR_DEV))) ehc->i.action |= ATA_EH_REVALIDATE; /* if we have offending qcs and the associated failed device */ @@ -1879,7 +1878,9 @@ static void ata_eh_link_report(struct ata_link *link) for (tag = 0; tag < ATA_MAX_QUEUE; tag++) { struct ata_queued_cmd *qc = __ata_qc_from_tag(ap, tag); - if (!(qc->flags & ATA_QCFLAG_FAILED) || qc->dev->link != link) + if (!(qc->flags & ATA_QCFLAG_FAILED) || qc->dev->link != link || + ((qc->flags & ATA_QCFLAG_QUIET) && + qc->err_mask == AC_ERR_DEV)) continue; if (qc->flags & ATA_QCFLAG_SENSE_VALID && !qc->err_mask) continue; @@ -2083,6 +2084,25 @@ int ata_eh_reset(struct ata_link *link, int classify, ata_eh_about_to_do(link, NULL, ehc->i.action & ATA_EH_RESET_MASK); + ata_link_for_each_dev(dev, link) { + /* If we issue an SRST then an ATA drive (not ATAPI) + * may change configuration and be in PIO0 timing. If + * we do a hard reset (or are coming from power on) + * this is true for ATA or ATAPI. Until we've set a + * suitable controller mode we should not touch the + * bus as we may be talking too fast. + */ + dev->pio_mode = XFER_PIO_0; + + /* If the controller has a pio mode setup function + * then use it to set the chipset to rights. Don't + * touch the DMA setup as that will be dealt with when + * configuring devices. + */ + if (ap->ops->set_piomode) + ap->ops->set_piomode(ap, dev); + } + /* Determine which reset to use and record in ehc->i.action. * prereset() may examine and modify it. */ @@ -2208,9 +2228,11 @@ int ata_eh_reset(struct ata_link *link, int classify, ata_link_for_each_dev(dev, link) { /* After the reset, the device state is PIO 0 * and the controller state is undefined. - * Record the mode. + * Reset also wakes up drives from sleeping + * mode. */ dev->pio_mode = XFER_PIO_0; + dev->flags &= ~ATA_DFLAG_SLEEPING; if (ata_link_offline(link)) continue; @@ -2416,7 +2438,7 @@ static int ata_eh_handle_dev_fail(struct ata_device *dev, int err) /* give it just one more chance */ ehc->tries[dev->devno] = min(ehc->tries[dev->devno], 1); case -EIO: - if (ehc->tries[dev->devno] == 1) { + if (ehc->tries[dev->devno] == 1 && dev->pio_mode > XFER_PIO_0) { /* This is the last chance, better to slow * down than lose it. */ @@ -2607,6 +2629,10 @@ int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset, ehc->i.flags &= ~ATA_EHI_SETMODE; } + if (ehc->i.action & ATA_EHI_LPM) + ata_link_for_each_dev(dev, link) + ata_dev_enable_pm(dev, ap->pm_policy); + /* this link is okay now */ ehc->i.flags = 0; continue; @@ -2672,8 +2698,15 @@ void ata_eh_finish(struct ata_port *ap) /* FIXME: Once EH migration is complete, * generate sense data in this function, * considering both err_mask and tf. + * + * There's no point in retrying invalid + * (detected by libata) and non-IO device + * errors (rejected by device). Finish them + * immediately. */ - if (qc->err_mask & AC_ERR_INVALID) + if ((qc->err_mask & AC_ERR_INVALID) || + (!(qc->flags & ATA_QCFLAG_IO) && + qc->err_mask == AC_ERR_DEV)) ata_eh_qc_complete(qc); else ata_eh_qc_retry(qc); diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index f5d5420a1ba..fc89590d377 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -110,6 +110,74 @@ static struct scsi_transport_template ata_scsi_transport_template = { }; +static const struct { + enum link_pm value; + const char *name; +} link_pm_policy[] = { + { NOT_AVAILABLE, "max_performance" }, + { MIN_POWER, "min_power" }, + { MAX_PERFORMANCE, "max_performance" }, + { MEDIUM_POWER, "medium_power" }, +}; + +const char *ata_scsi_lpm_get(enum link_pm policy) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(link_pm_policy); i++) + if (link_pm_policy[i].value == policy) + return link_pm_policy[i].name; + + return NULL; +} + +static ssize_t ata_scsi_lpm_put(struct class_device *class_dev, + const char *buf, size_t count) +{ + struct Scsi_Host *shost = class_to_shost(class_dev); + struct ata_port *ap = ata_shost_to_port(shost); + enum link_pm policy = 0; + int i; + + /* + * we are skipping array location 0 on purpose - this + * is because a value of NOT_AVAILABLE is displayed + * to the user as max_performance, but when the user + * writes "max_performance", they actually want the + * value to match MAX_PERFORMANCE. + */ + for (i = 1; i < ARRAY_SIZE(link_pm_policy); i++) { + const int len = strlen(link_pm_policy[i].name); + if (strncmp(link_pm_policy[i].name, buf, len) == 0 && + buf[len] == '\n') { + policy = link_pm_policy[i].value; + break; + } + } + if (!policy) + return -EINVAL; + + ata_lpm_schedule(ap, policy); + return count; +} + +static ssize_t +ata_scsi_lpm_show(struct class_device *class_dev, char *buf) +{ + struct Scsi_Host *shost = class_to_shost(class_dev); + struct ata_port *ap = ata_shost_to_port(shost); + const char *policy = + ata_scsi_lpm_get(ap->pm_policy); + + if (!policy) + return -EINVAL; + + return snprintf(buf, 23, "%s\n", policy); +} +CLASS_DEVICE_ATTR(link_power_management_policy, S_IRUGO | S_IWUSR, + ata_scsi_lpm_show, ata_scsi_lpm_put); +EXPORT_SYMBOL_GPL(class_device_attr_link_power_management_policy); + static void ata_scsi_invalid_field(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *)) { @@ -1040,6 +1108,9 @@ static unsigned int ata_scsi_flush_xlat(struct ata_queued_cmd *qc) else tf->command = ATA_CMD_FLUSH; + /* flush is critical for IO integrity, consider it an IO command */ + qc->flags |= ATA_QCFLAG_IO; + return 0; } @@ -1361,33 +1432,10 @@ nothing_to_do: static void ata_scsi_qc_complete(struct ata_queued_cmd *qc) { struct ata_port *ap = qc->ap; - struct ata_eh_info *ehi = &qc->dev->link->eh_info; struct scsi_cmnd *cmd = qc->scsicmd; u8 *cdb = cmd->cmnd; int need_sense = (qc->err_mask != 0); - /* We snoop the SET_FEATURES - Write Cache ON/OFF command, and - * schedule EH_REVALIDATE operation to update the IDENTIFY DEVICE - * cache - */ - if (ap->ops->error_handler && !need_sense) { - switch (qc->tf.command) { - case ATA_CMD_SET_FEATURES: - if ((qc->tf.feature == SETFEATURES_WC_ON) || - (qc->tf.feature == SETFEATURES_WC_OFF)) { - ehi->action |= ATA_EH_REVALIDATE; - ata_port_schedule_eh(ap); - } - break; - - case ATA_CMD_INIT_DEV_PARAMS: /* CHS translation changed */ - case ATA_CMD_SET_MULTI: /* multi_count changed */ - ehi->action |= ATA_EH_REVALIDATE; - ata_port_schedule_eh(ap); - break; - } - } - /* For ATA pass thru (SAT) commands, generate a sense block if * user mandated it or if there's an error. Note that if we * generate because the user forced us to, a check condition @@ -2719,8 +2767,8 @@ static unsigned int ata_scsi_pass_thru(struct ata_queued_cmd *qc) */ qc->nbytes = scsi_bufflen(scmd); - /* request result TF */ - qc->flags |= ATA_QCFLAG_RESULT_TF; + /* request result TF and be quiet about device error */ + qc->flags |= ATA_QCFLAG_RESULT_TF | ATA_QCFLAG_QUIET; return 0; diff --git a/drivers/ata/libata.h b/drivers/ata/libata.h index 90df58a3edc..0e6cf3a484d 100644 --- a/drivers/ata/libata.h +++ b/drivers/ata/libata.h @@ -101,6 +101,8 @@ extern int sata_link_init_spd(struct ata_link *link); extern int ata_task_ioctl(struct scsi_device *scsidev, void __user *arg); extern int ata_cmd_ioctl(struct scsi_device *scsidev, void __user *arg); extern struct ata_port *ata_port_alloc(struct ata_host *host); +extern void ata_dev_enable_pm(struct ata_device *dev, enum link_pm policy); +extern void ata_lpm_schedule(struct ata_port *ap, enum link_pm); /* libata-acpi.c */ #ifdef CONFIG_ATA_ACPI diff --git a/drivers/ata/pata_acpi.c b/drivers/ata/pata_acpi.c index 0f6f7bcc3de..e4542ab9c7f 100644 --- a/drivers/ata/pata_acpi.c +++ b/drivers/ata/pata_acpi.c @@ -181,7 +181,7 @@ static void pacpi_set_piomode(struct ata_port *ap, struct ata_device *adev) int unit = adev->devno; struct pata_acpi *acpi = ap->private_data; - if(!(acpi->gtm.flags & 0x10)) + if (!(acpi->gtm.flags & 0x10)) unit = 0; /* Now stuff the nS values into the structure */ @@ -202,7 +202,7 @@ static void pacpi_set_dmamode(struct ata_port *ap, struct ata_device *adev) int unit = adev->devno; struct pata_acpi *acpi = ap->private_data; - if(!(acpi->gtm.flags & 0x10)) + if (!(acpi->gtm.flags & 0x10)) unit = 0; /* Now stuff the nS values into the structure */ diff --git a/drivers/ata/pata_ns87415.c b/drivers/ata/pata_ns87415.c index b9a17eb100d..d0e2e50823b 100644 --- a/drivers/ata/pata_ns87415.c +++ b/drivers/ata/pata_ns87415.c @@ -215,6 +215,8 @@ static int ns87415_check_atapi_dma(struct ata_queued_cmd *qc) #include <asm/superio.h> +#define SUPERIO_IDE_MAX_RETRIES 25 + /** * ns87560_read_buggy - workaround buggy Super I/O chip * @port: Port to read diff --git a/drivers/ata/pata_optidma.c b/drivers/ata/pata_optidma.c index 6b07b5b4853..f9b485a487a 100644 --- a/drivers/ata/pata_optidma.c +++ b/drivers/ata/pata_optidma.c @@ -449,7 +449,7 @@ static int optiplus_with_udma(struct pci_dev *pdev) /* Find function 1 */ dev1 = pci_get_device(0x1045, 0xC701, NULL); - if(dev1 == NULL) + if (dev1 == NULL) return 0; /* Rev must be >= 0x10 */ diff --git a/drivers/ata/pata_pcmcia.c b/drivers/ata/pata_pcmcia.c index 5db2013230b..fd36099428a 100644 --- a/drivers/ata/pata_pcmcia.c +++ b/drivers/ata/pata_pcmcia.c @@ -74,8 +74,7 @@ static int pcmcia_set_mode(struct ata_link *link, struct ata_device **r_failed_d return ata_do_set_mode(link, r_failed_dev); if (memcmp(master->id + ATA_ID_FW_REV, slave->id + ATA_ID_FW_REV, - ATA_ID_FW_REV_LEN + ATA_ID_PROD_LEN) == 0) - { + ATA_ID_FW_REV_LEN + ATA_ID_PROD_LEN) == 0) { /* Suspicious match, but could be two cards from the same vendor - check serial */ if (memcmp(master->id + ATA_ID_SERNO, slave->id + ATA_ID_SERNO, @@ -248,7 +247,8 @@ static int pcmcia_init_one(struct pcmcia_device *pdev) goto next_entry; io_base = pdev->io.BasePort1; ctl_base = pdev->io.BasePort1 + 0x0e; - } else goto next_entry; + } else + goto next_entry; /* If we've got this far, we're done */ break; } @@ -285,8 +285,8 @@ next_entry: printk(KERN_WARNING DRV_NAME ": second channel not yet supported.\n"); /* - * Having done the PCMCIA plumbing the ATA side is relatively - * sane. + * Having done the PCMCIA plumbing the ATA side is relatively + * sane. */ ret = -ENOMEM; host = ata_host_alloc(&pdev->dev, 1); @@ -363,7 +363,7 @@ static struct pcmcia_device_id pcmcia_devices[] = { PCMCIA_DEVICE_MANF_CARD(0x0098, 0x0000), /* Toshiba */ PCMCIA_DEVICE_MANF_CARD(0x00a4, 0x002d), PCMCIA_DEVICE_MANF_CARD(0x00ce, 0x0000), /* Samsung */ - PCMCIA_DEVICE_MANF_CARD(0x0319, 0x0000), /* Hitachi */ + PCMCIA_DEVICE_MANF_CARD(0x0319, 0x0000), /* Hitachi */ PCMCIA_DEVICE_MANF_CARD(0x2080, 0x0001), PCMCIA_DEVICE_MANF_CARD(0x4e01, 0x0100), /* Viking CFA */ PCMCIA_DEVICE_MANF_CARD(0x4e01, 0x0200), /* Lexar, Viking CFA */ diff --git a/drivers/ata/pata_pdc2027x.c b/drivers/ata/pata_pdc2027x.c index 3d3f1558cde..2622577521a 100644 --- a/drivers/ata/pata_pdc2027x.c +++ b/drivers/ata/pata_pdc2027x.c @@ -348,7 +348,7 @@ static unsigned long pdc2027x_mode_filter(struct ata_device *adev, unsigned long ata_id_c_string(pair->id, model_num, ATA_ID_PROD, ATA_ID_PROD_LEN + 1); /* If the master is a maxtor in UDMA6 then the slave should not use UDMA 6 */ - if(strstr(model_num, "Maxtor") == 0 && pair->dma_mode == XFER_UDMA_6) + if (strstr(model_num, "Maxtor") == 0 && pair->dma_mode == XFER_UDMA_6) mask &= ~ (1 << (6 + ATA_SHIFT_UDMA)); return ata_pci_default_filter(adev, mask); diff --git a/drivers/ata/pata_pdc202xx_old.c b/drivers/ata/pata_pdc202xx_old.c index 65d951618c6..bc7c2d5d8d5 100644 --- a/drivers/ata/pata_pdc202xx_old.c +++ b/drivers/ata/pata_pdc202xx_old.c @@ -351,9 +351,9 @@ static int pdc202xx_init_one(struct pci_dev *dev, const struct pci_device_id *id struct pci_dev *bridge = dev->bus->self; /* Don't grab anything behind a Promise I2O RAID */ if (bridge && bridge->vendor == PCI_VENDOR_ID_INTEL) { - if( bridge->device == PCI_DEVICE_ID_INTEL_I960) + if (bridge->device == PCI_DEVICE_ID_INTEL_I960) return -ENODEV; - if( bridge->device == PCI_DEVICE_ID_INTEL_I960RM) + if (bridge->device == PCI_DEVICE_ID_INTEL_I960RM) return -ENODEV; } } diff --git a/drivers/ata/pata_scc.c b/drivers/ata/pata_scc.c index 55576138fae..ea2ef9fc15b 100644 --- a/drivers/ata/pata_scc.c +++ b/drivers/ata/pata_scc.c @@ -570,17 +570,8 @@ static unsigned int scc_bus_softreset(struct ata_port *ap, unsigned int devmask, udelay(20); out_be32(ioaddr->ctl_addr, ap->ctl); - /* spec mandates ">= 2ms" before checking status. - * We wait 150ms, because that was the magic delay used for - * ATAPI devices in Hale Landis's ATADRVR, for the period of time - * between when the ATA command register is written, and then - * status is checked. Because waiting for "a while" before - * checking status is fine, post SRST, we perform this magic - * delay here as well. - * - * Old drivers/ide uses the 2mS rule and then waits for ready - */ - msleep(150); + /* wait a while before checking status */ + ata_wait_after_reset(ap, deadline); /* Before we perform post reset processing we want to see if * the bus shows 0xFF because the odd clown forgets the D7 diff --git a/drivers/ata/pata_via.c b/drivers/ata/pata_via.c index ea7a9a652e6..a4175fbdd17 100644 --- a/drivers/ata/pata_via.c +++ b/drivers/ata/pata_via.c @@ -176,7 +176,7 @@ static int via_cable_detect(struct ata_port *ap) { if ((config->flags & VIA_UDMA) < VIA_UDMA_66) return ATA_CBL_PATA40; /* UDMA 66 chips have only drive side logic */ - else if((config->flags & VIA_UDMA) < VIA_UDMA_100) + else if ((config->flags & VIA_UDMA) < VIA_UDMA_100) return ATA_CBL_PATA_UNK; /* UDMA 100 or later */ pci_read_config_dword(pdev, 0x50, &ata66); diff --git a/drivers/ata/pata_winbond.c b/drivers/ata/pata_winbond.c index 549cbbe9fd0..311cdb3a556 100644 --- a/drivers/ata/pata_winbond.c +++ b/drivers/ata/pata_winbond.c @@ -279,7 +279,7 @@ static __init int winbond_init(void) if (request_region(port, 2, "pata_winbond")) { ret = winbond_init_one(port); - if(ret <= 0) + if (ret <= 0) release_region(port, 2); else ct+= ret; } diff --git a/drivers/ata/pdc_adma.c b/drivers/ata/pdc_adma.c index 199f7e150eb..bd4c2a3c88d 100644 --- a/drivers/ata/pdc_adma.c +++ b/drivers/ata/pdc_adma.c @@ -47,10 +47,10 @@ #define DRV_VERSION "1.0" /* macro to calculate base address for ATA regs */ -#define ADMA_ATA_REGS(base,port_no) ((base) + ((port_no) * 0x40)) +#define ADMA_ATA_REGS(base, port_no) ((base) + ((port_no) * 0x40)) /* macro to calculate base address for ADMA regs */ -#define ADMA_REGS(base,port_no) ((base) + 0x80 + ((port_no) * 0x20)) +#define ADMA_REGS(base, port_no) ((base) + 0x80 + ((port_no) * 0x20)) /* macro to obtain addresses from ata_port */ #define ADMA_PORT_REGS(ap) \ @@ -128,7 +128,7 @@ struct adma_port_priv { adma_state_t state; }; -static int adma_ata_init_one (struct pci_dev *pdev, +static int adma_ata_init_one(struct pci_dev *pdev, const struct pci_device_id *ent); static int adma_port_start(struct ata_port *ap); static void adma_host_stop(struct ata_host *host); @@ -340,8 +340,8 @@ static int adma_fill_sg(struct ata_queued_cmd *qc) buf[i++] = 0; /* pPKLW */ buf[i++] = 0; /* reserved */ - *(__le32 *)(buf + i) - = (pFLAGS & pEND) ? 0 : cpu_to_le32(pp->pkt_dma + i + 4); + *(__le32 *)(buf + i) = + (pFLAGS & pEND) ? 0 : cpu_to_le32(pp->pkt_dma + i + 4); i += 4; VPRINTK("PRD[%u] = (0x%lX, 0x%X)\n", i/4, @@ -617,7 +617,7 @@ static int adma_port_start(struct ata_port *ap) return -ENOMEM; /* paranoia? */ if ((pp->pkt_dma & 7) != 0) { - printk("bad alignment for pp->pkt_dma: %08x\n", + printk(KERN_ERR "bad alignment for pp->pkt_dma: %08x\n", (u32)pp->pkt_dma); return -ENOMEM; } diff --git a/drivers/ata/sata_inic162x.c b/drivers/ata/sata_inic162x.c index 08595f34b3e..323c087e8cc 100644 --- a/drivers/ata/sata_inic162x.c +++ b/drivers/ata/sata_inic162x.c @@ -143,7 +143,7 @@ static const int scr_map[] = { [SCR_CONTROL] = 2, }; -static void __iomem * inic_port_base(struct ata_port *ap) +static void __iomem *inic_port_base(struct ata_port *ap) { return ap->host->iomap[MMIO_BAR] + ap->port_no * PORT_SIZE; } @@ -448,7 +448,7 @@ static int inic_hardreset(struct ata_link *link, unsigned int *class, struct ata_taskfile tf; /* wait a while before checking status */ - msleep(150); + ata_wait_after_reset(ap, deadline); rc = ata_wait_ready(ap, deadline); /* link occupied, -ENODEV too is an error */ diff --git a/drivers/ata/sata_mv.c b/drivers/ata/sata_mv.c index b39648f0914..a43f64d2775 100644 --- a/drivers/ata/sata_mv.c +++ b/drivers/ata/sata_mv.c @@ -1156,7 +1156,7 @@ static void mv_fill_sg(struct ata_queued_cmd *qc) last_sg->flags_size |= cpu_to_le32(EPRD_FLAG_END_OF_TBL); } -static inline void mv_crqb_pack_cmd(__le16 *cmdw, u8 data, u8 addr, unsigned last) +static void mv_crqb_pack_cmd(__le16 *cmdw, u8 data, u8 addr, unsigned last) { u16 tmp = data | (addr << CRQB_CMD_ADDR_SHIFT) | CRQB_CMD_CS | (last ? CRQB_CMD_LAST : 0); @@ -2429,7 +2429,7 @@ static int mv_chip_id(struct ata_host *host, unsigned int board_idx) struct mv_host_priv *hpriv = host->private_data; u32 hp_flags = hpriv->hp_flags; - switch(board_idx) { + switch (board_idx) { case chip_5080: hpriv->ops = &mv5xxx_ops; hp_flags |= MV_HP_GEN_I; @@ -2510,7 +2510,8 @@ static int mv_chip_id(struct ata_host *host, unsigned int board_idx) break; default: - printk(KERN_ERR DRV_NAME ": BUG: invalid board index %u\n", board_idx); + dev_printk(KERN_ERR, &pdev->dev, + "BUG: invalid board index %u\n", board_idx); return 1; } diff --git a/drivers/ata/sata_nv.c b/drivers/ata/sata_nv.c index f1b422f7c74..35b2df29752 100644 --- a/drivers/ata/sata_nv.c +++ b/drivers/ata/sata_nv.c @@ -291,7 +291,7 @@ struct nv_swncq_port_priv { }; -#define NV_ADMA_CHECK_INTR(GCTL, PORT) ((GCTL) & ( 1 << (19 + (12 * (PORT))))) +#define NV_ADMA_CHECK_INTR(GCTL, PORT) ((GCTL) & (1 << (19 + (12 * (PORT))))) static int nv_init_one(struct pci_dev *pdev, const struct pci_device_id *ent); #ifdef CONFIG_PM @@ -884,8 +884,9 @@ static int nv_adma_check_cpb(struct ata_port *ap, int cpb_num, int force_err) /* Notifier bits set without a command may indicate the drive is misbehaving. Raise host state machine violation on this condition. */ - ata_port_printk(ap, KERN_ERR, "notifier for tag %d with no command?\n", - cpb_num); + ata_port_printk(ap, KERN_ERR, + "notifier for tag %d with no cmd?\n", + cpb_num); ehi->err_mask |= AC_ERR_HSM; ehi->action |= ATA_EH_SOFTRESET; ata_port_freeze(ap); @@ -1012,7 +1013,7 @@ static irqreturn_t nv_adma_interrupt(int irq, void *dev_instance) u32 check_commands; int pos, error = 0; - if(ata_tag_valid(ap->link.active_tag)) + if (ata_tag_valid(ap->link.active_tag)) check_commands = 1 << ap->link.active_tag; else check_commands = ap->link.sactive; @@ -1021,14 +1022,14 @@ static irqreturn_t nv_adma_interrupt(int irq, void *dev_instance) while ((pos = ffs(check_commands)) && !error) { pos--; error = nv_adma_check_cpb(ap, pos, - notifier_error & (1 << pos) ); - check_commands &= ~(1 << pos ); + notifier_error & (1 << pos)); + check_commands &= ~(1 << pos); } } } } - if(notifier_clears[0] || notifier_clears[1]) { + if (notifier_clears[0] || notifier_clears[1]) { /* Note: Both notifier clear registers must be written if either is set, even if one is zero, according to NVIDIA. */ struct nv_adma_port_priv *pp = host->ports[0]->private_data; @@ -1061,7 +1062,7 @@ static void nv_adma_freeze(struct ata_port *ap) tmp = readw(mmio + NV_ADMA_CTL); writew(tmp & ~(NV_ADMA_CTL_AIEN | NV_ADMA_CTL_HOTPLUG_IEN), mmio + NV_ADMA_CTL); - readw(mmio + NV_ADMA_CTL ); /* flush posted write */ + readw(mmio + NV_ADMA_CTL); /* flush posted write */ } static void nv_adma_thaw(struct ata_port *ap) @@ -1079,7 +1080,7 @@ static void nv_adma_thaw(struct ata_port *ap) tmp = readw(mmio + NV_ADMA_CTL); writew(tmp | (NV_ADMA_CTL_AIEN | NV_ADMA_CTL_HOTPLUG_IEN), mmio + NV_ADMA_CTL); - readw(mmio + NV_ADMA_CTL ); /* flush posted write */ + readw(mmio + NV_ADMA_CTL); /* flush posted write */ } static void nv_adma_irq_clear(struct ata_port *ap) @@ -1119,7 +1120,7 @@ static void nv_adma_post_internal_cmd(struct ata_queued_cmd *qc) { struct nv_adma_port_priv *pp = qc->ap->private_data; - if(pp->flags & NV_ADMA_PORT_REGISTER_MODE) + if (pp->flags & NV_ADMA_PORT_REGISTER_MODE) ata_bmdma_post_internal_cmd(qc); } @@ -1165,7 +1166,7 @@ static int nv_adma_port_start(struct ata_port *ap) pp->cpb_dma = mem_dma; writel(mem_dma & 0xFFFFFFFF, mmio + NV_ADMA_CPB_BASE_LOW); - writel((mem_dma >> 16 ) >> 16, mmio + NV_ADMA_CPB_BASE_HIGH); + writel((mem_dma >> 16) >> 16, mmio + NV_ADMA_CPB_BASE_HIGH); mem += NV_ADMA_MAX_CPBS * NV_ADMA_CPB_SZ; mem_dma += NV_ADMA_MAX_CPBS * NV_ADMA_CPB_SZ; @@ -1189,15 +1190,15 @@ static int nv_adma_port_start(struct ata_port *ap) /* clear GO for register mode, enable interrupt */ tmp = readw(mmio + NV_ADMA_CTL); - writew( (tmp & ~NV_ADMA_CTL_GO) | NV_ADMA_CTL_AIEN | - NV_ADMA_CTL_HOTPLUG_IEN, mmio + NV_ADMA_CTL); + writew((tmp & ~NV_ADMA_CTL_GO) | NV_ADMA_CTL_AIEN | + NV_ADMA_CTL_HOTPLUG_IEN, mmio + NV_ADMA_CTL); tmp = readw(mmio + NV_ADMA_CTL); writew(tmp | NV_ADMA_CTL_CHANNEL_RESET, mmio + NV_ADMA_CTL); - readw( mmio + NV_ADMA_CTL ); /* flush posted write */ + readw(mmio + NV_ADMA_CTL); /* flush posted write */ udelay(1); writew(tmp & ~NV_ADMA_CTL_CHANNEL_RESET, mmio + NV_ADMA_CTL); - readw( mmio + NV_ADMA_CTL ); /* flush posted write */ + readw(mmio + NV_ADMA_CTL); /* flush posted write */ return 0; } @@ -1237,7 +1238,7 @@ static int nv_adma_port_resume(struct ata_port *ap) /* set CPB block location */ writel(pp->cpb_dma & 0xFFFFFFFF, mmio + NV_ADMA_CPB_BASE_LOW); - writel((pp->cpb_dma >> 16 ) >> 16, mmio + NV_ADMA_CPB_BASE_HIGH); + writel((pp->cpb_dma >> 16) >> 16, mmio + NV_ADMA_CPB_BASE_HIGH); /* clear any outstanding interrupt conditions */ writew(0xffff, mmio + NV_ADMA_STAT); @@ -1250,15 +1251,15 @@ static int nv_adma_port_resume(struct ata_port *ap) /* clear GO for register mode, enable interrupt */ tmp = readw(mmio + NV_ADMA_CTL); - writew( (tmp & ~NV_ADMA_CTL_GO) | NV_ADMA_CTL_AIEN | - NV_ADMA_CTL_HOTPLUG_IEN, mmio + NV_ADMA_CTL); + writew((tmp & ~NV_ADMA_CTL_GO) | NV_ADMA_CTL_AIEN | + NV_ADMA_CTL_HOTPLUG_IEN, mmio + NV_ADMA_CTL); tmp = readw(mmio + NV_ADMA_CTL); writew(tmp | NV_ADMA_CTL_CHANNEL_RESET, mmio + NV_ADMA_CTL); - readw( mmio + NV_ADMA_CTL ); /* flush posted write */ + readw(mmio + NV_ADMA_CTL); /* flush posted write */ udelay(1); writew(tmp & ~NV_ADMA_CTL_CHANNEL_RESET, mmio + NV_ADMA_CTL); - readw( mmio + NV_ADMA_CTL ); /* flush posted write */ + readw(mmio + NV_ADMA_CTL); /* flush posted write */ return 0; } @@ -1342,7 +1343,8 @@ static void nv_adma_fill_sg(struct ata_queued_cmd *qc, struct nv_adma_cpb *cpb) idx = 0; ata_for_each_sg(sg, qc) { - aprd = (idx < 5) ? &cpb->aprd[idx] : &pp->aprd[NV_ADMA_SGTBL_LEN * qc->tag + (idx-5)]; + aprd = (idx < 5) ? &cpb->aprd[idx] : + &pp->aprd[NV_ADMA_SGTBL_LEN * qc->tag + (idx-5)]; nv_adma_fill_aprd(qc, sg, idx, aprd); idx++; } @@ -1359,12 +1361,12 @@ static int nv_adma_use_reg_mode(struct ata_queued_cmd *qc) /* ADMA engine can only be used for non-ATAPI DMA commands, or interrupt-driven no-data commands, where a result taskfile is not required. */ - if((pp->flags & NV_ADMA_ATAPI_SETUP_COMPLETE) || + if ((pp->flags & NV_ADMA_ATAPI_SETUP_COMPLETE) || (qc->tf.flags & ATA_TFLAG_POLLING) || (qc->flags & ATA_QCFLAG_RESULT_TF)) return 1; - if((qc->flags & ATA_QCFLAG_DMAMAP) || + if ((qc->flags & ATA_QCFLAG_DMAMAP) || (qc->tf.protocol == ATA_PROT_NODATA)) return 0; @@ -1401,14 +1403,14 @@ static void nv_adma_qc_prep(struct ata_queued_cmd *qc) nv_adma_tf_to_cpb(&qc->tf, cpb->tf); - if(qc->flags & ATA_QCFLAG_DMAMAP) { + if (qc->flags & ATA_QCFLAG_DMAMAP) { nv_adma_fill_sg(qc, cpb); ctl_flags |= NV_CPB_CTL_APRD_VALID; } else memset(&cpb->aprd[0], 0, sizeof(struct nv_adma_prd) * 5); - /* Be paranoid and don't let the device see NV_CPB_CTL_CPB_VALID until we are - finished filling in all of the contents */ + /* Be paranoid and don't let the device see NV_CPB_CTL_CPB_VALID + until we are finished filling in all of the contents */ wmb(); cpb->ctl_flags = ctl_flags; wmb(); @@ -1435,16 +1437,16 @@ static unsigned int nv_adma_qc_issue(struct ata_queued_cmd *qc) and (number of cpbs to append -1) in top 8 bits */ wmb(); - if(curr_ncq != pp->last_issue_ncq) { - /* Seems to need some delay before switching between NCQ and non-NCQ - commands, else we get command timeouts and such. */ + if (curr_ncq != pp->last_issue_ncq) { + /* Seems to need some delay before switching between NCQ and + non-NCQ commands, else we get command timeouts and such. */ udelay(20); pp->last_issue_ncq = curr_ncq; } writew(qc->tag, mmio + NV_ADMA_APPEND); - DPRINTK("Issued tag %u\n",qc->tag); + DPRINTK("Issued tag %u\n", qc->tag); return 0; } @@ -1641,12 +1643,12 @@ static void nv_error_handler(struct ata_port *ap) static void nv_adma_error_handler(struct ata_port *ap) { struct nv_adma_port_priv *pp = ap->private_data; - if(!(pp->flags & NV_ADMA_PORT_REGISTER_MODE)) { + if (!(pp->flags & NV_ADMA_PORT_REGISTER_MODE)) { void __iomem *mmio = pp->ctl_block; int i; u16 tmp; - if(ata_tag_valid(ap->link.active_tag) || ap->link.sactive) { + if (ata_tag_valid(ap->link.active_tag) || ap->link.sactive) { u32 notifier = readl(mmio + NV_ADMA_NOTIFIER); u32 notifier_error = readl(mmio + NV_ADMA_NOTIFIER_ERROR); u32 gen_ctl = readl(pp->gen_block + NV_ADMA_GEN_CTL); @@ -1654,16 +1656,17 @@ static void nv_adma_error_handler(struct ata_port *ap) u8 cpb_count = readb(mmio + NV_ADMA_CPB_COUNT); u8 next_cpb_idx = readb(mmio + NV_ADMA_NEXT_CPB_IDX); - ata_port_printk(ap, KERN_ERR, "EH in ADMA mode, notifier 0x%X " + ata_port_printk(ap, KERN_ERR, + "EH in ADMA mode, notifier 0x%X " "notifier_error 0x%X gen_ctl 0x%X status 0x%X " "next cpb count 0x%X next cpb idx 0x%x\n", notifier, notifier_error, gen_ctl, status, cpb_count, next_cpb_idx); - for( i=0;i<NV_ADMA_MAX_CPBS;i++) { + for (i = 0; i < NV_ADMA_MAX_CPBS; i++) { struct nv_adma_cpb *cpb = &pp->cpb[i]; - if( (ata_tag_valid(ap->link.active_tag) && i == ap->link.active_tag) || - ap->link.sactive & (1 << i) ) + if ((ata_tag_valid(ap->link.active_tag) && i == ap->link.active_tag) || + ap->link.sactive & (1 << i)) ata_port_printk(ap, KERN_ERR, "CPB %d: ctl_flags 0x%x, resp_flags 0x%x\n", i, cpb->ctl_flags, cpb->resp_flags); @@ -1673,8 +1676,9 @@ static void nv_adma_error_handler(struct ata_port *ap) /* Push us back into port register mode for error handling. */ nv_adma_register_mode(ap); - /* Mark all of the CPBs as invalid to prevent them from being executed */ - for( i=0;i<NV_ADMA_MAX_CPBS;i++) + /* Mark all of the CPBs as invalid to prevent them from + being executed */ + for (i = 0; i < NV_ADMA_MAX_CPBS; i++) pp->cpb[i].ctl_flags &= ~NV_CPB_CTL_CPB_VALID; /* clear CPB fetch count */ @@ -1683,10 +1687,10 @@ static void nv_adma_error_handler(struct ata_port *ap) /* Reset channel */ tmp = readw(mmio + NV_ADMA_CTL); writew(tmp | NV_ADMA_CTL_CHANNEL_RESET, mmio + NV_ADMA_CTL); - readw( mmio + NV_ADMA_CTL ); /* flush posted write */ + readw(mmio + NV_ADMA_CTL); /* flush posted write */ udelay(1); writew(tmp & ~NV_ADMA_CTL_CHANNEL_RESET, mmio + NV_ADMA_CTL); - readw( mmio + NV_ADMA_CTL ); /* flush posted write */ + readw(mmio + NV_ADMA_CTL); /* flush posted write */ } ata_bmdma_drive_eh(ap, ata_std_prereset, ata_std_softreset, @@ -2350,9 +2354,9 @@ static irqreturn_t nv_swncq_interrupt(int irq, void *dev_instance) return IRQ_RETVAL(handled); } -static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) +static int nv_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) { - static int printed_version = 0; + static int printed_version; const struct ata_port_info *ppi[] = { NULL, NULL }; struct ata_host *host; struct nv_host_priv *hpriv; @@ -2364,7 +2368,7 @@ static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) // Make sure this is a SATA controller by counting the number of bars // (NVIDIA SATA controllers will always have six bars). Otherwise, // it's an IDE controller and we ignore it. - for (bar=0; bar<6; bar++) + for (bar = 0; bar < 6; bar++) if (pci_resource_start(pdev, bar) == 0) return -ENODEV; @@ -2381,6 +2385,14 @@ static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) type = ADMA; } + if (type == SWNCQ) { + if (swncq_enabled) + dev_printk(KERN_NOTICE, &pdev->dev, + "Using SWNCQ mode\n"); + else + type = GENERIC; + } + ppi[0] = &nv_port_info[type]; rc = ata_pci_prepare_sff_host(pdev, ppi, &host); if (rc) @@ -2422,10 +2434,8 @@ static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) rc = nv_adma_host_init(host); if (rc) return rc; - } else if (type == SWNCQ && swncq_enabled) { - dev_printk(KERN_NOTICE, &pdev->dev, "Using SWNCQ mode\n"); + } else if (type == SWNCQ) nv_swncq_host_init(host); - } pci_set_master(pdev); return ata_host_activate(host, pdev->irq, ppi[0]->irq_handler, @@ -2440,37 +2450,37 @@ static int nv_pci_device_resume(struct pci_dev *pdev) int rc; rc = ata_pci_device_do_resume(pdev); - if(rc) + if (rc) return rc; if (pdev->dev.power.power_state.event == PM_EVENT_SUSPEND) { - if(hpriv->type >= CK804) { + if (hpriv->type >= CK804) { u8 regval; pci_read_config_byte(pdev, NV_MCP_SATA_CFG_20, ®val); regval |= NV_MCP_SATA_CFG_20_SATA_SPACE_EN; pci_write_config_byte(pdev, NV_MCP_SATA_CFG_20, regval); } - if(hpriv->type == ADMA) { + if (hpriv->type == ADMA) { u32 tmp32; struct nv_adma_port_priv *pp; /* enable/disable ADMA on the ports appropriately */ pci_read_config_dword(pdev, NV_MCP_SATA_CFG_20, &tmp32); pp = host->ports[0]->private_data; - if(pp->flags & NV_ADMA_ATAPI_SETUP_COMPLETE) + if (pp->flags & NV_ADMA_ATAPI_SETUP_COMPLETE) tmp32 &= ~(NV_MCP_SATA_CFG_20_PORT0_EN | - NV_MCP_SATA_CFG_20_PORT0_PWB_EN); + NV_MCP_SATA_CFG_20_PORT0_PWB_EN); else tmp32 |= (NV_MCP_SATA_CFG_20_PORT0_EN | - NV_MCP_SATA_CFG_20_PORT0_PWB_EN); + NV_MCP_SATA_CFG_20_PORT0_PWB_EN); pp = host->ports[1]->private_data; - if(pp->flags & NV_ADMA_ATAPI_SETUP_COMPLETE) + if (pp->flags & NV_ADMA_ATAPI_SETUP_COMPLETE) tmp32 &= ~(NV_MCP_SATA_CFG_20_PORT1_EN | - NV_MCP_SATA_CFG_20_PORT1_PWB_EN); + NV_MCP_SATA_CFG_20_PORT1_PWB_EN); else tmp32 |= (NV_MCP_SATA_CFG_20_PORT1_EN | - NV_MCP_SATA_CFG_20_PORT1_PWB_EN); + NV_MCP_SATA_CFG_20_PORT1_PWB_EN); pci_write_config_dword(pdev, NV_MCP_SATA_CFG_20, tmp32); } diff --git a/drivers/ata/sata_promise.c b/drivers/ata/sata_promise.c index 903213153b5..825e717bcef 100644 --- a/drivers/ata/sata_promise.c +++ b/drivers/ata/sata_promise.c @@ -2,6 +2,7 @@ * sata_promise.c - Promise SATA * * Maintained by: Jeff Garzik <jgarzik@pobox.com> + * Mikael Pettersson <mikpe@it.uu.se> * Please ALWAYS copy linux-ide@vger.kernel.org * on emails. * @@ -45,11 +46,12 @@ #include "sata_promise.h" #define DRV_NAME "sata_promise" -#define DRV_VERSION "2.10" +#define DRV_VERSION "2.11" enum { PDC_MAX_PORTS = 4, PDC_MMIO_BAR = 3, + PDC_MAX_PRD = LIBATA_MAX_PRD - 1, /* -1 for ASIC PRD bug workaround */ /* register offsets */ PDC_FEATURE = 0x04, /* Feature/Error reg (per port) */ @@ -83,10 +85,12 @@ enum { PDC_PCI_SYS_ERR = (1 << 22), /* PCI system error */ PDC1_PCI_PARITY_ERR = (1 << 23), /* PCI parity error (from SATA150 driver) */ PDC1_ERR_MASK = PDC1_PCI_PARITY_ERR, - PDC2_ERR_MASK = PDC2_HTO_ERR | PDC2_ATA_HBA_ERR | PDC2_ATA_DMA_CNT_ERR, - PDC_ERR_MASK = (PDC_PH_ERR | PDC_SH_ERR | PDC_DH_ERR | PDC_OVERRUN_ERR - | PDC_UNDERRUN_ERR | PDC_DRIVE_ERR | PDC_PCI_SYS_ERR - | PDC1_ERR_MASK | PDC2_ERR_MASK), + PDC2_ERR_MASK = PDC2_HTO_ERR | PDC2_ATA_HBA_ERR | + PDC2_ATA_DMA_CNT_ERR, + PDC_ERR_MASK = PDC_PH_ERR | PDC_SH_ERR | PDC_DH_ERR | + PDC_OVERRUN_ERR | PDC_UNDERRUN_ERR | + PDC_DRIVE_ERR | PDC_PCI_SYS_ERR | + PDC1_ERR_MASK | PDC2_ERR_MASK, board_2037x = 0, /* FastTrak S150 TX2plus */ board_2037x_pata = 1, /* FastTrak S150 TX2plus PATA port */ @@ -155,7 +159,7 @@ static struct scsi_host_template pdc_ata_sht = { .queuecommand = ata_scsi_queuecmd, .can_queue = ATA_DEF_QUEUE, .this_id = ATA_SHT_THIS_ID, - .sg_tablesize = LIBATA_MAX_PRD, + .sg_tablesize = PDC_MAX_PRD, .cmd_per_lun = ATA_SHT_CMD_PER_LUN, .emulated = ATA_SHT_EMULATED, .use_clustering = ATA_SHT_USE_CLUSTERING, @@ -238,7 +242,7 @@ static const struct ata_port_operations pdc_pata_ops = { }; static const struct ata_port_info pdc_port_info[] = { - /* board_2037x */ + [board_2037x] = { .flags = PDC_COMMON_FLAGS | ATA_FLAG_SATA | PDC_FLAG_SATA_PATA, @@ -248,7 +252,7 @@ static const struct ata_port_info pdc_port_info[] = { .port_ops = &pdc_old_sata_ops, }, - /* board_2037x_pata */ + [board_2037x_pata] = { .flags = PDC_COMMON_FLAGS | ATA_FLAG_SLAVE_POSS, .pio_mask = 0x1f, /* pio0-4 */ @@ -257,7 +261,7 @@ static const struct ata_port_info pdc_port_info[] = { .port_ops = &pdc_pata_ops, }, - /* board_20319 */ + [board_20319] = { .flags = PDC_COMMON_FLAGS | ATA_FLAG_SATA | PDC_FLAG_4_PORTS, @@ -267,7 +271,7 @@ static const struct ata_port_info pdc_port_info[] = { .port_ops = &pdc_old_sata_ops, }, - /* board_20619 */ + [board_20619] = { .flags = PDC_COMMON_FLAGS | ATA_FLAG_SLAVE_POSS | PDC_FLAG_4_PORTS, @@ -277,7 +281,7 @@ static const struct ata_port_info pdc_port_info[] = { .port_ops = &pdc_pata_ops, }, - /* board_2057x */ + [board_2057x] = { .flags = PDC_COMMON_FLAGS | ATA_FLAG_SATA | PDC_FLAG_GEN_II | PDC_FLAG_SATA_PATA, @@ -287,7 +291,7 @@ static const struct ata_port_info pdc_port_info[] = { .port_ops = &pdc_sata_ops, }, - /* board_2057x_pata */ + [board_2057x_pata] = { .flags = PDC_COMMON_FLAGS | ATA_FLAG_SLAVE_POSS | PDC_FLAG_GEN_II, @@ -297,7 +301,7 @@ static const struct ata_port_info pdc_port_info[] = { .port_ops = &pdc_pata_ops, }, - /* board_40518 */ + [board_40518] = { .flags = PDC_COMMON_FLAGS | ATA_FLAG_SATA | PDC_FLAG_GEN_II | PDC_FLAG_4_PORTS, @@ -521,6 +525,84 @@ static void pdc_atapi_pkt(struct ata_queued_cmd *qc) memcpy(buf+31, cdb, cdb_len); } +/** + * pdc_fill_sg - Fill PCI IDE PRD table + * @qc: Metadata associated with taskfile to be transferred + * + * Fill PCI IDE PRD (scatter-gather) table with segments + * associated with the current disk command. + * Make sure hardware does not choke on it. + * + * LOCKING: + * spin_lock_irqsave(host lock) + * + */ +static void pdc_fill_sg(struct ata_queued_cmd *qc) +{ + struct ata_port *ap = qc->ap; + struct scatterlist *sg; + unsigned int idx; + const u32 SG_COUNT_ASIC_BUG = 41*4; + + if (!(qc->flags & ATA_QCFLAG_DMAMAP)) + return; + + WARN_ON(qc->__sg == NULL); + WARN_ON(qc->n_elem == 0 && qc->pad_len == 0); + + idx = 0; + ata_for_each_sg(sg, qc) { + u32 addr, offset; + u32 sg_len, len; + + /* determine if physical DMA addr spans 64K boundary. + * Note h/w doesn't support 64-bit, so we unconditionally + * truncate dma_addr_t to u32. + */ + addr = (u32) sg_dma_address(sg); + sg_len = sg_dma_len(sg); + + while (sg_len) { + offset = addr & 0xffff; + len = sg_len; + if ((offset + sg_len) > 0x10000) + len = 0x10000 - offset; + + ap->prd[idx].addr = cpu_to_le32(addr); + ap->prd[idx].flags_len = cpu_to_le32(len & 0xffff); + VPRINTK("PRD[%u] = (0x%X, 0x%X)\n", idx, addr, len); + + idx++; + sg_len -= len; + addr += len; + } + } + + if (idx) { + u32 len = le32_to_cpu(ap->prd[idx - 1].flags_len); + + if (len > SG_COUNT_ASIC_BUG) { + u32 addr; + + VPRINTK("Splitting last PRD.\n"); + + addr = le32_to_cpu(ap->prd[idx - 1].addr); + ap->prd[idx - 1].flags_len -= cpu_to_le32(SG_COUNT_ASIC_BUG); + VPRINTK("PRD[%u] = (0x%X, 0x%X)\n", idx - 1, addr, SG_COUNT_ASIC_BUG); + + addr = addr + len - SG_COUNT_ASIC_BUG; + len = SG_COUNT_ASIC_BUG; + ap->prd[idx].addr = cpu_to_le32(addr); + ap->prd[idx].flags_len = cpu_to_le32(len); + VPRINTK("PRD[%u] = (0x%X, 0x%X)\n", idx, addr, len); + + idx++; + } + + ap->prd[idx - 1].flags_len |= cpu_to_le32(ATA_PRD_EOT); + } +} + static void pdc_qc_prep(struct ata_queued_cmd *qc) { struct pdc_port_priv *pp = qc->ap->private_data; @@ -530,7 +612,7 @@ static void pdc_qc_prep(struct ata_queued_cmd *qc) switch (qc->tf.protocol) { case ATA_PROT_DMA: - ata_qc_prep(qc); + pdc_fill_sg(qc); /* fall through */ case ATA_PROT_NODATA: @@ -546,11 +628,11 @@ static void pdc_qc_prep(struct ata_queued_cmd *qc) break; case ATA_PROT_ATAPI: - ata_qc_prep(qc); + pdc_fill_sg(qc); break; case ATA_PROT_ATAPI_DMA: - ata_qc_prep(qc); + pdc_fill_sg(qc); /*FALLTHROUGH*/ case ATA_PROT_ATAPI_NODATA: pdc_atapi_pkt(qc); @@ -695,19 +777,20 @@ static void pdc_irq_clear(struct ata_port *ap) readl(mmio + PDC_INT_SEQMASK); } -static inline int pdc_is_sataii_tx4(unsigned long flags) +static int pdc_is_sataii_tx4(unsigned long flags) { const unsigned long mask = PDC_FLAG_GEN_II | PDC_FLAG_4_PORTS; return (flags & mask) == mask; } -static inline unsigned int pdc_port_no_to_ata_no(unsigned int port_no, int is_sataii_tx4) +static unsigned int pdc_port_no_to_ata_no(unsigned int port_no, + int is_sataii_tx4) { static const unsigned char sataii_tx4_port_remap[4] = { 3, 1, 0, 2}; return is_sataii_tx4 ? sataii_tx4_port_remap[port_no] : port_no; } -static irqreturn_t pdc_interrupt (int irq, void *dev_instance) +static irqreturn_t pdc_interrupt(int irq, void *dev_instance) { struct ata_host *host = dev_instance; struct ata_port *ap; @@ -839,15 +922,16 @@ static unsigned int pdc_qc_issue_prot(struct ata_queued_cmd *qc) static void pdc_tf_load_mmio(struct ata_port *ap, const struct ata_taskfile *tf) { - WARN_ON (tf->protocol == ATA_PROT_DMA || - tf->protocol == ATA_PROT_ATAPI_DMA); + WARN_ON(tf->protocol == ATA_PROT_DMA || + tf->protocol == ATA_PROT_ATAPI_DMA); ata_tf_load(ap, tf); } -static void pdc_exec_command_mmio(struct ata_port *ap, const struct ata_taskfile *tf) +static void pdc_exec_command_mmio(struct ata_port *ap, + const struct ata_taskfile *tf) { - WARN_ON (tf->protocol == ATA_PROT_DMA || - tf->protocol == ATA_PROT_ATAPI_DMA); + WARN_ON(tf->protocol == ATA_PROT_DMA || + tf->protocol == ATA_PROT_ATAPI_DMA); ata_exec_command(ap, tf); } @@ -870,8 +954,11 @@ static int pdc_check_atapi_dma(struct ata_queued_cmd *qc) } /* -45150 (FFFF4FA2) to -1 (FFFFFFFF) shall use PIO mode */ if (scsicmd[0] == WRITE_10) { - unsigned int lba; - lba = (scsicmd[2] << 24) | (scsicmd[3] << 16) | (scsicmd[4] << 8) | scsicmd[5]; + unsigned int lba = + (scsicmd[2] << 24) | + (scsicmd[3] << 16) | + (scsicmd[4] << 8) | + scsicmd[5]; if (lba >= 0xFFFF4FA2) pio = 1; } @@ -956,7 +1043,8 @@ static void pdc_host_init(struct ata_host *host) writel(tmp, mmio + PDC_SLEW_CTL); } -static int pdc_ata_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) +static int pdc_ata_init_one(struct pci_dev *pdev, + const struct pci_device_id *ent) { static int printed_version; const struct ata_port_info *pi = &pdc_port_info[ent->driver_data]; diff --git a/drivers/ata/sata_qstor.c b/drivers/ata/sata_qstor.c index c4c4cd29eeb..6d43ba79e15 100644 --- a/drivers/ata/sata_qstor.c +++ b/drivers/ata/sata_qstor.c @@ -113,7 +113,7 @@ struct qs_port_priv { static int qs_scr_read(struct ata_port *ap, unsigned int sc_reg, u32 *val); static int qs_scr_write(struct ata_port *ap, unsigned int sc_reg, u32 val); -static int qs_ata_init_one (struct pci_dev *pdev, const struct pci_device_id *ent); +static int qs_ata_init_one(struct pci_dev *pdev, const struct pci_device_id *ent); static int qs_port_start(struct ata_port *ap); static void qs_host_stop(struct ata_host *host); static void qs_phy_reset(struct ata_port *ap); @@ -135,7 +135,6 @@ static struct scsi_host_template qs_ata_sht = { .sg_tablesize = QS_MAX_PRD, .cmd_per_lun = ATA_SHT_CMD_PER_LUN, .emulated = ATA_SHT_EMULATED, - //FIXME .use_clustering = ATA_SHT_USE_CLUSTERING, .use_clustering = ENABLE_CLUSTERING, .proc_name = DRV_NAME, .dma_boundary = QS_DMA_BOUNDARY, diff --git a/drivers/ata/sata_sil.c b/drivers/ata/sata_sil.c index ea3a0ab7e02..4e6e381279c 100644 --- a/drivers/ata/sata_sil.c +++ b/drivers/ata/sata_sil.c @@ -111,7 +111,7 @@ enum { SIL_QUIRK_UDMA5MAX = (1 << 1), }; -static int sil_init_one (struct pci_dev *pdev, const struct pci_device_id *ent); +static int sil_init_one(struct pci_dev *pdev, const struct pci_device_id *ent); #ifdef CONFIG_PM static int sil_pci_device_resume(struct pci_dev *pdev); #endif @@ -138,7 +138,7 @@ static const struct pci_device_id sil_pci_tbl[] = { /* TODO firmware versions should be added - eric */ static const struct sil_drivelist { - const char * product; + const char *product; unsigned int quirk; } sil_blacklist [] = { { "ST320012AS", SIL_QUIRK_MOD15WRITE }, @@ -279,7 +279,7 @@ MODULE_LICENSE("GPL"); MODULE_DEVICE_TABLE(pci, sil_pci_tbl); MODULE_VERSION(DRV_VERSION); -static int slow_down = 0; +static int slow_down; module_param(slow_down, int, 0444); MODULE_PARM_DESC(slow_down, "Sledgehammer used to work around random problems, by limiting commands to 15 sectors (0=off, 1=on)"); @@ -332,7 +332,8 @@ static int sil_set_mode(struct ata_link *link, struct ata_device **r_failed) return 0; } -static inline void __iomem *sil_scr_addr(struct ata_port *ap, unsigned int sc_reg) +static inline void __iomem *sil_scr_addr(struct ata_port *ap, + unsigned int sc_reg) { void __iomem *offset = ap->ioaddr.scr_addr; @@ -643,7 +644,7 @@ static void sil_init_controller(struct ata_host *host) } } -static int sil_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) +static int sil_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) { static int printed_version; int board_id = ent->driver_data; diff --git a/drivers/ata/sata_sil24.c b/drivers/ata/sata_sil24.c index 26ebffc10f3..187dcb02c68 100644 --- a/drivers/ata/sata_sil24.c +++ b/drivers/ata/sata_sil24.c @@ -265,11 +265,11 @@ static struct sil24_cerr_info { unsigned int err_mask, action; const char *desc; } sil24_cerr_db[] = { - [0] = { AC_ERR_DEV, ATA_EH_REVALIDATE, + [0] = { AC_ERR_DEV, 0, "device error" }, - [PORT_CERR_DEV] = { AC_ERR_DEV, ATA_EH_REVALIDATE, + [PORT_CERR_DEV] = { AC_ERR_DEV, 0, "device error via D2H FIS" }, - [PORT_CERR_SDB] = { AC_ERR_DEV, ATA_EH_REVALIDATE, + [PORT_CERR_SDB] = { AC_ERR_DEV, 0, "device error via SDB FIS" }, [PORT_CERR_DATA] = { AC_ERR_ATA_BUS, ATA_EH_SOFTRESET, "error in data FIS" }, @@ -674,7 +674,7 @@ static int sil24_do_softreset(struct ata_link *link, unsigned int *class, /* put the port into known state */ if (sil24_init_port(ap)) { - reason ="port not ready"; + reason = "port not ready"; goto err; } @@ -756,7 +756,8 @@ static int sil24_hardreset(struct ata_link *link, unsigned int *class, writel(PORT_CS_DEV_RST, port + PORT_CTRL_STAT); tmp = ata_wait_register(port + PORT_CTRL_STAT, - PORT_CS_DEV_RST, PORT_CS_DEV_RST, 10, tout_msec); + PORT_CS_DEV_RST, PORT_CS_DEV_RST, 10, + tout_msec); /* SStatus oscillates between zero and valid status after * DEV_RST, debounce it. @@ -1270,7 +1271,7 @@ static void sil24_init_controller(struct ata_host *host) PORT_CS_PORT_RST, 10, 100); if (tmp & PORT_CS_PORT_RST) dev_printk(KERN_ERR, host->dev, - "failed to clear port RST\n"); + "failed to clear port RST\n"); } /* configure port */ @@ -1283,7 +1284,7 @@ static void sil24_init_controller(struct ata_host *host) static int sil24_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) { - static int printed_version = 0; + static int printed_version; struct ata_port_info pi = sil24_port_info[ent->driver_data]; const struct ata_port_info *ppi[] = { &pi, NULL }; void __iomem * const *iomap; diff --git a/drivers/ata/sata_sis.c b/drivers/ata/sata_sis.c index f147dc7bf46..a01260a5643 100644 --- a/drivers/ata/sata_sis.c +++ b/drivers/ata/sata_sis.c @@ -63,17 +63,17 @@ enum { GENCTL_IOMAPPED_SCR = (1 << 26), /* if set, SCRs are in IO space */ }; -static int sis_init_one (struct pci_dev *pdev, const struct pci_device_id *ent); -static int sis_scr_read (struct ata_port *ap, unsigned int sc_reg, u32 *val); -static int sis_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val); +static int sis_init_one(struct pci_dev *pdev, const struct pci_device_id *ent); +static int sis_scr_read(struct ata_port *ap, unsigned int sc_reg, u32 *val); +static int sis_scr_write(struct ata_port *ap, unsigned int sc_reg, u32 val); static const struct pci_device_id sis_pci_tbl[] = { - { PCI_VDEVICE(SI, 0x0180), sis_180 }, /* SiS 964/180 */ - { PCI_VDEVICE(SI, 0x0181), sis_180 }, /* SiS 964/180 */ - { PCI_VDEVICE(SI, 0x0182), sis_180 }, /* SiS 965/965L */ - { PCI_VDEVICE(SI, 0x0183), sis_180 }, /* SiS 965/965L */ - { PCI_VDEVICE(SI, 0x1182), sis_180 }, /* SiS 966/680 */ - { PCI_VDEVICE(SI, 0x1183), sis_180 }, /* SiS 966/966L/968/680 */ + { PCI_VDEVICE(SI, 0x0180), sis_180 }, /* SiS 964/180 */ + { PCI_VDEVICE(SI, 0x0181), sis_180 }, /* SiS 964/180 */ + { PCI_VDEVICE(SI, 0x0182), sis_180 }, /* SiS 965/965L */ + { PCI_VDEVICE(SI, 0x0183), sis_180 }, /* SiS 965/965L */ + { PCI_VDEVICE(SI, 0x1182), sis_180 }, /* SiS 966/680 */ + { PCI_VDEVICE(SI, 0x1183), sis_180 }, /* SiS 966/966L/968/680 */ { } /* terminate list */ }; @@ -149,24 +149,24 @@ static unsigned int get_scr_cfg_addr(struct ata_port *ap, unsigned int sc_reg) if (ap->port_no) { switch (pdev->device) { - case 0x0180: - case 0x0181: - pci_read_config_byte(pdev, SIS_PMR, &pmr); - if ((pmr & SIS_PMR_COMBINED) == 0) - addr += SIS180_SATA1_OFS; - break; - - case 0x0182: - case 0x0183: - case 0x1182: - addr += SIS182_SATA1_OFS; - break; + case 0x0180: + case 0x0181: + pci_read_config_byte(pdev, SIS_PMR, &pmr); + if ((pmr & SIS_PMR_COMBINED) == 0) + addr += SIS180_SATA1_OFS; + break; + + case 0x0182: + case 0x0183: + case 0x1182: + addr += SIS182_SATA1_OFS; + break; } } return addr; } -static u32 sis_scr_cfg_read (struct ata_port *ap, unsigned int sc_reg, u32 *val) +static u32 sis_scr_cfg_read(struct ata_port *ap, unsigned int sc_reg, u32 *val) { struct pci_dev *pdev = to_pci_dev(ap->host->dev); unsigned int cfg_addr = get_scr_cfg_addr(ap, sc_reg); @@ -190,7 +190,7 @@ static u32 sis_scr_cfg_read (struct ata_port *ap, unsigned int sc_reg, u32 *val) return 0; } -static void sis_scr_cfg_write (struct ata_port *ap, unsigned int sc_reg, u32 val) +static void sis_scr_cfg_write(struct ata_port *ap, unsigned int sc_reg, u32 val) { struct pci_dev *pdev = to_pci_dev(ap->host->dev); unsigned int cfg_addr = get_scr_cfg_addr(ap, sc_reg); @@ -253,7 +253,7 @@ static int sis_scr_write(struct ata_port *ap, unsigned int sc_reg, u32 val) return 0; } -static int sis_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) +static int sis_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) { static int printed_version; struct ata_port_info pi = sis_port_info; @@ -309,29 +309,33 @@ static int sis_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) } else { dev_printk(KERN_INFO, &pdev->dev, "Detected SiS 180/181 chipset in combined mode\n"); - port2_start=0; + port2_start = 0; pi.flags |= ATA_FLAG_SLAVE_POSS; } break; case 0x0182: case 0x0183: - pci_read_config_dword ( pdev, 0x6C, &val); + pci_read_config_dword(pdev, 0x6C, &val); if (val & (1L << 31)) { - dev_printk(KERN_INFO, &pdev->dev, "Detected SiS 182/965 chipset\n"); + dev_printk(KERN_INFO, &pdev->dev, + "Detected SiS 182/965 chipset\n"); pi.flags |= ATA_FLAG_SLAVE_POSS; } else { - dev_printk(KERN_INFO, &pdev->dev, "Detected SiS 182/965L chipset\n"); + dev_printk(KERN_INFO, &pdev->dev, + "Detected SiS 182/965L chipset\n"); } break; case 0x1182: - dev_printk(KERN_INFO, &pdev->dev, "Detected SiS 1182/966/680 SATA controller\n"); + dev_printk(KERN_INFO, &pdev->dev, + "Detected SiS 1182/966/680 SATA controller\n"); pi.flags |= ATA_FLAG_SLAVE_POSS; break; case 0x1183: - dev_printk(KERN_INFO, &pdev->dev, "Detected SiS 1183/966/966L/968/680 controller in PATA mode\n"); + dev_printk(KERN_INFO, &pdev->dev, + "Detected SiS 1183/966/966L/968/680 controller in PATA mode\n"); ppi[0] = &sis_info133_for_sata; ppi[1] = &sis_info133_for_sata; break; diff --git a/drivers/ata/sata_svw.c b/drivers/ata/sata_svw.c index 12d613c48c1..69f651e0bc9 100644 --- a/drivers/ata/sata_svw.c +++ b/drivers/ata/sata_svw.c @@ -182,7 +182,7 @@ static void k2_sata_tf_read(struct ata_port *ap, struct ata_taskfile *tf) tf->hob_lbal = lbal >> 8; tf->hob_lbam = lbam >> 8; tf->hob_lbah = lbah >> 8; - } + } } /** @@ -193,7 +193,7 @@ static void k2_sata_tf_read(struct ata_port *ap, struct ata_taskfile *tf) * spin_lock_irqsave(host lock) */ -static void k2_bmdma_setup_mmio (struct ata_queued_cmd *qc) +static void k2_bmdma_setup_mmio(struct ata_queued_cmd *qc) { struct ata_port *ap = qc->ap; unsigned int rw = (qc->tf.flags & ATA_TFLAG_WRITE); @@ -224,7 +224,7 @@ static void k2_bmdma_setup_mmio (struct ata_queued_cmd *qc) * spin_lock_irqsave(host lock) */ -static void k2_bmdma_start_mmio (struct ata_queued_cmd *qc) +static void k2_bmdma_start_mmio(struct ata_queued_cmd *qc) { struct ata_port *ap = qc->ap; void __iomem *mmio = ap->ioaddr.bmdma_addr; @@ -255,7 +255,7 @@ static void k2_bmdma_start_mmio (struct ata_queued_cmd *qc) static u8 k2_stat_check_status(struct ata_port *ap) { - return readl(ap->ioaddr.status_addr); + return readl(ap->ioaddr.status_addr); } #ifdef CONFIG_PPC_OF @@ -395,7 +395,7 @@ static void k2_sata_setup_port(struct ata_ioports *port, void __iomem *base) } -static int k2_sata_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) +static int k2_sata_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) { static int printed_version; const struct ata_port_info *ppi[] = diff --git a/drivers/ata/sata_sx4.c b/drivers/ata/sata_sx4.c index b6026bceccd..4d857185f33 100644 --- a/drivers/ata/sata_sx4.c +++ b/drivers/ata/sata_sx4.c @@ -212,9 +212,9 @@ struct pdc_host_priv { }; -static int pdc_sata_init_one (struct pci_dev *pdev, const struct pci_device_id *ent); +static int pdc_sata_init_one(struct pci_dev *pdev, const struct pci_device_id *ent); static void pdc_eng_timeout(struct ata_port *ap); -static void pdc_20621_phy_reset (struct ata_port *ap); +static void pdc_20621_phy_reset(struct ata_port *ap); static int pdc_port_start(struct ata_port *ap); static void pdc20621_qc_prep(struct ata_queued_cmd *qc); static void pdc_tf_load_mmio(struct ata_port *ap, const struct ata_taskfile *tf); @@ -320,16 +320,16 @@ static int pdc_port_start(struct ata_port *ap) return 0; } -static void pdc_20621_phy_reset (struct ata_port *ap) +static void pdc_20621_phy_reset(struct ata_port *ap) { VPRINTK("ENTER\n"); - ap->cbl = ATA_CBL_SATA; - ata_port_probe(ap); - ata_bus_reset(ap); + ap->cbl = ATA_CBL_SATA; + ata_port_probe(ap); + ata_bus_reset(ap); } static inline void pdc20621_ata_sg(struct ata_taskfile *tf, u8 *buf, - unsigned int portno, + unsigned int portno, unsigned int total_len) { u32 addr; @@ -351,7 +351,7 @@ static inline void pdc20621_ata_sg(struct ata_taskfile *tf, u8 *buf, } static inline void pdc20621_host_sg(struct ata_taskfile *tf, u8 *buf, - unsigned int portno, + unsigned int portno, unsigned int total_len) { u32 addr; @@ -711,8 +711,8 @@ static unsigned int pdc20621_qc_issue_prot(struct ata_queued_cmd *qc) return ata_qc_issue_prot(qc); } -static inline unsigned int pdc20621_host_intr( struct ata_port *ap, - struct ata_queued_cmd *qc, +static inline unsigned int pdc20621_host_intr(struct ata_port *ap, + struct ata_queued_cmd *qc, unsigned int doing_hdma, void __iomem *mmio) { @@ -803,7 +803,7 @@ static void pdc20621_irq_clear(struct ata_port *ap) readl(mmio + PDC_20621_SEQMASK); } -static irqreturn_t pdc20621_interrupt (int irq, void *dev_instance) +static irqreturn_t pdc20621_interrupt(int irq, void *dev_instance) { struct ata_host *host = dev_instance; struct ata_port *ap; @@ -836,9 +836,9 @@ static irqreturn_t pdc20621_interrupt (int irq, void *dev_instance) return IRQ_NONE; } - spin_lock(&host->lock); + spin_lock(&host->lock); - for (i = 1; i < 9; i++) { + for (i = 1; i < 9; i++) { port_no = i - 1; if (port_no > 3) port_no -= 4; @@ -859,7 +859,7 @@ static irqreturn_t pdc20621_interrupt (int irq, void *dev_instance) } } - spin_unlock(&host->lock); + spin_unlock(&host->lock); VPRINTK("mask == 0x%x\n", mask); @@ -906,16 +906,16 @@ static void pdc_eng_timeout(struct ata_port *ap) static void pdc_tf_load_mmio(struct ata_port *ap, const struct ata_taskfile *tf) { - WARN_ON (tf->protocol == ATA_PROT_DMA || - tf->protocol == ATA_PROT_NODATA); + WARN_ON(tf->protocol == ATA_PROT_DMA || + tf->protocol == ATA_PROT_NODATA); ata_tf_load(ap, tf); } static void pdc_exec_command_mmio(struct ata_port *ap, const struct ata_taskfile *tf) { - WARN_ON (tf->protocol == ATA_PROT_DMA || - tf->protocol == ATA_PROT_NODATA); + WARN_ON(tf->protocol == ATA_PROT_DMA || + tf->protocol == ATA_PROT_NODATA); ata_exec_command(ap, tf); } @@ -953,7 +953,7 @@ static void pdc20621_get_from_dimm(struct ata_host *host, void *psource, mmio += PDC_CHIP0_OFS; page_mask = 0x00; - window_size = 0x2000 * 4; /* 32K byte uchar size */ + window_size = 0x2000 * 4; /* 32K byte uchar size */ idx = (u16) (offset / window_size); writel(0x01, mmio + PDC_GENERAL_CTLR); @@ -979,7 +979,7 @@ static void pdc20621_get_from_dimm(struct ata_host *host, void *psource, window_size / 4); psource += window_size; size -= window_size; - idx ++; + idx++; } if (size) { @@ -1008,7 +1008,7 @@ static void pdc20621_put_to_dimm(struct ata_host *host, void *psource, mmio += PDC_CHIP0_OFS; page_mask = 0x00; - window_size = 0x2000 * 4; /* 32K byte uchar size */ + window_size = 0x2000 * 4; /* 32K byte uchar size */ idx = (u16) (offset / window_size); writel(((idx) << page_mask), mmio + PDC_DIMM_WINDOW_CTLR); @@ -1031,7 +1031,7 @@ static void pdc20621_put_to_dimm(struct ata_host *host, void *psource, readl(mmio + PDC_GENERAL_CTLR); psource += window_size; size -= window_size; - idx ++; + idx++; } if (size) { @@ -1050,7 +1050,7 @@ static unsigned int pdc20621_i2c_read(struct ata_host *host, u32 device, void __iomem *mmio = host->iomap[PDC_MMIO_BAR]; u32 i2creg = 0; u32 status; - u32 count =0; + u32 count = 0; /* hard-code chip #0 */ mmio += PDC_CHIP0_OFS; @@ -1082,21 +1082,21 @@ static unsigned int pdc20621_i2c_read(struct ata_host *host, u32 device, static int pdc20621_detect_dimm(struct ata_host *host) { - u32 data=0 ; + u32 data = 0; if (pdc20621_i2c_read(host, PDC_DIMM0_SPD_DEV_ADDRESS, PDC_DIMM_SPD_SYSTEM_FREQ, &data)) { - if (data == 100) + if (data == 100) return 100; - } else + } else return 0; if (pdc20621_i2c_read(host, PDC_DIMM0_SPD_DEV_ADDRESS, 9, &data)) { - if(data <= 0x75) + if (data <= 0x75) return 133; - } else + } else return 0; - return 0; + return 0; } @@ -1104,8 +1104,8 @@ static int pdc20621_prog_dimm0(struct ata_host *host) { u32 spd0[50]; u32 data = 0; - int size, i; - u8 bdimmsize; + int size, i; + u8 bdimmsize; void __iomem *mmio = host->iomap[PDC_MMIO_BAR]; static const struct { unsigned int reg; @@ -1128,40 +1128,40 @@ static int pdc20621_prog_dimm0(struct ata_host *host) /* hard-code chip #0 */ mmio += PDC_CHIP0_OFS; - for(i=0; i<ARRAY_SIZE(pdc_i2c_read_data); i++) + for (i = 0; i < ARRAY_SIZE(pdc_i2c_read_data); i++) pdc20621_i2c_read(host, PDC_DIMM0_SPD_DEV_ADDRESS, pdc_i2c_read_data[i].reg, &spd0[pdc_i2c_read_data[i].ofs]); - data |= (spd0[4] - 8) | ((spd0[21] != 0) << 3) | ((spd0[3]-11) << 4); - data |= ((spd0[17] / 4) << 6) | ((spd0[5] / 2) << 7) | + data |= (spd0[4] - 8) | ((spd0[21] != 0) << 3) | ((spd0[3]-11) << 4); + data |= ((spd0[17] / 4) << 6) | ((spd0[5] / 2) << 7) | ((((spd0[27] + 9) / 10) - 1) << 8) ; - data |= (((((spd0[29] > spd0[28]) + data |= (((((spd0[29] > spd0[28]) ? spd0[29] : spd0[28]) + 9) / 10) - 1) << 10; - data |= ((spd0[30] - spd0[29] + 9) / 10 - 2) << 12; + data |= ((spd0[30] - spd0[29] + 9) / 10 - 2) << 12; - if (spd0[18] & 0x08) + if (spd0[18] & 0x08) data |= ((0x03) << 14); - else if (spd0[18] & 0x04) + else if (spd0[18] & 0x04) data |= ((0x02) << 14); - else if (spd0[18] & 0x01) + else if (spd0[18] & 0x01) data |= ((0x01) << 14); - else + else data |= (0 << 14); - /* + /* Calculate the size of bDIMMSize (power of 2) and merge the DIMM size by program start/end address. */ - bdimmsize = spd0[4] + (spd0[5] / 2) + spd0[3] + (spd0[17] / 2) + 3; - size = (1 << bdimmsize) >> 20; /* size = xxx(MB) */ - data |= (((size / 16) - 1) << 16); - data |= (0 << 23); + bdimmsize = spd0[4] + (spd0[5] / 2) + spd0[3] + (spd0[17] / 2) + 3; + size = (1 << bdimmsize) >> 20; /* size = xxx(MB) */ + data |= (((size / 16) - 1) << 16); + data |= (0 << 23); data |= 8; - writel(data, mmio + PDC_DIMM0_CONTROL); + writel(data, mmio + PDC_DIMM0_CONTROL); readl(mmio + PDC_DIMM0_CONTROL); - return size; + return size; } @@ -1172,9 +1172,9 @@ static unsigned int pdc20621_prog_dimm_global(struct ata_host *host) void __iomem *mmio = host->iomap[PDC_MMIO_BAR]; /* hard-code chip #0 */ - mmio += PDC_CHIP0_OFS; + mmio += PDC_CHIP0_OFS; - /* + /* Set To Default : DIMM Module Global Control Register (0x022259F1) DIMM Arbitration Disable (bit 20) DIMM Data/Control Output Driving Selection (bit12 - bit15) @@ -1193,40 +1193,40 @@ static unsigned int pdc20621_prog_dimm_global(struct ata_host *host) writel(data, mmio + PDC_SDRAM_CONTROL); readl(mmio + PDC_SDRAM_CONTROL); printk(KERN_ERR "Local DIMM ECC Enabled\n"); - } + } - /* DIMM Initialization Select/Enable (bit 18/19) */ - data &= (~(1<<18)); - data |= (1<<19); - writel(data, mmio + PDC_SDRAM_CONTROL); + /* DIMM Initialization Select/Enable (bit 18/19) */ + data &= (~(1<<18)); + data |= (1<<19); + writel(data, mmio + PDC_SDRAM_CONTROL); - error = 1; - for (i = 1; i <= 10; i++) { /* polling ~5 secs */ + error = 1; + for (i = 1; i <= 10; i++) { /* polling ~5 secs */ data = readl(mmio + PDC_SDRAM_CONTROL); if (!(data & (1<<19))) { - error = 0; - break; + error = 0; + break; } msleep(i*100); - } - return error; + } + return error; } static unsigned int pdc20621_dimm_init(struct ata_host *host) { int speed, size, length; - u32 addr,spd0,pci_status; - u32 tmp=0; - u32 time_period=0; - u32 tcount=0; - u32 ticks=0; - u32 clock=0; - u32 fparam=0; + u32 addr, spd0, pci_status; + u32 tmp = 0; + u32 time_period = 0; + u32 tcount = 0; + u32 ticks = 0; + u32 clock = 0; + u32 fparam = 0; void __iomem *mmio = host->iomap[PDC_MMIO_BAR]; /* hard-code chip #0 */ - mmio += PDC_CHIP0_OFS; + mmio += PDC_CHIP0_OFS; /* Initialize PLL based upon PCI Bus Frequency */ @@ -1254,7 +1254,7 @@ static unsigned int pdc20621_dimm_init(struct ata_host *host) If SX4 is on PCI-X bus, after 3 seconds, the timer counter register should be >= (0xffffffff - 3x10^8). */ - if(tcount >= PCI_X_TCOUNT) { + if (tcount >= PCI_X_TCOUNT) { ticks = (time_period - tcount); VPRINTK("Num counters 0x%x (%d)\n", ticks, ticks); @@ -1285,41 +1285,43 @@ static unsigned int pdc20621_dimm_init(struct ata_host *host) if (!(speed = pdc20621_detect_dimm(host))) { printk(KERN_ERR "Detect Local DIMM Fail\n"); return 1; /* DIMM error */ - } - VPRINTK("Local DIMM Speed = %d\n", speed); + } + VPRINTK("Local DIMM Speed = %d\n", speed); - /* Programming DIMM0 Module Control Register (index_CID0:80h) */ + /* Programming DIMM0 Module Control Register (index_CID0:80h) */ size = pdc20621_prog_dimm0(host); - VPRINTK("Local DIMM Size = %dMB\n",size); + VPRINTK("Local DIMM Size = %dMB\n", size); - /* Programming DIMM Module Global Control Register (index_CID0:88h) */ + /* Programming DIMM Module Global Control Register (index_CID0:88h) */ if (pdc20621_prog_dimm_global(host)) { printk(KERN_ERR "Programming DIMM Module Global Control Register Fail\n"); return 1; - } + } #ifdef ATA_VERBOSE_DEBUG { - u8 test_parttern1[40] = {0x55,0xAA,'P','r','o','m','i','s','e',' ', - 'N','o','t',' ','Y','e','t',' ','D','e','f','i','n','e','d',' ', - '1','.','1','0', - '9','8','0','3','1','6','1','2',0,0}; + u8 test_parttern1[40] = + {0x55,0xAA,'P','r','o','m','i','s','e',' ', + 'N','o','t',' ','Y','e','t',' ', + 'D','e','f','i','n','e','d',' ', + '1','.','1','0', + '9','8','0','3','1','6','1','2',0,0}; u8 test_parttern2[40] = {0}; - pdc20621_put_to_dimm(host, (void *) test_parttern2, 0x10040, 40); - pdc20621_put_to_dimm(host, (void *) test_parttern2, 0x40, 40); + pdc20621_put_to_dimm(host, test_parttern2, 0x10040, 40); + pdc20621_put_to_dimm(host, test_parttern2, 0x40, 40); - pdc20621_put_to_dimm(host, (void *) test_parttern1, 0x10040, 40); - pdc20621_get_from_dimm(host, (void *) test_parttern2, 0x40, 40); + pdc20621_put_to_dimm(host, test_parttern1, 0x10040, 40); + pdc20621_get_from_dimm(host, test_parttern2, 0x40, 40); printk(KERN_ERR "%x, %x, %s\n", test_parttern2[0], test_parttern2[1], &(test_parttern2[2])); - pdc20621_get_from_dimm(host, (void *) test_parttern2, 0x10040, + pdc20621_get_from_dimm(host, test_parttern2, 0x10040, 40); printk(KERN_ERR "%x, %x, %s\n", test_parttern2[0], test_parttern2[1], &(test_parttern2[2])); - pdc20621_put_to_dimm(host, (void *) test_parttern1, 0x40, 40); - pdc20621_get_from_dimm(host, (void *) test_parttern2, 0x40, 40); + pdc20621_put_to_dimm(host, test_parttern1, 0x40, 40); + pdc20621_get_from_dimm(host, test_parttern2, 0x40, 40); printk(KERN_ERR "%x, %x, %s\n", test_parttern2[0], test_parttern2[1], &(test_parttern2[2])); } @@ -1375,7 +1377,8 @@ static void pdc_20621_init(struct ata_host *host) readl(mmio + PDC_HDMA_CTLSTAT); /* flush */ } -static int pdc_sata_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) +static int pdc_sata_init_one(struct pci_dev *pdev, + const struct pci_device_id *ent) { static int printed_version; const struct ata_port_info *ppi[] = diff --git a/drivers/ata/sata_uli.c b/drivers/ata/sata_uli.c index d394da085ae..e710e71b7b9 100644 --- a/drivers/ata/sata_uli.c +++ b/drivers/ata/sata_uli.c @@ -56,9 +56,9 @@ struct uli_priv { unsigned int scr_cfg_addr[uli_max_ports]; }; -static int uli_init_one (struct pci_dev *pdev, const struct pci_device_id *ent); -static int uli_scr_read (struct ata_port *ap, unsigned int sc_reg, u32 *val); -static int uli_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val); +static int uli_init_one(struct pci_dev *pdev, const struct pci_device_id *ent); +static int uli_scr_read(struct ata_port *ap, unsigned int sc_reg, u32 *val); +static int uli_scr_write(struct ata_port *ap, unsigned int sc_reg, u32 val); static const struct pci_device_id uli_pci_tbl[] = { { PCI_VDEVICE(AL, 0x5289), uli_5289 }, @@ -143,7 +143,7 @@ static unsigned int get_scr_cfg_addr(struct ata_port *ap, unsigned int sc_reg) return hpriv->scr_cfg_addr[ap->port_no] + (4 * sc_reg); } -static u32 uli_scr_cfg_read (struct ata_port *ap, unsigned int sc_reg) +static u32 uli_scr_cfg_read(struct ata_port *ap, unsigned int sc_reg) { struct pci_dev *pdev = to_pci_dev(ap->host->dev); unsigned int cfg_addr = get_scr_cfg_addr(ap, sc_reg); @@ -153,7 +153,7 @@ static u32 uli_scr_cfg_read (struct ata_port *ap, unsigned int sc_reg) return val; } -static void uli_scr_cfg_write (struct ata_port *ap, unsigned int scr, u32 val) +static void uli_scr_cfg_write(struct ata_port *ap, unsigned int scr, u32 val) { struct pci_dev *pdev = to_pci_dev(ap->host->dev); unsigned int cfg_addr = get_scr_cfg_addr(ap, scr); @@ -161,7 +161,7 @@ static void uli_scr_cfg_write (struct ata_port *ap, unsigned int scr, u32 val) pci_write_config_dword(pdev, cfg_addr, val); } -static int uli_scr_read (struct ata_port *ap, unsigned int sc_reg, u32 *val) +static int uli_scr_read(struct ata_port *ap, unsigned int sc_reg, u32 *val) { if (sc_reg > SCR_CONTROL) return -EINVAL; @@ -170,16 +170,16 @@ static int uli_scr_read (struct ata_port *ap, unsigned int sc_reg, u32 *val) return 0; } -static int uli_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val) +static int uli_scr_write(struct ata_port *ap, unsigned int sc_reg, u32 val) { - if (sc_reg > SCR_CONTROL) //SCR_CONTROL=2, SCR_ERROR=1, SCR_STATUS=0 + if (sc_reg > SCR_CONTROL) //SCR_CONTROL=2, SCR_ERROR=1, SCR_STATUS=0 return -EINVAL; uli_scr_cfg_write(ap, sc_reg, val); return 0; } -static int uli_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) +static int uli_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) { static int printed_version; const struct ata_port_info *ppi[] = { &uli_port_info, NULL }; diff --git a/drivers/ata/sata_via.c b/drivers/ata/sata_via.c index cc6ee0890f5..3ef072ff319 100644 --- a/drivers/ata/sata_via.c +++ b/drivers/ata/sata_via.c @@ -3,7 +3,7 @@ * * Maintained by: Jeff Garzik <jgarzik@pobox.com> * Please ALWAYS copy linux-ide@vger.kernel.org - on emails. + * on emails. * * Copyright 2003-2004 Red Hat, Inc. All rights reserved. * Copyright 2003-2004 Jeff Garzik @@ -69,7 +69,7 @@ enum { SATA_EXT_PHY = (1 << 6), /* 0==use PATA, 1==ext phy */ }; -static int svia_init_one (struct pci_dev *pdev, const struct pci_device_id *ent); +static int svia_init_one(struct pci_dev *pdev, const struct pci_device_id *ent); static int svia_scr_read(struct ata_port *ap, unsigned int sc_reg, u32 *val); static int svia_scr_write(struct ata_port *ap, unsigned int sc_reg, u32 val); static void svia_noop_freeze(struct ata_port *ap); @@ -372,12 +372,12 @@ static const unsigned int vt6421_bar_sizes[] = { 16, 16, 16, 16, 32, 128 }; -static void __iomem * svia_scr_addr(void __iomem *addr, unsigned int port) +static void __iomem *svia_scr_addr(void __iomem *addr, unsigned int port) { return addr + (port * 128); } -static void __iomem * vt6421_scr_addr(void __iomem *addr, unsigned int port) +static void __iomem *vt6421_scr_addr(void __iomem *addr, unsigned int port) { return addr + (port * 64); } @@ -472,7 +472,7 @@ static void svia_configure(struct pci_dev *pdev) if ((tmp8 & ALL_PORTS) != ALL_PORTS) { dev_printk(KERN_DEBUG, &pdev->dev, "enabling SATA channels (0x%x)\n", - (int) tmp8); + (int) tmp8); tmp8 |= ALL_PORTS; pci_write_config_byte(pdev, SATA_CHAN_ENAB, tmp8); } @@ -482,7 +482,7 @@ static void svia_configure(struct pci_dev *pdev) if ((tmp8 & ALL_PORTS) != ALL_PORTS) { dev_printk(KERN_DEBUG, &pdev->dev, "enabling SATA channel interrupts (0x%x)\n", - (int) tmp8); + (int) tmp8); tmp8 |= ALL_PORTS; pci_write_config_byte(pdev, SATA_INT_GATE, tmp8); } @@ -492,13 +492,13 @@ static void svia_configure(struct pci_dev *pdev) if ((tmp8 & NATIVE_MODE_ALL) != NATIVE_MODE_ALL) { dev_printk(KERN_DEBUG, &pdev->dev, "enabling SATA channel native mode (0x%x)\n", - (int) tmp8); + (int) tmp8); tmp8 |= NATIVE_MODE_ALL; pci_write_config_byte(pdev, SATA_NATIVE_MODE, tmp8); } } -static int svia_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) +static int svia_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) { static int printed_version; unsigned int i; @@ -525,8 +525,8 @@ static int svia_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) dev_printk(KERN_ERR, &pdev->dev, "invalid PCI BAR %u (sz 0x%llx, val 0x%llx)\n", i, - (unsigned long long)pci_resource_start(pdev, i), - (unsigned long long)pci_resource_len(pdev, i)); + (unsigned long long)pci_resource_start(pdev, i), + (unsigned long long)pci_resource_len(pdev, i)); return -ENODEV; } diff --git a/drivers/ata/sata_vsc.c b/drivers/ata/sata_vsc.c index 0d9be168487..95ae3ed24a9 100644 --- a/drivers/ata/sata_vsc.c +++ b/drivers/ata/sata_vsc.c @@ -162,7 +162,8 @@ static void vsc_sata_tf_load(struct ata_port *ap, const struct ata_taskfile *tf) /* * The only thing the ctl register is used for is SRST. * That is not enabled or disabled via tf_load. - * However, if ATA_NIEN is changed, then we need to change the interrupt register. + * However, if ATA_NIEN is changed, then we need to change + * the interrupt register. */ if ((tf->ctl & ATA_NIEN) != (ap->last_ctl & ATA_NIEN)) { ap->last_ctl = tf->ctl; @@ -219,7 +220,7 @@ static void vsc_sata_tf_read(struct ata_port *ap, struct ata_taskfile *tf) tf->hob_lbal = lbal >> 8; tf->hob_lbam = lbam >> 8; tf->hob_lbah = lbah >> 8; - } + } } static inline void vsc_error_intr(u8 port_status, struct ata_port *ap) @@ -256,9 +257,10 @@ static void vsc_port_intr(u8 port_status, struct ata_port *ap) /* * vsc_sata_interrupt * - * Read the interrupt register and process for the devices that have them pending. + * Read the interrupt register and process for the devices that have + * them pending. */ -static irqreturn_t vsc_sata_interrupt (int irq, void *dev_instance) +static irqreturn_t vsc_sata_interrupt(int irq, void *dev_instance) { struct ata_host *host = dev_instance; unsigned int i; @@ -287,7 +289,7 @@ static irqreturn_t vsc_sata_interrupt (int irq, void *dev_instance) handled++; } else dev_printk(KERN_ERR, host->dev, - ": interrupt from disabled port %d\n", i); + "interrupt from disabled port %d\n", i); } } @@ -363,7 +365,8 @@ static void __devinit vsc_sata_setup_port(struct ata_ioports *port, } -static int __devinit vsc_sata_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) +static int __devinit vsc_sata_init_one(struct pci_dev *pdev, + const struct pci_device_id *ent) { static const struct ata_port_info pi = { .flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c index 5a6fe17fc63..7d704968765 100644 --- a/drivers/block/cciss.c +++ b/drivers/block/cciss.c @@ -1,20 +1,20 @@ /* - * Disk Array driver for HP SA 5xxx and 6xxx Controllers - * Copyright 2000, 2006 Hewlett-Packard Development Company, L.P. + * Disk Array driver for HP Smart Array controllers. + * (C) Copyright 2000, 2007 Hewlett-Packard Development Company, L.P. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. + * the Free Software Foundation; 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, GOOD TITLE or - * NON INFRINGEMENT. See the GNU General Public License for more details. + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + * 02111-1307, USA. * * Questions/Comments/Bugfixes to iss_storagedev@hp.com * diff --git a/drivers/block/cciss_scsi.c b/drivers/block/cciss_scsi.c index 4aca7ddfddd..63ee6c076cb 100644 --- a/drivers/block/cciss_scsi.c +++ b/drivers/block/cciss_scsi.c @@ -1,20 +1,20 @@ /* - * Disk Array driver for Compaq SA53xx Controllers, SCSI Tape module - * Copyright 2001 Compaq Computer Corporation + * Disk Array driver for HP Smart Array controllers, SCSI Tape module. + * (C) Copyright 2001, 2007 Hewlett-Packard Development Company, L.P. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. + * the Free Software Foundation; 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, GOOD TITLE or - * NON INFRINGEMENT. See the GNU General Public License for more details. + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 59 Temple Place, Suite 300, Boston, MA + * 02111-1307, USA. * * Questions/Comments/Bugfixes to iss_storagedev@hp.com * diff --git a/drivers/block/cciss_scsi.h b/drivers/block/cciss_scsi.h index 5e7e06c07d6..d9c2c586502 100644 --- a/drivers/block/cciss_scsi.h +++ b/drivers/block/cciss_scsi.h @@ -1,20 +1,20 @@ /* - * Disk Array driver for Compaq SA53xx Controllers, SCSI Tape module - * Copyright 2001 Compaq Computer Corporation + * Disk Array driver for HP Smart Array controllers, SCSI Tape module. + * (C) Copyright 2001, 2007 Hewlett-Packard Development Company, L.P. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. + * the Free Software Foundation; 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, GOOD TITLE or - * NON INFRINGEMENT. See the GNU General Public License for more details. + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 59 Temple Place, Suite 300, Boston, MA + * 02111-1307, USA. * * Questions/Comments/Bugfixes to iss_storagedev@hp.com * diff --git a/drivers/char/agp/Kconfig b/drivers/char/agp/Kconfig index f22c253bc09..ccb1fa89de2 100644 --- a/drivers/char/agp/Kconfig +++ b/drivers/char/agp/Kconfig @@ -56,9 +56,9 @@ config AGP_AMD X on AMD Irongate, 761, and 762 chipsets. config AGP_AMD64 - tristate "AMD Opteron/Athlon64 on-CPU GART support" if !IOMMU + tristate "AMD Opteron/Athlon64 on-CPU GART support" if !GART_IOMMU depends on AGP && X86 - default y if IOMMU + default y if GART_IOMMU help This option gives you AGP support for the GLX component of X using the on-CPU northbridge of the AMD Athlon64/Opteron CPUs. diff --git a/drivers/char/agp/amd64-agp.c b/drivers/char/agp/amd64-agp.c index d95662e9632..d8200ac8f8c 100644 --- a/drivers/char/agp/amd64-agp.c +++ b/drivers/char/agp/amd64-agp.c @@ -787,7 +787,7 @@ static void __exit agp_amd64_cleanup(void) /* On AMD64 the PCI driver needs to initialize this driver early for the IOMMU, so it has to be called via a backdoor. */ -#ifndef CONFIG_IOMMU +#ifndef CONFIG_GART_IOMMU module_init(agp_amd64_init); module_exit(agp_amd64_cleanup); #endif diff --git a/drivers/char/mem.c b/drivers/char/mem.c index 0e937f64a78..20070b7c573 100644 --- a/drivers/char/mem.c +++ b/drivers/char/mem.c @@ -41,7 +41,7 @@ */ static inline int uncached_access(struct file *file, unsigned long addr) { -#if defined(__i386__) +#if defined(__i386__) && !defined(__arch_um__) /* * On the PPro and successors, the MTRRs are used to set * memory types for physical addresses outside main memory, @@ -57,7 +57,7 @@ static inline int uncached_access(struct file *file, unsigned long addr) test_bit(X86_FEATURE_CYRIX_ARR, boot_cpu_data.x86_capability) || test_bit(X86_FEATURE_CENTAUR_MCR, boot_cpu_data.x86_capability) ) && addr >= __pa(high_memory); -#elif defined(__x86_64__) +#elif defined(__x86_64__) && !defined(__arch_um__) /* * This is broken because it can generate memory type aliases, * which can cause cache corruptions diff --git a/drivers/cpuidle/cpuidle.c b/drivers/cpuidle/cpuidle.c index fdf4106b817..d2fabe7863a 100644 --- a/drivers/cpuidle/cpuidle.c +++ b/drivers/cpuidle/cpuidle.c @@ -19,7 +19,6 @@ #include "cpuidle.h" DEFINE_PER_CPU(struct cpuidle_device *, cpuidle_devices); -EXPORT_PER_CPU_SYMBOL_GPL(cpuidle_devices); DEFINE_MUTEX(cpuidle_lock); LIST_HEAD(cpuidle_detected_devices); diff --git a/drivers/cpuidle/governor.c b/drivers/cpuidle/governor.c index bb699cb2dc5..70b59642a70 100644 --- a/drivers/cpuidle/governor.c +++ b/drivers/cpuidle/governor.c @@ -94,8 +94,6 @@ int cpuidle_register_governor(struct cpuidle_governor *gov) return ret; } -EXPORT_SYMBOL_GPL(cpuidle_register_governor); - /** * cpuidle_replace_governor - find a replacement governor * @exclude_rating: the rating that will be skipped while looking for @@ -138,4 +136,3 @@ void cpuidle_unregister_governor(struct cpuidle_governor *gov) mutex_unlock(&cpuidle_lock); } -EXPORT_SYMBOL_GPL(cpuidle_unregister_governor); diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig index 9c91b0fd134..6a7d25fc247 100644 --- a/drivers/dma/Kconfig +++ b/drivers/dma/Kconfig @@ -43,7 +43,6 @@ comment "DMA Clients" config NET_DMA bool "Network: TCP receive copy offload" depends on DMA_ENGINE && NET - default y help This enables the use of DMA engines in the network stack to offload receive copy-to-user operations, freeing CPU cycles. diff --git a/drivers/isdn/capi/capidrv.c b/drivers/isdn/capi/capidrv.c index 476012b6dfa..48c1775ef5b 100644 --- a/drivers/isdn/capi/capidrv.c +++ b/drivers/isdn/capi/capidrv.c @@ -1843,6 +1843,7 @@ static int if_sendbuf(int id, int channel, int doack, struct sk_buff *skb) int msglen; u16 errcode; u16 datahandle; + u32 data; if (!card) { printk(KERN_ERR "capidrv: if_sendbuf called with invalid driverId %d!\n", @@ -1860,9 +1861,26 @@ static int if_sendbuf(int id, int channel, int doack, struct sk_buff *skb) return 0; } datahandle = nccip->datahandle; + + /* + * Here we copy pointer skb->data into the 32-bit 'Data' field. + * The 'Data' field is not used in practice in linux kernel + * (neither in 32 or 64 bit), but should have some value, + * since a CAPI message trace will display it. + * + * The correct value in the 32 bit case is the address of the + * data, in 64 bit it makes no sense, we use 0 there. + */ + +#ifdef CONFIG_64BIT + data = 0; +#else + data = (unsigned long) skb->data; +#endif + capi_fill_DATA_B3_REQ(&sendcmsg, global.ap.applid, card->msgid++, nccip->ncci, /* adr */ - (u32) skb->data, /* Data */ + data, /* Data */ skb->len, /* DataLength */ datahandle, /* DataHandle */ 0 /* Flags */ @@ -2123,7 +2141,10 @@ static int capidrv_delcontr(u16 contr) printk(KERN_ERR "capidrv: delcontr: no contr %u\n", contr); return -1; } - #warning FIXME: maybe a race condition the card should be removed here from global list /kkeil + + /* FIXME: maybe a race condition the card should be removed + * here from global list /kkeil + */ spin_unlock_irqrestore(&global_lock, flags); del_timer(&card->listentimer); diff --git a/drivers/md/raid6algos.c b/drivers/md/raid6algos.c index 92657615657..77a6e4bf503 100644 --- a/drivers/md/raid6algos.c +++ b/drivers/md/raid6algos.c @@ -52,7 +52,7 @@ const struct raid6_calls * const raid6_algos[] = { &raid6_intx16, &raid6_intx32, #endif -#if defined(__i386__) +#if defined(__i386__) && !defined(__arch_um__) &raid6_mmxx1, &raid6_mmxx2, &raid6_sse1x1, @@ -60,7 +60,7 @@ const struct raid6_calls * const raid6_algos[] = { &raid6_sse2x1, &raid6_sse2x2, #endif -#if defined(__x86_64__) +#if defined(__x86_64__) && !defined(__arch_um__) &raid6_sse2x1, &raid6_sse2x2, &raid6_sse2x4, diff --git a/drivers/md/raid6mmx.c b/drivers/md/raid6mmx.c index 6181a5a3365..d4e4a1bd70a 100644 --- a/drivers/md/raid6mmx.c +++ b/drivers/md/raid6mmx.c @@ -16,7 +16,7 @@ * MMX implementation of RAID-6 syndrome functions */ -#if defined(__i386__) +#if defined(__i386__) && !defined(__arch_um__) #include "raid6.h" #include "raid6x86.h" diff --git a/drivers/md/raid6sse1.c b/drivers/md/raid6sse1.c index f0a1ba8f40b..0666237276f 100644 --- a/drivers/md/raid6sse1.c +++ b/drivers/md/raid6sse1.c @@ -21,7 +21,7 @@ * worthwhile as a separate implementation. */ -#if defined(__i386__) +#if defined(__i386__) && !defined(__arch_um__) #include "raid6.h" #include "raid6x86.h" diff --git a/drivers/md/raid6sse2.c b/drivers/md/raid6sse2.c index 0f019762a7c..b034ad86803 100644 --- a/drivers/md/raid6sse2.c +++ b/drivers/md/raid6sse2.c @@ -17,7 +17,7 @@ * */ -#if defined(__i386__) || defined(__x86_64__) +#if (defined(__i386__) || defined(__x86_64__)) && !defined(__arch_um__) #include "raid6.h" #include "raid6x86.h" @@ -161,7 +161,7 @@ const struct raid6_calls raid6_sse2x2 = { #endif -#ifdef __x86_64__ +#if defined(__x86_64__) && !defined(__arch_um__) /* * Unrolled-by-4 SSE2 implementation diff --git a/drivers/md/raid6x86.h b/drivers/md/raid6x86.h index 9111950414f..99fea7a70ca 100644 --- a/drivers/md/raid6x86.h +++ b/drivers/md/raid6x86.h @@ -19,7 +19,7 @@ #ifndef LINUX_RAID_RAID6X86_H #define LINUX_RAID_RAID6X86_H -#if defined(__i386__) || defined(__x86_64__) +#if (defined(__i386__) || defined(__x86_64__)) && !defined(__arch_um__) #ifdef __KERNEL__ /* Real code */ diff --git a/drivers/misc/fujitsu-laptop.c b/drivers/misc/fujitsu-laptop.c index d366a6cc1fd..c8d62c268b1 100644 --- a/drivers/misc/fujitsu-laptop.c +++ b/drivers/misc/fujitsu-laptop.c @@ -122,9 +122,6 @@ static int get_lcd_level(void) else fujitsu->brightness_changed = 0; - if (status < 0) - return status; - return fujitsu->brightness_level; } @@ -198,7 +195,7 @@ static struct platform_driver fujitsupf_driver = { /* ACPI device */ -int acpi_fujitsu_add(struct acpi_device *device) +static int acpi_fujitsu_add(struct acpi_device *device) { int result = 0; int state = 0; @@ -229,7 +226,7 @@ int acpi_fujitsu_add(struct acpi_device *device) return result; } -int acpi_fujitsu_remove(struct acpi_device *device, int type) +static int acpi_fujitsu_remove(struct acpi_device *device, int type) { ACPI_FUNCTION_TRACE("acpi_fujitsu_remove"); diff --git a/drivers/mmc/host/imxmmc.c b/drivers/mmc/host/imxmmc.c index fc72e1fadb6..f2070a19cfa 100644 --- a/drivers/mmc/host/imxmmc.c +++ b/drivers/mmc/host/imxmmc.c @@ -262,7 +262,7 @@ static void imxmci_setup_data(struct imxmci_host *host, struct mmc_data *data) } /* Convert back to virtual address */ - host->data_ptr = (u16*)sg_virt(sg); + host->data_ptr = (u16*)sg_virt(data->sg); host->data_cnt = 0; clear_bit(IMXMCI_PEND_DMA_DATA_b, &host->pending_events); diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 86b8641b466..867cb7345b5 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -166,13 +166,14 @@ config NET_SB1000 If you don't have this card, of course say N. config IP1000 - tristate "IP1000 Gigabit Ethernet support" - depends on PCI && EXPERIMENTAL - ---help--- - This driver supports IP1000 gigabit Ethernet cards. + tristate "IP1000 Gigabit Ethernet support" + depends on PCI && EXPERIMENTAL + select MII + ---help--- + This driver supports IP1000 gigabit Ethernet cards. - To compile this driver as a module, choose M here: the module - will be called ipg. This is recommended. + To compile this driver as a module, choose M here: the module + will be called ipg. This is recommended. source "drivers/net/arcnet/Kconfig" @@ -1880,6 +1881,30 @@ config FEC2 Say Y here if you want to use the second built-in 10/100 Fast ethernet controller on some Motorola ColdFire processors. +config FEC_MPC52xx + tristate "MPC52xx FEC driver" + depends on PPC_MPC52xx + select PPC_BESTCOMM + select PPC_BESTCOMM_FEC + select CRC32 + select PHYLIB + ---help--- + This option enables support for the MPC5200's on-chip + Fast Ethernet Controller + If compiled as module, it will be called 'fec_mpc52xx.ko'. + +config FEC_MPC52xx_MDIO + bool "MPC52xx FEC MDIO bus driver" + depends on FEC_MPC52xx + default y + ---help--- + The MPC5200's FEC can connect to the Ethernet either with + an external MII PHY chip or 10 Mbps 7-wire interface + (Motorola? industry standard). + If your board uses an external PHY connected to FEC, enable this. + If not sure, enable. + If compiled as module, it will be called 'fec_mpc52xx_phy.ko'. + config NE_H8300 tristate "NE2000 compatible support for H8/300" depends on H8300 diff --git a/drivers/net/Makefile b/drivers/net/Makefile index 593262065c9..0e5fde4a1b2 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -96,6 +96,10 @@ obj-$(CONFIG_SHAPER) += shaper.o obj-$(CONFIG_HP100) += hp100.o obj-$(CONFIG_SMC9194) += smc9194.o obj-$(CONFIG_FEC) += fec.o +obj-$(CONFIG_FEC_MPC52xx) += fec_mpc52xx.o +ifeq ($(CONFIG_FEC_MPC52xx_MDIO),y) + obj-$(CONFIG_FEC_MPC52xx) += fec_mpc52xx_phy.o +endif obj-$(CONFIG_68360_ENET) += 68360enet.o obj-$(CONFIG_WD80x3) += wd.o 8390.o obj-$(CONFIG_EL2) += 3c503.o 8390.o diff --git a/drivers/net/bfin_mac.c b/drivers/net/bfin_mac.c index 53fe7ded5d5..084acfd6fc5 100644 --- a/drivers/net/bfin_mac.c +++ b/drivers/net/bfin_mac.c @@ -371,7 +371,6 @@ static void bf537_adjust_link(struct net_device *dev) if (phydev->speed != lp->old_speed) { #if defined(CONFIG_BFIN_MAC_RMII) u32 opmode = bfin_read_EMAC_OPMODE(); - bf537mac_disable(); switch (phydev->speed) { case 10: opmode |= RMII_10; @@ -386,7 +385,6 @@ static void bf537_adjust_link(struct net_device *dev) break; } bfin_write_EMAC_OPMODE(opmode); - bf537mac_enable(); #endif new_state = 1; diff --git a/drivers/net/e1000/e1000.h b/drivers/net/e1000/e1000.h index 781ed996848..3b840283a9c 100644 --- a/drivers/net/e1000/e1000.h +++ b/drivers/net/e1000/e1000.h @@ -351,4 +351,12 @@ enum e1000_state_t { __E1000_DOWN }; +extern char e1000_driver_name[]; +extern const char e1000_driver_version[]; + +extern void e1000_power_up_phy(struct e1000_adapter *); +extern void e1000_set_ethtool_ops(struct net_device *netdev); +extern void e1000_check_options(struct e1000_adapter *adapter); + + #endif /* _E1000_H_ */ diff --git a/drivers/net/e1000/e1000_ethtool.c b/drivers/net/e1000/e1000_ethtool.c index 6c9a643426f..667f18bcc17 100644 --- a/drivers/net/e1000/e1000_ethtool.c +++ b/drivers/net/e1000/e1000_ethtool.c @@ -32,9 +32,6 @@ #include <asm/uaccess.h> -extern char e1000_driver_name[]; -extern char e1000_driver_version[]; - extern int e1000_up(struct e1000_adapter *adapter); extern void e1000_down(struct e1000_adapter *adapter); extern void e1000_reinit_locked(struct e1000_adapter *adapter); @@ -733,16 +730,16 @@ err_setup: #define REG_PATTERN_TEST(R, M, W) \ { \ - uint32_t pat, value; \ - uint32_t test[] = \ + uint32_t pat, val; \ + const uint32_t test[] = \ {0x5A5A5A5A, 0xA5A5A5A5, 0x00000000, 0xFFFFFFFF}; \ - for (pat = 0; pat < ARRAY_SIZE(test); pat++) { \ + for (pat = 0; pat < ARRAY_SIZE(test); pat++) { \ E1000_WRITE_REG(&adapter->hw, R, (test[pat] & W)); \ - value = E1000_READ_REG(&adapter->hw, R); \ - if (value != (test[pat] & W & M)) { \ + val = E1000_READ_REG(&adapter->hw, R); \ + if (val != (test[pat] & W & M)) { \ DPRINTK(DRV, ERR, "pattern test reg %04X failed: got " \ "0x%08X expected 0x%08X\n", \ - E1000_##R, value, (test[pat] & W & M)); \ + E1000_##R, val, (test[pat] & W & M)); \ *data = (adapter->hw.mac_type < e1000_82543) ? \ E1000_82542_##R : E1000_##R; \ return 1; \ @@ -752,12 +749,12 @@ err_setup: #define REG_SET_AND_CHECK(R, M, W) \ { \ - uint32_t value; \ + uint32_t val; \ E1000_WRITE_REG(&adapter->hw, R, W & M); \ - value = E1000_READ_REG(&adapter->hw, R); \ - if ((W & M) != (value & M)) { \ + val = E1000_READ_REG(&adapter->hw, R); \ + if ((W & M) != (val & M)) { \ DPRINTK(DRV, ERR, "set/check reg %04X test failed: got 0x%08X "\ - "expected 0x%08X\n", E1000_##R, (value & M), (W & M)); \ + "expected 0x%08X\n", E1000_##R, (val & M), (W & M)); \ *data = (adapter->hw.mac_type < e1000_82543) ? \ E1000_82542_##R : E1000_##R; \ return 1; \ @@ -1621,8 +1618,6 @@ e1000_get_sset_count(struct net_device *netdev, int sset) } } -extern void e1000_power_up_phy(struct e1000_adapter *); - static void e1000_diag_test(struct net_device *netdev, struct ethtool_test *eth_test, uint64_t *data) @@ -1859,8 +1854,8 @@ e1000_phys_id(struct net_device *netdev, uint32_t data) { struct e1000_adapter *adapter = netdev_priv(netdev); - if (!data || data > (uint32_t)(MAX_SCHEDULE_TIMEOUT / HZ)) - data = (uint32_t)(MAX_SCHEDULE_TIMEOUT / HZ); + if (!data) + data = INT_MAX; if (adapter->hw.mac_type < e1000_82571) { if (!adapter->blink_timer.function) { diff --git a/drivers/net/e1000/e1000_hw.c b/drivers/net/e1000/e1000_hw.c index 8fa0fe4009d..7c6888c58c2 100644 --- a/drivers/net/e1000/e1000_hw.c +++ b/drivers/net/e1000/e1000_hw.c @@ -8607,7 +8607,7 @@ e1000_read_ich8_data(struct e1000_hw *hw, uint32_t index, DEBUGFUNC("e1000_read_ich8_data"); - if (size < 1 || size > 2 || data == 0x0 || + if (size < 1 || size > 2 || data == NULL || index > ICH_FLASH_LINEAR_ADDR_MASK) return error; @@ -8841,7 +8841,7 @@ e1000_read_ich8_word(struct e1000_hw *hw, uint32_t index, uint16_t *data) * amount of NVM used in each bank is a *minimum* of 4 KBytes, but in fact the * bank size may be 4, 8 or 64 KBytes *****************************************************************************/ -int32_t +static int32_t e1000_erase_ich8_4k_segment(struct e1000_hw *hw, uint32_t bank) { union ich8_hws_flash_status hsfsts; diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index f1ce348470c..72deff0d4d9 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c @@ -37,8 +37,8 @@ static char e1000_driver_string[] = "Intel(R) PRO/1000 Network Driver"; #define DRIVERNAPI "-NAPI" #endif #define DRV_VERSION "7.3.20-k2"DRIVERNAPI -char e1000_driver_version[] = DRV_VERSION; -static char e1000_copyright[] = "Copyright (c) 1999-2006 Intel Corporation."; +const char e1000_driver_version[] = DRV_VERSION; +static const char e1000_copyright[] = "Copyright (c) 1999-2006 Intel Corporation."; /* e1000_pci_tbl - PCI Device ID Table * @@ -188,7 +188,6 @@ static void e1000_alloc_rx_buffers_ps(struct e1000_adapter *adapter, static int e1000_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd); static int e1000_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd); -void e1000_set_ethtool_ops(struct net_device *netdev); static void e1000_enter_82542_rst(struct e1000_adapter *adapter); static void e1000_leave_82542_rst(struct e1000_adapter *adapter); static void e1000_tx_timeout(struct net_device *dev); @@ -213,8 +212,6 @@ static void e1000_shutdown(struct pci_dev *pdev); static void e1000_netpoll (struct net_device *netdev); #endif -extern void e1000_check_options(struct e1000_adapter *adapter); - #define COPYBREAK_DEFAULT 256 static unsigned int copybreak __read_mostly = COPYBREAK_DEFAULT; module_param(copybreak, uint, 0644); diff --git a/drivers/net/e1000/e1000_param.c b/drivers/net/e1000/e1000_param.c index f485874a63f..e6565ce686b 100644 --- a/drivers/net/e1000/e1000_param.c +++ b/drivers/net/e1000/e1000_param.c @@ -46,7 +46,7 @@ #define E1000_PARAM_INIT { [0 ... E1000_MAX_NIC] = OPTION_UNSET } #define E1000_PARAM(X, desc) \ static int __devinitdata X[E1000_MAX_NIC+1] = E1000_PARAM_INIT; \ - static int num_##X = 0; \ + static unsigned int num_##X; \ module_param_array_named(X, X, int, &num_##X, 0); \ MODULE_PARM_DESC(X, desc); @@ -198,9 +198,9 @@ E1000_PARAM(KumeranLockLoss, "Enable Kumeran lock loss workaround"); struct e1000_option { enum { enable_option, range_option, list_option } type; - char *name; - char *err; - int def; + const char *name; + const char *err; + int def; union { struct { /* range_option info */ int min; @@ -214,8 +214,9 @@ struct e1000_option { }; static int __devinit -e1000_validate_option(int *value, struct e1000_option *opt, - struct e1000_adapter *adapter) +e1000_validate_option(unsigned int *value, + const struct e1000_option *opt, + struct e1000_adapter *adapter) { if (*value == OPTION_UNSET) { *value = opt->def; @@ -348,7 +349,7 @@ e1000_check_options(struct e1000_adapter *adapter) }; if (num_XsumRX > bd) { - int rx_csum = XsumRX[bd]; + unsigned int rx_csum = XsumRX[bd]; e1000_validate_option(&rx_csum, &opt, adapter); adapter->rx_csum = rx_csum; } else { @@ -374,7 +375,7 @@ e1000_check_options(struct e1000_adapter *adapter) }; if (num_FlowControl > bd) { - int fc = FlowControl[bd]; + unsigned int fc = FlowControl[bd]; e1000_validate_option(&fc, &opt, adapter); adapter->hw.fc = adapter->hw.original_fc = fc; } else { @@ -506,7 +507,7 @@ e1000_check_options(struct e1000_adapter *adapter) }; if (num_SmartPowerDownEnable > bd) { - int spd = SmartPowerDownEnable[bd]; + unsigned int spd = SmartPowerDownEnable[bd]; e1000_validate_option(&spd, &opt, adapter); adapter->smart_power_down = spd; } else { @@ -522,7 +523,7 @@ e1000_check_options(struct e1000_adapter *adapter) }; if (num_KumeranLockLoss > bd) { - int kmrn_lock_loss = KumeranLockLoss[bd]; + unsigned int kmrn_lock_loss = KumeranLockLoss[bd]; e1000_validate_option(&kmrn_lock_loss, &opt, adapter); adapter->hw.kmrn_lock_loss_workaround_disabled = !kmrn_lock_loss; } else { @@ -581,7 +582,7 @@ e1000_check_fiber_options(struct e1000_adapter *adapter) static void __devinit e1000_check_copper_options(struct e1000_adapter *adapter) { - int speed, dplx, an; + unsigned int speed, dplx, an; int bd = adapter->bd_number; { /* Speed */ diff --git a/drivers/net/e1000e/82571.c b/drivers/net/e1000e/82571.c index cf70522fc85..14141a55eaa 100644 --- a/drivers/net/e1000e/82571.c +++ b/drivers/net/e1000e/82571.c @@ -283,7 +283,7 @@ static s32 e1000_get_invariants_82571(struct e1000_adapter *adapter) adapter->flags &= ~FLAG_HAS_WOL; /* quad ports only support WoL on port A */ if (adapter->flags & FLAG_IS_QUAD_PORT && - (!adapter->flags & FLAG_IS_QUAD_PORT_A)) + (!(adapter->flags & FLAG_IS_QUAD_PORT_A))) adapter->flags &= ~FLAG_HAS_WOL; break; diff --git a/drivers/net/e1000e/e1000.h b/drivers/net/e1000e/e1000.h index d2499bb07c1..473f78de4be 100644 --- a/drivers/net/e1000e/e1000.h +++ b/drivers/net/e1000e/e1000.h @@ -122,7 +122,8 @@ struct e1000_buffer { u16 next_to_watch; }; /* RX */ - struct page *page; + /* arrays of page information for packet split */ + struct e1000_ps_page *ps_pages; }; }; @@ -142,8 +143,6 @@ struct e1000_ring { /* array of buffer information structs */ struct e1000_buffer *buffer_info; - /* arrays of page information for packet split */ - struct e1000_ps_page *ps_pages; struct sk_buff *rx_skb_top; struct e1000_queue_stats stats; diff --git a/drivers/net/e1000e/ethtool.c b/drivers/net/e1000e/ethtool.c index 0666e62e9ad..6a39784e7ee 100644 --- a/drivers/net/e1000e/ethtool.c +++ b/drivers/net/e1000e/ethtool.c @@ -1680,8 +1680,8 @@ static int e1000_phys_id(struct net_device *netdev, u32 data) { struct e1000_adapter *adapter = netdev_priv(netdev); - if (!data || data > (u32)(MAX_SCHEDULE_TIMEOUT / HZ)) - data = (u32)(MAX_SCHEDULE_TIMEOUT / HZ); + if (!data) + data = INT_MAX; if (adapter->hw.phy.type == e1000_phy_ife) { if (!adapter->blink_timer.function) { diff --git a/drivers/net/e1000e/netdev.c b/drivers/net/e1000e/netdev.c index 033e124d1c1..4fd2e23720b 100644 --- a/drivers/net/e1000e/netdev.c +++ b/drivers/net/e1000e/netdev.c @@ -245,37 +245,36 @@ static void e1000_alloc_rx_buffers_ps(struct e1000_adapter *adapter, rx_desc = E1000_RX_DESC_PS(*rx_ring, i); for (j = 0; j < PS_PAGE_BUFFERS; j++) { - ps_page = &rx_ring->ps_pages[(i * PS_PAGE_BUFFERS) - + j]; - if (j < adapter->rx_ps_pages) { + ps_page = &buffer_info->ps_pages[j]; + if (j >= adapter->rx_ps_pages) { + /* all unused desc entries get hw null ptr */ + rx_desc->read.buffer_addr[j+1] = ~0; + continue; + } + if (!ps_page->page) { + ps_page->page = alloc_page(GFP_ATOMIC); if (!ps_page->page) { - ps_page->page = alloc_page(GFP_ATOMIC); - if (!ps_page->page) { - adapter->alloc_rx_buff_failed++; - goto no_buffers; - } - ps_page->dma = pci_map_page(pdev, - ps_page->page, - 0, PAGE_SIZE, - PCI_DMA_FROMDEVICE); - if (pci_dma_mapping_error( - ps_page->dma)) { - dev_err(&adapter->pdev->dev, - "RX DMA page map failed\n"); - adapter->rx_dma_failed++; - goto no_buffers; - } + adapter->alloc_rx_buff_failed++; + goto no_buffers; + } + ps_page->dma = pci_map_page(pdev, + ps_page->page, + 0, PAGE_SIZE, + PCI_DMA_FROMDEVICE); + if (pci_dma_mapping_error(ps_page->dma)) { + dev_err(&adapter->pdev->dev, + "RX DMA page map failed\n"); + adapter->rx_dma_failed++; + goto no_buffers; } - /* - * Refresh the desc even if buffer_addrs - * didn't change because each write-back - * erases this info. - */ - rx_desc->read.buffer_addr[j+1] = - cpu_to_le64(ps_page->dma); - } else { - rx_desc->read.buffer_addr[j+1] = ~0; } + /* + * Refresh the desc even if buffer_addrs + * didn't change because each write-back + * erases this info. + */ + rx_desc->read.buffer_addr[j+1] = + cpu_to_le64(ps_page->dma); } skb = netdev_alloc_skb(netdev, @@ -334,94 +333,6 @@ no_buffers: } /** - * e1000_alloc_rx_buffers_jumbo - Replace used jumbo receive buffers - * - * @adapter: address of board private structure - * @cleaned_count: number of buffers to allocate this pass - **/ -static void e1000_alloc_rx_buffers_jumbo(struct e1000_adapter *adapter, - int cleaned_count) -{ - struct net_device *netdev = adapter->netdev; - struct pci_dev *pdev = adapter->pdev; - struct e1000_ring *rx_ring = adapter->rx_ring; - struct e1000_rx_desc *rx_desc; - struct e1000_buffer *buffer_info; - struct sk_buff *skb; - unsigned int i; - unsigned int bufsz = 256 - - 16 /*for skb_reserve */ - - NET_IP_ALIGN; - - i = rx_ring->next_to_use; - buffer_info = &rx_ring->buffer_info[i]; - - while (cleaned_count--) { - skb = buffer_info->skb; - if (skb) { - skb_trim(skb, 0); - goto check_page; - } - - skb = netdev_alloc_skb(netdev, bufsz); - if (!skb) { - /* Better luck next round */ - adapter->alloc_rx_buff_failed++; - break; - } - - /* Make buffer alignment 2 beyond a 16 byte boundary - * this will result in a 16 byte aligned IP header after - * the 14 byte MAC header is removed - */ - skb_reserve(skb, NET_IP_ALIGN); - - buffer_info->skb = skb; -check_page: - /* allocate a new page if necessary */ - if (!buffer_info->page) { - buffer_info->page = alloc_page(GFP_ATOMIC); - if (!buffer_info->page) { - adapter->alloc_rx_buff_failed++; - break; - } - } - - if (!buffer_info->dma) - buffer_info->dma = pci_map_page(pdev, - buffer_info->page, 0, - PAGE_SIZE, - PCI_DMA_FROMDEVICE); - if (pci_dma_mapping_error(buffer_info->dma)) { - dev_err(&adapter->pdev->dev, "RX DMA page map failed\n"); - adapter->rx_dma_failed++; - break; - } - - rx_desc = E1000_RX_DESC(*rx_ring, i); - rx_desc->buffer_addr = cpu_to_le64(buffer_info->dma); - - i++; - if (i == rx_ring->count) - i = 0; - buffer_info = &rx_ring->buffer_info[i]; - } - - if (rx_ring->next_to_use != i) { - rx_ring->next_to_use = i; - if (i-- == 0) - i = (rx_ring->count - 1); - - /* Force memory writes to complete before letting h/w - * know there are new descriptors to fetch. (Only - * applicable for weak-ordered memory model archs, - * such as IA-64). */ - wmb(); - writel(i, adapter->hw.hw_addr + rx_ring->tail); - } -} - -/** * e1000_clean_rx_irq - Send received data up the network stack; legacy * @adapter: board private structure * @@ -495,10 +406,6 @@ static bool e1000_clean_rx_irq(struct e1000_adapter *adapter, goto next_desc; } - /* adjust length to remove Ethernet CRC */ - length -= 4; - - /* probably a little skewed due to removing CRC */ total_rx_bytes += length; total_rx_packets++; @@ -554,15 +461,6 @@ next_desc: return cleaned; } -static void e1000_consume_page(struct e1000_buffer *bi, struct sk_buff *skb, - u16 length) -{ - bi->page = NULL; - skb->len += length; - skb->data_len += length; - skb->truesize += length; -} - static void e1000_put_txbuf(struct e1000_adapter *adapter, struct e1000_buffer *buffer_info) { @@ -699,174 +597,6 @@ static bool e1000_clean_tx_irq(struct e1000_adapter *adapter) } /** - * e1000_clean_rx_irq_jumbo - Send received data up the network stack; legacy - * @adapter: board private structure - * - * the return value indicates whether actual cleaning was done, there - * is no guarantee that everything was cleaned - **/ -static bool e1000_clean_rx_irq_jumbo(struct e1000_adapter *adapter, - int *work_done, int work_to_do) -{ - struct net_device *netdev = adapter->netdev; - struct pci_dev *pdev = adapter->pdev; - struct e1000_ring *rx_ring = adapter->rx_ring; - struct e1000_rx_desc *rx_desc, *next_rxd; - struct e1000_buffer *buffer_info, *next_buffer; - u32 length; - unsigned int i; - int cleaned_count = 0; - bool cleaned = 0; - unsigned int total_rx_bytes = 0, total_rx_packets = 0; - - i = rx_ring->next_to_clean; - rx_desc = E1000_RX_DESC(*rx_ring, i); - buffer_info = &rx_ring->buffer_info[i]; - - while (rx_desc->status & E1000_RXD_STAT_DD) { - struct sk_buff *skb; - u8 status; - - if (*work_done >= work_to_do) - break; - (*work_done)++; - - status = rx_desc->status; - skb = buffer_info->skb; - buffer_info->skb = NULL; - - i++; - if (i == rx_ring->count) - i = 0; - next_rxd = E1000_RX_DESC(*rx_ring, i); - prefetch(next_rxd); - - next_buffer = &rx_ring->buffer_info[i]; - - cleaned = 1; - cleaned_count++; - pci_unmap_page(pdev, - buffer_info->dma, - PAGE_SIZE, - PCI_DMA_FROMDEVICE); - buffer_info->dma = 0; - - length = le16_to_cpu(rx_desc->length); - - /* errors is only valid for DD + EOP descriptors */ - if ((status & E1000_RXD_STAT_EOP) && - (rx_desc->errors & E1000_RXD_ERR_FRAME_ERR_MASK)) { - /* recycle both page and skb */ - buffer_info->skb = skb; - /* an error means any chain goes out the window too */ - if (rx_ring->rx_skb_top) - dev_kfree_skb(rx_ring->rx_skb_top); - rx_ring->rx_skb_top = NULL; - goto next_desc; - } - -#define rxtop rx_ring->rx_skb_top - if (!(status & E1000_RXD_STAT_EOP)) { - /* this descriptor is only the beginning (or middle) */ - if (!rxtop) { - /* this is the beginning of a chain */ - rxtop = skb; - skb_fill_page_desc(rxtop, 0, buffer_info->page, - 0, length); - } else { - /* this is the middle of a chain */ - skb_fill_page_desc(rxtop, - skb_shinfo(rxtop)->nr_frags, - buffer_info->page, 0, - length); - /* re-use the skb, only consumed the page */ - buffer_info->skb = skb; - } - e1000_consume_page(buffer_info, rxtop, length); - goto next_desc; - } else { - if (rxtop) { - /* end of the chain */ - skb_fill_page_desc(rxtop, - skb_shinfo(rxtop)->nr_frags, - buffer_info->page, 0, length); - /* re-use the current skb, we only consumed the - * page */ - buffer_info->skb = skb; - skb = rxtop; - rxtop = NULL; - e1000_consume_page(buffer_info, skb, length); - } else { - /* no chain, got EOP, this buf is the packet - * copybreak to save the put_page/alloc_page */ - if (length <= copybreak && - skb_tailroom(skb) >= length) { - u8 *vaddr; - vaddr = kmap_atomic(buffer_info->page, - KM_SKB_DATA_SOFTIRQ); - memcpy(skb_tail_pointer(skb), - vaddr, length); - kunmap_atomic(vaddr, - KM_SKB_DATA_SOFTIRQ); - /* re-use the page, so don't erase - * buffer_info->page */ - skb_put(skb, length); - } else { - skb_fill_page_desc(skb, 0, - buffer_info->page, 0, - length); - e1000_consume_page(buffer_info, skb, - length); - } - } - } - - /* Receive Checksum Offload XXX recompute due to CRC strip? */ - e1000_rx_checksum(adapter, - (u32)(status) | - ((u32)(rx_desc->errors) << 24), - le16_to_cpu(rx_desc->csum), skb); - - pskb_trim(skb, skb->len - 4); - - /* probably a little skewed due to removing CRC */ - total_rx_bytes += skb->len; - total_rx_packets++; - - /* eth type trans needs skb->data to point to something */ - if (!pskb_may_pull(skb, ETH_HLEN)) { - ndev_err(netdev, "__pskb_pull_tail failed.\n"); - dev_kfree_skb(skb); - goto next_desc; - } - - e1000_receive_skb(adapter, netdev, skb,status,rx_desc->special); - -next_desc: - rx_desc->status = 0; - - /* return some buffers to hardware, one at a time is too slow */ - if (cleaned_count >= E1000_RX_BUFFER_WRITE) { - adapter->alloc_rx_buf(adapter, cleaned_count); - cleaned_count = 0; - } - - /* use prefetched values */ - rx_desc = next_rxd; - buffer_info = next_buffer; - } - rx_ring->next_to_clean = i; - - cleaned_count = e1000_desc_unused(rx_ring); - if (cleaned_count) - adapter->alloc_rx_buf(adapter, cleaned_count); - - adapter->total_rx_packets += total_rx_packets; - adapter->total_rx_bytes += total_rx_bytes; - return cleaned; -} - -/** * e1000_clean_rx_irq_ps - Send received data up the network stack; packet split * @adapter: board private structure * @@ -953,7 +683,7 @@ static bool e1000_clean_rx_irq_ps(struct e1000_adapter *adapter, ((length + l1) <= adapter->rx_ps_bsize0)) { u8 *vaddr; - ps_page = &rx_ring->ps_pages[i * PS_PAGE_BUFFERS]; + ps_page = &buffer_info->ps_pages[0]; /* there is no documentation about how to call * kmap_atomic, so we can't hold the mapping @@ -965,8 +695,7 @@ static bool e1000_clean_rx_irq_ps(struct e1000_adapter *adapter, kunmap_atomic(vaddr, KM_SKB_DATA_SOFTIRQ); pci_dma_sync_single_for_device(pdev, ps_page->dma, PAGE_SIZE, PCI_DMA_FROMDEVICE); - /* remove the CRC */ - l1 -= 4; + skb_put(skb, l1); goto copydone; } /* if */ @@ -977,7 +706,7 @@ static bool e1000_clean_rx_irq_ps(struct e1000_adapter *adapter, if (!length) break; - ps_page = &rx_ring->ps_pages[(i * PS_PAGE_BUFFERS) + j]; + ps_page = &buffer_info->ps_pages[j]; pci_unmap_page(pdev, ps_page->dma, PAGE_SIZE, PCI_DMA_FROMDEVICE); ps_page->dma = 0; @@ -988,10 +717,6 @@ static bool e1000_clean_rx_irq_ps(struct e1000_adapter *adapter, skb->truesize += length; } - /* strip the ethernet crc, problem is we're using pages now so - * this whole operation can get a little cpu intensive */ - pskb_trim(skb, skb->len - 4); - copydone: total_rx_bytes += skb->len; total_rx_packets++; @@ -1043,7 +768,6 @@ static void e1000_clean_rx_ring(struct e1000_adapter *adapter) struct e1000_buffer *buffer_info; struct e1000_ps_page *ps_page; struct pci_dev *pdev = adapter->pdev; - unsigned long size; unsigned int i, j; /* Free all the Rx ring sk_buffs */ @@ -1054,9 +778,6 @@ static void e1000_clean_rx_ring(struct e1000_adapter *adapter) pci_unmap_single(pdev, buffer_info->dma, adapter->rx_buffer_len, PCI_DMA_FROMDEVICE); - else if (adapter->clean_rx == e1000_clean_rx_irq_jumbo) - pci_unmap_page(pdev, buffer_info->dma, - PAGE_SIZE, PCI_DMA_FROMDEVICE); else if (adapter->clean_rx == e1000_clean_rx_irq_ps) pci_unmap_single(pdev, buffer_info->dma, adapter->rx_ps_bsize0, @@ -1064,19 +785,13 @@ static void e1000_clean_rx_ring(struct e1000_adapter *adapter) buffer_info->dma = 0; } - if (buffer_info->page) { - put_page(buffer_info->page); - buffer_info->page = NULL; - } - if (buffer_info->skb) { dev_kfree_skb(buffer_info->skb); buffer_info->skb = NULL; } for (j = 0; j < PS_PAGE_BUFFERS; j++) { - ps_page = &rx_ring->ps_pages[(i * PS_PAGE_BUFFERS) - + j]; + ps_page = &buffer_info->ps_pages[j]; if (!ps_page->page) break; pci_unmap_page(pdev, ps_page->dma, PAGE_SIZE, @@ -1093,12 +808,6 @@ static void e1000_clean_rx_ring(struct e1000_adapter *adapter) rx_ring->rx_skb_top = NULL; } - size = sizeof(struct e1000_buffer) * rx_ring->count; - memset(rx_ring->buffer_info, 0, size); - size = sizeof(struct e1000_ps_page) - * (rx_ring->count * PS_PAGE_BUFFERS); - memset(rx_ring->ps_pages, 0, size); - /* Zero out the descriptor ring */ memset(rx_ring->desc, 0, rx_ring->size); @@ -1421,7 +1130,8 @@ err: int e1000e_setup_rx_resources(struct e1000_adapter *adapter) { struct e1000_ring *rx_ring = adapter->rx_ring; - int size, desc_len, err = -ENOMEM; + struct e1000_buffer *buffer_info; + int i, size, desc_len, err = -ENOMEM; size = sizeof(struct e1000_buffer) * rx_ring->count; rx_ring->buffer_info = vmalloc(size); @@ -1429,11 +1139,14 @@ int e1000e_setup_rx_resources(struct e1000_adapter *adapter) goto err; memset(rx_ring->buffer_info, 0, size); - rx_ring->ps_pages = kcalloc(rx_ring->count * PS_PAGE_BUFFERS, - sizeof(struct e1000_ps_page), - GFP_KERNEL); - if (!rx_ring->ps_pages) - goto err; + for (i = 0; i < rx_ring->count; i++) { + buffer_info = &rx_ring->buffer_info[i]; + buffer_info->ps_pages = kcalloc(PS_PAGE_BUFFERS, + sizeof(struct e1000_ps_page), + GFP_KERNEL); + if (!buffer_info->ps_pages) + goto err_pages; + } desc_len = sizeof(union e1000_rx_desc_packet_split); @@ -1443,16 +1156,21 @@ int e1000e_setup_rx_resources(struct e1000_adapter *adapter) err = e1000_alloc_ring_dma(adapter, rx_ring); if (err) - goto err; + goto err_pages; rx_ring->next_to_clean = 0; rx_ring->next_to_use = 0; rx_ring->rx_skb_top = NULL; return 0; + +err_pages: + for (i = 0; i < rx_ring->count; i++) { + buffer_info = &rx_ring->buffer_info[i]; + kfree(buffer_info->ps_pages); + } err: vfree(rx_ring->buffer_info); - kfree(rx_ring->ps_pages); ndev_err(adapter->netdev, "Unable to allocate memory for the transmit descriptor ring\n"); return err; @@ -1518,15 +1236,17 @@ void e1000e_free_rx_resources(struct e1000_adapter *adapter) { struct pci_dev *pdev = adapter->pdev; struct e1000_ring *rx_ring = adapter->rx_ring; + int i; e1000_clean_rx_ring(adapter); + for (i = 0; i < rx_ring->count; i++) { + kfree(rx_ring->buffer_info[i].ps_pages); + } + vfree(rx_ring->buffer_info); rx_ring->buffer_info = NULL; - kfree(rx_ring->ps_pages); - rx_ring->ps_pages = NULL; - dma_free_coherent(&pdev->dev, rx_ring->size, rx_ring->desc, rx_ring->dma); rx_ring->desc = NULL; @@ -2032,9 +1752,11 @@ static void e1000_setup_rctl(struct e1000_adapter *adapter) ew32(RFCTL, rfctl); - /* disable the stripping of CRC because it breaks - * BMC firmware connected over SMBUS */ - rctl |= E1000_RCTL_DTYP_PS /* | E1000_RCTL_SECRC */; + /* Enable Packet split descriptors */ + rctl |= E1000_RCTL_DTYP_PS; + + /* Enable hardware CRC frame stripping */ + rctl |= E1000_RCTL_SECRC; psrctl |= adapter->rx_ps_bsize0 >> E1000_PSRCTL_BSIZE0_SHIFT; @@ -2077,11 +1799,6 @@ static void e1000_configure_rx(struct e1000_adapter *adapter) sizeof(union e1000_rx_desc_packet_split); adapter->clean_rx = e1000_clean_rx_irq_ps; adapter->alloc_rx_buf = e1000_alloc_rx_buffers_ps; - } else if (adapter->netdev->mtu > ETH_FRAME_LEN + VLAN_HLEN + 4) { - rdlen = rx_ring->count * - sizeof(struct e1000_rx_desc); - adapter->clean_rx = e1000_clean_rx_irq_jumbo; - adapter->alloc_rx_buf = e1000_alloc_rx_buffers_jumbo; } else { rdlen = rx_ring->count * sizeof(struct e1000_rx_desc); @@ -2326,8 +2043,11 @@ void e1000e_reset(struct e1000_adapter *adapter) struct e1000_mac_info *mac = &adapter->hw.mac; struct e1000_hw *hw = &adapter->hw; u32 tx_space, min_tx_space, min_rx_space; + u32 pba; u16 hwm; + ew32(PBA, adapter->pba); + if (mac->max_frame_size > ETH_FRAME_LEN + ETH_FCS_LEN ) { /* To maintain wire speed transmits, the Tx FIFO should be * large enough to accommodate two full transmit packets, @@ -2335,11 +2055,11 @@ void e1000e_reset(struct e1000_adapter *adapter) * the Rx FIFO should be large enough to accommodate at least * one full receive packet and is similarly rounded up and * expressed in KB. */ - adapter->pba = er32(PBA); + pba = er32(PBA); /* upper 16 bits has Tx packet buffer allocation size in KB */ - tx_space = adapter->pba >> 16; + tx_space = pba >> 16; /* lower 16 bits has Rx packet buffer allocation size in KB */ - adapter->pba &= 0xffff; + pba &= 0xffff; /* the tx fifo also stores 16 bytes of information about the tx * but don't include ethernet FCS because hardware appends it */ min_tx_space = (mac->max_frame_size + @@ -2355,20 +2075,21 @@ void e1000e_reset(struct e1000_adapter *adapter) /* If current Tx allocation is less than the min Tx FIFO size, * and the min Tx FIFO size is less than the current Rx FIFO * allocation, take space away from current Rx allocation */ - if (tx_space < min_tx_space && - ((min_tx_space - tx_space) < adapter->pba)) { - adapter->pba -= - (min_tx_space - tx_space); + if ((tx_space < min_tx_space) && + ((min_tx_space - tx_space) < pba)) { + pba -= min_tx_space - tx_space; /* if short on rx space, rx wins and must trump tx * adjustment or use Early Receive if available */ - if ((adapter->pba < min_rx_space) && + if ((pba < min_rx_space) && (!(adapter->flags & FLAG_HAS_ERT))) /* ERT enabled in e1000_configure_rx */ - adapter->pba = min_rx_space; + pba = min_rx_space; } + + ew32(PBA, pba); } - ew32(PBA, adapter->pba); /* flow control settings */ /* The high water mark must be low enough to fit one full frame @@ -3624,9 +3345,7 @@ static int e1000_change_mtu(struct net_device *netdev, int new_mtu) /* NOTE: netdev_alloc_skb reserves 16 bytes, and typically NET_IP_ALIGN * means we reserve 2 more, this pushes us to allocate from the next * larger slab size. - * i.e. RXBUFFER_2048 --> size-4096 slab - * however with the new *_jumbo* routines, jumbo receives will use - * fragmented skbs */ + * i.e. RXBUFFER_2048 --> size-4096 slab */ if (max_frame <= 256) adapter->rx_buffer_len = 256; diff --git a/drivers/net/e1000e/param.c b/drivers/net/e1000e/param.c index e4e655efb23..332789238b9 100644 --- a/drivers/net/e1000e/param.c +++ b/drivers/net/e1000e/param.c @@ -52,10 +52,11 @@ MODULE_PARM_DESC(copybreak, */ #define E1000_PARAM_INIT { [0 ... E1000_MAX_NIC] = OPTION_UNSET } -#define E1000_PARAM(X, desc) \ - static int __devinitdata X[E1000_MAX_NIC+1] = E1000_PARAM_INIT; \ - static int num_##X; \ - module_param_array_named(X, X, int, &num_##X, 0); \ +#define E1000_PARAM(X, desc) \ + static int __devinitdata X[E1000_MAX_NIC+1] \ + = E1000_PARAM_INIT; \ + static unsigned int num_##X; \ + module_param_array_named(X, X, int, &num_##X, 0); \ MODULE_PARM_DESC(X, desc); @@ -124,9 +125,9 @@ E1000_PARAM(KumeranLockLoss, "Enable Kumeran lock loss workaround"); struct e1000_option { enum { enable_option, range_option, list_option } type; - char *name; - char *err; - int def; + const char *name; + const char *err; + int def; union { struct { /* range_option info */ int min; @@ -139,8 +140,8 @@ struct e1000_option { } arg; }; -static int __devinit e1000_validate_option(int *value, - struct e1000_option *opt, +static int __devinit e1000_validate_option(unsigned int *value, + const struct e1000_option *opt, struct e1000_adapter *adapter) { if (*value == OPTION_UNSET) { @@ -213,7 +214,7 @@ void __devinit e1000e_check_options(struct e1000_adapter *adapter) } { /* Transmit Interrupt Delay */ - struct e1000_option opt = { + const struct e1000_option opt = { .type = range_option, .name = "Transmit Interrupt Delay", .err = "using default of " @@ -232,7 +233,7 @@ void __devinit e1000e_check_options(struct e1000_adapter *adapter) } } { /* Transmit Absolute Interrupt Delay */ - struct e1000_option opt = { + const struct e1000_option opt = { .type = range_option, .name = "Transmit Absolute Interrupt Delay", .err = "using default of " @@ -277,7 +278,7 @@ void __devinit e1000e_check_options(struct e1000_adapter *adapter) } } { /* Receive Absolute Interrupt Delay */ - struct e1000_option opt = { + const struct e1000_option opt = { .type = range_option, .name = "Receive Absolute Interrupt Delay", .err = "using default of " @@ -296,7 +297,7 @@ void __devinit e1000e_check_options(struct e1000_adapter *adapter) } } { /* Interrupt Throttling Rate */ - struct e1000_option opt = { + const struct e1000_option opt = { .type = range_option, .name = "Interrupt Throttling Rate (ints/sec)", .err = "using default of " @@ -344,7 +345,7 @@ void __devinit e1000e_check_options(struct e1000_adapter *adapter) } } { /* Smart Power Down */ - struct e1000_option opt = { + const struct e1000_option opt = { .type = enable_option, .name = "PHY Smart Power Down", .err = "defaulting to Disabled", @@ -352,7 +353,7 @@ void __devinit e1000e_check_options(struct e1000_adapter *adapter) }; if (num_SmartPowerDownEnable > bd) { - int spd = SmartPowerDownEnable[bd]; + unsigned int spd = SmartPowerDownEnable[bd]; e1000_validate_option(&spd, &opt, adapter); if ((adapter->flags & FLAG_HAS_SMART_POWER_DOWN) && spd) @@ -360,7 +361,7 @@ void __devinit e1000e_check_options(struct e1000_adapter *adapter) } } { /* Kumeran Lock Loss Workaround */ - struct e1000_option opt = { + const struct e1000_option opt = { .type = enable_option, .name = "Kumeran Lock Loss Workaround", .err = "defaulting to Enabled", @@ -368,7 +369,7 @@ void __devinit e1000e_check_options(struct e1000_adapter *adapter) }; if (num_KumeranLockLoss > bd) { - int kmrn_lock_loss = KumeranLockLoss[bd]; + unsigned int kmrn_lock_loss = KumeranLockLoss[bd]; e1000_validate_option(&kmrn_lock_loss, &opt, adapter); if (hw->mac.type == e1000_ich8lan) e1000e_set_kmrn_lock_loss_workaround_ich8lan(hw, diff --git a/drivers/net/ehea/ehea.h b/drivers/net/ehea/ehea.h index 4b4b74e47a6..f78e5bf7cb3 100644 --- a/drivers/net/ehea/ehea.h +++ b/drivers/net/ehea/ehea.h @@ -40,7 +40,7 @@ #include <asm/io.h> #define DRV_NAME "ehea" -#define DRV_VERSION "EHEA_0079" +#define DRV_VERSION "EHEA_0080" /* eHEA capability flags */ #define DLPAR_PORT_ADD_REM 1 diff --git a/drivers/net/ehea/ehea_main.c b/drivers/net/ehea/ehea_main.c index 0a7e7892554..f0319f1e8e0 100644 --- a/drivers/net/ehea/ehea_main.c +++ b/drivers/net/ehea/ehea_main.c @@ -33,6 +33,9 @@ #include <linux/if.h> #include <linux/list.h> #include <linux/if_ether.h> +#include <linux/notifier.h> +#include <linux/reboot.h> + #include <net/ip.h> #include "ehea.h" @@ -3295,6 +3298,20 @@ static int __devexit ehea_remove(struct of_device *dev) return 0; } +static int ehea_reboot_notifier(struct notifier_block *nb, + unsigned long action, void *unused) +{ + if (action == SYS_RESTART) { + ehea_info("Reboot: freeing all eHEA resources"); + ibmebus_unregister_driver(&ehea_driver); + } + return NOTIFY_DONE; +} + +static struct notifier_block ehea_reboot_nb = { + .notifier_call = ehea_reboot_notifier, +}; + static int check_module_parm(void) { int ret = 0; @@ -3351,6 +3368,8 @@ int __init ehea_module_init(void) if (ret) goto out; + register_reboot_notifier(&ehea_reboot_nb); + ret = ibmebus_register_driver(&ehea_driver); if (ret) { ehea_error("failed registering eHEA device driver on ebus"); @@ -3362,6 +3381,7 @@ int __init ehea_module_init(void) if (ret) { ehea_error("failed to register capabilities attribute, ret=%d", ret); + unregister_reboot_notifier(&ehea_reboot_nb); ibmebus_unregister_driver(&ehea_driver); goto out; } @@ -3375,6 +3395,7 @@ static void __exit ehea_module_exit(void) flush_scheduled_work(); driver_remove_file(&ehea_driver.driver, &driver_attr_capabilities); ibmebus_unregister_driver(&ehea_driver); + unregister_reboot_notifier(&ehea_reboot_nb); ehea_destroy_busmap(); } diff --git a/drivers/net/fec_mpc52xx.c b/drivers/net/fec_mpc52xx.c new file mode 100644 index 00000000000..fc1cf0b742b --- /dev/null +++ b/drivers/net/fec_mpc52xx.c @@ -0,0 +1,1112 @@ +/* + * Driver for the MPC5200 Fast Ethernet Controller + * + * Originally written by Dale Farnsworth <dfarnsworth@mvista.com> and + * now maintained by Sylvain Munaut <tnt@246tNt.com> + * + * Copyright (C) 2007 Domen Puncer, Telargo, Inc. + * Copyright (C) 2007 Sylvain Munaut <tnt@246tNt.com> + * Copyright (C) 2003-2004 MontaVista, Software, Inc. + * + * This file is licensed under the terms of the GNU General Public License + * version 2. This program is licensed "as is" without any warranty of any + * kind, whether express or implied. + * + */ + +#include <linux/module.h> + +#include <linux/kernel.h> +#include <linux/types.h> +#include <linux/spinlock.h> +#include <linux/errno.h> +#include <linux/init.h> +#include <linux/crc32.h> +#include <linux/hardirq.h> +#include <linux/delay.h> +#include <linux/of_device.h> +#include <linux/of_platform.h> + +#include <linux/netdevice.h> +#include <linux/etherdevice.h> +#include <linux/ethtool.h> +#include <linux/skbuff.h> + +#include <asm/io.h> +#include <asm/delay.h> +#include <asm/mpc52xx.h> + +#include <sysdev/bestcomm/bestcomm.h> +#include <sysdev/bestcomm/fec.h> + +#include "fec_mpc52xx.h" + +#define DRIVER_NAME "mpc52xx-fec" + +static irqreturn_t mpc52xx_fec_interrupt(int, void *); +static irqreturn_t mpc52xx_fec_rx_interrupt(int, void *); +static irqreturn_t mpc52xx_fec_tx_interrupt(int, void *); +static void mpc52xx_fec_stop(struct net_device *dev); +static void mpc52xx_fec_start(struct net_device *dev); +static void mpc52xx_fec_reset(struct net_device *dev); + +static u8 mpc52xx_fec_mac_addr[6]; +module_param_array_named(mac, mpc52xx_fec_mac_addr, byte, NULL, 0); +MODULE_PARM_DESC(mac, "six hex digits, ie. 0x1,0x2,0xc0,0x01,0xba,0xbe"); + +#define MPC52xx_MESSAGES_DEFAULT ( NETIF_MSG_DRV | NETIF_MSG_PROBE | \ + NETIF_MSG_LINK | NETIF_MSG_IFDOWN | NETIF_MSG_IFDOWN ) +static int debug = -1; /* the above default */ +module_param(debug, int, 0); +MODULE_PARM_DESC(debug, "debugging messages level"); + +static void mpc52xx_fec_tx_timeout(struct net_device *dev) +{ + dev_warn(&dev->dev, "transmit timed out\n"); + + mpc52xx_fec_reset(dev); + + dev->stats.tx_errors++; + + netif_wake_queue(dev); +} + +static void mpc52xx_fec_set_paddr(struct net_device *dev, u8 *mac) +{ + struct mpc52xx_fec_priv *priv = netdev_priv(dev); + struct mpc52xx_fec __iomem *fec = priv->fec; + + out_be32(&fec->paddr1, *(u32 *)(&mac[0])); + out_be32(&fec->paddr2, (*(u16 *)(&mac[4]) << 16) | FEC_PADDR2_TYPE); +} + +static void mpc52xx_fec_get_paddr(struct net_device *dev, u8 *mac) +{ + struct mpc52xx_fec_priv *priv = netdev_priv(dev); + struct mpc52xx_fec __iomem *fec = priv->fec; + + *(u32 *)(&mac[0]) = in_be32(&fec->paddr1); + *(u16 *)(&mac[4]) = in_be32(&fec->paddr2) >> 16; +} + +static int mpc52xx_fec_set_mac_address(struct net_device *dev, void *addr) +{ + struct sockaddr *sock = addr; + + memcpy(dev->dev_addr, sock->sa_data, dev->addr_len); + + mpc52xx_fec_set_paddr(dev, sock->sa_data); + return 0; +} + +static void mpc52xx_fec_free_rx_buffers(struct net_device *dev, struct bcom_task *s) +{ + while (!bcom_queue_empty(s)) { + struct bcom_fec_bd *bd; + struct sk_buff *skb; + + skb = bcom_retrieve_buffer(s, NULL, (struct bcom_bd **)&bd); + dma_unmap_single(&dev->dev, bd->skb_pa, skb->len, DMA_FROM_DEVICE); + kfree_skb(skb); + } +} + +static int mpc52xx_fec_alloc_rx_buffers(struct net_device *dev, struct bcom_task *rxtsk) +{ + while (!bcom_queue_full(rxtsk)) { + struct sk_buff *skb; + struct bcom_fec_bd *bd; + + skb = dev_alloc_skb(FEC_RX_BUFFER_SIZE); + if (skb == NULL) + return -EAGAIN; + + /* zero out the initial receive buffers to aid debugging */ + memset(skb->data, 0, FEC_RX_BUFFER_SIZE); + + bd = (struct bcom_fec_bd *)bcom_prepare_next_buffer(rxtsk); + + bd->status = FEC_RX_BUFFER_SIZE; + bd->skb_pa = dma_map_single(&dev->dev, skb->data, + FEC_RX_BUFFER_SIZE, DMA_FROM_DEVICE); + + bcom_submit_next_buffer(rxtsk, skb); + } + + return 0; +} + +/* based on generic_adjust_link from fs_enet-main.c */ +static void mpc52xx_fec_adjust_link(struct net_device *dev) +{ + struct mpc52xx_fec_priv *priv = netdev_priv(dev); + struct phy_device *phydev = priv->phydev; + int new_state = 0; + + if (phydev->link != PHY_DOWN) { + if (phydev->duplex != priv->duplex) { + struct mpc52xx_fec __iomem *fec = priv->fec; + u32 rcntrl; + u32 tcntrl; + + new_state = 1; + priv->duplex = phydev->duplex; + + rcntrl = in_be32(&fec->r_cntrl); + tcntrl = in_be32(&fec->x_cntrl); + + rcntrl &= ~FEC_RCNTRL_DRT; + tcntrl &= ~FEC_TCNTRL_FDEN; + if (phydev->duplex == DUPLEX_FULL) + tcntrl |= FEC_TCNTRL_FDEN; /* FD enable */ + else + rcntrl |= FEC_RCNTRL_DRT; /* disable Rx on Tx (HD) */ + + out_be32(&fec->r_cntrl, rcntrl); + out_be32(&fec->x_cntrl, tcntrl); + } + + if (phydev->speed != priv->speed) { + new_state = 1; + priv->speed = phydev->speed; + } + + if (priv->link == PHY_DOWN) { + new_state = 1; + priv->link = phydev->link; + netif_schedule(dev); + netif_carrier_on(dev); + netif_start_queue(dev); + } + + } else if (priv->link) { + new_state = 1; + priv->link = PHY_DOWN; + priv->speed = 0; + priv->duplex = -1; + netif_stop_queue(dev); + netif_carrier_off(dev); + } + + if (new_state && netif_msg_link(priv)) + phy_print_status(phydev); +} + +static int mpc52xx_fec_init_phy(struct net_device *dev) +{ + struct mpc52xx_fec_priv *priv = netdev_priv(dev); + struct phy_device *phydev; + char phy_id[BUS_ID_SIZE]; + + snprintf(phy_id, BUS_ID_SIZE, PHY_ID_FMT, + (unsigned int)dev->base_addr, priv->phy_addr); + + priv->link = PHY_DOWN; + priv->speed = 0; + priv->duplex = -1; + + phydev = phy_connect(dev, phy_id, &mpc52xx_fec_adjust_link, 0, PHY_INTERFACE_MODE_MII); + if (IS_ERR(phydev)) { + dev_err(&dev->dev, "phy_connect failed\n"); + return PTR_ERR(phydev); + } + dev_info(&dev->dev, "attached phy %i to driver %s\n", + phydev->addr, phydev->drv->name); + + priv->phydev = phydev; + + return 0; +} + +static int mpc52xx_fec_phy_start(struct net_device *dev) +{ + struct mpc52xx_fec_priv *priv = netdev_priv(dev); + int err; + + if (!priv->has_phy) + return 0; + + err = mpc52xx_fec_init_phy(dev); + if (err) { + dev_err(&dev->dev, "mpc52xx_fec_init_phy failed\n"); + return err; + } + + /* reset phy - this also wakes it from PDOWN */ + phy_write(priv->phydev, MII_BMCR, BMCR_RESET); + phy_start(priv->phydev); + + return 0; +} + +static void mpc52xx_fec_phy_stop(struct net_device *dev) +{ + struct mpc52xx_fec_priv *priv = netdev_priv(dev); + + if (!priv->has_phy) + return; + + phy_disconnect(priv->phydev); + /* power down phy */ + phy_stop(priv->phydev); + phy_write(priv->phydev, MII_BMCR, BMCR_PDOWN); +} + +static int mpc52xx_fec_phy_mii_ioctl(struct mpc52xx_fec_priv *priv, + struct mii_ioctl_data *mii_data, int cmd) +{ + if (!priv->has_phy) + return -ENOTSUPP; + + return phy_mii_ioctl(priv->phydev, mii_data, cmd); +} + +static void mpc52xx_fec_phy_hw_init(struct mpc52xx_fec_priv *priv) +{ + struct mpc52xx_fec __iomem *fec = priv->fec; + + if (!priv->has_phy) + return; + + out_be32(&fec->mii_speed, priv->phy_speed); +} + +static int mpc52xx_fec_open(struct net_device *dev) +{ + struct mpc52xx_fec_priv *priv = netdev_priv(dev); + int err = -EBUSY; + + if (request_irq(dev->irq, &mpc52xx_fec_interrupt, IRQF_SHARED, + DRIVER_NAME "_ctrl", dev)) { + dev_err(&dev->dev, "ctrl interrupt request failed\n"); + goto out; + } + if (request_irq(priv->r_irq, &mpc52xx_fec_rx_interrupt, 0, + DRIVER_NAME "_rx", dev)) { + dev_err(&dev->dev, "rx interrupt request failed\n"); + goto free_ctrl_irq; + } + if (request_irq(priv->t_irq, &mpc52xx_fec_tx_interrupt, 0, + DRIVER_NAME "_tx", dev)) { + dev_err(&dev->dev, "tx interrupt request failed\n"); + goto free_2irqs; + } + + bcom_fec_rx_reset(priv->rx_dmatsk); + bcom_fec_tx_reset(priv->tx_dmatsk); + + err = mpc52xx_fec_alloc_rx_buffers(dev, priv->rx_dmatsk); + if (err) { + dev_err(&dev->dev, "mpc52xx_fec_alloc_rx_buffers failed\n"); + goto free_irqs; + } + + err = mpc52xx_fec_phy_start(dev); + if (err) + goto free_skbs; + + bcom_enable(priv->rx_dmatsk); + bcom_enable(priv->tx_dmatsk); + + mpc52xx_fec_start(dev); + + netif_start_queue(dev); + + return 0; + + free_skbs: + mpc52xx_fec_free_rx_buffers(dev, priv->rx_dmatsk); + + free_irqs: + free_irq(priv->t_irq, dev); + free_2irqs: + free_irq(priv->r_irq, dev); + free_ctrl_irq: + free_irq(dev->irq, dev); + out: + + return err; +} + +static int mpc52xx_fec_close(struct net_device *dev) +{ + struct mpc52xx_fec_priv *priv = netdev_priv(dev); + + netif_stop_queue(dev); + + mpc52xx_fec_stop(dev); + + mpc52xx_fec_free_rx_buffers(dev, priv->rx_dmatsk); + + free_irq(dev->irq, dev); + free_irq(priv->r_irq, dev); + free_irq(priv->t_irq, dev); + + mpc52xx_fec_phy_stop(dev); + + return 0; +} + +/* This will only be invoked if your driver is _not_ in XOFF state. + * What this means is that you need not check it, and that this + * invariant will hold if you make sure that the netif_*_queue() + * calls are done at the proper times. + */ +static int mpc52xx_fec_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) +{ + struct mpc52xx_fec_priv *priv = netdev_priv(dev); + struct bcom_fec_bd *bd; + + if (bcom_queue_full(priv->tx_dmatsk)) { + if (net_ratelimit()) + dev_err(&dev->dev, "transmit queue overrun\n"); + return 1; + } + + spin_lock_irq(&priv->lock); + dev->trans_start = jiffies; + + bd = (struct bcom_fec_bd *) + bcom_prepare_next_buffer(priv->tx_dmatsk); + + bd->status = skb->len | BCOM_FEC_TX_BD_TFD | BCOM_FEC_TX_BD_TC; + bd->skb_pa = dma_map_single(&dev->dev, skb->data, skb->len, DMA_TO_DEVICE); + + bcom_submit_next_buffer(priv->tx_dmatsk, skb); + + if (bcom_queue_full(priv->tx_dmatsk)) { + netif_stop_queue(dev); + } + + spin_unlock_irq(&priv->lock); + + return 0; +} + +/* This handles BestComm transmit task interrupts + */ +static irqreturn_t mpc52xx_fec_tx_interrupt(int irq, void *dev_id) +{ + struct net_device *dev = dev_id; + struct mpc52xx_fec_priv *priv = netdev_priv(dev); + + spin_lock(&priv->lock); + + while (bcom_buffer_done(priv->tx_dmatsk)) { + struct sk_buff *skb; + struct bcom_fec_bd *bd; + skb = bcom_retrieve_buffer(priv->tx_dmatsk, NULL, + (struct bcom_bd **)&bd); + dma_unmap_single(&dev->dev, bd->skb_pa, skb->len, DMA_TO_DEVICE); + + dev_kfree_skb_irq(skb); + } + + netif_wake_queue(dev); + + spin_unlock(&priv->lock); + + return IRQ_HANDLED; +} + +static irqreturn_t mpc52xx_fec_rx_interrupt(int irq, void *dev_id) +{ + struct net_device *dev = dev_id; + struct mpc52xx_fec_priv *priv = netdev_priv(dev); + + while (bcom_buffer_done(priv->rx_dmatsk)) { + struct sk_buff *skb; + struct sk_buff *rskb; + struct bcom_fec_bd *bd; + u32 status; + + rskb = bcom_retrieve_buffer(priv->rx_dmatsk, &status, + (struct bcom_bd **)&bd); + dma_unmap_single(&dev->dev, bd->skb_pa, skb->len, DMA_FROM_DEVICE); + + /* Test for errors in received frame */ + if (status & BCOM_FEC_RX_BD_ERRORS) { + /* Drop packet and reuse the buffer */ + bd = (struct bcom_fec_bd *) + bcom_prepare_next_buffer(priv->rx_dmatsk); + + bd->status = FEC_RX_BUFFER_SIZE; + bd->skb_pa = dma_map_single(&dev->dev, rskb->data, + FEC_RX_BUFFER_SIZE, DMA_FROM_DEVICE); + + bcom_submit_next_buffer(priv->rx_dmatsk, rskb); + + dev->stats.rx_dropped++; + + continue; + } + + /* skbs are allocated on open, so now we allocate a new one, + * and remove the old (with the packet) */ + skb = dev_alloc_skb(FEC_RX_BUFFER_SIZE); + if (skb) { + /* Process the received skb */ + int length = status & BCOM_FEC_RX_BD_LEN_MASK; + + skb_put(rskb, length - 4); /* length without CRC32 */ + + rskb->dev = dev; + rskb->protocol = eth_type_trans(rskb, dev); + + netif_rx(rskb); + dev->last_rx = jiffies; + } else { + /* Can't get a new one : reuse the same & drop pkt */ + dev_notice(&dev->dev, "Memory squeeze, dropping packet.\n"); + dev->stats.rx_dropped++; + + skb = rskb; + } + + bd = (struct bcom_fec_bd *) + bcom_prepare_next_buffer(priv->rx_dmatsk); + + bd->status = FEC_RX_BUFFER_SIZE; + bd->skb_pa = dma_map_single(&dev->dev, rskb->data, + FEC_RX_BUFFER_SIZE, DMA_FROM_DEVICE); + + bcom_submit_next_buffer(priv->rx_dmatsk, skb); + } + + return IRQ_HANDLED; +} + +static irqreturn_t mpc52xx_fec_interrupt(int irq, void *dev_id) +{ + struct net_device *dev = dev_id; + struct mpc52xx_fec_priv *priv = netdev_priv(dev); + struct mpc52xx_fec __iomem *fec = priv->fec; + u32 ievent; + + ievent = in_be32(&fec->ievent); + + ievent &= ~FEC_IEVENT_MII; /* mii is handled separately */ + if (!ievent) + return IRQ_NONE; + + out_be32(&fec->ievent, ievent); /* clear pending events */ + + if (ievent & ~(FEC_IEVENT_RFIFO_ERROR | FEC_IEVENT_XFIFO_ERROR)) { + if (ievent & ~FEC_IEVENT_TFINT) + dev_dbg(&dev->dev, "ievent: %08x\n", ievent); + return IRQ_HANDLED; + } + + if (net_ratelimit() && (ievent & FEC_IEVENT_RFIFO_ERROR)) + dev_warn(&dev->dev, "FEC_IEVENT_RFIFO_ERROR\n"); + if (net_ratelimit() && (ievent & FEC_IEVENT_XFIFO_ERROR)) + dev_warn(&dev->dev, "FEC_IEVENT_XFIFO_ERROR\n"); + + mpc52xx_fec_reset(dev); + + netif_wake_queue(dev); + return IRQ_HANDLED; +} + +/* + * Get the current statistics. + * This may be called with the card open or closed. + */ +static struct net_device_stats *mpc52xx_fec_get_stats(struct net_device *dev) +{ + struct mpc52xx_fec_priv *priv = netdev_priv(dev); + struct net_device_stats *stats = &dev->stats; + struct mpc52xx_fec __iomem *fec = priv->fec; + + stats->rx_bytes = in_be32(&fec->rmon_r_octets); + stats->rx_packets = in_be32(&fec->rmon_r_packets); + stats->rx_errors = in_be32(&fec->rmon_r_crc_align) + + in_be32(&fec->rmon_r_undersize) + + in_be32(&fec->rmon_r_oversize) + + in_be32(&fec->rmon_r_frag) + + in_be32(&fec->rmon_r_jab); + + stats->tx_bytes = in_be32(&fec->rmon_t_octets); + stats->tx_packets = in_be32(&fec->rmon_t_packets); + stats->tx_errors = in_be32(&fec->rmon_t_crc_align) + + in_be32(&fec->rmon_t_undersize) + + in_be32(&fec->rmon_t_oversize) + + in_be32(&fec->rmon_t_frag) + + in_be32(&fec->rmon_t_jab); + + stats->multicast = in_be32(&fec->rmon_r_mc_pkt); + stats->collisions = in_be32(&fec->rmon_t_col); + + /* detailed rx_errors: */ + stats->rx_length_errors = in_be32(&fec->rmon_r_undersize) + + in_be32(&fec->rmon_r_oversize) + + in_be32(&fec->rmon_r_frag) + + in_be32(&fec->rmon_r_jab); + stats->rx_over_errors = in_be32(&fec->r_macerr); + stats->rx_crc_errors = in_be32(&fec->ieee_r_crc); + stats->rx_frame_errors = in_be32(&fec->ieee_r_align); + stats->rx_fifo_errors = in_be32(&fec->rmon_r_drop); + stats->rx_missed_errors = in_be32(&fec->rmon_r_drop); + + /* detailed tx_errors: */ + stats->tx_aborted_errors = 0; + stats->tx_carrier_errors = in_be32(&fec->ieee_t_cserr); + stats->tx_fifo_errors = in_be32(&fec->rmon_t_drop); + stats->tx_heartbeat_errors = in_be32(&fec->ieee_t_sqe); + stats->tx_window_errors = in_be32(&fec->ieee_t_lcol); + + return stats; +} + +/* + * Read MIB counters in order to reset them, + * then zero all the stats fields in memory + */ +static void mpc52xx_fec_reset_stats(struct net_device *dev) +{ + struct mpc52xx_fec_priv *priv = netdev_priv(dev); + struct mpc52xx_fec __iomem *fec = priv->fec; + + out_be32(&fec->mib_control, FEC_MIB_DISABLE); + memset_io(&fec->rmon_t_drop, 0, (__force u32)&fec->reserved10 - + (__force u32)&fec->rmon_t_drop); + out_be32(&fec->mib_control, 0); + + memset(&dev->stats, 0, sizeof(dev->stats)); +} + +/* + * Set or clear the multicast filter for this adaptor. + */ +static void mpc52xx_fec_set_multicast_list(struct net_device *dev) +{ + struct mpc52xx_fec_priv *priv = netdev_priv(dev); + struct mpc52xx_fec __iomem *fec = priv->fec; + u32 rx_control; + + rx_control = in_be32(&fec->r_cntrl); + + if (dev->flags & IFF_PROMISC) { + rx_control |= FEC_RCNTRL_PROM; + out_be32(&fec->r_cntrl, rx_control); + } else { + rx_control &= ~FEC_RCNTRL_PROM; + out_be32(&fec->r_cntrl, rx_control); + + if (dev->flags & IFF_ALLMULTI) { + out_be32(&fec->gaddr1, 0xffffffff); + out_be32(&fec->gaddr2, 0xffffffff); + } else { + u32 crc; + int i; + struct dev_mc_list *dmi; + u32 gaddr1 = 0x00000000; + u32 gaddr2 = 0x00000000; + + dmi = dev->mc_list; + for (i=0; i<dev->mc_count; i++) { + crc = ether_crc_le(6, dmi->dmi_addr) >> 26; + if (crc >= 32) + gaddr1 |= 1 << (crc-32); + else + gaddr2 |= 1 << crc; + dmi = dmi->next; + } + out_be32(&fec->gaddr1, gaddr1); + out_be32(&fec->gaddr2, gaddr2); + } + } +} + +/** + * mpc52xx_fec_hw_init + * @dev: network device + * + * Setup various hardware setting, only needed once on start + */ +static void mpc52xx_fec_hw_init(struct net_device *dev) +{ + struct mpc52xx_fec_priv *priv = netdev_priv(dev); + struct mpc52xx_fec __iomem *fec = priv->fec; + int i; + + /* Whack a reset. We should wait for this. */ + out_be32(&fec->ecntrl, FEC_ECNTRL_RESET); + for (i = 0; i < FEC_RESET_DELAY; ++i) { + if ((in_be32(&fec->ecntrl) & FEC_ECNTRL_RESET) == 0) + break; + udelay(1); + } + if (i == FEC_RESET_DELAY) + dev_err(&dev->dev, "FEC Reset timeout!\n"); + + /* set pause to 0x20 frames */ + out_be32(&fec->op_pause, FEC_OP_PAUSE_OPCODE | 0x20); + + /* high service request will be deasserted when there's < 7 bytes in fifo + * low service request will be deasserted when there's < 4*7 bytes in fifo + */ + out_be32(&fec->rfifo_cntrl, FEC_FIFO_CNTRL_FRAME | FEC_FIFO_CNTRL_LTG_7); + out_be32(&fec->tfifo_cntrl, FEC_FIFO_CNTRL_FRAME | FEC_FIFO_CNTRL_LTG_7); + + /* alarm when <= x bytes in FIFO */ + out_be32(&fec->rfifo_alarm, 0x0000030c); + out_be32(&fec->tfifo_alarm, 0x00000100); + + /* begin transmittion when 256 bytes are in FIFO (or EOF or FIFO full) */ + out_be32(&fec->x_wmrk, FEC_FIFO_WMRK_256B); + + /* enable crc generation */ + out_be32(&fec->xmit_fsm, FEC_XMIT_FSM_APPEND_CRC | FEC_XMIT_FSM_ENABLE_CRC); + out_be32(&fec->iaddr1, 0x00000000); /* No individual filter */ + out_be32(&fec->iaddr2, 0x00000000); /* No individual filter */ + + /* set phy speed. + * this can't be done in phy driver, since it needs to be called + * before fec stuff (even on resume) */ + mpc52xx_fec_phy_hw_init(priv); +} + +/** + * mpc52xx_fec_start + * @dev: network device + * + * This function is called to start or restart the FEC during a link + * change. This happens on fifo errors or when switching between half + * and full duplex. + */ +static void mpc52xx_fec_start(struct net_device *dev) +{ + struct mpc52xx_fec_priv *priv = netdev_priv(dev); + struct mpc52xx_fec __iomem *fec = priv->fec; + u32 rcntrl; + u32 tcntrl; + u32 tmp; + + /* clear sticky error bits */ + tmp = FEC_FIFO_STATUS_ERR | FEC_FIFO_STATUS_UF | FEC_FIFO_STATUS_OF; + out_be32(&fec->rfifo_status, in_be32(&fec->rfifo_status) & tmp); + out_be32(&fec->tfifo_status, in_be32(&fec->tfifo_status) & tmp); + + /* FIFOs will reset on mpc52xx_fec_enable */ + out_be32(&fec->reset_cntrl, FEC_RESET_CNTRL_ENABLE_IS_RESET); + + /* Set station address. */ + mpc52xx_fec_set_paddr(dev, dev->dev_addr); + + mpc52xx_fec_set_multicast_list(dev); + + /* set max frame len, enable flow control, select mii mode */ + rcntrl = FEC_RX_BUFFER_SIZE << 16; /* max frame length */ + rcntrl |= FEC_RCNTRL_FCE; + + if (priv->has_phy) + rcntrl |= FEC_RCNTRL_MII_MODE; + + if (priv->duplex == DUPLEX_FULL) + tcntrl = FEC_TCNTRL_FDEN; /* FD enable */ + else { + rcntrl |= FEC_RCNTRL_DRT; /* disable Rx on Tx (HD) */ + tcntrl = 0; + } + out_be32(&fec->r_cntrl, rcntrl); + out_be32(&fec->x_cntrl, tcntrl); + + /* Clear any outstanding interrupt. */ + out_be32(&fec->ievent, 0xffffffff); + + /* Enable interrupts we wish to service. */ + out_be32(&fec->imask, FEC_IMASK_ENABLE); + + /* And last, enable the transmit and receive processing. */ + out_be32(&fec->ecntrl, FEC_ECNTRL_ETHER_EN); + out_be32(&fec->r_des_active, 0x01000000); +} + +/** + * mpc52xx_fec_stop + * @dev: network device + * + * stop all activity on fec and empty dma buffers + */ +static void mpc52xx_fec_stop(struct net_device *dev) +{ + struct mpc52xx_fec_priv *priv = netdev_priv(dev); + struct mpc52xx_fec __iomem *fec = priv->fec; + unsigned long timeout; + + /* disable all interrupts */ + out_be32(&fec->imask, 0); + + /* Disable the rx task. */ + bcom_disable(priv->rx_dmatsk); + + /* Wait for tx queue to drain, but only if we're in process context */ + if (!in_interrupt()) { + timeout = jiffies + msecs_to_jiffies(2000); + while (time_before(jiffies, timeout) && + !bcom_queue_empty(priv->tx_dmatsk)) + msleep(100); + + if (time_after_eq(jiffies, timeout)) + dev_err(&dev->dev, "queues didn't drain\n"); +#if 1 + if (time_after_eq(jiffies, timeout)) { + dev_err(&dev->dev, " tx: index: %i, outdex: %i\n", + priv->tx_dmatsk->index, + priv->tx_dmatsk->outdex); + dev_err(&dev->dev, " rx: index: %i, outdex: %i\n", + priv->rx_dmatsk->index, + priv->rx_dmatsk->outdex); + } +#endif + } + + bcom_disable(priv->tx_dmatsk); + + /* Stop FEC */ + out_be32(&fec->ecntrl, in_be32(&fec->ecntrl) & ~FEC_ECNTRL_ETHER_EN); + + return; +} + +/* reset fec and bestcomm tasks */ +static void mpc52xx_fec_reset(struct net_device *dev) +{ + struct mpc52xx_fec_priv *priv = netdev_priv(dev); + struct mpc52xx_fec __iomem *fec = priv->fec; + + mpc52xx_fec_stop(dev); + + out_be32(&fec->rfifo_status, in_be32(&fec->rfifo_status)); + out_be32(&fec->reset_cntrl, FEC_RESET_CNTRL_RESET_FIFO); + + mpc52xx_fec_free_rx_buffers(dev, priv->rx_dmatsk); + + mpc52xx_fec_hw_init(dev); + + phy_stop(priv->phydev); + phy_write(priv->phydev, MII_BMCR, BMCR_RESET); + phy_start(priv->phydev); + + bcom_fec_rx_reset(priv->rx_dmatsk); + bcom_fec_tx_reset(priv->tx_dmatsk); + + mpc52xx_fec_alloc_rx_buffers(dev, priv->rx_dmatsk); + + bcom_enable(priv->rx_dmatsk); + bcom_enable(priv->tx_dmatsk); + + mpc52xx_fec_start(dev); +} + + +/* ethtool interface */ +static void mpc52xx_fec_get_drvinfo(struct net_device *dev, + struct ethtool_drvinfo *info) +{ + strcpy(info->driver, DRIVER_NAME); +} + +static int mpc52xx_fec_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) +{ + struct mpc52xx_fec_priv *priv = netdev_priv(dev); + return phy_ethtool_gset(priv->phydev, cmd); +} + +static int mpc52xx_fec_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) +{ + struct mpc52xx_fec_priv *priv = netdev_priv(dev); + return phy_ethtool_sset(priv->phydev, cmd); +} + +static u32 mpc52xx_fec_get_msglevel(struct net_device *dev) +{ + struct mpc52xx_fec_priv *priv = netdev_priv(dev); + return priv->msg_enable; +} + +static void mpc52xx_fec_set_msglevel(struct net_device *dev, u32 level) +{ + struct mpc52xx_fec_priv *priv = netdev_priv(dev); + priv->msg_enable = level; +} + +static const struct ethtool_ops mpc52xx_fec_ethtool_ops = { + .get_drvinfo = mpc52xx_fec_get_drvinfo, + .get_settings = mpc52xx_fec_get_settings, + .set_settings = mpc52xx_fec_set_settings, + .get_link = ethtool_op_get_link, + .get_msglevel = mpc52xx_fec_get_msglevel, + .set_msglevel = mpc52xx_fec_set_msglevel, +}; + + +static int mpc52xx_fec_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) +{ + struct mpc52xx_fec_priv *priv = netdev_priv(dev); + + return mpc52xx_fec_phy_mii_ioctl(priv, if_mii(rq), cmd); +} + +/* ======================================================================== */ +/* OF Driver */ +/* ======================================================================== */ + +static int __devinit +mpc52xx_fec_probe(struct of_device *op, const struct of_device_id *match) +{ + int rv; + struct net_device *ndev; + struct mpc52xx_fec_priv *priv = NULL; + struct resource mem; + const phandle *ph; + + phys_addr_t rx_fifo; + phys_addr_t tx_fifo; + + /* Get the ether ndev & it's private zone */ + ndev = alloc_etherdev(sizeof(struct mpc52xx_fec_priv)); + if (!ndev) + return -ENOMEM; + + priv = netdev_priv(ndev); + + /* Reserve FEC control zone */ + rv = of_address_to_resource(op->node, 0, &mem); + if (rv) { + printk(KERN_ERR DRIVER_NAME ": " + "Error while parsing device node resource\n" ); + return rv; + } + if ((mem.end - mem.start + 1) != sizeof(struct mpc52xx_fec)) { + printk(KERN_ERR DRIVER_NAME + " - invalid resource size (%lx != %x), check mpc52xx_devices.c\n", + (unsigned long)(mem.end - mem.start + 1), sizeof(struct mpc52xx_fec)); + return -EINVAL; + } + + if (!request_mem_region(mem.start, sizeof(struct mpc52xx_fec), DRIVER_NAME)) + return -EBUSY; + + /* Init ether ndev with what we have */ + ndev->open = mpc52xx_fec_open; + ndev->stop = mpc52xx_fec_close; + ndev->hard_start_xmit = mpc52xx_fec_hard_start_xmit; + ndev->do_ioctl = mpc52xx_fec_ioctl; + ndev->ethtool_ops = &mpc52xx_fec_ethtool_ops; + ndev->get_stats = mpc52xx_fec_get_stats; + ndev->set_mac_address = mpc52xx_fec_set_mac_address; + ndev->set_multicast_list = mpc52xx_fec_set_multicast_list; + ndev->tx_timeout = mpc52xx_fec_tx_timeout; + ndev->watchdog_timeo = FEC_WATCHDOG_TIMEOUT; + ndev->base_addr = mem.start; + + priv->t_irq = priv->r_irq = ndev->irq = NO_IRQ; /* IRQ are free for now */ + + spin_lock_init(&priv->lock); + + /* ioremap the zones */ + priv->fec = ioremap(mem.start, sizeof(struct mpc52xx_fec)); + + if (!priv->fec) { + rv = -ENOMEM; + goto probe_error; + } + + /* Bestcomm init */ + rx_fifo = ndev->base_addr + offsetof(struct mpc52xx_fec, rfifo_data); + tx_fifo = ndev->base_addr + offsetof(struct mpc52xx_fec, tfifo_data); + + priv->rx_dmatsk = bcom_fec_rx_init(FEC_RX_NUM_BD, rx_fifo, FEC_RX_BUFFER_SIZE); + priv->tx_dmatsk = bcom_fec_tx_init(FEC_TX_NUM_BD, tx_fifo); + + if (!priv->rx_dmatsk || !priv->tx_dmatsk) { + printk(KERN_ERR DRIVER_NAME ": Can not init SDMA tasks\n" ); + rv = -ENOMEM; + goto probe_error; + } + + /* Get the IRQ we need one by one */ + /* Control */ + ndev->irq = irq_of_parse_and_map(op->node, 0); + + /* RX */ + priv->r_irq = bcom_get_task_irq(priv->rx_dmatsk); + + /* TX */ + priv->t_irq = bcom_get_task_irq(priv->tx_dmatsk); + + /* MAC address init */ + if (!is_zero_ether_addr(mpc52xx_fec_mac_addr)) + memcpy(ndev->dev_addr, mpc52xx_fec_mac_addr, 6); + else + mpc52xx_fec_get_paddr(ndev, ndev->dev_addr); + + priv->msg_enable = netif_msg_init(debug, MPC52xx_MESSAGES_DEFAULT); + priv->duplex = DUPLEX_FULL; + + /* is the phy present in device tree? */ + ph = of_get_property(op->node, "phy-handle", NULL); + if (ph) { + const unsigned int *prop; + struct device_node *phy_dn; + priv->has_phy = 1; + + phy_dn = of_find_node_by_phandle(*ph); + prop = of_get_property(phy_dn, "reg", NULL); + priv->phy_addr = *prop; + + of_node_put(phy_dn); + + /* Phy speed */ + priv->phy_speed = ((mpc52xx_find_ipb_freq(op->node) >> 20) / 5) << 1; + } else { + dev_info(&ndev->dev, "can't find \"phy-handle\" in device" + " tree, using 7-wire mode\n"); + } + + /* Hardware init */ + mpc52xx_fec_hw_init(ndev); + + mpc52xx_fec_reset_stats(ndev); + + /* Register the new network device */ + rv = register_netdev(ndev); + if (rv < 0) + goto probe_error; + + /* We're done ! */ + dev_set_drvdata(&op->dev, ndev); + + return 0; + + + /* Error handling - free everything that might be allocated */ +probe_error: + + irq_dispose_mapping(ndev->irq); + + if (priv->rx_dmatsk) + bcom_fec_rx_release(priv->rx_dmatsk); + if (priv->tx_dmatsk) + bcom_fec_tx_release(priv->tx_dmatsk); + + if (priv->fec) + iounmap(priv->fec); + + release_mem_region(mem.start, sizeof(struct mpc52xx_fec)); + + free_netdev(ndev); + + return rv; +} + +static int +mpc52xx_fec_remove(struct of_device *op) +{ + struct net_device *ndev; + struct mpc52xx_fec_priv *priv; + + ndev = dev_get_drvdata(&op->dev); + priv = netdev_priv(ndev); + + unregister_netdev(ndev); + + irq_dispose_mapping(ndev->irq); + + bcom_fec_rx_release(priv->rx_dmatsk); + bcom_fec_tx_release(priv->tx_dmatsk); + + iounmap(priv->fec); + + release_mem_region(ndev->base_addr, sizeof(struct mpc52xx_fec)); + + free_netdev(ndev); + + dev_set_drvdata(&op->dev, NULL); + return 0; +} + +#ifdef CONFIG_PM +static int mpc52xx_fec_of_suspend(struct of_device *op, pm_message_t state) +{ + struct net_device *dev = dev_get_drvdata(&op->dev); + + if (netif_running(dev)) + mpc52xx_fec_close(dev); + + return 0; +} + +static int mpc52xx_fec_of_resume(struct of_device *op) +{ + struct net_device *dev = dev_get_drvdata(&op->dev); + + mpc52xx_fec_hw_init(dev); + mpc52xx_fec_reset_stats(dev); + + if (netif_running(dev)) + mpc52xx_fec_open(dev); + + return 0; +} +#endif + +static struct of_device_id mpc52xx_fec_match[] = { + { + .type = "network", + .compatible = "mpc5200-fec", + }, + { } +}; + +MODULE_DEVICE_TABLE(of, mpc52xx_fec_match); + +static struct of_platform_driver mpc52xx_fec_driver = { + .owner = THIS_MODULE, + .name = DRIVER_NAME, + .match_table = mpc52xx_fec_match, + .probe = mpc52xx_fec_probe, + .remove = mpc52xx_fec_remove, +#ifdef CONFIG_PM + .suspend = mpc52xx_fec_of_suspend, + .resume = mpc52xx_fec_of_resume, +#endif +}; + + +/* ======================================================================== */ +/* Module */ +/* ======================================================================== */ + +static int __init +mpc52xx_fec_init(void) +{ +#ifdef CONFIG_FEC_MPC52xx_MDIO + int ret; + ret = of_register_platform_driver(&mpc52xx_fec_mdio_driver); + if (ret) { + printk(KERN_ERR DRIVER_NAME ": failed to register mdio driver\n"); + return ret; + } +#endif + return of_register_platform_driver(&mpc52xx_fec_driver); +} + +static void __exit +mpc52xx_fec_exit(void) +{ + of_unregister_platform_driver(&mpc52xx_fec_driver); +#ifdef CONFIG_FEC_MPC52xx_MDIO + of_unregister_platform_driver(&mpc52xx_fec_mdio_driver); +#endif +} + + +module_init(mpc52xx_fec_init); +module_exit(mpc52xx_fec_exit); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Dale Farnsworth"); +MODULE_DESCRIPTION("Ethernet driver for the Freescale MPC52xx FEC"); diff --git a/drivers/net/fec_mpc52xx.h b/drivers/net/fec_mpc52xx.h new file mode 100644 index 00000000000..8b1f75397b9 --- /dev/null +++ b/drivers/net/fec_mpc52xx.h @@ -0,0 +1,313 @@ +/* + * drivers/drivers/net/fec_mpc52xx/fec.h + * + * Driver for the MPC5200 Fast Ethernet Controller + * + * Author: Dale Farnsworth <dfarnsworth@mvista.com> + * + * 2003-2004 (c) MontaVista, Software, Inc. This file is licensed under + * the terms of the GNU General Public License version 2. This program + * is licensed "as is" without any warranty of any kind, whether express + * or implied. + */ + +#ifndef __DRIVERS_NET_MPC52XX_FEC_H__ +#define __DRIVERS_NET_MPC52XX_FEC_H__ + +#include <linux/phy.h> + +/* Tunable constant */ +/* FEC_RX_BUFFER_SIZE includes 4 bytes for CRC32 */ +#define FEC_RX_BUFFER_SIZE 1522 /* max receive packet size */ +#define FEC_RX_NUM_BD 256 +#define FEC_TX_NUM_BD 64 + +#define FEC_RESET_DELAY 50 /* uS */ + +#define FEC_WATCHDOG_TIMEOUT ((400*HZ)/1000) + +struct mpc52xx_fec_priv { + int duplex; + int r_irq; + int t_irq; + struct mpc52xx_fec __iomem *fec; + struct bcom_task *rx_dmatsk; + struct bcom_task *tx_dmatsk; + spinlock_t lock; + int msg_enable; + + int has_phy; + unsigned int phy_speed; + unsigned int phy_addr; + struct phy_device *phydev; + enum phy_state link; + int speed; +}; + + +/* ======================================================================== */ +/* Hardware register sets & bits */ +/* ======================================================================== */ + +struct mpc52xx_fec { + u32 fec_id; /* FEC + 0x000 */ + u32 ievent; /* FEC + 0x004 */ + u32 imask; /* FEC + 0x008 */ + + u32 reserved0[1]; /* FEC + 0x00C */ + u32 r_des_active; /* FEC + 0x010 */ + u32 x_des_active; /* FEC + 0x014 */ + u32 r_des_active_cl; /* FEC + 0x018 */ + u32 x_des_active_cl; /* FEC + 0x01C */ + u32 ivent_set; /* FEC + 0x020 */ + u32 ecntrl; /* FEC + 0x024 */ + + u32 reserved1[6]; /* FEC + 0x028-03C */ + u32 mii_data; /* FEC + 0x040 */ + u32 mii_speed; /* FEC + 0x044 */ + u32 mii_status; /* FEC + 0x048 */ + + u32 reserved2[5]; /* FEC + 0x04C-05C */ + u32 mib_data; /* FEC + 0x060 */ + u32 mib_control; /* FEC + 0x064 */ + + u32 reserved3[6]; /* FEC + 0x068-7C */ + u32 r_activate; /* FEC + 0x080 */ + u32 r_cntrl; /* FEC + 0x084 */ + u32 r_hash; /* FEC + 0x088 */ + u32 r_data; /* FEC + 0x08C */ + u32 ar_done; /* FEC + 0x090 */ + u32 r_test; /* FEC + 0x094 */ + u32 r_mib; /* FEC + 0x098 */ + u32 r_da_low; /* FEC + 0x09C */ + u32 r_da_high; /* FEC + 0x0A0 */ + + u32 reserved4[7]; /* FEC + 0x0A4-0BC */ + u32 x_activate; /* FEC + 0x0C0 */ + u32 x_cntrl; /* FEC + 0x0C4 */ + u32 backoff; /* FEC + 0x0C8 */ + u32 x_data; /* FEC + 0x0CC */ + u32 x_status; /* FEC + 0x0D0 */ + u32 x_mib; /* FEC + 0x0D4 */ + u32 x_test; /* FEC + 0x0D8 */ + u32 fdxfc_da1; /* FEC + 0x0DC */ + u32 fdxfc_da2; /* FEC + 0x0E0 */ + u32 paddr1; /* FEC + 0x0E4 */ + u32 paddr2; /* FEC + 0x0E8 */ + u32 op_pause; /* FEC + 0x0EC */ + + u32 reserved5[4]; /* FEC + 0x0F0-0FC */ + u32 instr_reg; /* FEC + 0x100 */ + u32 context_reg; /* FEC + 0x104 */ + u32 test_cntrl; /* FEC + 0x108 */ + u32 acc_reg; /* FEC + 0x10C */ + u32 ones; /* FEC + 0x110 */ + u32 zeros; /* FEC + 0x114 */ + u32 iaddr1; /* FEC + 0x118 */ + u32 iaddr2; /* FEC + 0x11C */ + u32 gaddr1; /* FEC + 0x120 */ + u32 gaddr2; /* FEC + 0x124 */ + u32 random; /* FEC + 0x128 */ + u32 rand1; /* FEC + 0x12C */ + u32 tmp; /* FEC + 0x130 */ + + u32 reserved6[3]; /* FEC + 0x134-13C */ + u32 fifo_id; /* FEC + 0x140 */ + u32 x_wmrk; /* FEC + 0x144 */ + u32 fcntrl; /* FEC + 0x148 */ + u32 r_bound; /* FEC + 0x14C */ + u32 r_fstart; /* FEC + 0x150 */ + u32 r_count; /* FEC + 0x154 */ + u32 r_lag; /* FEC + 0x158 */ + u32 r_read; /* FEC + 0x15C */ + u32 r_write; /* FEC + 0x160 */ + u32 x_count; /* FEC + 0x164 */ + u32 x_lag; /* FEC + 0x168 */ + u32 x_retry; /* FEC + 0x16C */ + u32 x_write; /* FEC + 0x170 */ + u32 x_read; /* FEC + 0x174 */ + + u32 reserved7[2]; /* FEC + 0x178-17C */ + u32 fm_cntrl; /* FEC + 0x180 */ + u32 rfifo_data; /* FEC + 0x184 */ + u32 rfifo_status; /* FEC + 0x188 */ + u32 rfifo_cntrl; /* FEC + 0x18C */ + u32 rfifo_lrf_ptr; /* FEC + 0x190 */ + u32 rfifo_lwf_ptr; /* FEC + 0x194 */ + u32 rfifo_alarm; /* FEC + 0x198 */ + u32 rfifo_rdptr; /* FEC + 0x19C */ + u32 rfifo_wrptr; /* FEC + 0x1A0 */ + u32 tfifo_data; /* FEC + 0x1A4 */ + u32 tfifo_status; /* FEC + 0x1A8 */ + u32 tfifo_cntrl; /* FEC + 0x1AC */ + u32 tfifo_lrf_ptr; /* FEC + 0x1B0 */ + u32 tfifo_lwf_ptr; /* FEC + 0x1B4 */ + u32 tfifo_alarm; /* FEC + 0x1B8 */ + u32 tfifo_rdptr; /* FEC + 0x1BC */ + u32 tfifo_wrptr; /* FEC + 0x1C0 */ + + u32 reset_cntrl; /* FEC + 0x1C4 */ + u32 xmit_fsm; /* FEC + 0x1C8 */ + + u32 reserved8[3]; /* FEC + 0x1CC-1D4 */ + u32 rdes_data0; /* FEC + 0x1D8 */ + u32 rdes_data1; /* FEC + 0x1DC */ + u32 r_length; /* FEC + 0x1E0 */ + u32 x_length; /* FEC + 0x1E4 */ + u32 x_addr; /* FEC + 0x1E8 */ + u32 cdes_data; /* FEC + 0x1EC */ + u32 status; /* FEC + 0x1F0 */ + u32 dma_control; /* FEC + 0x1F4 */ + u32 des_cmnd; /* FEC + 0x1F8 */ + u32 data; /* FEC + 0x1FC */ + + u32 rmon_t_drop; /* FEC + 0x200 */ + u32 rmon_t_packets; /* FEC + 0x204 */ + u32 rmon_t_bc_pkt; /* FEC + 0x208 */ + u32 rmon_t_mc_pkt; /* FEC + 0x20C */ + u32 rmon_t_crc_align; /* FEC + 0x210 */ + u32 rmon_t_undersize; /* FEC + 0x214 */ + u32 rmon_t_oversize; /* FEC + 0x218 */ + u32 rmon_t_frag; /* FEC + 0x21C */ + u32 rmon_t_jab; /* FEC + 0x220 */ + u32 rmon_t_col; /* FEC + 0x224 */ + u32 rmon_t_p64; /* FEC + 0x228 */ + u32 rmon_t_p65to127; /* FEC + 0x22C */ + u32 rmon_t_p128to255; /* FEC + 0x230 */ + u32 rmon_t_p256to511; /* FEC + 0x234 */ + u32 rmon_t_p512to1023; /* FEC + 0x238 */ + u32 rmon_t_p1024to2047; /* FEC + 0x23C */ + u32 rmon_t_p_gte2048; /* FEC + 0x240 */ + u32 rmon_t_octets; /* FEC + 0x244 */ + u32 ieee_t_drop; /* FEC + 0x248 */ + u32 ieee_t_frame_ok; /* FEC + 0x24C */ + u32 ieee_t_1col; /* FEC + 0x250 */ + u32 ieee_t_mcol; /* FEC + 0x254 */ + u32 ieee_t_def; /* FEC + 0x258 */ + u32 ieee_t_lcol; /* FEC + 0x25C */ + u32 ieee_t_excol; /* FEC + 0x260 */ + u32 ieee_t_macerr; /* FEC + 0x264 */ + u32 ieee_t_cserr; /* FEC + 0x268 */ + u32 ieee_t_sqe; /* FEC + 0x26C */ + u32 t_fdxfc; /* FEC + 0x270 */ + u32 ieee_t_octets_ok; /* FEC + 0x274 */ + + u32 reserved9[2]; /* FEC + 0x278-27C */ + u32 rmon_r_drop; /* FEC + 0x280 */ + u32 rmon_r_packets; /* FEC + 0x284 */ + u32 rmon_r_bc_pkt; /* FEC + 0x288 */ + u32 rmon_r_mc_pkt; /* FEC + 0x28C */ + u32 rmon_r_crc_align; /* FEC + 0x290 */ + u32 rmon_r_undersize; /* FEC + 0x294 */ + u32 rmon_r_oversize; /* FEC + 0x298 */ + u32 rmon_r_frag; /* FEC + 0x29C */ + u32 rmon_r_jab; /* FEC + 0x2A0 */ + + u32 rmon_r_resvd_0; /* FEC + 0x2A4 */ + + u32 rmon_r_p64; /* FEC + 0x2A8 */ + u32 rmon_r_p65to127; /* FEC + 0x2AC */ + u32 rmon_r_p128to255; /* FEC + 0x2B0 */ + u32 rmon_r_p256to511; /* FEC + 0x2B4 */ + u32 rmon_r_p512to1023; /* FEC + 0x2B8 */ + u32 rmon_r_p1024to2047; /* FEC + 0x2BC */ + u32 rmon_r_p_gte2048; /* FEC + 0x2C0 */ + u32 rmon_r_octets; /* FEC + 0x2C4 */ + u32 ieee_r_drop; /* FEC + 0x2C8 */ + u32 ieee_r_frame_ok; /* FEC + 0x2CC */ + u32 ieee_r_crc; /* FEC + 0x2D0 */ + u32 ieee_r_align; /* FEC + 0x2D4 */ + u32 r_macerr; /* FEC + 0x2D8 */ + u32 r_fdxfc; /* FEC + 0x2DC */ + u32 ieee_r_octets_ok; /* FEC + 0x2E0 */ + + u32 reserved10[7]; /* FEC + 0x2E4-2FC */ + + u32 reserved11[64]; /* FEC + 0x300-3FF */ +}; + +#define FEC_MIB_DISABLE 0x80000000 + +#define FEC_IEVENT_HBERR 0x80000000 +#define FEC_IEVENT_BABR 0x40000000 +#define FEC_IEVENT_BABT 0x20000000 +#define FEC_IEVENT_GRA 0x10000000 +#define FEC_IEVENT_TFINT 0x08000000 +#define FEC_IEVENT_MII 0x00800000 +#define FEC_IEVENT_LATE_COL 0x00200000 +#define FEC_IEVENT_COL_RETRY_LIM 0x00100000 +#define FEC_IEVENT_XFIFO_UN 0x00080000 +#define FEC_IEVENT_XFIFO_ERROR 0x00040000 +#define FEC_IEVENT_RFIFO_ERROR 0x00020000 + +#define FEC_IMASK_HBERR 0x80000000 +#define FEC_IMASK_BABR 0x40000000 +#define FEC_IMASK_BABT 0x20000000 +#define FEC_IMASK_GRA 0x10000000 +#define FEC_IMASK_MII 0x00800000 +#define FEC_IMASK_LATE_COL 0x00200000 +#define FEC_IMASK_COL_RETRY_LIM 0x00100000 +#define FEC_IMASK_XFIFO_UN 0x00080000 +#define FEC_IMASK_XFIFO_ERROR 0x00040000 +#define FEC_IMASK_RFIFO_ERROR 0x00020000 + +/* all but MII, which is enabled separately */ +#define FEC_IMASK_ENABLE (FEC_IMASK_HBERR | FEC_IMASK_BABR | \ + FEC_IMASK_BABT | FEC_IMASK_GRA | FEC_IMASK_LATE_COL | \ + FEC_IMASK_COL_RETRY_LIM | FEC_IMASK_XFIFO_UN | \ + FEC_IMASK_XFIFO_ERROR | FEC_IMASK_RFIFO_ERROR) + +#define FEC_RCNTRL_MAX_FL_SHIFT 16 +#define FEC_RCNTRL_LOOP 0x01 +#define FEC_RCNTRL_DRT 0x02 +#define FEC_RCNTRL_MII_MODE 0x04 +#define FEC_RCNTRL_PROM 0x08 +#define FEC_RCNTRL_BC_REJ 0x10 +#define FEC_RCNTRL_FCE 0x20 + +#define FEC_TCNTRL_GTS 0x00000001 +#define FEC_TCNTRL_HBC 0x00000002 +#define FEC_TCNTRL_FDEN 0x00000004 +#define FEC_TCNTRL_TFC_PAUSE 0x00000008 +#define FEC_TCNTRL_RFC_PAUSE 0x00000010 + +#define FEC_ECNTRL_RESET 0x00000001 +#define FEC_ECNTRL_ETHER_EN 0x00000002 + +#define FEC_MII_DATA_ST 0x40000000 /* Start frame */ +#define FEC_MII_DATA_OP_RD 0x20000000 /* Perform read */ +#define FEC_MII_DATA_OP_WR 0x10000000 /* Perform write */ +#define FEC_MII_DATA_PA_MSK 0x0f800000 /* PHY Address mask */ +#define FEC_MII_DATA_RA_MSK 0x007c0000 /* PHY Register mask */ +#define FEC_MII_DATA_TA 0x00020000 /* Turnaround */ +#define FEC_MII_DATA_DATAMSK 0x0000ffff /* PHY data mask */ + +#define FEC_MII_READ_FRAME (FEC_MII_DATA_ST | FEC_MII_DATA_OP_RD | FEC_MII_DATA_TA) +#define FEC_MII_WRITE_FRAME (FEC_MII_DATA_ST | FEC_MII_DATA_OP_WR | FEC_MII_DATA_TA) + +#define FEC_MII_DATA_RA_SHIFT 0x12 /* MII reg addr bits */ +#define FEC_MII_DATA_PA_SHIFT 0x17 /* MII PHY addr bits */ + +#define FEC_PADDR2_TYPE 0x8808 + +#define FEC_OP_PAUSE_OPCODE 0x00010000 + +#define FEC_FIFO_WMRK_256B 0x3 + +#define FEC_FIFO_STATUS_ERR 0x00400000 +#define FEC_FIFO_STATUS_UF 0x00200000 +#define FEC_FIFO_STATUS_OF 0x00100000 + +#define FEC_FIFO_CNTRL_FRAME 0x08000000 +#define FEC_FIFO_CNTRL_LTG_7 0x07000000 + +#define FEC_RESET_CNTRL_RESET_FIFO 0x02000000 +#define FEC_RESET_CNTRL_ENABLE_IS_RESET 0x01000000 + +#define FEC_XMIT_FSM_APPEND_CRC 0x02000000 +#define FEC_XMIT_FSM_ENABLE_CRC 0x01000000 + + +extern struct of_platform_driver mpc52xx_fec_mdio_driver; + +#endif /* __DRIVERS_NET_MPC52XX_FEC_H__ */ diff --git a/drivers/net/fec_mpc52xx_phy.c b/drivers/net/fec_mpc52xx_phy.c new file mode 100644 index 00000000000..ba6e8b218e0 --- /dev/null +++ b/drivers/net/fec_mpc52xx_phy.c @@ -0,0 +1,198 @@ +/* + * Driver for the MPC5200 Fast Ethernet Controller - MDIO bus driver + * + * Copyright (C) 2007 Domen Puncer, Telargo, Inc. + * + * This file is licensed under the terms of the GNU General Public License + * version 2. This program is licensed "as is" without any warranty of any + * kind, whether express or implied. + */ + +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/netdevice.h> +#include <linux/phy.h> +#include <linux/of_platform.h> +#include <asm/io.h> +#include <asm/mpc52xx.h> +#include "fec_mpc52xx.h" + +struct mpc52xx_fec_mdio_priv { + struct mpc52xx_fec __iomem *regs; +}; + +static int mpc52xx_fec_mdio_read(struct mii_bus *bus, int phy_id, int reg) +{ + struct mpc52xx_fec_mdio_priv *priv = bus->priv; + struct mpc52xx_fec __iomem *fec; + int tries = 100; + u32 request = FEC_MII_READ_FRAME; + + fec = priv->regs; + out_be32(&fec->ievent, FEC_IEVENT_MII); + + request |= (phy_id << FEC_MII_DATA_PA_SHIFT) & FEC_MII_DATA_PA_MSK; + request |= (reg << FEC_MII_DATA_RA_SHIFT) & FEC_MII_DATA_RA_MSK; + + out_be32(&priv->regs->mii_data, request); + + /* wait for it to finish, this takes about 23 us on lite5200b */ + while (!(in_be32(&fec->ievent) & FEC_IEVENT_MII) && --tries) + udelay(5); + + if (tries == 0) + return -ETIMEDOUT; + + return in_be32(&priv->regs->mii_data) & FEC_MII_DATA_DATAMSK; +} + +static int mpc52xx_fec_mdio_write(struct mii_bus *bus, int phy_id, int reg, u16 data) +{ + struct mpc52xx_fec_mdio_priv *priv = bus->priv; + struct mpc52xx_fec __iomem *fec; + u32 value = data; + int tries = 100; + + fec = priv->regs; + out_be32(&fec->ievent, FEC_IEVENT_MII); + + value |= FEC_MII_WRITE_FRAME; + value |= (phy_id << FEC_MII_DATA_PA_SHIFT) & FEC_MII_DATA_PA_MSK; + value |= (reg << FEC_MII_DATA_RA_SHIFT) & FEC_MII_DATA_RA_MSK; + + out_be32(&priv->regs->mii_data, value); + + /* wait for request to finish */ + while (!(in_be32(&fec->ievent) & FEC_IEVENT_MII) && --tries) + udelay(5); + + if (tries == 0) + return -ETIMEDOUT; + + return 0; +} + +static int mpc52xx_fec_mdio_probe(struct of_device *of, const struct of_device_id *match) +{ + struct device *dev = &of->dev; + struct device_node *np = of->node; + struct device_node *child = NULL; + struct mii_bus *bus; + struct mpc52xx_fec_mdio_priv *priv; + struct resource res = {}; + int err; + int i; + + bus = kzalloc(sizeof(*bus), GFP_KERNEL); + if (bus == NULL) + return -ENOMEM; + priv = kzalloc(sizeof(*priv), GFP_KERNEL); + if (priv == NULL) { + err = -ENOMEM; + goto out_free; + } + + bus->name = "mpc52xx MII bus"; + bus->read = mpc52xx_fec_mdio_read; + bus->write = mpc52xx_fec_mdio_write; + + /* setup irqs */ + bus->irq = kmalloc(sizeof(bus->irq[0]) * PHY_MAX_ADDR, GFP_KERNEL); + if (bus->irq == NULL) { + err = -ENOMEM; + goto out_free; + } + for (i=0; i<PHY_MAX_ADDR; i++) + bus->irq[i] = PHY_POLL; + + while ((child = of_get_next_child(np, child)) != NULL) { + int irq = irq_of_parse_and_map(child, 0); + if (irq != NO_IRQ) { + const u32 *id = of_get_property(child, "reg", NULL); + bus->irq[*id] = irq; + } + } + + /* setup registers */ + err = of_address_to_resource(np, 0, &res); + if (err) + goto out_free; + priv->regs = ioremap(res.start, res.end - res.start + 1); + if (priv->regs == NULL) { + err = -ENOMEM; + goto out_free; + } + + bus->id = res.start; + bus->priv = priv; + + bus->dev = dev; + dev_set_drvdata(dev, bus); + + /* set MII speed */ + out_be32(&priv->regs->mii_speed, ((mpc52xx_find_ipb_freq(of->node) >> 20) / 5) << 1); + + /* enable MII interrupt */ + out_be32(&priv->regs->imask, in_be32(&priv->regs->imask) | FEC_IMASK_MII); + + err = mdiobus_register(bus); + if (err) + goto out_unmap; + + return 0; + + out_unmap: + iounmap(priv->regs); + out_free: + for (i=0; i<PHY_MAX_ADDR; i++) + if (bus->irq[i] != PHY_POLL) + irq_dispose_mapping(bus->irq[i]); + kfree(bus->irq); + kfree(priv); + kfree(bus); + + return err; +} + +static int mpc52xx_fec_mdio_remove(struct of_device *of) +{ + struct device *dev = &of->dev; + struct mii_bus *bus = dev_get_drvdata(dev); + struct mpc52xx_fec_mdio_priv *priv = bus->priv; + int i; + + mdiobus_unregister(bus); + dev_set_drvdata(dev, NULL); + + iounmap(priv->regs); + for (i=0; i<PHY_MAX_ADDR; i++) + if (bus->irq[i]) + irq_dispose_mapping(bus->irq[i]); + kfree(priv); + kfree(bus->irq); + kfree(bus); + + return 0; +} + + +static struct of_device_id mpc52xx_fec_mdio_match[] = { + { + .type = "mdio", + .compatible = "mpc5200b-fec-phy", + }, + {}, +}; + +struct of_platform_driver mpc52xx_fec_mdio_driver = { + .name = "mpc5200b-fec-phy", + .probe = mpc52xx_fec_mdio_probe, + .remove = mpc52xx_fec_mdio_remove, + .match_table = mpc52xx_fec_mdio_match, +}; + +/* let fec driver call it, since this has to be registered before it */ +EXPORT_SYMBOL_GPL(mpc52xx_fec_mdio_driver); + + +MODULE_LICENSE("Dual BSD/GPL"); diff --git a/drivers/net/irda/au1k_ir.c b/drivers/net/irda/au1k_ir.c index 4dbdfaaf37b..a1e4508717c 100644 --- a/drivers/net/irda/au1k_ir.c +++ b/drivers/net/irda/au1k_ir.c @@ -627,19 +627,16 @@ static int au1k_irda_rx(struct net_device *dev) } -void au1k_irda_interrupt(int irq, void *dev_id) +static irqreturn_t au1k_irda_interrupt(int dummy, void *dev_id) { - struct net_device *dev = (struct net_device *) dev_id; - - if (dev == NULL) { - printk(KERN_ERR "%s: isr: null dev ptr\n", dev->name); - return; - } + struct net_device *dev = dev_id; writel(0, IR_INT_CLEAR); /* ack irda interrupts */ au1k_irda_rx(dev); au1k_tx_ack(dev); + + return IRQ_HANDLED; } diff --git a/drivers/net/ixgb/ixgb.h b/drivers/net/ixgb/ixgb.h index 1eee8894c73..3d2e7217e9a 100644 --- a/drivers/net/ixgb/ixgb.h +++ b/drivers/net/ixgb/ixgb.h @@ -196,4 +196,11 @@ struct ixgb_adapter { uint32_t alloc_rx_buff_failed; boolean_t have_msi; }; + +/* Exported from other modules */ +extern void ixgb_check_options(struct ixgb_adapter *adapter); +extern void ixgb_set_ethtool_ops(struct net_device *netdev); +extern char ixgb_driver_name[]; +extern const char ixgb_driver_version[]; + #endif /* _IXGB_H_ */ diff --git a/drivers/net/ixgb/ixgb_ethtool.c b/drivers/net/ixgb/ixgb_ethtool.c index fddd5844168..a267dd86252 100644 --- a/drivers/net/ixgb/ixgb_ethtool.c +++ b/drivers/net/ixgb/ixgb_ethtool.c @@ -32,9 +32,6 @@ #include <asm/uaccess.h> -extern char ixgb_driver_name[]; -extern char ixgb_driver_version[]; - extern int ixgb_up(struct ixgb_adapter *adapter); extern void ixgb_down(struct ixgb_adapter *adapter, boolean_t kill_watchdog); extern void ixgb_reset(struct ixgb_adapter *adapter); @@ -639,8 +636,8 @@ ixgb_phys_id(struct net_device *netdev, uint32_t data) { struct ixgb_adapter *adapter = netdev_priv(netdev); - if(!data || data > (uint32_t)(MAX_SCHEDULE_TIMEOUT / HZ)) - data = (uint32_t)(MAX_SCHEDULE_TIMEOUT / HZ); + if (!data) + data = INT_MAX; if(!adapter->blink_timer.function) { init_timer(&adapter->blink_timer); diff --git a/drivers/net/ixgb/ixgb_hw.c b/drivers/net/ixgb/ixgb_hw.c index ecbf45861c6..2c6367ace3c 100644 --- a/drivers/net/ixgb/ixgb_hw.c +++ b/drivers/net/ixgb/ixgb_hw.c @@ -1174,7 +1174,7 @@ mac_addr_valid(uint8_t *mac_addr) * * hw - Struct containing variables accessed by shared code *****************************************************************************/ -boolean_t +static boolean_t ixgb_link_reset(struct ixgb_hw *hw) { boolean_t link_status = FALSE; @@ -1205,7 +1205,7 @@ ixgb_link_reset(struct ixgb_hw *hw) * * hw - Struct containing variables accessed by shared code *****************************************************************************/ -void +static void ixgb_optics_reset(struct ixgb_hw *hw) { if (hw->phy_type == ixgb_phy_type_txn17401) { diff --git a/drivers/net/ixgb/ixgb_main.c b/drivers/net/ixgb/ixgb_main.c index d444de58ba3..3021234b1e1 100644 --- a/drivers/net/ixgb/ixgb_main.c +++ b/drivers/net/ixgb/ixgb_main.c @@ -37,8 +37,8 @@ static char ixgb_driver_string[] = "Intel(R) PRO/10GbE Network Driver"; #define DRIVERNAPI "-NAPI" #endif #define DRV_VERSION "1.0.126-k2"DRIVERNAPI -char ixgb_driver_version[] = DRV_VERSION; -static char ixgb_copyright[] = "Copyright (c) 1999-2006 Intel Corporation."; +const char ixgb_driver_version[] = DRV_VERSION; +static const char ixgb_copyright[] = "Copyright (c) 1999-2006 Intel Corporation."; /* ixgb_pci_tbl - PCI Device ID Table * @@ -104,7 +104,6 @@ static boolean_t ixgb_clean_rx_irq(struct ixgb_adapter *adapter, static boolean_t ixgb_clean_rx_irq(struct ixgb_adapter *adapter); #endif static void ixgb_alloc_rx_buffers(struct ixgb_adapter *adapter); -void ixgb_set_ethtool_ops(struct net_device *netdev); static void ixgb_tx_timeout(struct net_device *dev); static void ixgb_tx_timeout_task(struct work_struct *work); static void ixgb_vlan_rx_register(struct net_device *netdev, @@ -123,9 +122,6 @@ static pci_ers_result_t ixgb_io_error_detected (struct pci_dev *pdev, static pci_ers_result_t ixgb_io_slot_reset (struct pci_dev *pdev); static void ixgb_io_resume (struct pci_dev *pdev); -/* Exported from other modules */ -extern void ixgb_check_options(struct ixgb_adapter *adapter); - static struct pci_error_handlers ixgb_err_handler = { .error_detected = ixgb_io_error_detected, .slot_reset = ixgb_io_slot_reset, @@ -1085,7 +1081,8 @@ ixgb_set_multi(struct net_device *netdev) rctl |= IXGB_RCTL_MPE; IXGB_WRITE_REG(hw, RCTL, rctl); } else { - uint8_t mta[netdev->mc_count * IXGB_ETH_LENGTH_OF_ADDRESS]; + uint8_t mta[IXGB_MAX_NUM_MULTICAST_ADDRESSES * + IXGB_ETH_LENGTH_OF_ADDRESS]; IXGB_WRITE_REG(hw, RCTL, rctl); @@ -1324,8 +1321,8 @@ ixgb_tx_map(struct ixgb_adapter *adapter, struct sk_buff *skb, /* Workaround for premature desc write-backs * in TSO mode. Append 4-byte sentinel desc */ - if (unlikely(mss && !nr_frags && size == len - && size > 8)) + if (unlikely(mss && (f == (nr_frags - 1)) + && size == len && size > 8)) size -= 4; buffer_info->length = size; diff --git a/drivers/net/ixgb/ixgb_param.c b/drivers/net/ixgb/ixgb_param.c index 5d5ddabf436..865d14d6e5a 100644 --- a/drivers/net/ixgb/ixgb_param.c +++ b/drivers/net/ixgb/ixgb_param.c @@ -44,10 +44,11 @@ */ #define IXGB_PARAM_INIT { [0 ... IXGB_MAX_NIC] = OPTION_UNSET } -#define IXGB_PARAM(X, desc) \ - static int __devinitdata X[IXGB_MAX_NIC+1] = IXGB_PARAM_INIT; \ - static int num_##X = 0; \ - module_param_array_named(X, X, int, &num_##X, 0); \ +#define IXGB_PARAM(X, desc) \ + static int __devinitdata X[IXGB_MAX_NIC+1] \ + = IXGB_PARAM_INIT; \ + static unsigned int num_##X = 0; \ + module_param_array_named(X, X, int, &num_##X, 0); \ MODULE_PARM_DESC(X, desc); /* Transmit Descriptor Count @@ -178,8 +179,8 @@ IXGB_PARAM(IntDelayEnable, "Transmit Interrupt Delay Enable"); struct ixgb_option { enum { enable_option, range_option, list_option } type; - char *name; - char *err; + const char *name; + const char *err; int def; union { struct { /* range_option info */ @@ -197,7 +198,7 @@ struct ixgb_option { }; static int __devinit -ixgb_validate_option(int *value, struct ixgb_option *opt) +ixgb_validate_option(unsigned int *value, const struct ixgb_option *opt) { if(*value == OPTION_UNSET) { *value = opt->def; @@ -266,7 +267,7 @@ ixgb_check_options(struct ixgb_adapter *adapter) } { /* Transmit Descriptor Count */ - struct ixgb_option opt = { + const struct ixgb_option opt = { .type = range_option, .name = "Transmit Descriptors", .err = "using default of " __MODULE_STRING(DEFAULT_TXD), @@ -285,7 +286,7 @@ ixgb_check_options(struct ixgb_adapter *adapter) tx_ring->count = ALIGN(tx_ring->count, IXGB_REQ_TX_DESCRIPTOR_MULTIPLE); } { /* Receive Descriptor Count */ - struct ixgb_option opt = { + const struct ixgb_option opt = { .type = range_option, .name = "Receive Descriptors", .err = "using default of " __MODULE_STRING(DEFAULT_RXD), @@ -304,7 +305,7 @@ ixgb_check_options(struct ixgb_adapter *adapter) rx_ring->count = ALIGN(rx_ring->count, IXGB_REQ_RX_DESCRIPTOR_MULTIPLE); } { /* Receive Checksum Offload Enable */ - struct ixgb_option opt = { + const struct ixgb_option opt = { .type = enable_option, .name = "Receive Checksum Offload", .err = "defaulting to Enabled", @@ -312,7 +313,7 @@ ixgb_check_options(struct ixgb_adapter *adapter) }; if(num_XsumRX > bd) { - int rx_csum = XsumRX[bd]; + unsigned int rx_csum = XsumRX[bd]; ixgb_validate_option(&rx_csum, &opt); adapter->rx_csum = rx_csum; } else { @@ -328,7 +329,7 @@ ixgb_check_options(struct ixgb_adapter *adapter) { ixgb_fc_full, "Flow Control Enabled" }, { ixgb_fc_default, "Flow Control Hardware Default" }}; - struct ixgb_option opt = { + const struct ixgb_option opt = { .type = list_option, .name = "Flow Control", .err = "reading default settings from EEPROM", @@ -338,7 +339,7 @@ ixgb_check_options(struct ixgb_adapter *adapter) }; if(num_FlowControl > bd) { - int fc = FlowControl[bd]; + unsigned int fc = FlowControl[bd]; ixgb_validate_option(&fc, &opt); adapter->hw.fc.type = fc; } else { @@ -346,7 +347,7 @@ ixgb_check_options(struct ixgb_adapter *adapter) } } { /* Receive Flow Control High Threshold */ - struct ixgb_option opt = { + const struct ixgb_option opt = { .type = range_option, .name = "Rx Flow Control High Threshold", .err = "using default of " __MODULE_STRING(DEFAULT_FCRTH), @@ -366,7 +367,7 @@ ixgb_check_options(struct ixgb_adapter *adapter) "Ignoring RxFCHighThresh when no RxFC\n"); } { /* Receive Flow Control Low Threshold */ - struct ixgb_option opt = { + const struct ixgb_option opt = { .type = range_option, .name = "Rx Flow Control Low Threshold", .err = "using default of " __MODULE_STRING(DEFAULT_FCRTL), @@ -386,7 +387,7 @@ ixgb_check_options(struct ixgb_adapter *adapter) "Ignoring RxFCLowThresh when no RxFC\n"); } { /* Flow Control Pause Time Request*/ - struct ixgb_option opt = { + const struct ixgb_option opt = { .type = range_option, .name = "Flow Control Pause Time Request", .err = "using default of "__MODULE_STRING(DEFAULT_FCPAUSE), @@ -396,7 +397,7 @@ ixgb_check_options(struct ixgb_adapter *adapter) }; if(num_FCReqTimeout > bd) { - int pause_time = FCReqTimeout[bd]; + unsigned int pause_time = FCReqTimeout[bd]; ixgb_validate_option(&pause_time, &opt); adapter->hw.fc.pause_time = pause_time; } else { @@ -419,7 +420,7 @@ ixgb_check_options(struct ixgb_adapter *adapter) } } { /* Receive Interrupt Delay */ - struct ixgb_option opt = { + const struct ixgb_option opt = { .type = range_option, .name = "Receive Interrupt Delay", .err = "using default of " __MODULE_STRING(DEFAULT_RDTR), @@ -436,7 +437,7 @@ ixgb_check_options(struct ixgb_adapter *adapter) } } { /* Transmit Interrupt Delay */ - struct ixgb_option opt = { + const struct ixgb_option opt = { .type = range_option, .name = "Transmit Interrupt Delay", .err = "using default of " __MODULE_STRING(DEFAULT_TIDV), @@ -454,7 +455,7 @@ ixgb_check_options(struct ixgb_adapter *adapter) } { /* Transmit Interrupt Delay Enable */ - struct ixgb_option opt = { + const struct ixgb_option opt = { .type = enable_option, .name = "Tx Interrupt Delay Enable", .err = "defaulting to Enabled", @@ -462,7 +463,7 @@ ixgb_check_options(struct ixgb_adapter *adapter) }; if(num_IntDelayEnable > bd) { - int ide = IntDelayEnable[bd]; + unsigned int ide = IntDelayEnable[bd]; ixgb_validate_option(&ide, &opt); adapter->tx_int_delay_enable = ide; } else { diff --git a/drivers/net/ixgbe/ixgbe.h b/drivers/net/ixgbe/ixgbe.h index c160a7d91e2..bc51432b8d2 100644 --- a/drivers/net/ixgbe/ixgbe.h +++ b/drivers/net/ixgbe/ixgbe.h @@ -244,7 +244,7 @@ extern struct ixgbe_info ixgbe_82598EB_info; extern struct ixgbe_info ixgbe_82598AT_info; extern char ixgbe_driver_name[]; -extern char ixgbe_driver_version[]; +extern const char ixgbe_driver_version[]; extern int ixgbe_up(struct ixgbe_adapter *adapter); extern void ixgbe_down(struct ixgbe_adapter *adapter); diff --git a/drivers/net/ixgbe/ixgbe_82598.c b/drivers/net/ixgbe/ixgbe_82598.c index 00ee20125ca..4d64673164c 100644 --- a/drivers/net/ixgbe/ixgbe_82598.c +++ b/drivers/net/ixgbe/ixgbe_82598.c @@ -30,8 +30,7 @@ #include <linux/delay.h> #include <linux/sched.h> -#include "ixgbe_type.h" -#include "ixgbe_common.h" +#include "ixgbe.h" #include "ixgbe_phy.h" #define IXGBE_82598_MAX_TX_QUEUES 32 diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index b75f1c6efc4..00bc525c656 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -45,12 +45,13 @@ #include "ixgbe_common.h" char ixgbe_driver_name[] = "ixgbe"; -static char ixgbe_driver_string[] = - "Intel(R) 10 Gigabit PCI Express Network Driver"; +static const char ixgbe_driver_string[] = + "Intel(R) 10 Gigabit PCI Express Network Driver"; #define DRV_VERSION "1.1.18" -char ixgbe_driver_version[] = DRV_VERSION; -static char ixgbe_copyright[] = "Copyright (c) 1999-2007 Intel Corporation."; +const char ixgbe_driver_version[] = DRV_VERSION; +static const char ixgbe_copyright[] = + "Copyright (c) 1999-2007 Intel Corporation."; static const struct ixgbe_info *ixgbe_info_tbl[] = { [board_82598AF] = &ixgbe_82598AF_info, diff --git a/drivers/net/pcmcia/3c574_cs.c b/drivers/net/pcmcia/3c574_cs.c index 73dcbb7296d..ad134a61302 100644 --- a/drivers/net/pcmcia/3c574_cs.c +++ b/drivers/net/pcmcia/3c574_cs.c @@ -274,7 +274,7 @@ static int tc574_probe(struct pcmcia_device *link) spin_lock_init(&lp->window_lock); link->io.NumPorts1 = 32; link->io.Attributes1 = IO_DATA_PATH_WIDTH_16; - link->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT; + link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING|IRQ_HANDLE_PRESENT; link->irq.IRQInfo1 = IRQ_LEVEL_ID; link->irq.Handler = &el3_interrupt; link->irq.Instance = dev; diff --git a/drivers/net/pcmcia/3c589_cs.c b/drivers/net/pcmcia/3c589_cs.c index 32076ca6a9e..a98fe07cce7 100644 --- a/drivers/net/pcmcia/3c589_cs.c +++ b/drivers/net/pcmcia/3c589_cs.c @@ -188,7 +188,7 @@ static int tc589_probe(struct pcmcia_device *link) spin_lock_init(&lp->lock); link->io.NumPorts1 = 16; link->io.Attributes1 = IO_DATA_PATH_WIDTH_16; - link->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT; + link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING|IRQ_HANDLE_PRESENT; link->irq.IRQInfo1 = IRQ_LEVEL_ID; link->irq.Handler = &el3_interrupt; link->irq.Instance = dev; diff --git a/drivers/net/pcmcia/axnet_cs.c b/drivers/net/pcmcia/axnet_cs.c index a95a2cae6b2..8d910a372f8 100644 --- a/drivers/net/pcmcia/axnet_cs.c +++ b/drivers/net/pcmcia/axnet_cs.c @@ -158,7 +158,7 @@ static int axnet_probe(struct pcmcia_device *link) info = PRIV(dev); info->p_dev = link; link->priv = dev; - link->irq.Attributes = IRQ_TYPE_EXCLUSIVE; + link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING; link->irq.IRQInfo1 = IRQ_LEVEL_ID; link->conf.Attributes = CONF_ENABLE_IRQ; link->conf.IntType = INT_MEMORY_AND_IO; diff --git a/drivers/net/pcmcia/fmvj18x_cs.c b/drivers/net/pcmcia/fmvj18x_cs.c index 62844677c78..8c719b4df54 100644 --- a/drivers/net/pcmcia/fmvj18x_cs.c +++ b/drivers/net/pcmcia/fmvj18x_cs.c @@ -249,7 +249,7 @@ static int fmvj18x_probe(struct pcmcia_device *link) link->io.IOAddrLines = 5; /* Interrupt setup */ - link->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT; + link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING|IRQ_HANDLE_PRESENT; link->irq.IRQInfo1 = IRQ_LEVEL_ID; link->irq.Handler = &fjn_interrupt; link->irq.Instance = dev; diff --git a/drivers/net/pcmcia/pcnet_cs.c b/drivers/net/pcmcia/pcnet_cs.c index 9d45e9696e1..db6a97d1d7b 100644 --- a/drivers/net/pcmcia/pcnet_cs.c +++ b/drivers/net/pcmcia/pcnet_cs.c @@ -254,7 +254,7 @@ static int pcnet_probe(struct pcmcia_device *link) info->p_dev = link; link->priv = dev; - link->irq.Attributes = IRQ_TYPE_EXCLUSIVE; + link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING; link->irq.IRQInfo1 = IRQ_LEVEL_ID; link->conf.Attributes = CONF_ENABLE_IRQ; link->conf.IntType = INT_MEMORY_AND_IO; diff --git a/drivers/net/pcmcia/smc91c92_cs.c b/drivers/net/pcmcia/smc91c92_cs.c index 58d716fd17c..c9868e9dac4 100644 --- a/drivers/net/pcmcia/smc91c92_cs.c +++ b/drivers/net/pcmcia/smc91c92_cs.c @@ -328,7 +328,7 @@ static int smc91c92_probe(struct pcmcia_device *link) link->io.NumPorts1 = 16; link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; link->io.IOAddrLines = 4; - link->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT; + link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING|IRQ_HANDLE_PRESENT; link->irq.IRQInfo1 = IRQ_LEVEL_ID; link->irq.Handler = &smc_interrupt; link->irq.Instance = dev; diff --git a/drivers/net/pcmcia/xirc2ps_cs.c b/drivers/net/pcmcia/xirc2ps_cs.c index c3b69602e27..1f09bea6db5 100644 --- a/drivers/net/pcmcia/xirc2ps_cs.c +++ b/drivers/net/pcmcia/xirc2ps_cs.c @@ -886,7 +886,7 @@ xirc2ps_config(struct pcmcia_device * link) } printk(KNOT_XIRC "no ports available\n"); } else { - link->irq.Attributes |= IRQ_TYPE_EXCLUSIVE; + link->irq.Attributes |= IRQ_TYPE_DYNAMIC_SHARING; link->io.NumPorts1 = 16; for (ioaddr = 0x300; ioaddr < 0x400; ioaddr += 0x10) { link->io.BasePort1 = ioaddr; diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c index e8960f294a6..b94fa7ef195 100644 --- a/drivers/net/r8169.c +++ b/drivers/net/r8169.c @@ -392,7 +392,9 @@ struct rtl8169_private { void __iomem *mmio_addr; /* memory map physical address */ struct pci_dev *pci_dev; /* Index of PCI device */ struct net_device *dev; +#ifdef CONFIG_R8169_NAPI struct napi_struct napi; +#endif spinlock_t lock; /* spin lock flag */ u32 msg_enable; int chipset; @@ -2989,13 +2991,16 @@ static void rtl8169_down(struct net_device *dev) { struct rtl8169_private *tp = netdev_priv(dev); void __iomem *ioaddr = tp->mmio_addr; - unsigned int poll_locked = 0; unsigned int intrmask; rtl8169_delete_timer(dev); netif_stop_queue(dev); +#ifdef CONFIG_R8169_NAPI + napi_disable(&tp->napi); +#endif + core_down: spin_lock_irq(&tp->lock); @@ -3009,11 +3014,6 @@ core_down: synchronize_irq(dev->irq); - if (!poll_locked) { - napi_disable(&tp->napi); - poll_locked++; - } - /* Give a racing hard_start_xmit a few cycles to complete. */ synchronize_sched(); /* FIXME: should this be synchronize_irq()? */ diff --git a/drivers/net/ucc_geth.c b/drivers/net/ucc_geth.c index 9741d613ba6..a3ff270593f 100644 --- a/drivers/net/ucc_geth.c +++ b/drivers/net/ucc_geth.c @@ -2214,9 +2214,7 @@ static void ucc_geth_set_multi(struct net_device *dev) struct dev_mc_list *dmi; struct ucc_fast *uf_regs; struct ucc_geth_82xx_address_filtering_pram *p_82xx_addr_filt; - u8 tempaddr[6]; - u8 *mcptr, *tdptr; - int i, j; + int i; ugeth = netdev_priv(dev); @@ -2255,19 +2253,10 @@ static void ucc_geth_set_multi(struct net_device *dev) if (!(dmi->dmi_addr[0] & 1)) continue; - /* The address in dmi_addr is LSB first, - * and taddr is MSB first. We have to - * copy bytes MSB first from dmi_addr. - */ - mcptr = (u8 *) dmi->dmi_addr + 5; - tdptr = (u8 *) tempaddr; - for (j = 0; j < 6; j++) - *tdptr++ = *mcptr--; - /* Ask CPM to run CRC and set bit in * filter mask. */ - hw_add_addr_in_hash(ugeth, tempaddr); + hw_add_addr_in_hash(ugeth, dmi->dmi_addr); } } } diff --git a/drivers/net/usb/dm9601.c b/drivers/net/usb/dm9601.c index a2de32fabc1..2c685734b7a 100644 --- a/drivers/net/usb/dm9601.c +++ b/drivers/net/usb/dm9601.c @@ -586,6 +586,10 @@ static const struct usb_device_id products[] = { USB_DEVICE(0x0a46, 0x0268), /* ShanTou ST268 USB NIC */ .driver_info = (unsigned long)&dm9601_info, }, + { + USB_DEVICE(0x0a46, 0x8515), /* ADMtek ADM8515 USB NIC */ + .driver_info = (unsigned long)&dm9601_info, + }, {}, // END }; diff --git a/drivers/net/wan/lmc/lmc_main.c b/drivers/net/wan/lmc/lmc_main.c index 5ea877221f4..64eb5789360 100644 --- a/drivers/net/wan/lmc/lmc_main.c +++ b/drivers/net/wan/lmc/lmc_main.c @@ -142,9 +142,10 @@ int lmc_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd) /*fold00*/ * To date internally, just copy this out to the user. */ case LMCIOCGINFO: /*fold01*/ - if (copy_to_user(ifr->ifr_data, &sc->ictl, sizeof (lmc_ctl_t))) - return -EFAULT; - ret = 0; + if (copy_to_user(ifr->ifr_data, &sc->ictl, sizeof(lmc_ctl_t))) + ret = -EFAULT; + else + ret = 0; break; case LMCIOCSINFO: /*fold01*/ @@ -159,8 +160,10 @@ int lmc_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd) /*fold00*/ break; } - if (copy_from_user(&ctl, ifr->ifr_data, sizeof (lmc_ctl_t))) - return -EFAULT; + if (copy_from_user(&ctl, ifr->ifr_data, sizeof(lmc_ctl_t))) { + ret = -EFAULT; + break; + } sc->lmc_media->set_status (sc, &ctl); @@ -190,8 +193,10 @@ int lmc_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd) /*fold00*/ break; } - if (copy_from_user(&new_type, ifr->ifr_data, sizeof(u_int16_t))) - return -EFAULT; + if (copy_from_user(&new_type, ifr->ifr_data, sizeof(u_int16_t))) { + ret = -EFAULT; + break; + } if (new_type == old_type) @@ -229,9 +234,10 @@ int lmc_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd) /*fold00*/ sc->lmc_xinfo.Magic1 = 0xDEADBEEF; if (copy_to_user(ifr->ifr_data, &sc->lmc_xinfo, - sizeof (struct lmc_xinfo))) - return -EFAULT; - ret = 0; + sizeof(struct lmc_xinfo))) { + ret = -EFAULT; + else + ret = 0; break; @@ -262,9 +268,9 @@ int lmc_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd) /*fold00*/ if (copy_to_user(ifr->ifr_data, &sc->stats, sizeof (struct lmc_statistics))) - return -EFAULT; - - ret = 0; + ret = -EFAULT; + else + ret = 0; break; case LMCIOCCLEARLMCSTATS: /*fold01*/ @@ -292,8 +298,10 @@ int lmc_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd) /*fold00*/ break; } - if (copy_from_user(&ctl, ifr->ifr_data, sizeof (lmc_ctl_t))) - return -EFAULT; + if (copy_from_user(&ctl, ifr->ifr_data, sizeof(lmc_ctl_t))) { + ret = -EFAULT; + break; + } sc->lmc_media->set_circuit_type(sc, ctl.circuit_type); sc->ictl.circuit_type = ctl.circuit_type; ret = 0; @@ -318,12 +326,15 @@ int lmc_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd) /*fold00*/ #ifdef DEBUG case LMCIOCDUMPEVENTLOG: - if (copy_to_user(ifr->ifr_data, &lmcEventLogIndex, sizeof (u32))) - return -EFAULT; + if (copy_to_user(ifr->ifr_data, &lmcEventLogIndex, sizeof(u32))) { + ret = -EFAULT; + break; + } if (copy_to_user(ifr->ifr_data + sizeof (u32), lmcEventLogBuf, sizeof (lmcEventLogBuf))) - return -EFAULT; + ret = -EFAULT; + else + ret = 0; - ret = 0; break; #endif /* end ifdef _DBG_EVENTLOG */ case LMCIOCT1CONTROL: /*fold01*/ @@ -346,8 +357,10 @@ int lmc_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd) /*fold00*/ */ netif_stop_queue(dev); - if (copy_from_user(&xc, ifr->ifr_data, sizeof (struct lmc_xilinx_control))) - return -EFAULT; + if (copy_from_user(&xc, ifr->ifr_data, sizeof(struct lmc_xilinx_control))) { + ret = -EFAULT; + break; + } switch(xc.command){ case lmc_xilinx_reset: /*fold02*/ { diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index 9d9ff76a9bc..5058e60e570 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -2391,7 +2391,7 @@ out_requeue: if (b43_debug(dev, B43_DBG_PWORK_FAST)) delay = msecs_to_jiffies(50); else - delay = round_jiffies(HZ * 15); + delay = round_jiffies_relative(HZ * 15); queue_delayed_work(wl->hw->workqueue, &dev->periodic_work, delay); out: mutex_unlock(&wl->mutex); diff --git a/drivers/net/wireless/b43legacy/main.c b/drivers/net/wireless/b43legacy/main.c index d09479e816c..f0e56dfc9ec 100644 --- a/drivers/net/wireless/b43legacy/main.c +++ b/drivers/net/wireless/b43legacy/main.c @@ -2260,7 +2260,7 @@ out_requeue: if (b43legacy_debug(dev, B43legacy_DBG_PWORK_FAST)) delay = msecs_to_jiffies(50); else - delay = round_jiffies(HZ); + delay = round_jiffies_relative(HZ); queue_delayed_work(dev->wl->hw->workqueue, &dev->periodic_work, delay); out: diff --git a/drivers/net/wireless/ipw2100.c b/drivers/net/wireless/ipw2100.c index a6c7904de28..8d53d08b969 100644 --- a/drivers/net/wireless/ipw2100.c +++ b/drivers/net/wireless/ipw2100.c @@ -1769,7 +1769,7 @@ static int ipw2100_up(struct ipw2100_priv *priv, int deferred) if (priv->stop_rf_kill) { priv->stop_rf_kill = 0; queue_delayed_work(priv->workqueue, &priv->rf_kill, - round_jiffies(HZ)); + round_jiffies_relative(HZ)); } deferred = 1; @@ -2086,7 +2086,8 @@ static void isr_indicate_rf_kill(struct ipw2100_priv *priv, u32 status) /* Make sure the RF Kill check timer is running */ priv->stop_rf_kill = 0; cancel_delayed_work(&priv->rf_kill); - queue_delayed_work(priv->workqueue, &priv->rf_kill, round_jiffies(HZ)); + queue_delayed_work(priv->workqueue, &priv->rf_kill, + round_jiffies_relative(HZ)); } static void send_scan_event(void *data) @@ -2123,7 +2124,7 @@ static void isr_scan_complete(struct ipw2100_priv *priv, u32 status) if (!delayed_work_pending(&priv->scan_event_later)) queue_delayed_work(priv->workqueue, &priv->scan_event_later, - round_jiffies(msecs_to_jiffies(4000))); + round_jiffies_relative(msecs_to_jiffies(4000))); } else { priv->user_requested_scan = 0; cancel_delayed_work(&priv->scan_event_later); @@ -4242,7 +4243,7 @@ static int ipw_radio_kill_sw(struct ipw2100_priv *priv, int disable_radio) priv->stop_rf_kill = 0; cancel_delayed_work(&priv->rf_kill); queue_delayed_work(priv->workqueue, &priv->rf_kill, - round_jiffies(HZ)); + round_jiffies_relative(HZ)); } else schedule_reset(priv); } @@ -5981,7 +5982,7 @@ static void ipw2100_rf_kill(struct work_struct *work) IPW_DEBUG_RF_KILL("RF Kill active, rescheduling GPIO check\n"); if (!priv->stop_rf_kill) queue_delayed_work(priv->workqueue, &priv->rf_kill, - round_jiffies(HZ)); + round_jiffies_relative(HZ)); goto exit_unlock; } diff --git a/drivers/net/wireless/ipw2200.c b/drivers/net/wireless/ipw2200.c index e3c828401b9..54f44e5473c 100644 --- a/drivers/net/wireless/ipw2200.c +++ b/drivers/net/wireless/ipw2200.c @@ -1753,7 +1753,7 @@ static int ipw_radio_kill_sw(struct ipw_priv *priv, int disable_radio) /* Make sure the RF_KILL check timer is running */ cancel_delayed_work(&priv->rf_kill); queue_delayed_work(priv->workqueue, &priv->rf_kill, - round_jiffies(2 * HZ)); + round_jiffies_relative(2 * HZ)); } else queue_work(priv->workqueue, &priv->up); } @@ -4364,7 +4364,7 @@ static void handle_scan_event(struct ipw_priv *priv) if (!priv->user_requested_scan) { if (!delayed_work_pending(&priv->scan_event)) queue_delayed_work(priv->workqueue, &priv->scan_event, - round_jiffies(msecs_to_jiffies(4000))); + round_jiffies_relative(msecs_to_jiffies(4000))); } else { union iwreq_data wrqu; @@ -4728,7 +4728,7 @@ static void ipw_rx_notification(struct ipw_priv *priv, && priv->status & STATUS_ASSOCIATED) queue_delayed_work(priv->workqueue, &priv->request_scan, - round_jiffies(HZ)); + round_jiffies_relative(HZ)); /* Send an empty event to user space. * We don't send the received data on the event because diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index 557deebca1b..891f90d2f01 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -3232,9 +3232,7 @@ int iwl4965_tx_cmd(struct iwl_priv *priv, struct iwl_cmd *out_cmd, tx->rate_n_flags = iwl_hw_set_rate_n_flags(iwl_rates[rate_index].plcp, rate_flags); - if (ieee80211_is_probe_request(fc)) - tx->tx_flags |= TX_CMD_FLG_TSF_MSK; - else if (ieee80211_is_back_request(fc)) + if (ieee80211_is_back_request(fc)) tx->tx_flags |= TX_CMD_FLG_ACK_MSK | TX_CMD_FLG_IMM_BA_RSP_MASK; #ifdef CONFIG_IWLWIFI_HT @@ -3872,7 +3870,7 @@ static void iwl4965_rx_reply_rx(struct iwl_priv *priv, */ case IEEE80211_STYPE_ASSOC_RESP: case IEEE80211_STYPE_REASSOC_RESP: - if (network_packet && iwl_is_associated(priv)) { + if (network_packet) { #ifdef CONFIG_IWLWIFI_HT u8 *pos = NULL; struct ieee802_11_elems elems; diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 83019d1d7cc..4f22a7174ca 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -6478,8 +6478,9 @@ static void iwl_bg_scan_check(struct work_struct *data) IWL_DEBUG(IWL_DL_INFO | IWL_DL_SCAN, "Scan completion watchdog resetting adapter (%dms)\n", jiffies_to_msecs(IWL_SCAN_CHECK_WATCHDOG)); + if (!test_bit(STATUS_EXIT_PENDING, &priv->status)) - queue_work(priv->workqueue, &priv->restart); + iwl_send_scan_abort(priv); } mutex_unlock(&priv->mutex); } @@ -6575,7 +6576,7 @@ static void iwl_bg_request_scan(struct work_struct *data) spin_unlock_irqrestore(&priv->lock, flags); scan->suspend_time = 0; - scan->max_out_time = cpu_to_le32(600 * 1024); + scan->max_out_time = cpu_to_le32(200 * 1024); if (!interval) interval = suspend_time; /* @@ -6605,7 +6606,7 @@ static void iwl_bg_request_scan(struct work_struct *data) memcpy(scan->direct_scan[0].ssid, priv->direct_ssid, priv->direct_ssid_len); direct_mask = 1; - } else if (!iwl_is_associated(priv)) { + } else if (!iwl_is_associated(priv) && priv->essid_len) { scan->direct_scan[0].id = WLAN_EID_SSID; scan->direct_scan[0].len = priv->essid_len; memcpy(scan->direct_scan[0].ssid, priv->essid, priv->essid_len); @@ -6744,6 +6745,12 @@ static void iwl_bg_post_associate(struct work_struct *data) mutex_lock(&priv->mutex); + if (!priv->interface_id || !priv->is_open) { + mutex_unlock(&priv->mutex); + return; + } + iwl_scan_cancel_timeout(priv, 200); + conf = ieee80211_get_hw_conf(priv->hw); priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK; @@ -6882,9 +6889,19 @@ static void iwl_mac_stop(struct ieee80211_hw *hw) struct iwl_priv *priv = hw->priv; IWL_DEBUG_MAC80211("enter\n"); + + + mutex_lock(&priv->mutex); + /* stop mac, cancel any scan request and clear + * RXON_FILTER_ASSOC_MSK BIT + */ priv->is_open = 0; - /*netif_stop_queue(dev); */ - flush_workqueue(priv->workqueue); + iwl_scan_cancel_timeout(priv, 100); + cancel_delayed_work(&priv->post_associate); + priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK; + iwl_commit_rxon(priv); + mutex_unlock(&priv->mutex); + IWL_DEBUG_MAC80211("leave\n"); } @@ -7169,8 +7186,6 @@ static int iwl_mac_config_interface(struct ieee80211_hw *hw, int if_id, if (priv->iw_mode == IEEE80211_IF_TYPE_AP) iwl_config_ap(priv); else { - priv->staging_rxon.filter_flags |= - RXON_FILTER_ASSOC_MSK; rc = iwl_commit_rxon(priv); if ((priv->iw_mode == IEEE80211_IF_TYPE_STA) && rc) iwl_add_station(priv, @@ -7178,6 +7193,7 @@ static int iwl_mac_config_interface(struct ieee80211_hw *hw, int if_id, } } else { + iwl_scan_cancel_timeout(priv, 100); priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK; iwl_commit_rxon(priv); } @@ -7217,6 +7233,12 @@ static void iwl_mac_remove_interface(struct ieee80211_hw *hw, IWL_DEBUG_MAC80211("enter\n"); mutex_lock(&priv->mutex); + + iwl_scan_cancel_timeout(priv, 100); + cancel_delayed_work(&priv->post_associate); + priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK; + iwl_commit_rxon(priv); + if (priv->interface_id == conf->if_id) { priv->interface_id = 0; memset(priv->bssid, 0, ETH_ALEN); @@ -7238,6 +7260,7 @@ static int iwl_mac_hw_scan(struct ieee80211_hw *hw, u8 *ssid, size_t len) IWL_DEBUG_MAC80211("enter\n"); + mutex_lock(&priv->mutex); spin_lock_irqsave(&priv->lock, flags); if (!iwl_is_ready_rf(priv)) { @@ -7268,7 +7291,8 @@ static int iwl_mac_hw_scan(struct ieee80211_hw *hw, u8 *ssid, size_t len) priv->direct_ssid_len = (u8) min((u8) len, (u8) IW_ESSID_MAX_SIZE); memcpy(priv->direct_ssid, ssid, priv->direct_ssid_len); - } + } else + priv->one_direct_scan = 0; rc = iwl_scan_initiate(priv); @@ -7276,6 +7300,7 @@ static int iwl_mac_hw_scan(struct ieee80211_hw *hw, u8 *ssid, size_t len) out_unlock: spin_unlock_irqrestore(&priv->lock, flags); + mutex_unlock(&priv->mutex); return rc; } @@ -7310,6 +7335,8 @@ static int iwl_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, mutex_lock(&priv->mutex); + iwl_scan_cancel_timeout(priv, 100); + switch (cmd) { case SET_KEY: rc = iwl_update_sta_key_info(priv, key, sta_id); @@ -7479,8 +7506,18 @@ static void iwl_mac_reset_tsf(struct ieee80211_hw *hw) spin_unlock_irqrestore(&priv->lock, flags); + /* we are restarting association process + * clear RXON_FILTER_ASSOC_MSK bit + */ + if (priv->iw_mode != IEEE80211_IF_TYPE_AP) { + iwl_scan_cancel_timeout(priv, 100); + priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK; + iwl_commit_rxon(priv); + } + /* Per mac80211.h: This is only used in IBSS mode... */ if (priv->iw_mode != IEEE80211_IF_TYPE_IBSS) { + IWL_DEBUG_MAC80211("leave - not in IBSS\n"); mutex_unlock(&priv->mutex); return; @@ -8558,6 +8595,9 @@ static void iwl_pci_remove(struct pci_dev *pdev) iwl_rate_control_unregister(priv->hw); } + /*netif_stop_queue(dev); */ + flush_workqueue(priv->workqueue); + /* ieee80211_unregister_hw calls iwl_mac_stop, which flushes * priv->workqueue... so we can't take down the workqueue * until now... */ diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c index 5e1279263b2..d60adcb9bd4 100644 --- a/drivers/net/wireless/iwlwifi/iwl4965-base.c +++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c @@ -6845,8 +6845,9 @@ static void iwl_bg_scan_check(struct work_struct *data) IWL_DEBUG(IWL_DL_INFO | IWL_DL_SCAN, "Scan completion watchdog resetting adapter (%dms)\n", jiffies_to_msecs(IWL_SCAN_CHECK_WATCHDOG)); + if (!test_bit(STATUS_EXIT_PENDING, &priv->status)) - queue_work(priv->workqueue, &priv->restart); + iwl_send_scan_abort(priv); } mutex_unlock(&priv->mutex); } @@ -6942,7 +6943,7 @@ static void iwl_bg_request_scan(struct work_struct *data) spin_unlock_irqrestore(&priv->lock, flags); scan->suspend_time = 0; - scan->max_out_time = cpu_to_le32(600 * 1024); + scan->max_out_time = cpu_to_le32(200 * 1024); if (!interval) interval = suspend_time; @@ -6965,7 +6966,7 @@ static void iwl_bg_request_scan(struct work_struct *data) memcpy(scan->direct_scan[0].ssid, priv->direct_ssid, priv->direct_ssid_len); direct_mask = 1; - } else if (!iwl_is_associated(priv)) { + } else if (!iwl_is_associated(priv) && priv->essid_len) { scan->direct_scan[0].id = WLAN_EID_SSID; scan->direct_scan[0].len = priv->essid_len; memcpy(scan->direct_scan[0].ssid, priv->essid, priv->essid_len); @@ -7118,6 +7119,12 @@ static void iwl_bg_post_associate(struct work_struct *data) mutex_lock(&priv->mutex); + if (!priv->interface_id || !priv->is_open) { + mutex_unlock(&priv->mutex); + return; + } + iwl_scan_cancel_timeout(priv, 200); + conf = ieee80211_get_hw_conf(priv->hw); priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK; @@ -7271,9 +7278,19 @@ static void iwl_mac_stop(struct ieee80211_hw *hw) struct iwl_priv *priv = hw->priv; IWL_DEBUG_MAC80211("enter\n"); + + + mutex_lock(&priv->mutex); + /* stop mac, cancel any scan request and clear + * RXON_FILTER_ASSOC_MSK BIT + */ priv->is_open = 0; - /*netif_stop_queue(dev); */ - flush_workqueue(priv->workqueue); + iwl_scan_cancel_timeout(priv, 100); + cancel_delayed_work(&priv->post_associate); + priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK; + iwl_commit_rxon(priv); + mutex_unlock(&priv->mutex); + IWL_DEBUG_MAC80211("leave\n"); } @@ -7573,8 +7590,6 @@ static int iwl_mac_config_interface(struct ieee80211_hw *hw, int if_id, if (priv->iw_mode == IEEE80211_IF_TYPE_AP) iwl_config_ap(priv); else { - priv->staging_rxon.filter_flags |= - RXON_FILTER_ASSOC_MSK; rc = iwl_commit_rxon(priv); if ((priv->iw_mode == IEEE80211_IF_TYPE_STA) && rc) iwl_rxon_add_station( @@ -7582,6 +7597,7 @@ static int iwl_mac_config_interface(struct ieee80211_hw *hw, int if_id, } } else { + iwl_scan_cancel_timeout(priv, 100); priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK; iwl_commit_rxon(priv); } @@ -7621,6 +7637,12 @@ static void iwl_mac_remove_interface(struct ieee80211_hw *hw, IWL_DEBUG_MAC80211("enter\n"); mutex_lock(&priv->mutex); + + iwl_scan_cancel_timeout(priv, 100); + cancel_delayed_work(&priv->post_associate); + priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK; + iwl_commit_rxon(priv); + if (priv->interface_id == conf->if_id) { priv->interface_id = 0; memset(priv->bssid, 0, ETH_ALEN); @@ -7642,6 +7664,7 @@ static int iwl_mac_hw_scan(struct ieee80211_hw *hw, u8 *ssid, size_t len) IWL_DEBUG_MAC80211("enter\n"); + mutex_lock(&priv->mutex); spin_lock_irqsave(&priv->lock, flags); if (!iwl_is_ready_rf(priv)) { @@ -7672,7 +7695,8 @@ static int iwl_mac_hw_scan(struct ieee80211_hw *hw, u8 *ssid, size_t len) priv->direct_ssid_len = (u8) min((u8) len, (u8) IW_ESSID_MAX_SIZE); memcpy(priv->direct_ssid, ssid, priv->direct_ssid_len); - } + } else + priv->one_direct_scan = 0; rc = iwl_scan_initiate(priv); @@ -7680,6 +7704,7 @@ static int iwl_mac_hw_scan(struct ieee80211_hw *hw, u8 *ssid, size_t len) out_unlock: spin_unlock_irqrestore(&priv->lock, flags); + mutex_unlock(&priv->mutex); return rc; } @@ -7713,6 +7738,8 @@ static int iwl_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, mutex_lock(&priv->mutex); + iwl_scan_cancel_timeout(priv, 100); + switch (cmd) { case SET_KEY: rc = iwl_update_sta_key_info(priv, key, sta_id); @@ -7903,8 +7930,18 @@ static void iwl_mac_reset_tsf(struct ieee80211_hw *hw) spin_unlock_irqrestore(&priv->lock, flags); + /* we are restarting association process + * clear RXON_FILTER_ASSOC_MSK bit + */ + if (priv->iw_mode != IEEE80211_IF_TYPE_AP) { + iwl_scan_cancel_timeout(priv, 100); + priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK; + iwl_commit_rxon(priv); + } + /* Per mac80211.h: This is only used in IBSS mode... */ if (priv->iw_mode != IEEE80211_IF_TYPE_IBSS) { + IWL_DEBUG_MAC80211("leave - not in IBSS\n"); mutex_unlock(&priv->mutex); return; @@ -9152,6 +9189,9 @@ static void iwl_pci_remove(struct pci_dev *pdev) iwl_rate_control_unregister(priv->hw); } + /*netif_stop_queue(dev); */ + flush_workqueue(priv->workqueue); + /* ieee80211_unregister_hw calls iwl_mac_stop, which flushes * priv->workqueue... so we can't take down the workqueue * until now... */ diff --git a/drivers/net/wireless/rt2x00/rt2x00lib.h b/drivers/net/wireless/rt2x00/rt2x00lib.h index 298faa9d3f6..06d9bc0015c 100644 --- a/drivers/net/wireless/rt2x00/rt2x00lib.h +++ b/drivers/net/wireless/rt2x00/rt2x00lib.h @@ -30,7 +30,7 @@ * Interval defines * Both the link tuner as the rfkill will be called once per second. */ -#define LINK_TUNE_INTERVAL ( round_jiffies(HZ) ) +#define LINK_TUNE_INTERVAL ( round_jiffies_relative(HZ) ) #define RFKILL_POLL_INTERVAL ( 1000 ) /* diff --git a/drivers/net/wireless/rtl8187_dev.c b/drivers/net/wireless/rtl8187_dev.c index de61c8fe649..e454ae83e97 100644 --- a/drivers/net/wireless/rtl8187_dev.c +++ b/drivers/net/wireless/rtl8187_dev.c @@ -433,6 +433,9 @@ static int rtl8187_start(struct ieee80211_hw *dev) rtl818x_iowrite16(priv, &priv->map->INT_MASK, 0xFFFF); + rtl818x_iowrite32(priv, &priv->map->MAR[0], ~0); + rtl818x_iowrite32(priv, &priv->map->MAR[1], ~0); + rtl8187_init_urbs(dev); reg = RTL818X_RX_CONF_ONLYERLPKT | @@ -582,32 +585,31 @@ static int rtl8187_config_interface(struct ieee80211_hw *dev, int if_id, static void rtl8187_configure_filter(struct ieee80211_hw *dev, unsigned int changed_flags, unsigned int *total_flags, - int mc_count, struct dev_addr_list *mc_list) + int mc_count, struct dev_addr_list *mclist) { struct rtl8187_priv *priv = dev->priv; - *total_flags = 0; - - if (changed_flags & FIF_ALLMULTI) - priv->rx_conf ^= RTL818X_RX_CONF_MULTICAST; if (changed_flags & FIF_FCSFAIL) priv->rx_conf ^= RTL818X_RX_CONF_FCS; if (changed_flags & FIF_CONTROL) priv->rx_conf ^= RTL818X_RX_CONF_CTRL; if (changed_flags & FIF_OTHER_BSS) priv->rx_conf ^= RTL818X_RX_CONF_MONITOR; - - if (mc_count > 0) + if (*total_flags & FIF_ALLMULTI || mc_count > 0) priv->rx_conf |= RTL818X_RX_CONF_MULTICAST; + else + priv->rx_conf &= ~RTL818X_RX_CONF_MULTICAST; + + *total_flags = 0; - if (priv->rx_conf & RTL818X_RX_CONF_MULTICAST) - *total_flags |= FIF_ALLMULTI; if (priv->rx_conf & RTL818X_RX_CONF_FCS) *total_flags |= FIF_FCSFAIL; if (priv->rx_conf & RTL818X_RX_CONF_CTRL) *total_flags |= FIF_CONTROL; if (priv->rx_conf & RTL818X_RX_CONF_MONITOR) *total_flags |= FIF_OTHER_BSS; + if (priv->rx_conf & RTL818X_RX_CONF_MULTICAST) + *total_flags |= FIF_ALLMULTI; rtl818x_iowrite32_async(priv, &priv->map->RX_CONF, priv->rx_conf); } diff --git a/drivers/pci/intel-iommu.c b/drivers/pci/intel-iommu.c index 0c4ab3b0727..e079a5237c9 100644 --- a/drivers/pci/intel-iommu.c +++ b/drivers/pci/intel-iommu.c @@ -34,7 +34,7 @@ #include "intel-iommu.h" #include <asm/proto.h> /* force_iommu in this header in x86-64*/ #include <asm/cacheflush.h> -#include <asm/iommu.h> +#include <asm/gart.h> #include "pci.h" #define IS_GFX_DEVICE(pdev) ((pdev->class >> 16) == PCI_BASE_CLASS_DISPLAY) @@ -745,12 +745,12 @@ static char *fault_reason_strings[] = "non-zero reserved fields in PTE", "Unknown" }; -#define MAX_FAULT_REASON_IDX ARRAY_SIZE(fault_reason_strings) +#define MAX_FAULT_REASON_IDX ARRAY_SIZE(fault_reason_strings) - 1 char *dmar_get_fault_reason(u8 fault_reason) { - if (fault_reason > MAX_FAULT_REASON_IDX) - return fault_reason_strings[MAX_FAULT_REASON_IDX]; + if (fault_reason >= MAX_FAULT_REASON_IDX) + return fault_reason_strings[MAX_FAULT_REASON_IDX - 1]; else return fault_reason_strings[fault_reason]; } @@ -995,7 +995,6 @@ static struct intel_iommu *alloc_iommu(struct dmar_drhd_unit *drhd) return iommu; error_unmap: iounmap(iommu->reg); - iommu->reg = 0; error: kfree(iommu); return NULL; @@ -1808,7 +1807,7 @@ get_valid_domain_for_dev(struct pci_dev *pdev) if (!domain) { printk(KERN_ERR "Allocating domain for %s failed", pci_name(pdev)); - return 0; + return NULL; } /* make sure context mapping is ok */ @@ -1818,7 +1817,7 @@ get_valid_domain_for_dev(struct pci_dev *pdev) printk(KERN_ERR "Domain context map for %s failed", pci_name(pdev)); - return 0; + return NULL; } } diff --git a/drivers/pci/intel-iommu.h b/drivers/pci/intel-iommu.h index ee88dd2400c..459ad1f9dc5 100644 --- a/drivers/pci/intel-iommu.h +++ b/drivers/pci/intel-iommu.h @@ -58,7 +58,7 @@ hi = readl(dmar + reg + 4); \ (((u64) hi) << 32) + lo; }) */ -static inline u64 dmar_readq(void *addr) +static inline u64 dmar_readq(void __iomem *addr) { u32 lo, hi; lo = readl(addr); diff --git a/drivers/rtc/rtc-s3c.c b/drivers/rtc/rtc-s3c.c index 8c1012b432b..e2041b4d0c8 100644 --- a/drivers/rtc/rtc-s3c.c +++ b/drivers/rtc/rtc-s3c.c @@ -542,8 +542,6 @@ static int s3c_rtc_probe(struct platform_device *pdev) /* RTC Power management control */ -static struct timespec s3c_rtc_delta; - static int ticnt_save; static int s3c_rtc_suspend(struct platform_device *pdev, pm_message_t state) diff --git a/drivers/s390/scsi/zfcp_def.h b/drivers/s390/scsi/zfcp_def.h index 0754542978b..e268f79bdbd 100644 --- a/drivers/s390/scsi/zfcp_def.h +++ b/drivers/s390/scsi/zfcp_def.h @@ -70,11 +70,12 @@ zfcp_sg_to_address(struct scatterlist *list) * zfcp_address_to_sg - set up struct scatterlist from kernel address * @address: kernel address * @list: struct scatterlist + * @size: buffer size */ static inline void -zfcp_address_to_sg(void *address, struct scatterlist *list) +zfcp_address_to_sg(void *address, struct scatterlist *list, unsigned int size) { - sg_set_buf(list, address, 0); + sg_set_buf(list, address, size); } #define REQUEST_LIST_SIZE 128 diff --git a/drivers/scsi/aacraid/commctrl.c b/drivers/scsi/aacraid/commctrl.c index 72b0393b459..1e6d7a9c75b 100644 --- a/drivers/scsi/aacraid/commctrl.c +++ b/drivers/scsi/aacraid/commctrl.c @@ -391,7 +391,7 @@ static int close_getadapter_fib(struct aac_dev * dev, void __user *arg) /* * Extract the fibctx from the input parameters */ - if (fibctx->unique == (u32)(ptrdiff_t)arg) /* We found a winner */ + if (fibctx->unique == (u32)(uintptr_t)arg) /* We found a winner */ break; entry = entry->next; fibctx = NULL; @@ -590,7 +590,7 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg) } addr = (u64)upsg->sg[i].addr[0]; addr += ((u64)upsg->sg[i].addr[1]) << 32; - sg_user[i] = (void __user *)(ptrdiff_t)addr; + sg_user[i] = (void __user *)(uintptr_t)addr; sg_list[i] = p; // save so we can clean up later sg_indx = i; @@ -633,7 +633,7 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg) rcode = -ENOMEM; goto cleanup; } - sg_user[i] = (void __user *)(ptrdiff_t)usg->sg[i].addr; + sg_user[i] = (void __user *)(uintptr_t)usg->sg[i].addr; sg_list[i] = p; // save so we can clean up later sg_indx = i; @@ -664,7 +664,7 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg) if (actual_fibsize64 == fibsize) { struct user_sgmap64* usg = (struct user_sgmap64 *)upsg; for (i = 0; i < upsg->count; i++) { - u64 addr; + uintptr_t addr; void* p; /* Does this really need to be GFP_DMA? */ p = kmalloc(usg->sg[i].count,GFP_KERNEL|__GFP_DMA); @@ -676,7 +676,7 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg) } addr = (u64)usg->sg[i].addr[0]; addr += ((u64)usg->sg[i].addr[1]) << 32; - sg_user[i] = (void __user *)(ptrdiff_t)addr; + sg_user[i] = (void __user *)addr; sg_list[i] = p; // save so we can clean up later sg_indx = i; @@ -704,7 +704,7 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg) rcode = -ENOMEM; goto cleanup; } - sg_user[i] = (void __user *)(ptrdiff_t)upsg->sg[i].addr; + sg_user[i] = (void __user *)(uintptr_t)upsg->sg[i].addr; sg_list[i] = p; // save so we can clean up later sg_indx = i; diff --git a/drivers/scsi/aacraid/comminit.c b/drivers/scsi/aacraid/comminit.c index 3009ad8c407..8736813a029 100644 --- a/drivers/scsi/aacraid/comminit.c +++ b/drivers/scsi/aacraid/comminit.c @@ -110,7 +110,7 @@ static int aac_alloc_comm(struct aac_dev *dev, void **commaddr, unsigned long co /* * Align the beginning of Headers to commalign */ - align = (commalign - ((ptrdiff_t)(base) & (commalign - 1))); + align = (commalign - ((uintptr_t)(base) & (commalign - 1))); base = base + align; phys = phys + align; /* diff --git a/drivers/scsi/aacraid/dpcsup.c b/drivers/scsi/aacraid/dpcsup.c index fcd25f7d0bc..e6032ffc66a 100644 --- a/drivers/scsi/aacraid/dpcsup.c +++ b/drivers/scsi/aacraid/dpcsup.c @@ -254,7 +254,7 @@ unsigned int aac_intr_normal(struct aac_dev * dev, u32 Index) kfree (fib); return 1; } - memcpy(hw_fib, (struct hw_fib *)(((ptrdiff_t)(dev->regs.sa)) + + memcpy(hw_fib, (struct hw_fib *)(((uintptr_t)(dev->regs.sa)) + (index & ~0x00000002L)), sizeof(struct hw_fib)); INIT_LIST_HEAD(&fib->fiblink); fib->type = FSAFS_NTC_FIB_CONTEXT; diff --git a/drivers/scsi/arcmsr/arcmsr.h b/drivers/scsi/arcmsr/arcmsr.h index ace7a15b413..a67e29f83ae 100644 --- a/drivers/scsi/arcmsr/arcmsr.h +++ b/drivers/scsi/arcmsr/arcmsr.h @@ -141,14 +141,14 @@ struct CMD_MESSAGE_FIELD #define IS_SG64_ADDR 0x01000000 /* bit24 */ struct SG32ENTRY { - uint32_t length; - uint32_t address; + __le32 length; + __le32 address; }; struct SG64ENTRY { - uint32_t length; - uint32_t address; - uint32_t addresshigh; + __le32 length; + __le32 address; + __le32 addresshigh; }; struct SGENTRY_UNION { @@ -339,23 +339,15 @@ struct MessageUnit_B uint32_t done_qbuffer[ARCMSR_MAX_HBB_POSTQUEUE]; uint32_t postq_index; uint32_t doneq_index; - uint32_t *drv2iop_doorbell_reg; - uint32_t *drv2iop_doorbell_mask_reg; - uint32_t *iop2drv_doorbell_reg; - uint32_t *iop2drv_doorbell_mask_reg; - uint32_t *msgcode_rwbuffer_reg; - uint32_t *ioctl_wbuffer_reg; - uint32_t *ioctl_rbuffer_reg; + uint32_t __iomem *drv2iop_doorbell_reg; + uint32_t __iomem *drv2iop_doorbell_mask_reg; + uint32_t __iomem *iop2drv_doorbell_reg; + uint32_t __iomem *iop2drv_doorbell_mask_reg; + uint32_t __iomem *msgcode_rwbuffer_reg; + uint32_t __iomem *ioctl_wbuffer_reg; + uint32_t __iomem *ioctl_rbuffer_reg; }; -struct MessageUnit -{ - union - { - struct MessageUnit_A pmu_A; - struct MessageUnit_B pmu_B; - } u; -}; /* ******************************************************************************* ** Adapter Control Block @@ -374,7 +366,10 @@ struct AdapterControlBlock /* Offset is used in making arc cdb physical to virtual calculations */ uint32_t outbound_int_enable; - struct MessageUnit * pmu; + union { + struct MessageUnit_A __iomem * pmuA; + struct MessageUnit_B * pmuB; + }; /* message unit ATU inbound base address0 */ uint32_t acb_flags; @@ -558,7 +553,7 @@ struct SENSE_DATA extern void arcmsr_post_ioctldata2iop(struct AdapterControlBlock *); extern void arcmsr_iop_message_read(struct AdapterControlBlock *); -extern struct QBUFFER *arcmsr_get_iop_rqbuffer(struct AdapterControlBlock *); +extern struct QBUFFER __iomem *arcmsr_get_iop_rqbuffer(struct AdapterControlBlock *); extern struct class_device_attribute *arcmsr_host_attrs[]; extern int arcmsr_alloc_sysfs_attr(struct AdapterControlBlock *); void arcmsr_free_sysfs_attr(struct AdapterControlBlock *acb); diff --git a/drivers/scsi/arcmsr/arcmsr_attr.c b/drivers/scsi/arcmsr/arcmsr_attr.c index d04d1aa28fa..7d7b0a55427 100644 --- a/drivers/scsi/arcmsr/arcmsr_attr.c +++ b/drivers/scsi/arcmsr/arcmsr_attr.c @@ -85,13 +85,13 @@ static ssize_t arcmsr_sysfs_iop_message_read(struct kobject *kobj, allxfer_len++; } if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { - struct QBUFFER *prbuffer; - uint8_t *iop_data; + struct QBUFFER __iomem *prbuffer; + uint8_t __iomem *iop_data; int32_t iop_len; acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; prbuffer = arcmsr_get_iop_rqbuffer(acb); - iop_data = (uint8_t *)prbuffer->data; + iop_data = prbuffer->data; iop_len = readl(&prbuffer->data_len); while (iop_len > 0) { acb->rqbuffer[acb->rqbuf_lastindex] = readb(iop_data); diff --git a/drivers/scsi/arcmsr/arcmsr_hba.c b/drivers/scsi/arcmsr/arcmsr_hba.c index f7a252885a5..d466a2dac1d 100644 --- a/drivers/scsi/arcmsr/arcmsr_hba.c +++ b/drivers/scsi/arcmsr/arcmsr_hba.c @@ -236,18 +236,22 @@ static int arcmsr_alloc_ccb_pool(struct AdapterControlBlock *acb) uint32_t intmask_org; int i, j; - acb->pmu = ioremap(pci_resource_start(pdev, 0), pci_resource_len(pdev, 0)); - if (!acb->pmu) { + acb->pmuA = ioremap(pci_resource_start(pdev, 0), pci_resource_len(pdev, 0)); + if (!acb->pmuA) { printk(KERN_NOTICE "arcmsr%d: memory mapping region fail \n", acb->host->host_no); + return -ENOMEM; } dma_coherent = dma_alloc_coherent(&pdev->dev, ARCMSR_MAX_FREECCB_NUM * sizeof (struct CommandControlBlock) + 0x20, &dma_coherent_handle, GFP_KERNEL); - if (!dma_coherent) + + if (!dma_coherent) { + iounmap(acb->pmuA); return -ENOMEM; + } acb->dma_coherent = dma_coherent; acb->dma_coherent_handle = dma_coherent_handle; @@ -287,7 +291,7 @@ static int arcmsr_alloc_ccb_pool(struct AdapterControlBlock *acb) struct pci_dev *pdev = acb->pdev; struct MessageUnit_B *reg; - void *mem_base0, *mem_base1; + void __iomem *mem_base0, *mem_base1; void *dma_coherent; dma_addr_t dma_coherent_handle, dma_addr; uint32_t intmask_org; @@ -328,25 +332,28 @@ static int arcmsr_alloc_ccb_pool(struct AdapterControlBlock *acb) reg = (struct MessageUnit_B *)(dma_coherent + ARCMSR_MAX_FREECCB_NUM * sizeof(struct CommandControlBlock)); - acb->pmu = (struct MessageUnit *)reg; + acb->pmuB = reg; mem_base0 = ioremap(pci_resource_start(pdev, 0), pci_resource_len(pdev, 0)); + if (!mem_base0) + goto out; + mem_base1 = ioremap(pci_resource_start(pdev, 2), pci_resource_len(pdev, 2)); - reg->drv2iop_doorbell_reg = (uint32_t *)((char *)mem_base0 + - ARCMSR_DRV2IOP_DOORBELL); - reg->drv2iop_doorbell_mask_reg = (uint32_t *)((char *)mem_base0 + - ARCMSR_DRV2IOP_DOORBELL_MASK); - reg->iop2drv_doorbell_reg = (uint32_t *)((char *)mem_base0 + - ARCMSR_IOP2DRV_DOORBELL); - reg->iop2drv_doorbell_mask_reg = (uint32_t *)((char *)mem_base0 + - ARCMSR_IOP2DRV_DOORBELL_MASK); - reg->ioctl_wbuffer_reg = (uint32_t *)((char *)mem_base1 + - ARCMSR_IOCTL_WBUFFER); - reg->ioctl_rbuffer_reg = (uint32_t *)((char *)mem_base1 + - ARCMSR_IOCTL_RBUFFER); - reg->msgcode_rwbuffer_reg = (uint32_t *)((char *)mem_base1 + - ARCMSR_MSGCODE_RWBUFFER); + if (!mem_base1) { + iounmap(mem_base0); + goto out; + } + + reg->drv2iop_doorbell_reg = mem_base0 + ARCMSR_DRV2IOP_DOORBELL; + reg->drv2iop_doorbell_mask_reg = mem_base0 + + ARCMSR_DRV2IOP_DOORBELL_MASK; + reg->iop2drv_doorbell_reg = mem_base0 + ARCMSR_IOP2DRV_DOORBELL; + reg->iop2drv_doorbell_mask_reg = mem_base0 + + ARCMSR_IOP2DRV_DOORBELL_MASK; + reg->ioctl_wbuffer_reg = mem_base1 + ARCMSR_IOCTL_WBUFFER; + reg->ioctl_rbuffer_reg = mem_base1 + ARCMSR_IOCTL_RBUFFER; + reg->msgcode_rwbuffer_reg = mem_base1 + ARCMSR_MSGCODE_RWBUFFER; acb->vir2phy_offset = (unsigned long)ccb_tmp -(unsigned long)dma_addr; for (i = 0; i < ARCMSR_MAX_TARGETID; i++) @@ -362,6 +369,12 @@ static int arcmsr_alloc_ccb_pool(struct AdapterControlBlock *acb) break; } return 0; + +out: + dma_free_coherent(&acb->pdev->dev, + ARCMSR_MAX_FREECCB_NUM * sizeof(struct CommandControlBlock) + 0x20, + acb->dma_coherent, acb->dma_coherent_handle); + return -ENOMEM; } static int arcmsr_probe(struct pci_dev *pdev, @@ -454,7 +467,6 @@ static int arcmsr_probe(struct pci_dev *pdev, free_irq(pdev->irq, acb); out_free_ccb_pool: arcmsr_free_ccb_pool(acb); - iounmap(acb->pmu); out_release_regions: pci_release_regions(pdev); out_host_put: @@ -467,7 +479,7 @@ static int arcmsr_probe(struct pci_dev *pdev, static uint8_t arcmsr_hba_wait_msgint_ready(struct AdapterControlBlock *acb) { - struct MessageUnit_A __iomem *reg = (struct MessageUnit_A *)acb->pmu; + struct MessageUnit_A __iomem *reg = acb->pmuA; uint32_t Index; uint8_t Retries = 0x00; @@ -488,7 +500,7 @@ static uint8_t arcmsr_hba_wait_msgint_ready(struct AdapterControlBlock *acb) static uint8_t arcmsr_hbb_wait_msgint_ready(struct AdapterControlBlock *acb) { - struct MessageUnit_B *reg = (struct MessageUnit_B *)acb->pmu; + struct MessageUnit_B *reg = acb->pmuB; uint32_t Index; uint8_t Retries = 0x00; @@ -509,7 +521,7 @@ static uint8_t arcmsr_hbb_wait_msgint_ready(struct AdapterControlBlock *acb) static void arcmsr_abort_hba_allcmd(struct AdapterControlBlock *acb) { - struct MessageUnit_A __iomem *reg = (struct MessageUnit_A *)acb->pmu; + struct MessageUnit_A __iomem *reg = acb->pmuA; writel(ARCMSR_INBOUND_MESG0_ABORT_CMD, ®->inbound_msgaddr0); if (arcmsr_hba_wait_msgint_ready(acb)) @@ -520,7 +532,7 @@ static void arcmsr_abort_hba_allcmd(struct AdapterControlBlock *acb) static void arcmsr_abort_hbb_allcmd(struct AdapterControlBlock *acb) { - struct MessageUnit_B *reg = (struct MessageUnit_B *)acb->pmu; + struct MessageUnit_B *reg = acb->pmuB; writel(ARCMSR_MESSAGE_ABORT_CMD, reg->drv2iop_doorbell_reg); if (arcmsr_hbb_wait_msgint_ready(acb)) @@ -566,7 +578,7 @@ static void arcmsr_ccb_complete(struct CommandControlBlock *ccb, int stand_flag) static void arcmsr_flush_hba_cache(struct AdapterControlBlock *acb) { - struct MessageUnit_A __iomem *reg = (struct MessageUnit_A *)acb->pmu; + struct MessageUnit_A __iomem *reg = acb->pmuA; int retry_count = 30; writel(ARCMSR_INBOUND_MESG0_FLUSH_CACHE, ®->inbound_msgaddr0); @@ -583,7 +595,7 @@ static void arcmsr_flush_hba_cache(struct AdapterControlBlock *acb) static void arcmsr_flush_hbb_cache(struct AdapterControlBlock *acb) { - struct MessageUnit_B *reg = (struct MessageUnit_B *)acb->pmu; + struct MessageUnit_B *reg = acb->pmuB; int retry_count = 30; writel(ARCMSR_MESSAGE_FLUSH_CACHE, reg->drv2iop_doorbell_reg); @@ -637,7 +649,7 @@ static u32 arcmsr_disable_outbound_ints(struct AdapterControlBlock *acb) switch (acb->adapter_type) { case ACB_ADAPTER_TYPE_A : { - struct MessageUnit_A __iomem *reg = (struct MessageUnit_A *)acb->pmu; + struct MessageUnit_A __iomem *reg = acb->pmuA; orig_mask = readl(®->outbound_intmask)|\ ARCMSR_MU_OUTBOUND_MESSAGE0_INTMASKENABLE; writel(orig_mask|ARCMSR_MU_OUTBOUND_ALL_INTMASKENABLE, \ @@ -646,7 +658,7 @@ static u32 arcmsr_disable_outbound_ints(struct AdapterControlBlock *acb) break; case ACB_ADAPTER_TYPE_B : { - struct MessageUnit_B *reg = (struct MessageUnit_B *)acb->pmu; + struct MessageUnit_B *reg = acb->pmuB; orig_mask = readl(reg->iop2drv_doorbell_mask_reg) & \ (~ARCMSR_IOP2DRV_MESSAGE_CMD_DONE); writel(0, reg->iop2drv_doorbell_mask_reg); @@ -748,14 +760,13 @@ static void arcmsr_done4abort_postqueue(struct AdapterControlBlock *acb) switch (acb->adapter_type) { case ACB_ADAPTER_TYPE_A: { - struct MessageUnit_A __iomem *reg = \ - (struct MessageUnit_A *)acb->pmu; + struct MessageUnit_A __iomem *reg = acb->pmuA; uint32_t outbound_intstatus; - outbound_intstatus = readl(®->outbound_intstatus) & \ + outbound_intstatus = readl(®->outbound_intstatus) & acb->outbound_int_enable; /*clear and abort all outbound posted Q*/ writel(outbound_intstatus, ®->outbound_intstatus);/*clear interrupt*/ - while (((flag_ccb = readl(®->outbound_queueport)) != 0xFFFFFFFF) \ + while (((flag_ccb = readl(®->outbound_queueport)) != 0xFFFFFFFF) && (i++ < ARCMSR_MAX_OUTSTANDING_CMD)) { arcmsr_drain_donequeue(acb, flag_ccb); } @@ -763,7 +774,7 @@ static void arcmsr_done4abort_postqueue(struct AdapterControlBlock *acb) break; case ACB_ADAPTER_TYPE_B: { - struct MessageUnit_B *reg = (struct MessageUnit_B *)acb->pmu; + struct MessageUnit_B *reg = acb->pmuB; /*clear all outbound posted Q*/ for (i = 0; i < ARCMSR_MAX_HBB_POSTQUEUE; i++) { if ((flag_ccb = readl(®->done_qbuffer[i])) != 0) { @@ -816,7 +827,6 @@ static void arcmsr_remove(struct pci_dev *pdev) } free_irq(pdev->irq, acb); - iounmap(acb->pmu); arcmsr_free_ccb_pool(acb); pci_release_regions(pdev); @@ -859,7 +869,7 @@ static void arcmsr_enable_outbound_ints(struct AdapterControlBlock *acb, \ switch (acb->adapter_type) { case ACB_ADAPTER_TYPE_A : { - struct MessageUnit_A __iomem *reg = (struct MessageUnit_A *)acb->pmu; + struct MessageUnit_A __iomem *reg = acb->pmuA; mask = intmask_org & ~(ARCMSR_MU_OUTBOUND_POSTQUEUE_INTMASKENABLE | ARCMSR_MU_OUTBOUND_DOORBELL_INTMASKENABLE); writel(mask, ®->outbound_intmask); @@ -868,7 +878,7 @@ static void arcmsr_enable_outbound_ints(struct AdapterControlBlock *acb, \ break; case ACB_ADAPTER_TYPE_B : { - struct MessageUnit_B *reg = (struct MessageUnit_B *)acb->pmu; + struct MessageUnit_B *reg = acb->pmuB; mask = intmask_org | (ARCMSR_IOP2DRV_DATA_WRITE_OK | \ ARCMSR_IOP2DRV_DATA_READ_OK | ARCMSR_IOP2DRV_CDB_DONE); writel(mask, reg->iop2drv_doorbell_mask_reg); @@ -882,7 +892,7 @@ static void arcmsr_build_ccb(struct AdapterControlBlock *acb, { struct ARCMSR_CDB *arcmsr_cdb = (struct ARCMSR_CDB *)&ccb->arcmsr_cdb; int8_t *psge = (int8_t *)&arcmsr_cdb->u; - uint32_t address_lo, address_hi; + __le32 address_lo, address_hi; int arccdbsize = 0x30; int nseg; @@ -900,7 +910,8 @@ static void arcmsr_build_ccb(struct AdapterControlBlock *acb, BUG_ON(nseg < 0); if (nseg) { - int length, i, cdb_sgcount = 0; + __le32 length; + int i, cdb_sgcount = 0; struct scatterlist *sg; /* map stor port SG list to our iop SG List. */ @@ -921,7 +932,7 @@ static void arcmsr_build_ccb(struct AdapterControlBlock *acb, pdma_sg->addresshigh = address_hi; pdma_sg->address = address_lo; - pdma_sg->length = length|IS_SG64_ADDR; + pdma_sg->length = length|cpu_to_le32(IS_SG64_ADDR); psge += sizeof (struct SG64ENTRY); arccdbsize += sizeof (struct SG64ENTRY); } @@ -947,7 +958,7 @@ static void arcmsr_post_ccb(struct AdapterControlBlock *acb, struct CommandContr switch (acb->adapter_type) { case ACB_ADAPTER_TYPE_A: { - struct MessageUnit_A *reg = (struct MessageUnit_A *)acb->pmu; + struct MessageUnit_A __iomem *reg = acb->pmuA; if (arcmsr_cdb->Flags & ARCMSR_CDB_FLAG_SGL_BSIZE) writel(cdb_shifted_phyaddr | ARCMSR_CCBPOST_FLAG_SGL_BSIZE, @@ -959,7 +970,7 @@ static void arcmsr_post_ccb(struct AdapterControlBlock *acb, struct CommandContr break; case ACB_ADAPTER_TYPE_B: { - struct MessageUnit_B *reg = (struct MessageUnit_B *)acb->pmu; + struct MessageUnit_B *reg = acb->pmuB; uint32_t ending_index, index = reg->postq_index; ending_index = ((index + 1) % ARCMSR_MAX_HBB_POSTQUEUE); @@ -982,7 +993,7 @@ static void arcmsr_post_ccb(struct AdapterControlBlock *acb, struct CommandContr static void arcmsr_stop_hba_bgrb(struct AdapterControlBlock *acb) { - struct MessageUnit_A __iomem *reg = (struct MessageUnit_A *)acb->pmu; + struct MessageUnit_A __iomem *reg = acb->pmuA; acb->acb_flags &= ~ACB_F_MSG_START_BGRB; writel(ARCMSR_INBOUND_MESG0_STOP_BGRB, ®->inbound_msgaddr0); @@ -995,7 +1006,7 @@ static void arcmsr_stop_hba_bgrb(struct AdapterControlBlock *acb) static void arcmsr_stop_hbb_bgrb(struct AdapterControlBlock *acb) { - struct MessageUnit_B *reg = (struct MessageUnit_B *)acb->pmu; + struct MessageUnit_B *reg = acb->pmuB; acb->acb_flags &= ~ACB_F_MSG_START_BGRB; writel(ARCMSR_MESSAGE_STOP_BGRB, reg->drv2iop_doorbell_reg); @@ -1023,6 +1034,17 @@ static void arcmsr_stop_adapter_bgrb(struct AdapterControlBlock *acb) static void arcmsr_free_ccb_pool(struct AdapterControlBlock *acb) { + switch (acb->adapter_type) { + case ACB_ADAPTER_TYPE_A: { + iounmap(acb->pmuA); + break; + } + case ACB_ADAPTER_TYPE_B: { + struct MessageUnit_B *reg = acb->pmuB; + iounmap(reg->drv2iop_doorbell_reg - ARCMSR_DRV2IOP_DOORBELL); + iounmap(reg->ioctl_wbuffer_reg - ARCMSR_IOCTL_WBUFFER); + } + } dma_free_coherent(&acb->pdev->dev, ARCMSR_MAX_FREECCB_NUM * sizeof (struct CommandControlBlock) + 0x20, acb->dma_coherent, @@ -1033,13 +1055,13 @@ void arcmsr_iop_message_read(struct AdapterControlBlock *acb) { switch (acb->adapter_type) { case ACB_ADAPTER_TYPE_A: { - struct MessageUnit_A __iomem *reg = (struct MessageUnit_A *)acb->pmu; + struct MessageUnit_A __iomem *reg = acb->pmuA; writel(ARCMSR_INBOUND_DRIVER_DATA_READ_OK, ®->inbound_doorbell); } break; case ACB_ADAPTER_TYPE_B: { - struct MessageUnit_B *reg = (struct MessageUnit_B *)acb->pmu; + struct MessageUnit_B *reg = acb->pmuB; writel(ARCMSR_DRV2IOP_DATA_READ_OK, reg->drv2iop_doorbell_reg); } break; @@ -1050,7 +1072,7 @@ static void arcmsr_iop_message_wrote(struct AdapterControlBlock *acb) { switch (acb->adapter_type) { case ACB_ADAPTER_TYPE_A: { - struct MessageUnit_A __iomem *reg = (struct MessageUnit_A *)acb->pmu; + struct MessageUnit_A __iomem *reg = acb->pmuA; /* ** push inbound doorbell tell iop, driver data write ok ** and wait reply on next hwinterrupt for next Qbuffer post @@ -1060,7 +1082,7 @@ static void arcmsr_iop_message_wrote(struct AdapterControlBlock *acb) break; case ACB_ADAPTER_TYPE_B: { - struct MessageUnit_B *reg = (struct MessageUnit_B *)acb->pmu; + struct MessageUnit_B *reg = acb->pmuB; /* ** push inbound doorbell tell iop, driver data write ok ** and wait reply on next hwinterrupt for next Qbuffer post @@ -1071,41 +1093,41 @@ static void arcmsr_iop_message_wrote(struct AdapterControlBlock *acb) } } -struct QBUFFER *arcmsr_get_iop_rqbuffer(struct AdapterControlBlock *acb) +struct QBUFFER __iomem *arcmsr_get_iop_rqbuffer(struct AdapterControlBlock *acb) { - static struct QBUFFER *qbuffer; + struct QBUFFER __iomem *qbuffer = NULL; switch (acb->adapter_type) { case ACB_ADAPTER_TYPE_A: { - struct MessageUnit_A __iomem *reg = (struct MessageUnit_A *)acb->pmu; - qbuffer = (struct QBUFFER __iomem *) ®->message_rbuffer; + struct MessageUnit_A __iomem *reg = acb->pmuA; + qbuffer = (struct QBUFFER __iomem *)®->message_rbuffer; } break; case ACB_ADAPTER_TYPE_B: { - struct MessageUnit_B *reg = (struct MessageUnit_B *)acb->pmu; - qbuffer = (struct QBUFFER __iomem *) reg->ioctl_rbuffer_reg; + struct MessageUnit_B *reg = acb->pmuB; + qbuffer = (struct QBUFFER __iomem *)reg->ioctl_rbuffer_reg; } break; } return qbuffer; } -static struct QBUFFER *arcmsr_get_iop_wqbuffer(struct AdapterControlBlock *acb) +static struct QBUFFER __iomem *arcmsr_get_iop_wqbuffer(struct AdapterControlBlock *acb) { - static struct QBUFFER *pqbuffer; + struct QBUFFER __iomem *pqbuffer = NULL; switch (acb->adapter_type) { case ACB_ADAPTER_TYPE_A: { - struct MessageUnit_A __iomem *reg = (struct MessageUnit_A *)acb->pmu; - pqbuffer = (struct QBUFFER *) ®->message_wbuffer; + struct MessageUnit_A __iomem *reg = acb->pmuA; + pqbuffer = (struct QBUFFER __iomem *) ®->message_wbuffer; } break; case ACB_ADAPTER_TYPE_B: { - struct MessageUnit_B *reg = (struct MessageUnit_B *)acb->pmu; + struct MessageUnit_B *reg = acb->pmuB; pqbuffer = (struct QBUFFER __iomem *)reg->ioctl_wbuffer_reg; } break; @@ -1115,15 +1137,15 @@ static struct QBUFFER *arcmsr_get_iop_wqbuffer(struct AdapterControlBlock *acb) static void arcmsr_iop2drv_data_wrote_handle(struct AdapterControlBlock *acb) { - struct QBUFFER *prbuffer; + struct QBUFFER __iomem *prbuffer; struct QBUFFER *pQbuffer; - uint8_t *iop_data; + uint8_t __iomem *iop_data; int32_t my_empty_len, iop_len, rqbuf_firstindex, rqbuf_lastindex; rqbuf_lastindex = acb->rqbuf_lastindex; rqbuf_firstindex = acb->rqbuf_firstindex; prbuffer = arcmsr_get_iop_rqbuffer(acb); - iop_data = (uint8_t *)prbuffer->data; + iop_data = (uint8_t __iomem *)prbuffer->data; iop_len = prbuffer->data_len; my_empty_len = (rqbuf_firstindex - rqbuf_lastindex -1)&(ARCMSR_MAX_QBUFFER -1); @@ -1151,8 +1173,8 @@ static void arcmsr_iop2drv_data_read_handle(struct AdapterControlBlock *acb) acb->acb_flags |= ACB_F_MESSAGE_WQBUFFER_READED; if (acb->wqbuf_firstindex != acb->wqbuf_lastindex) { uint8_t *pQbuffer; - struct QBUFFER *pwbuffer; - uint8_t *iop_data; + struct QBUFFER __iomem *pwbuffer; + uint8_t __iomem *iop_data; int32_t allxfer_len = 0; acb->acb_flags &= (~ACB_F_MESSAGE_WQBUFFER_READED); @@ -1181,7 +1203,7 @@ static void arcmsr_iop2drv_data_read_handle(struct AdapterControlBlock *acb) static void arcmsr_hba_doorbell_isr(struct AdapterControlBlock *acb) { uint32_t outbound_doorbell; - struct MessageUnit_A __iomem *reg = (struct MessageUnit_A *)acb->pmu; + struct MessageUnit_A __iomem *reg = acb->pmuA; outbound_doorbell = readl(®->outbound_doorbell); writel(outbound_doorbell, ®->outbound_doorbell); @@ -1197,7 +1219,7 @@ static void arcmsr_hba_doorbell_isr(struct AdapterControlBlock *acb) static void arcmsr_hba_postqueue_isr(struct AdapterControlBlock *acb) { uint32_t flag_ccb; - struct MessageUnit_A __iomem *reg = (struct MessageUnit_A *)acb->pmu; + struct MessageUnit_A __iomem *reg = acb->pmuA; while ((flag_ccb = readl(®->outbound_queueport)) != 0xFFFFFFFF) { arcmsr_drain_donequeue(acb, flag_ccb); @@ -1208,7 +1230,7 @@ static void arcmsr_hbb_postqueue_isr(struct AdapterControlBlock *acb) { uint32_t index; uint32_t flag_ccb; - struct MessageUnit_B *reg = (struct MessageUnit_B *)acb->pmu; + struct MessageUnit_B *reg = acb->pmuB; index = reg->doneq_index; @@ -1224,7 +1246,7 @@ static void arcmsr_hbb_postqueue_isr(struct AdapterControlBlock *acb) static int arcmsr_handle_hba_isr(struct AdapterControlBlock *acb) { uint32_t outbound_intstatus; - struct MessageUnit_A __iomem *reg = (struct MessageUnit_A *)acb->pmu; + struct MessageUnit_A __iomem *reg = acb->pmuA; outbound_intstatus = readl(®->outbound_intstatus) & \ acb->outbound_int_enable; @@ -1244,7 +1266,7 @@ static int arcmsr_handle_hba_isr(struct AdapterControlBlock *acb) static int arcmsr_handle_hbb_isr(struct AdapterControlBlock *acb) { uint32_t outbound_doorbell; - struct MessageUnit_B *reg = (struct MessageUnit_B *)acb->pmu; + struct MessageUnit_B *reg = acb->pmuB; outbound_doorbell = readl(reg->iop2drv_doorbell_reg) & \ acb->outbound_int_enable; @@ -1305,8 +1327,8 @@ void arcmsr_post_ioctldata2iop(struct AdapterControlBlock *acb) { int32_t wqbuf_firstindex, wqbuf_lastindex; uint8_t *pQbuffer; - struct QBUFFER *pwbuffer; - uint8_t *iop_data; + struct QBUFFER __iomem *pwbuffer; + uint8_t __iomem *iop_data; int32_t allxfer_len = 0; pwbuffer = arcmsr_get_iop_wqbuffer(acb); @@ -1380,13 +1402,13 @@ static int arcmsr_iop_message_xfer(struct AdapterControlBlock *acb, \ } if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { - struct QBUFFER *prbuffer; - uint8_t *iop_data; + struct QBUFFER __iomem *prbuffer; + uint8_t __iomem *iop_data; int32_t iop_len; acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; prbuffer = arcmsr_get_iop_rqbuffer(acb); - iop_data = (uint8_t *)prbuffer->data; + iop_data = prbuffer->data; iop_len = readl(&prbuffer->data_len); while (iop_len > 0) { acb->rqbuffer[acb->rqbuf_lastindex] = readb(iop_data); @@ -1669,11 +1691,11 @@ static int arcmsr_queue_command(struct scsi_cmnd *cmd, static void arcmsr_get_hba_config(struct AdapterControlBlock *acb) { - struct MessageUnit_A __iomem *reg = (struct MessageUnit_A *)acb->pmu; + struct MessageUnit_A __iomem *reg = acb->pmuA; char *acb_firm_model = acb->firm_model; char *acb_firm_version = acb->firm_version; - char *iop_firm_model = (char *) (®->message_rwbuffer[15]); - char *iop_firm_version = (char *) (®->message_rwbuffer[17]); + char __iomem *iop_firm_model = (char __iomem *)(®->message_rwbuffer[15]); + char __iomem *iop_firm_version = (char __iomem *)(®->message_rwbuffer[17]); int count; writel(ARCMSR_INBOUND_MESG0_GET_CONFIG, ®->inbound_msgaddr0); @@ -1710,13 +1732,13 @@ static void arcmsr_get_hba_config(struct AdapterControlBlock *acb) static void arcmsr_get_hbb_config(struct AdapterControlBlock *acb) { - struct MessageUnit_B *reg = (struct MessageUnit_B *)acb->pmu; - uint32_t *lrwbuffer = reg->msgcode_rwbuffer_reg; + struct MessageUnit_B *reg = acb->pmuB; + uint32_t __iomem *lrwbuffer = reg->msgcode_rwbuffer_reg; char *acb_firm_model = acb->firm_model; char *acb_firm_version = acb->firm_version; - char *iop_firm_model = (char *) (&lrwbuffer[15]); + char __iomem *iop_firm_model = (char __iomem *)(&lrwbuffer[15]); /*firm_model,15,60-67*/ - char *iop_firm_version = (char *) (&lrwbuffer[17]); + char __iomem *iop_firm_version = (char __iomem *)(&lrwbuffer[17]); /*firm_version,17,68-83*/ int count; @@ -1777,7 +1799,7 @@ static void arcmsr_get_firmware_spec(struct AdapterControlBlock *acb) static void arcmsr_polling_hba_ccbdone(struct AdapterControlBlock *acb, struct CommandControlBlock *poll_ccb) { - struct MessageUnit_A __iomem *reg = (struct MessageUnit_A *)acb->pmu; + struct MessageUnit_A __iomem *reg = acb->pmuA; struct CommandControlBlock *ccb; uint32_t flag_ccb, outbound_intstatus, poll_ccb_done = 0, poll_count = 0; @@ -1826,7 +1848,7 @@ static void arcmsr_polling_hba_ccbdone(struct AdapterControlBlock *acb, static void arcmsr_polling_hbb_ccbdone(struct AdapterControlBlock *acb, \ struct CommandControlBlock *poll_ccb) { - struct MessageUnit_B *reg = (struct MessageUnit_B *)acb->pmu; + struct MessageUnit_B *reg = acb->pmuB; struct CommandControlBlock *ccb; uint32_t flag_ccb, poll_ccb_done = 0, poll_count = 0; int index; @@ -1918,8 +1940,7 @@ static int arcmsr_iop_confirm(struct AdapterControlBlock *acb) case ACB_ADAPTER_TYPE_A: { if (ccb_phyaddr_hi32 != 0) { - struct MessageUnit_A __iomem *reg = \ - (struct MessageUnit_A *)acb->pmu; + struct MessageUnit_A __iomem *reg = acb->pmuA; uint32_t intmask_org; intmask_org = arcmsr_disable_outbound_ints(acb); writel(ARCMSR_SIGNATURE_SET_CONFIG, \ @@ -1940,9 +1961,9 @@ static int arcmsr_iop_confirm(struct AdapterControlBlock *acb) case ACB_ADAPTER_TYPE_B: { unsigned long post_queue_phyaddr; - uint32_t *rwbuffer; + uint32_t __iomem *rwbuffer; - struct MessageUnit_B *reg = (struct MessageUnit_B *)acb->pmu; + struct MessageUnit_B *reg = acb->pmuB; uint32_t intmask_org; intmask_org = arcmsr_disable_outbound_ints(acb); reg->postq_index = 0; @@ -1994,7 +2015,7 @@ static void arcmsr_wait_firmware_ready(struct AdapterControlBlock *acb) switch (acb->adapter_type) { case ACB_ADAPTER_TYPE_A: { - struct MessageUnit_A __iomem *reg = (struct MessageUnit_A *)acb->pmu; + struct MessageUnit_A __iomem *reg = acb->pmuA; do { firmware_state = readl(®->outbound_msgaddr1); } while ((firmware_state & ARCMSR_OUTBOUND_MESG1_FIRMWARE_OK) == 0); @@ -2002,7 +2023,7 @@ static void arcmsr_wait_firmware_ready(struct AdapterControlBlock *acb) break; case ACB_ADAPTER_TYPE_B: { - struct MessageUnit_B *reg = (struct MessageUnit_B *)acb->pmu; + struct MessageUnit_B *reg = acb->pmuB; do { firmware_state = readl(reg->iop2drv_doorbell_reg); } while ((firmware_state & ARCMSR_MESSAGE_FIRMWARE_OK) == 0); @@ -2013,7 +2034,7 @@ static void arcmsr_wait_firmware_ready(struct AdapterControlBlock *acb) static void arcmsr_start_hba_bgrb(struct AdapterControlBlock *acb) { - struct MessageUnit_A __iomem *reg = (struct MessageUnit_A *)acb->pmu; + struct MessageUnit_A __iomem *reg = acb->pmuA; acb->acb_flags |= ACB_F_MSG_START_BGRB; writel(ARCMSR_INBOUND_MESG0_START_BGRB, ®->inbound_msgaddr0); if (arcmsr_hba_wait_msgint_ready(acb)) { @@ -2024,7 +2045,7 @@ static void arcmsr_start_hba_bgrb(struct AdapterControlBlock *acb) static void arcmsr_start_hbb_bgrb(struct AdapterControlBlock *acb) { - struct MessageUnit_B *reg = (struct MessageUnit_B *)acb->pmu; + struct MessageUnit_B *reg = acb->pmuB; acb->acb_flags |= ACB_F_MSG_START_BGRB; writel(ARCMSR_MESSAGE_START_BGRB, reg->drv2iop_doorbell_reg); if (arcmsr_hbb_wait_msgint_ready(acb)) { @@ -2049,7 +2070,7 @@ static void arcmsr_clear_doorbell_queue_buffer(struct AdapterControlBlock *acb) { switch (acb->adapter_type) { case ACB_ADAPTER_TYPE_A: { - struct MessageUnit_A *reg = (struct MessageUnit_A *)acb->pmu; + struct MessageUnit_A __iomem *reg = acb->pmuA; uint32_t outbound_doorbell; /* empty doorbell Qbuffer if door bell ringed */ outbound_doorbell = readl(®->outbound_doorbell); @@ -2060,7 +2081,7 @@ static void arcmsr_clear_doorbell_queue_buffer(struct AdapterControlBlock *acb) break; case ACB_ADAPTER_TYPE_B: { - struct MessageUnit_B *reg = (struct MessageUnit_B *)acb->pmu; + struct MessageUnit_B *reg = acb->pmuB; /*clear interrupt and message state*/ writel(ARCMSR_MESSAGE_INT_CLEAR_PATTERN, reg->iop2drv_doorbell_reg); writel(ARCMSR_DRV2IOP_DATA_READ_OK, reg->drv2iop_doorbell_reg); diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c index b5fa4f09138..f1871ea0404 100644 --- a/drivers/scsi/sg.c +++ b/drivers/scsi/sg.c @@ -1652,6 +1652,7 @@ sg_build_sgat(Sg_scatter_hold * schp, const Sg_fd * sfp, int tablesize) schp->buffer = kzalloc(sg_bufflen, gfp_flags); if (!schp->buffer) return -ENOMEM; + sg_init_table(schp->buffer, tablesize); schp->sglist_len = sg_bufflen; return tablesize; /* number of scat_gath elements allocated */ } diff --git a/drivers/serial/serial_cs.c b/drivers/serial/serial_cs.c index 5afcb2fa7cd..d8b660061c1 100644 --- a/drivers/serial/serial_cs.c +++ b/drivers/serial/serial_cs.c @@ -345,7 +345,7 @@ static int serial_probe(struct pcmcia_device *link) link->io.Attributes1 = IO_DATA_PATH_WIDTH_8; link->io.NumPorts1 = 8; - link->irq.Attributes = IRQ_TYPE_EXCLUSIVE; + link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING; link->irq.IRQInfo1 = IRQ_LEVEL_ID; link->conf.Attributes = CONF_ENABLE_IRQ; if (do_sound) { diff --git a/drivers/serial/serial_txx9.c b/drivers/serial/serial_txx9.c index 6846a6c38b6..7ad21925869 100644 --- a/drivers/serial/serial_txx9.c +++ b/drivers/serial/serial_txx9.c @@ -657,7 +657,15 @@ static void serial_txx9_pm(struct uart_port *port, unsigned int state, unsigned int oldstate) { - if (state == 0) + /* + * If oldstate was -1 this is called from + * uart_configure_port(). In this case do not initialize the + * port now, because the port was already initialized (for + * non-console port) or should not be initialized here (for + * console port). If we initialized the port here we lose + * serial console settings. + */ + if (state == 0 && oldstate != -1) serial_txx9_initialize(port); } diff --git a/drivers/spi/spidev.c b/drivers/spi/spidev.c index c55459c592b..b3518ca9f04 100644 --- a/drivers/spi/spidev.c +++ b/drivers/spi/spidev.c @@ -184,14 +184,14 @@ static int spidev_message(struct spidev_data *spidev, if (u_tmp->rx_buf) { k_tmp->rx_buf = buf; if (!access_ok(VERIFY_WRITE, (u8 __user *) - (ptrdiff_t) u_tmp->rx_buf, + (uintptr_t) u_tmp->rx_buf, u_tmp->len)) goto done; } if (u_tmp->tx_buf) { k_tmp->tx_buf = buf; if (copy_from_user(buf, (const u8 __user *) - (ptrdiff_t) u_tmp->tx_buf, + (uintptr_t) u_tmp->tx_buf, u_tmp->len)) goto done; } @@ -224,7 +224,7 @@ static int spidev_message(struct spidev_data *spidev, for (n = n_xfers, u_tmp = u_xfers; n; n--, u_tmp++) { if (u_tmp->rx_buf) { if (__copy_to_user((u8 __user *) - (ptrdiff_t) u_tmp->rx_buf, buf, + (uintptr_t) u_tmp->rx_buf, buf, u_tmp->len)) { status = -EFAULT; goto done; diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c index eb4ac47612a..316a746e008 100644 --- a/drivers/usb/core/message.c +++ b/drivers/usb/core/message.c @@ -434,7 +434,7 @@ int usb_sg_init ( if (dma) { io->urbs [i]->transfer_dma = sg_dma_address (sg + i); len = sg_dma_len (sg + i); -#if defined(CONFIG_HIGHMEM) || defined(CONFIG_IOMMU) +#if defined(CONFIG_HIGHMEM) || defined(CONFIG_GART_IOMMU) io->urbs[i]->transfer_buffer = NULL; #else io->urbs[i]->transfer_buffer = sg_virt(&sg[i]); diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index fb9d8d0b2c0..61717fa1afb 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig @@ -1892,9 +1892,7 @@ config FB_VIRTUAL If unsure, say N. -if ARCH_OMAP - source "drivers/video/omap/Kconfig" -endif +source "drivers/video/omap/Kconfig" source "drivers/video/backlight/Kconfig" source "drivers/video/display/Kconfig" diff --git a/drivers/video/aty/radeon_pm.c b/drivers/video/aty/radeon_pm.c index be1d57bf9dc..83ee3e75386 100644 --- a/drivers/video/aty/radeon_pm.c +++ b/drivers/video/aty/radeon_pm.c @@ -27,8 +27,6 @@ #include "ati_ids.h" -static void radeon_reinitialize_M10(struct radeonfb_info *rinfo); - /* * Workarounds for bugs in PC laptops: * - enable D2 sleep in some IBM Thinkpads @@ -39,6 +37,8 @@ static void radeon_reinitialize_M10(struct radeonfb_info *rinfo); */ #if defined(CONFIG_PM) && defined(CONFIG_X86) +static void radeon_reinitialize_M10(struct radeonfb_info *rinfo); + struct radeon_device_id { const char *ident; /* (arbitrary) Name */ const unsigned short subsystem_vendor; /* Subsystem Vendor ID */ diff --git a/drivers/video/omap/Kconfig b/drivers/video/omap/Kconfig index f4fcf11b290..44408850e2e 100644 --- a/drivers/video/omap/Kconfig +++ b/drivers/video/omap/Kconfig @@ -1,6 +1,6 @@ config FB_OMAP tristate "OMAP frame buffer support (EXPERIMENTAL)" - depends on FB + depends on FB && ARCH_OMAP select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT diff --git a/fs/locks.c b/fs/locks.c index 0127a284681..8b8388eca05 100644 --- a/fs/locks.c +++ b/fs/locks.c @@ -696,17 +696,28 @@ EXPORT_SYMBOL(posix_test_lock); * Note: the above assumption may not be true when handling lock requests * from a broken NFS client. But broken NFS clients have a lot more to * worry about than proper deadlock detection anyway... --okir + * + * However, the failure of this assumption (also possible in the case of + * multiple tasks sharing the same open file table) also means there's no + * guarantee that the loop below will terminate. As a hack, we give up + * after a few iterations. */ + +#define MAX_DEADLK_ITERATIONS 10 + static int posix_locks_deadlock(struct file_lock *caller_fl, struct file_lock *block_fl) { struct file_lock *fl; + int i = 0; next_task: if (posix_same_owner(caller_fl, block_fl)) return 1; list_for_each_entry(fl, &blocked_list, fl_link) { if (posix_same_owner(fl, block_fl)) { + if (i++ > MAX_DEADLK_ITERATIONS) + return 0; fl = fl->fl_next; block_fl = fl; goto next_task; diff --git a/fs/proc/array.c b/fs/proc/array.c index 63c95afb561..eba339ecba2 100644 --- a/fs/proc/array.c +++ b/fs/proc/array.c @@ -358,7 +358,8 @@ static cputime_t task_utime(struct task_struct *p) } utime = (clock_t)temp; - return clock_t_to_cputime(utime); + p->prev_utime = max(p->prev_utime, clock_t_to_cputime(utime)); + return p->prev_utime; } static cputime_t task_stime(struct task_struct *p) @@ -373,7 +374,8 @@ static cputime_t task_stime(struct task_struct *p) stime = nsec_to_clock_t(p->se.sum_exec_runtime) - cputime_to_clock_t(task_utime(p)); - return clock_t_to_cputime(stime); + p->prev_stime = max(p->prev_stime, clock_t_to_cputime(stime)); + return p->prev_stime; } #endif diff --git a/fs/ufs/super.c b/fs/ufs/super.c index 584cf12cc40..c78c04fd993 100644 --- a/fs/ufs/super.c +++ b/fs/ufs/super.c @@ -933,20 +933,19 @@ magic_found: goto again; } - /* Set sbi->s_flags here, used by ufs_get_fs_state() below */ - sbi->s_flags = flags; + sbi->s_flags = flags;/*after that line some functions use s_flags*/ ufs_print_super_stuff(sb, usb1, usb2, usb3); /* * Check, if file system was correctly unmounted. * If not, make it read only. */ - if ((((flags & UFS_ST_MASK) == UFS_ST_44BSD) || - ((flags & UFS_ST_MASK) == UFS_ST_OLD) || - ((flags & UFS_ST_MASK) == UFS_ST_SUN) || - ((flags & UFS_ST_MASK) == UFS_ST_SUNOS) || - ((flags & UFS_ST_MASK) == UFS_ST_SUNx86)) && - (ufs_get_fs_state(sb, usb1, usb3) == (UFS_FSOK - fs32_to_cpu(sb, usb1->fs_time)))) { + if (((flags & UFS_ST_MASK) == UFS_ST_44BSD) || + ((flags & UFS_ST_MASK) == UFS_ST_OLD) || + (((flags & UFS_ST_MASK) == UFS_ST_SUN || + (flags & UFS_ST_MASK) == UFS_ST_SUNOS || + (flags & UFS_ST_MASK) == UFS_ST_SUNx86) && + (ufs_get_fs_state(sb, usb1, usb3) == (UFS_FSOK - fs32_to_cpu(sb, usb1->fs_time))))) { switch(usb1->fs_clean) { case UFS_FSCLEAN: UFSD("fs is clean\n"); diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h index 7b74b60a68a..19c3ead2a90 100644 --- a/include/acpi/acpi_bus.h +++ b/include/acpi/acpi_bus.h @@ -168,8 +168,7 @@ struct acpi_device_flags { u32 power_manageable:1; u32 performance_manageable:1; u32 wake_capable:1; /* Wakeup(_PRW) supported? */ - u32 force_power_state:1; - u32 reserved:19; + u32 reserved:20; }; /* File System */ diff --git a/include/asm-blackfin/bfin-global.h b/include/asm-blackfin/bfin-global.h index 14cb8d35924..0212e180b90 100644 --- a/include/asm-blackfin/bfin-global.h +++ b/include/asm-blackfin/bfin-global.h @@ -80,6 +80,7 @@ extern int atomic_sub32(void); extern int atomic_ior32(void); extern int atomic_and32(void); extern int atomic_xor32(void); +extern void safe_user_instruction(void); extern void sigreturn_stub(void); extern void *l1_data_A_sram_alloc(size_t); diff --git a/include/asm-blackfin/fixed_code.h b/include/asm-blackfin/fixed_code.h index e6df84ee155..37db66c7030 100644 --- a/include/asm-blackfin/fixed_code.h +++ b/include/asm-blackfin/fixed_code.h @@ -17,4 +17,6 @@ #define ATOMIC_SEQS_END 0x480 -#define FIXED_CODE_END 0x480 +#define SAFE_USER_INSTRUCTION 0x480 + +#define FIXED_CODE_END 0x490 diff --git a/include/asm-blackfin/gptimers.h b/include/asm-blackfin/gptimers.h index c97ab03e43a..8265ea473d5 100644 --- a/include/asm-blackfin/gptimers.h +++ b/include/asm-blackfin/gptimers.h @@ -197,6 +197,8 @@ uint32_t get_gptimer_period (int timer_id); uint32_t get_gptimer_count (int timer_id); uint16_t get_gptimer_intr (int timer_id); void clear_gptimer_intr (int timer_id); +uint16_t get_gptimer_over (int timer_id); +void clear_gptimer_over (int timer_id); void set_gptimer_config (int timer_id, uint16_t config); uint16_t get_gptimer_config (int timer_id); void set_gptimer_pulse_hi (int timer_id); diff --git a/include/asm-blackfin/mach-bf527/defBF52x_base.h b/include/asm-blackfin/mach-bf527/defBF52x_base.h index d6c24c54699..fc69cf93f14 100644 --- a/include/asm-blackfin/mach-bf527/defBF52x_base.h +++ b/include/asm-blackfin/mach-bf527/defBF52x_base.h @@ -1718,55 +1718,55 @@ /* Bit masks for HOST_CONTROL */ -#define HOST_EN 0x1 /* Host Enable */ -#define nHOST_EN 0x0 -#define HOST_END 0x2 /* Host Endianess */ -#define nHOST_END 0x0 -#define DATA_SIZE 0x4 /* Data Size */ -#define nDATA_SIZE 0x0 -#define HOST_RST 0x8 /* Host Reset */ -#define nHOST_RST 0x0 -#define HRDY_OVR 0x20 /* Host Ready Override */ -#define nHRDY_OVR 0x0 -#define INT_MODE 0x40 /* Interrupt Mode */ -#define nINT_MODE 0x0 -#define BT_EN 0x80 /* Bus Timeout Enable */ -#define nBT_EN 0x0 -#define EHW 0x100 /* Enable Host Write */ -#define nEHW 0x0 -#define EHR 0x200 /* Enable Host Read */ -#define nEHR 0x0 -#define BDR 0x400 /* Burst DMA Requests */ -#define nBDR 0x0 +#define HOST_CNTR_HOST_EN 0x1 /* Host Enable */ +#define HOST_CNTR_nHOST_EN 0x0 +#define HOST_CNTR_HOST_END 0x2 /* Host Endianess */ +#define HOST_CNTR_nHOST_END 0x0 +#define HOST_CNTR_DATA_SIZE 0x4 /* Data Size */ +#define HOST_CNTR_nDATA_SIZE 0x0 +#define HOST_CNTR_HOST_RST 0x8 /* Host Reset */ +#define HOST_CNTR_nHOST_RST 0x0 +#define HOST_CNTR_HRDY_OVR 0x20 /* Host Ready Override */ +#define HOST_CNTR_nHRDY_OVR 0x0 +#define HOST_CNTR_INT_MODE 0x40 /* Interrupt Mode */ +#define HOST_CNTR_nINT_MODE 0x0 +#define HOST_CNTR_BT_EN 0x80 /* Bus Timeout Enable */ +#define HOST_CNTR_ nBT_EN 0x0 +#define HOST_CNTR_EHW 0x100 /* Enable Host Write */ +#define HOST_CNTR_nEHW 0x0 +#define HOST_CNTR_EHR 0x200 /* Enable Host Read */ +#define HOST_CNTR_nEHR 0x0 +#define HOST_CNTR_BDR 0x400 /* Burst DMA Requests */ +#define HOST_CNTR_nBDR 0x0 /* Bit masks for HOST_STATUS */ -#define READY 0x1 /* DMA Ready */ -#define nREADY 0x0 -#define FIFOFULL 0x2 /* FIFO Full */ -#define nFIFOFULL 0x0 -#define FIFOEMPTY 0x4 /* FIFO Empty */ -#define nFIFOEMPTY 0x0 -#define COMPLETE 0x8 /* DMA Complete */ -#define nCOMPLETE 0x0 -#define HSHK 0x10 /* Host Handshake */ -#define nHSHK 0x0 -#define TIMEOUT 0x20 /* Host Timeout */ -#define nTIMEOUT 0x0 -#define HIRQ 0x40 /* Host Interrupt Request */ -#define nHIRQ 0x0 -#define ALLOW_CNFG 0x80 /* Allow New Configuration */ -#define nALLOW_CNFG 0x0 -#define DMA_DIR 0x100 /* DMA Direction */ -#define nDMA_DIR 0x0 -#define BTE 0x200 /* Bus Timeout Enabled */ -#define nBTE 0x0 -#define HOSTRD_DONE 0x8000 /* Host Read Completion Interrupt */ -#define nHOSTRD_DONE 0x0 +#define HOST_STAT_READY 0x1 /* DMA Ready */ +#define HOST_STAT_nREADY 0x0 +#define HOST_STAT_FIFOFULL 0x2 /* FIFO Full */ +#define HOST_STAT_nFIFOFULL 0x0 +#define HOST_STAT_FIFOEMPTY 0x4 /* FIFO Empty */ +#define HOST_STAT_nFIFOEMPTY 0x0 +#define HOST_STAT_COMPLETE 0x8 /* DMA Complete */ +#define HOST_STAT_nCOMPLETE 0x0 +#define HOST_STAT_HSHK 0x10 /* Host Handshake */ +#define HOST_STAT_nHSHK 0x0 +#define HOST_STAT_TIMEOUT 0x20 /* Host Timeout */ +#define HOST_STAT_nTIMEOUT 0x0 +#define HOST_STAT_HIRQ 0x40 /* Host Interrupt Request */ +#define HOST_STAT_nHIRQ 0x0 +#define HOST_STAT_ALLOW_CNFG 0x80 /* Allow New Configuration */ +#define HOST_STAT_nALLOW_CNFG 0x0 +#define HOST_STAT_DMA_DIR 0x100 /* DMA Direction */ +#define HOST_STAT_nDMA_DIR 0x0 +#define HOST_STAT_BTE 0x200 /* Bus Timeout Enabled */ +#define HOST_STAT_nBTE 0x0 +#define HOST_STAT_HOSTRD_DONE 0x8000 /* Host Read Completion Interrupt */ +#define HOST_STAT_nHOSTRD_DONE 0x0 /* Bit masks for HOST_TIMEOUT */ -#define COUNT_TIMEOUT 0x7ff /* Host Timeout count */ +#define HOST_COUNT_TIMEOUT 0x7ff /* Host Timeout count */ /* Bit masks for CNT_CONFIG */ diff --git a/include/asm-blackfin/mach-bf527/dma.h b/include/asm-blackfin/mach-bf527/dma.h index a41627ae913..2dfee12864f 100644 --- a/include/asm-blackfin/mach-bf527/dma.h +++ b/include/asm-blackfin/mach-bf527/dma.h @@ -35,7 +35,6 @@ #define MAX_BLACKFIN_DMA_CHANNEL 16 #define CH_PPI 0 /* PPI receive/transmit or NFC */ -#define CH_NFC 0 /* PPI receive/transmit or NFC */ #define CH_EMAC_RX 1 /* Ethernet MAC receive or HOSTDP */ #define CH_EMAC_HOSTDP 1 /* Ethernet MAC receive or HOSTDP */ #define CH_EMAC_TX 2 /* Ethernet MAC transmit or NFC */ @@ -54,6 +53,12 @@ #define CH_MEM_STREAM1_DEST 14 /* TX */ #define CH_MEM_STREAM1_SRC 15 /* RX */ +#if defined(CONFIG_BF527_NAND_D_PORTF) +#define CH_NFC CH_PPI /* PPI receive/transmit or NFC */ +#elif defined(CONFIG_BF527_NAND_D_PORTH) +#define CH_NFC CH_EMAC_TX /* PPI receive/transmit or NFC */ +#endif + extern int channel2irq(unsigned int channel); extern struct dma_register *base_addr[]; diff --git a/include/asm-blackfin/mach-bf548/defBF549.h b/include/asm-blackfin/mach-bf548/defBF549.h index 4e46d657e50..fcb72b41e00 100644 --- a/include/asm-blackfin/mach-bf548/defBF549.h +++ b/include/asm-blackfin/mach-bf548/defBF549.h @@ -1671,7 +1671,7 @@ /* Bit masks for MXVR_DMAx_CONFIG */ #define MDMAEN 0x1 /* DMA Channel Enable */ -#define DD 0x2 /* DMA Channel Direction */ +#define DMADD 0x2 /* DMA Channel Direction */ #define BY4SWAPEN 0x20 /* DMA Channel Four Byte Swap Enable */ #define LCHAN 0x3c0 /* DMA Channel Logical Channel */ #define BITSWAPEN 0x400 /* DMA Channel Bit Swap Enable */ diff --git a/include/asm-blackfin/mach-bf548/defBF54x_base.h b/include/asm-blackfin/mach-bf548/defBF54x_base.h index 1d365c844ff..da979cb62f7 100644 --- a/include/asm-blackfin/mach-bf548/defBF54x_base.h +++ b/include/asm-blackfin/mach-bf548/defBF54x_base.h @@ -2252,6 +2252,13 @@ #define PLL_OFF 0x2 /* Disable PLL */ #define DF 0x1 /* Divide Frequency */ +/* SWRST Masks */ +#define SYSTEM_RESET 0x0007 /* Initiates A System Software Reset */ +#define DOUBLE_FAULT 0x0008 /* Core Double Fault Causes Reset */ +#define RESET_DOUBLE 0x2000 /* SW Reset Generated By Core Double-Fault */ +#define RESET_WDOG 0x4000 /* SW Reset Generated By Watchdog Timer */ +#define RESET_SOFTWARE 0x8000 /* SW Reset Occurred Since Last Read Of SWRST */ + /* Bit masks for PLL_STAT */ #define PLL_LOCKED 0x20 /* PLL Locked Status */ diff --git a/include/asm-blackfin/mach-bf548/portmux.h b/include/asm-blackfin/mach-bf548/portmux.h index b382deb501a..6b485120015 100644 --- a/include/asm-blackfin/mach-bf548/portmux.h +++ b/include/asm-blackfin/mach-bf548/portmux.h @@ -267,4 +267,18 @@ #define P_AMC_BG (P_DEFINED | P_IDENT(GPIO_PJ12) | P_FUNCT(0)) #define P_AMC_BGH (P_DEFINED | P_IDENT(GPIO_PJ13) | P_FUNCT(0)) + +#define P_NAND_D0 (P_DONTCARE) +#define P_NAND_D1 (P_DONTCARE) +#define P_NAND_D2 (P_DONTCARE) +#define P_NAND_D3 (P_DONTCARE) +#define P_NAND_D4 (P_DONTCARE) +#define P_NAND_D5 (P_DONTCARE) +#define P_NAND_D6 (P_DONTCARE) +#define P_NAND_D7 (P_DONTCARE) +#define P_NAND_WE (P_DONTCARE) +#define P_NAND_RE (P_DONTCARE) +#define P_NAND_CLE (P_DONTCARE) +#define P_NAND_ALE (P_DONTCARE) + #endif /* _MACH_PORTMUX_H_ */ diff --git a/include/asm-blackfin/mach-bf561/defBF561.h b/include/asm-blackfin/mach-bf561/defBF561.h index bf7dc4e0006..7945e8a3a84 100644 --- a/include/asm-blackfin/mach-bf561/defBF561.h +++ b/include/asm-blackfin/mach-bf561/defBF561.h @@ -55,6 +55,9 @@ /* For MMR's that are reserved on Core B, set up defines to better integrate with other ports */ #define SWRST SICA_SWRST #define SYSCR SICA_SYSCR +#define RESET_DOUBLE (SWRST_DBL_FAULT_B|SWRST_DBL_FAULT_A) +#define RESET_WDOG (SWRST_WDT_B|SWRST_WDT_A) +#define RESET_SOFTWARE (SWRST_OCCURRED) /* System Reset and Interrupt Controller registers for core A (0xFFC0 0100-0xFFC0 01FF) */ #define SICA_SWRST 0xFFC00100 /* Software Reset register */ diff --git a/include/asm-mips/ip32/ip32_ints.h b/include/asm-mips/ip32/ip32_ints.h index 042f821899a..ab5612f90f6 100644 --- a/include/asm-mips/ip32/ip32_ints.h +++ b/include/asm-mips/ip32/ip32_ints.h @@ -22,10 +22,12 @@ enum ip32_irq_no { * CPU interrupts are 0 ... 7 */ + CRIME_IRQ_BASE = MIPS_CPU_IRQ_BASE, + /* * MACE */ - MACE_VID_IN1_IRQ = MIPS_CPU_IRQ_BASE + 8, + MACE_VID_IN1_IRQ = CRIME_IRQ_BASE, MACE_VID_IN2_IRQ, MACE_VID_OUT_IRQ, MACE_ETHERNET_IRQ, diff --git a/include/asm-mips/jmr3927/jmr3927.h b/include/asm-mips/jmr3927/jmr3927.h index b2dc35f5618..81602c8047e 100644 --- a/include/asm-mips/jmr3927/jmr3927.h +++ b/include/asm-mips/jmr3927/jmr3927.h @@ -132,9 +132,7 @@ #define JMR3927_IRQ_IRC_DMA (JMR3927_IRQ_IRC + TX3927_IR_DMA) #define JMR3927_IRQ_IRC_PIO (JMR3927_IRQ_IRC + TX3927_IR_PIO) #define JMR3927_IRQ_IRC_PCI (JMR3927_IRQ_IRC + TX3927_IR_PCI) -#define JMR3927_IRQ_IRC_TMR0 (JMR3927_IRQ_IRC + TX3927_IR_TMR0) -#define JMR3927_IRQ_IRC_TMR1 (JMR3927_IRQ_IRC + TX3927_IR_TMR1) -#define JMR3927_IRQ_IRC_TMR2 (JMR3927_IRQ_IRC + TX3927_IR_TMR2) +#define JMR3927_IRQ_IRC_TMR(ch) (JMR3927_IRQ_IRC + TX3927_IR_TMR(ch)) #define JMR3927_IRQ_IOC_PCIA (JMR3927_IRQ_IOC + JMR3927_IOC_INTB_PCIA) #define JMR3927_IRQ_IOC_PCIB (JMR3927_IRQ_IOC + JMR3927_IOC_INTB_PCIB) #define JMR3927_IRQ_IOC_PCIC (JMR3927_IRQ_IOC + JMR3927_IOC_INTB_PCIC) @@ -148,17 +146,12 @@ #define JMR3927_IRQ_IOCINT JMR3927_IRQ_IRC_INT1 /* TC35815 100M Ether (JMR-TX3912:JPW4:2-3 Short) */ #define JMR3927_IRQ_ETHER0 JMR3927_IRQ_IRC_INT3 -/* Clock Tick (10ms) */ -#define JMR3927_IRQ_TICK JMR3927_IRQ_IRC_TMR0 /* Clocks */ #define JMR3927_CORECLK 132710400 /* 132.7MHz */ #define JMR3927_GBUSCLK (JMR3927_CORECLK / 2) /* 66.35MHz */ #define JMR3927_IMCLK (JMR3927_CORECLK / 4) /* 33.17MHz */ -#define jmr3927_tmrptr tx3927_tmrptr(0) /* TMR0 */ - - /* * TX3927 Pin Configuration: * diff --git a/include/asm-mips/jmr3927/tx3927.h b/include/asm-mips/jmr3927/tx3927.h index 211bcf47fff..338f99882a3 100644 --- a/include/asm-mips/jmr3927/tx3927.h +++ b/include/asm-mips/jmr3927/tx3927.h @@ -222,9 +222,7 @@ struct tx3927_ccfg_reg { #define TX3927_IR_DMA 8 #define TX3927_IR_PIO 9 #define TX3927_IR_PCI 10 -#define TX3927_IR_TMR0 13 -#define TX3927_IR_TMR1 14 -#define TX3927_IR_TMR2 15 +#define TX3927_IR_TMR(ch) (13 + (ch)) #define TX3927_NUM_IR 16 /* diff --git a/include/asm-mips/jmr3927/txx927.h b/include/asm-mips/jmr3927/txx927.h index 58a8ff6be81..0474fe8dac3 100644 --- a/include/asm-mips/jmr3927/txx927.h +++ b/include/asm-mips/jmr3927/txx927.h @@ -10,22 +10,6 @@ #ifndef __ASM_TXX927_H #define __ASM_TXX927_H -struct txx927_tmr_reg { - volatile unsigned long tcr; - volatile unsigned long tisr; - volatile unsigned long cpra; - volatile unsigned long cprb; - volatile unsigned long itmr; - volatile unsigned long unused0[3]; - volatile unsigned long ccdr; - volatile unsigned long unused1[3]; - volatile unsigned long pgmr; - volatile unsigned long unused2[3]; - volatile unsigned long wtmr; - volatile unsigned long unused3[43]; - volatile unsigned long trr; -}; - struct txx927_sio_reg { volatile unsigned long lcr; volatile unsigned long dicr; @@ -51,27 +35,6 @@ struct txx927_pio_reg { }; /* - * TMR - */ -/* TMTCR : Timer Control */ -#define TXx927_TMTCR_TCE 0x00000080 -#define TXx927_TMTCR_CCDE 0x00000040 -#define TXx927_TMTCR_CRE 0x00000020 -#define TXx927_TMTCR_ECES 0x00000008 -#define TXx927_TMTCR_CCS 0x00000004 -#define TXx927_TMTCR_TMODE_MASK 0x00000003 -#define TXx927_TMTCR_TMODE_ITVL 0x00000000 - -/* TMTISR : Timer Int. Status */ -#define TXx927_TMTISR_TPIBS 0x00000004 -#define TXx927_TMTISR_TPIAS 0x00000002 -#define TXx927_TMTISR_TIIS 0x00000001 - -/* TMTITMR : Interval Timer Mode */ -#define TXx927_TMTITMR_TIIE 0x00008000 -#define TXx927_TMTITMR_TZCE 0x00000001 - -/* * SIO */ /* SILCR : Line Control */ diff --git a/include/asm-mips/time.h b/include/asm-mips/time.h index bc47af313bc..0a6bc7dc158 100644 --- a/include/asm-mips/time.h +++ b/include/asm-mips/time.h @@ -58,7 +58,6 @@ extern void local_timer_interrupt(int irq, void *dev_id); */ struct irqaction; extern void plat_time_init(void); -extern void plat_timer_setup(struct irqaction *irq); /* * mips_hpt_frequency - must be set if you intend to use an R4k-compatible @@ -78,6 +77,7 @@ extern int (*perf_irq)(void); */ #ifdef CONFIG_CEVT_R4K extern void mips_clockevent_init(void); +extern unsigned int __weak get_c0_compare_int(void); #else static inline void mips_clockevent_init(void) { diff --git a/include/asm-mips/tx4927/tx4927_pci.h b/include/asm-mips/tx4927/tx4927_pci.h index f98b2bb719d..3f1e470192e 100644 --- a/include/asm-mips/tx4927/tx4927_pci.h +++ b/include/asm-mips/tx4927/tx4927_pci.h @@ -9,6 +9,7 @@ #define __ASM_TX4927_TX4927_PCI_H #define TX4927_CCFG_TOE 0x00004000 +#define TX4927_CCFG_TINTDIS 0x01000000 #define TX4927_PCIMEM 0x08000000 #define TX4927_PCIMEM_SIZE 0x08000000 @@ -20,6 +21,8 @@ #define TX4927_PCIC_REG 0xff1fd000 #define TX4927_CCFG_REG 0xff1fe000 #define TX4927_IRC_REG 0xff1ff600 +#define TX4927_NR_TMR 3 +#define TX4927_TMR_REG(ch) (0xff1ff000 + (ch) * 0x100) #define TX4927_CE3 0x17f00000 /* 1M */ #define TX4927_PCIRESET_ADDR 0xbc00f006 #define TX4927_PCI_CLK_ADDR (KSEG1 + TX4927_CE3 + 0x00040020) diff --git a/include/asm-mips/tx4938/tx4938.h b/include/asm-mips/tx4938/tx4938.h index 650b010761f..f7c448b9057 100644 --- a/include/asm-mips/tx4938/tx4938.h +++ b/include/asm-mips/tx4938/tx4938.h @@ -641,7 +641,6 @@ struct tx4938_ccfg_reg { #define tx4938_pcicptr ((struct tx4938_pcic_reg *)TX4938_PCIC_REG) #define tx4938_pcic1ptr ((struct tx4938_pcic_reg *)TX4938_PCIC1_REG) #define tx4938_ccfgptr ((struct tx4938_ccfg_reg *)TX4938_CCFG_REG) -#define tx4938_tmrptr(ch) ((struct tx4938_tmr_reg *)TX4938_TMR_REG(ch)) #define tx4938_sioptr(ch) ((struct tx4938_sio_reg *)TX4938_SIO_REG(ch)) #define tx4938_pioptr ((struct tx4938_pio_reg *)TX4938_PIO_REG) #define tx4938_aclcptr ((struct tx4938_aclc_reg *)TX4938_ACLC_REG) diff --git a/include/asm-mips/txx9tmr.h b/include/asm-mips/txx9tmr.h new file mode 100644 index 00000000000..67f70a8f09b --- /dev/null +++ b/include/asm-mips/txx9tmr.h @@ -0,0 +1,67 @@ +/* + * include/asm-mips/txx9tmr.h + * TX39/TX49 timer controller definitions. + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ +#ifndef __ASM_TXX9TMR_H +#define __ASM_TXX9TMR_H + +#include <linux/types.h> + +struct txx9_tmr_reg { + u32 tcr; + u32 tisr; + u32 cpra; + u32 cprb; + u32 itmr; + u32 unused0[3]; + u32 ccdr; + u32 unused1[3]; + u32 pgmr; + u32 unused2[3]; + u32 wtmr; + u32 unused3[43]; + u32 trr; +}; + +/* TMTCR : Timer Control */ +#define TXx9_TMTCR_TCE 0x00000080 +#define TXx9_TMTCR_CCDE 0x00000040 +#define TXx9_TMTCR_CRE 0x00000020 +#define TXx9_TMTCR_ECES 0x00000008 +#define TXx9_TMTCR_CCS 0x00000004 +#define TXx9_TMTCR_TMODE_MASK 0x00000003 +#define TXx9_TMTCR_TMODE_ITVL 0x00000000 +#define TXx9_TMTCR_TMODE_PGEN 0x00000001 +#define TXx9_TMTCR_TMODE_WDOG 0x00000002 + +/* TMTISR : Timer Int. Status */ +#define TXx9_TMTISR_TPIBS 0x00000004 +#define TXx9_TMTISR_TPIAS 0x00000002 +#define TXx9_TMTISR_TIIS 0x00000001 + +/* TMITMR : Interval Timer Mode */ +#define TXx9_TMITMR_TIIE 0x00008000 +#define TXx9_TMITMR_TZCE 0x00000001 + +/* TMWTMR : Watchdog Timer Mode */ +#define TXx9_TMWTMR_TWIE 0x00008000 +#define TXx9_TMWTMR_WDIS 0x00000080 +#define TXx9_TMWTMR_TWC 0x00000001 + +void txx9_clocksource_init(unsigned long baseaddr, + unsigned int imbusclk); +void txx9_clockevent_init(unsigned long baseaddr, int irq, + unsigned int imbusclk); +void txx9_tmr_init(unsigned long baseaddr); + +#ifdef CONFIG_CPU_TX39XX +#define TXX9_TIMER_BITS 24 +#else +#define TXX9_TIMER_BITS 32 +#endif + +#endif /* __ASM_TXX9TMR_H */ diff --git a/include/asm-um/unistd.h b/include/asm-um/unistd.h index 732c83f04c3..38bd9d94ee4 100644 --- a/include/asm-um/unistd.h +++ b/include/asm-um/unistd.h @@ -14,7 +14,6 @@ extern int um_execve(const char *file, char *const argv[], char *const env[]); #ifdef __KERNEL__ /* We get __ARCH_WANT_OLD_STAT and __ARCH_WANT_STAT64 from the base arch */ -#define __ARCH_WANT_IPC_PARSE_VERSION #define __ARCH_WANT_OLD_READDIR #define __ARCH_WANT_SYS_ALARM #define __ARCH_WANT_SYS_GETHOSTNAME diff --git a/include/asm-x86/gart.h b/include/asm-x86/gart.h new file mode 100644 index 00000000000..f704c50519b --- /dev/null +++ b/include/asm-x86/gart.h @@ -0,0 +1,29 @@ +#ifndef _ASM_X8664_IOMMU_H +#define _ASM_X8664_IOMMU_H 1 + +extern void pci_iommu_shutdown(void); +extern void no_iommu_init(void); +extern int force_iommu, no_iommu; +extern int iommu_detected; +#ifdef CONFIG_GART_IOMMU +extern void gart_iommu_init(void); +extern void gart_iommu_shutdown(void); +extern void __init gart_parse_options(char *); +extern void gart_iommu_hole_init(void); +extern int fallback_aper_order; +extern int fallback_aper_force; +extern int gart_iommu_aperture; +extern int gart_iommu_aperture_allowed; +extern int gart_iommu_aperture_disabled; +extern int fix_aperture; +#else +#define gart_iommu_aperture 0 +#define gart_iommu_aperture_allowed 0 + +static inline void gart_iommu_shutdown(void) +{ +} + +#endif + +#endif diff --git a/include/asm-x86/iommu.h b/include/asm-x86/iommu.h index 5af471f228e..07862fdd23c 100644 --- a/include/asm-x86/iommu.h +++ b/include/asm-x86/iommu.h @@ -1,5 +1,5 @@ -#ifndef _ASM_X8664_IOMMU_H -#define _ASM_X8664_IOMMU_H 1 +#ifndef _ASM_X8664_GART_H +#define _ASM_X8664_GART_H 1 extern void pci_iommu_shutdown(void); extern void no_iommu_init(void); diff --git a/include/asm-x86/pci_64.h b/include/asm-x86/pci_64.h index 9baa46d9f59..ef54226a932 100644 --- a/include/asm-x86/pci_64.h +++ b/include/asm-x86/pci_64.h @@ -37,7 +37,7 @@ extern int iommu_setup(char *opt); */ #define PCI_DMA_BUS_IS_PHYS (dma_ops->is_phys) -#if defined(CONFIG_IOMMU) || defined(CONFIG_CALGARY_IOMMU) +#if defined(CONFIG_GART_IOMMU) || defined(CONFIG_CALGARY_IOMMU) #define DECLARE_PCI_UNMAP_ADDR(ADDR_NAME) \ dma_addr_t ADDR_NAME; diff --git a/include/linux/Kbuild b/include/linux/Kbuild index 6a65231bc78..bd33c22315c 100644 --- a/include/linux/Kbuild +++ b/include/linux/Kbuild @@ -149,6 +149,7 @@ header-y += ticable.h header-y += times.h header-y += tiocl.h header-y += tipc.h +header-y += tipc_config.h header-y += toshiba.h header-y += ultrasound.h header-y += un.h diff --git a/include/linux/ata.h b/include/linux/ata.h index 8263a7b74d3..128dc7ad490 100644 --- a/include/linux/ata.h +++ b/include/linux/ata.h @@ -180,6 +180,7 @@ enum { ATA_CMD_VERIFY_EXT = 0x42, ATA_CMD_STANDBYNOW1 = 0xE0, ATA_CMD_IDLEIMMEDIATE = 0xE1, + ATA_CMD_SLEEP = 0xE6, ATA_CMD_INIT_DEV_PARAMS = 0x91, ATA_CMD_READ_NATIVE_MAX = 0xF8, ATA_CMD_READ_NATIVE_MAX_EXT = 0x27, @@ -235,6 +236,7 @@ enum { /* SETFEATURE Sector counts for SATA features */ SATA_AN = 0x05, /* Asynchronous Notification */ + SATA_DIPM = 0x03, /* Device Initiated Power Management */ /* ATAPI stuff */ ATAPI_PKT_DMA = (1 << 0), @@ -377,6 +379,26 @@ struct ata_taskfile { #define ata_id_cdb_intr(id) (((id)[0] & 0x60) == 0x20) +static inline bool ata_id_has_hipm(const u16 *id) +{ + u16 val = id[76]; + + if (val == 0 || val == 0xffff) + return false; + + return val & (1 << 9); +} + +static inline bool ata_id_has_dipm(const u16 *id) +{ + u16 val = id[78]; + + if (val == 0 || val == 0xffff) + return false; + + return val & (1 << 3); +} + static inline int ata_id_has_fua(const u16 *id) { if ((id[84] & 0xC000) != 0x4000) diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index bbf906a0b41..8396db24d01 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -341,7 +341,6 @@ enum blk_queue_state { struct blk_queue_tag { struct request **tag_index; /* map of busy tags */ unsigned long *tag_map; /* bit map of free/busy tags */ - struct list_head busy_list; /* fifo list of busy tags */ int busy; /* current depth */ int max_depth; /* what we will send to device */ int real_max_depth; /* what the array can hold */ @@ -435,6 +434,7 @@ struct request_queue unsigned int dma_alignment; struct blk_queue_tag *queue_tags; + struct list_head tag_busy_list; unsigned int nr_sorted; unsigned int in_flight; diff --git a/include/linux/bootmem.h b/include/linux/bootmem.h index c83534ee1e7..0365ec9fc0c 100644 --- a/include/linux/bootmem.h +++ b/include/linux/bootmem.h @@ -59,7 +59,6 @@ extern void *__alloc_bootmem_core(struct bootmem_data *bdata, unsigned long align, unsigned long goal, unsigned long limit); -extern void *alloc_bootmem_high_node(pg_data_t *pgdat, unsigned long size); #ifndef CONFIG_HAVE_ARCH_BOOTMEM_NODE extern void reserve_bootmem(unsigned long addr, unsigned long size); diff --git a/include/linux/eventpoll.h b/include/linux/eventpoll.h index d2a96cbf4f0..cf79853967f 100644 --- a/include/linux/eventpoll.h +++ b/include/linux/eventpoll.h @@ -32,18 +32,13 @@ * On x86-64 make the 64bit structure have the same alignment as the * 32bit structure. This makes 32bit emulation easier. * - * UML/x86_64 needs the same packing as x86_64 - UML + UML_X86 + - * 64_BIT adds up to UML/x86_64. + * UML/x86_64 needs the same packing as x86_64 */ #ifdef __x86_64__ #define EPOLL_PACKED __attribute__((packed)) #else -#if defined(CONFIG_UML) && defined(CONFIG_UML_X86) && defined(CONFIG_64BIT) -#define EPOLL_PACKED __attribute__((packed)) -#else #define EPOLL_PACKED #endif -#endif struct epoll_event { __u32 events; diff --git a/include/linux/ipmi_smi.h b/include/linux/ipmi_smi.h index 56ae438ae51..6e8cec50338 100644 --- a/include/linux/ipmi_smi.h +++ b/include/linux/ipmi_smi.h @@ -173,7 +173,7 @@ static inline int ipmi_demangle_device_id(const unsigned char *data, id->firmware_revision_2 = data[3]; id->ipmi_version = data[4]; id->additional_device_support = data[5]; - if (data_len >= 6) { + if (data_len >= 11) { id->manufacturer_id = (data[6] | (data[7] << 8) | (data[8] << 16)); id->product_id = data[9] | (data[10] << 8); diff --git a/include/linux/libata.h b/include/linux/libata.h index 6fd24e03622..1e277852ba4 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -133,11 +133,14 @@ enum { ATA_DFLAG_ACPI_PENDING = (1 << 5), /* ACPI resume action pending */ ATA_DFLAG_ACPI_FAILED = (1 << 6), /* ACPI on devcfg has failed */ ATA_DFLAG_AN = (1 << 7), /* AN configured */ + ATA_DFLAG_HIPM = (1 << 8), /* device supports HIPM */ + ATA_DFLAG_DIPM = (1 << 9), /* device supports DIPM */ ATA_DFLAG_CFG_MASK = (1 << 12) - 1, ATA_DFLAG_PIO = (1 << 12), /* device limited to PIO mode */ ATA_DFLAG_NCQ_OFF = (1 << 13), /* device limited to non-NCQ mode */ ATA_DFLAG_SPUNDOWN = (1 << 14), /* XXX: for spindown_compat */ + ATA_DFLAG_SLEEPING = (1 << 15), /* device is sleeping */ ATA_DFLAG_INIT_MASK = (1 << 16) - 1, ATA_DFLAG_DETACH = (1 << 16), @@ -185,6 +188,7 @@ enum { ATA_FLAG_ACPI_SATA = (1 << 17), /* need native SATA ACPI layout */ ATA_FLAG_AN = (1 << 18), /* controller supports AN */ ATA_FLAG_PMP = (1 << 19), /* controller supports PMP */ + ATA_FLAG_IPM = (1 << 20), /* driver can handle IPM */ /* The following flag belongs to ap->pflags but is kept in * ap->flags because it's referenced in many LLDs and will be @@ -217,6 +221,7 @@ enum { ATA_QCFLAG_IO = (1 << 3), /* standard IO command */ ATA_QCFLAG_RESULT_TF = (1 << 4), /* result TF requested */ ATA_QCFLAG_CLEAR_EXCL = (1 << 5), /* clear excl_link on completion */ + ATA_QCFLAG_QUIET = (1 << 6), /* don't report device error */ ATA_QCFLAG_FAILED = (1 << 16), /* cmd failed and is owned by EH */ ATA_QCFLAG_SENSE_VALID = (1 << 17), /* sense data valid */ @@ -234,6 +239,13 @@ enum { ATA_TMOUT_INTERNAL = 30 * HZ, ATA_TMOUT_INTERNAL_QUICK = 5 * HZ, + /* FIXME: GoVault needs 2s but we can't afford that without + * parallel probing. 800ms is enough for iVDR disk + * HHD424020F7SV00. Increase to 2secs when parallel probing + * is in place. + */ + ATA_TMOUT_FF_WAIT = 4 * HZ / 5, + /* ATA bus states */ BUS_UNKNOWN = 0, BUS_DMA = 1, @@ -294,6 +306,7 @@ enum { ATA_EHI_RESUME_LINK = (1 << 1), /* resume link (reset modifier) */ ATA_EHI_NO_AUTOPSY = (1 << 2), /* no autopsy */ ATA_EHI_QUIET = (1 << 3), /* be quiet */ + ATA_EHI_LPM = (1 << 4), /* link power management action */ ATA_EHI_DID_SOFTRESET = (1 << 16), /* already soft-reset this port */ ATA_EHI_DID_HARDRESET = (1 << 17), /* already soft-reset this port */ @@ -325,6 +338,7 @@ enum { ATA_HORKAGE_BROKEN_HPA = (1 << 4), /* Broken HPA */ ATA_HORKAGE_SKIP_PM = (1 << 5), /* Skip PM operations */ ATA_HORKAGE_HPA_SIZE = (1 << 6), /* native size off by one */ + ATA_HORKAGE_IPM = (1 << 7), /* Link PM problems */ /* DMA mask for user DMA control: User visible values; DO NOT renumber */ @@ -370,6 +384,18 @@ typedef int (*ata_reset_fn_t)(struct ata_link *link, unsigned int *classes, unsigned long deadline); typedef void (*ata_postreset_fn_t)(struct ata_link *link, unsigned int *classes); +/* + * host pm policy: If you alter this, you also need to alter libata-scsi.c + * (for the ascii descriptions) + */ +enum link_pm { + NOT_AVAILABLE, + MIN_POWER, + MAX_PERFORMANCE, + MEDIUM_POWER, +}; +extern struct class_device_attribute class_device_attr_link_power_management_policy; + struct ata_ioports { void __iomem *cmd_addr; void __iomem *data_addr; @@ -616,6 +642,7 @@ struct ata_port { pm_message_t pm_mesg; int *pm_result; + enum link_pm pm_policy; struct timer_list fastdrain_timer; unsigned long fastdrain_cnt; @@ -683,7 +710,8 @@ struct ata_port_operations { int (*port_suspend) (struct ata_port *ap, pm_message_t mesg); int (*port_resume) (struct ata_port *ap); - + int (*enable_pm) (struct ata_port *ap, enum link_pm policy); + void (*disable_pm) (struct ata_port *ap); int (*port_start) (struct ata_port *ap); void (*port_stop) (struct ata_port *ap); @@ -799,6 +827,7 @@ extern void ata_host_resume(struct ata_host *host); extern int ata_ratelimit(void); extern int ata_busy_sleep(struct ata_port *ap, unsigned long timeout_pat, unsigned long timeout); +extern void ata_wait_after_reset(struct ata_port *ap, unsigned long deadline); extern int ata_wait_ready(struct ata_port *ap, unsigned long deadline); extern void ata_port_queue_task(struct ata_port *ap, work_func_t fn, void *data, unsigned long delay); diff --git a/include/linux/mv643xx_eth.h b/include/linux/mv643xx_eth.h index 8df230a279a..30e11aa3c1c 100644 --- a/include/linux/mv643xx_eth.h +++ b/include/linux/mv643xx_eth.h @@ -8,9 +8,9 @@ #define MV643XX_ETH_NAME "mv643xx_eth" #define MV643XX_ETH_SHARED_REGS 0x2000 #define MV643XX_ETH_SHARED_REGS_SIZE 0x2000 -#define MV643XX_ETH_BAR_4 0x220 -#define MV643XX_ETH_SIZE_REG_4 0x224 -#define MV643XX_ETH_BASE_ADDR_ENABLE_REG 0x0290 +#define MV643XX_ETH_BAR_4 0x2220 +#define MV643XX_ETH_SIZE_REG_4 0x2224 +#define MV643XX_ETH_BASE_ADDR_ENABLE_REG 0x2290 struct mv643xx_eth_platform_data { int port_number; diff --git a/include/linux/scatterlist.h b/include/linux/scatterlist.h index 45712317138..32326c293d7 100644 --- a/include/linux/scatterlist.h +++ b/include/linux/scatterlist.h @@ -150,7 +150,7 @@ static inline struct scatterlist *sg_last(struct scatterlist *sgl, struct scatterlist *ret = &sgl[nents - 1]; #else struct scatterlist *sg, *ret = NULL; - int i; + unsigned int i; for_each_sg(sgl, sg, nents, i) ret = sg; @@ -179,7 +179,11 @@ static inline void sg_chain(struct scatterlist *prv, unsigned int prv_nents, #ifndef ARCH_HAS_SG_CHAIN BUG(); #endif - prv[prv_nents - 1].page_link = (unsigned long) sgl | 0x01; + /* + * Set lowest bit to indicate a link pointer, and make sure to clear + * the termination bit if it happens to be set. + */ + prv[prv_nents - 1].page_link = ((unsigned long) sgl | 0x01) & ~0x02; } /** @@ -239,7 +243,7 @@ static inline void sg_init_table(struct scatterlist *sgl, unsigned int nents) sg_mark_end(sgl, nents); #ifdef CONFIG_DEBUG_SG { - int i; + unsigned int i; for (i = 0; i < nents; i++) sgl[i].sg_magic = SG_MAGIC; } diff --git a/include/linux/sched.h b/include/linux/sched.h index 3c07d595979..155d7438f7a 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -1009,6 +1009,7 @@ struct task_struct { unsigned int rt_priority; cputime_t utime, stime, utimescaled, stimescaled; cputime_t gtime; + cputime_t prev_utime, prev_stime; unsigned long nvcsw, nivcsw; /* context switch counts */ struct timespec start_time; /* monotonic time */ struct timespec real_start_time; /* boot based time */ diff --git a/include/linux/sunrpc/rpc_rdma.h b/include/linux/sunrpc/rpc_rdma.h index 0013a0d8dc6..87b895d5c78 100644 --- a/include/linux/sunrpc/rpc_rdma.h +++ b/include/linux/sunrpc/rpc_rdma.h @@ -41,17 +41,17 @@ #define _LINUX_SUNRPC_RPC_RDMA_H struct rpcrdma_segment { - uint32_t rs_handle; /* Registered memory handle */ - uint32_t rs_length; /* Length of the chunk in bytes */ - uint64_t rs_offset; /* Chunk virtual address or offset */ + __be32 rs_handle; /* Registered memory handle */ + __be32 rs_length; /* Length of the chunk in bytes */ + __be64 rs_offset; /* Chunk virtual address or offset */ }; /* * read chunk(s), encoded as a linked list. */ struct rpcrdma_read_chunk { - uint32_t rc_discrim; /* 1 indicates presence */ - uint32_t rc_position; /* Position in XDR stream */ + __be32 rc_discrim; /* 1 indicates presence */ + __be32 rc_position; /* Position in XDR stream */ struct rpcrdma_segment rc_target; }; @@ -66,29 +66,29 @@ struct rpcrdma_write_chunk { * write chunk(s), encoded as a counted array. */ struct rpcrdma_write_array { - uint32_t wc_discrim; /* 1 indicates presence */ - uint32_t wc_nchunks; /* Array count */ + __be32 wc_discrim; /* 1 indicates presence */ + __be32 wc_nchunks; /* Array count */ struct rpcrdma_write_chunk wc_array[0]; }; struct rpcrdma_msg { - uint32_t rm_xid; /* Mirrors the RPC header xid */ - uint32_t rm_vers; /* Version of this protocol */ - uint32_t rm_credit; /* Buffers requested/granted */ - uint32_t rm_type; /* Type of message (enum rpcrdma_proc) */ + __be32 rm_xid; /* Mirrors the RPC header xid */ + __be32 rm_vers; /* Version of this protocol */ + __be32 rm_credit; /* Buffers requested/granted */ + __be32 rm_type; /* Type of message (enum rpcrdma_proc) */ union { struct { /* no chunks */ - uint32_t rm_empty[3]; /* 3 empty chunk lists */ + __be32 rm_empty[3]; /* 3 empty chunk lists */ } rm_nochunks; struct { /* no chunks and padded */ - uint32_t rm_align; /* Padding alignment */ - uint32_t rm_thresh; /* Padding threshold */ - uint32_t rm_pempty[3]; /* 3 empty chunk lists */ + __be32 rm_align; /* Padding alignment */ + __be32 rm_thresh; /* Padding threshold */ + __be32 rm_pempty[3]; /* 3 empty chunk lists */ } rm_padded; - uint32_t rm_chunks[0]; /* read, write and reply chunks */ + __be32 rm_chunks[0]; /* read, write and reply chunks */ } rm_body; }; diff --git a/include/linux/types.h b/include/linux/types.h index 4f0dad21c91..f4f8d19158e 100644 --- a/include/linux/types.h +++ b/include/linux/types.h @@ -37,6 +37,8 @@ typedef __kernel_gid32_t gid_t; typedef __kernel_uid16_t uid16_t; typedef __kernel_gid16_t gid16_t; +typedef unsigned long uintptr_t; + #ifdef CONFIG_UID16 /* This is defined by include/asm-{arch}/posix_types.h */ typedef __kernel_old_uid_t old_uid_t; diff --git a/include/net/sctp/auth.h b/include/net/sctp/auth.h index 9e8f13b7da5..5db261a1e85 100644 --- a/include/net/sctp/auth.h +++ b/include/net/sctp/auth.h @@ -103,7 +103,7 @@ struct sctp_hmac *sctp_auth_asoc_get_hmac(const struct sctp_association *asoc); void sctp_auth_asoc_set_default_hmac(struct sctp_association *asoc, struct sctp_hmac_algo_param *hmacs); int sctp_auth_asoc_verify_hmac_id(const struct sctp_association *asoc, - __u16 hmac_id); + __be16 hmac_id); int sctp_auth_send_cid(sctp_cid_t chunk, const struct sctp_association *asoc); int sctp_auth_recv_cid(sctp_cid_t chunk, const struct sctp_association *asoc); void sctp_auth_calculate_hmac(const struct sctp_association *asoc, diff --git a/kernel/fork.c b/kernel/fork.c index ddafdfac945..28a74015198 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -1056,6 +1056,8 @@ static struct task_struct *copy_process(unsigned long clone_flags, p->gtime = cputime_zero; p->utimescaled = cputime_zero; p->stimescaled = cputime_zero; + p->prev_utime = cputime_zero; + p->prev_stime = cputime_zero; #ifdef CONFIG_TASK_XACCT p->rchar = 0; /* I/O counter: bytes read */ diff --git a/kernel/hrtimer.c b/kernel/hrtimer.c index b6d2ff7e37e..22a25142e4c 100644 --- a/kernel/hrtimer.c +++ b/kernel/hrtimer.c @@ -602,7 +602,7 @@ static int hrtimer_switch_to_hres(void) /* "Retrigger" the interrupt to get things going */ retrigger_next_event(NULL); local_irq_restore(flags); - printk(KERN_INFO "Switched to high resolution mode on CPU %d\n", + printk(KERN_DEBUG "Switched to high resolution mode on CPU %d\n", smp_processor_id()); return 1; } diff --git a/kernel/sched.c b/kernel/sched.c index b4fbbc44045..3f6bd111290 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -172,6 +172,7 @@ struct task_group { unsigned long shares; /* spinlock to serialize modification to shares */ spinlock_t lock; + struct rcu_head rcu; }; /* Default task group's sched entity on each cpu */ @@ -258,7 +259,6 @@ struct cfs_rq { */ struct list_head leaf_cfs_rq_list; /* Better name : task_cfs_rq_list? */ struct task_group *tg; /* group that "owns" this runqueue */ - struct rcu_head rcu; #endif }; @@ -3355,7 +3355,7 @@ void account_user_time(struct task_struct *p, cputime_t cputime) * @p: the process that the cpu time gets accounted to * @cputime: the cpu time spent in virtual machine since the last update */ -void account_guest_time(struct task_struct *p, cputime_t cputime) +static void account_guest_time(struct task_struct *p, cputime_t cputime) { cputime64_t tmp; struct cpu_usage_stat *cpustat = &kstat_this_cpu.cpustat; @@ -5365,7 +5365,7 @@ static struct ctl_table sd_ctl_dir[] = { .procname = "sched_domain", .mode = 0555, }, - {0,}, + {0, }, }; static struct ctl_table sd_ctl_root[] = { @@ -5375,7 +5375,7 @@ static struct ctl_table sd_ctl_root[] = { .mode = 0555, .child = sd_ctl_dir, }, - {0,}, + {0, }, }; static struct ctl_table *sd_alloc_ctl_entry(int n) @@ -7019,8 +7019,8 @@ err: /* rcu callback to free various structures associated with a task group */ static void free_sched_group(struct rcu_head *rhp) { - struct cfs_rq *cfs_rq = container_of(rhp, struct cfs_rq, rcu); - struct task_group *tg = cfs_rq->tg; + struct task_group *tg = container_of(rhp, struct task_group, rcu); + struct cfs_rq *cfs_rq; struct sched_entity *se; int i; @@ -7041,7 +7041,7 @@ static void free_sched_group(struct rcu_head *rhp) /* Destroy runqueue etc associated with a task group */ void sched_destroy_group(struct task_group *tg) { - struct cfs_rq *cfs_rq; + struct cfs_rq *cfs_rq = NULL; int i; for_each_possible_cpu(i) { @@ -7049,10 +7049,10 @@ void sched_destroy_group(struct task_group *tg) list_del_rcu(&cfs_rq->leaf_cfs_rq_list); } - cfs_rq = tg->cfs_rq[0]; + BUG_ON(!cfs_rq); /* wait for possible concurrent references to cfs_rqs complete */ - call_rcu(&cfs_rq->rcu, free_sched_group); + call_rcu(&tg->rcu, free_sched_group); } /* change task's runqueue when it moves between groups. @@ -7211,25 +7211,53 @@ static u64 cpu_shares_read_uint(struct cgroup *cgrp, struct cftype *cft) return (u64) tg->shares; } -static struct cftype cpu_shares = { - .name = "shares", - .read_uint = cpu_shares_read_uint, - .write_uint = cpu_shares_write_uint, +static u64 cpu_usage_read(struct cgroup *cgrp, struct cftype *cft) +{ + struct task_group *tg = cgroup_tg(cgrp); + unsigned long flags; + u64 res = 0; + int i; + + for_each_possible_cpu(i) { + /* + * Lock to prevent races with updating 64-bit counters + * on 32-bit arches. + */ + spin_lock_irqsave(&cpu_rq(i)->lock, flags); + res += tg->se[i]->sum_exec_runtime; + spin_unlock_irqrestore(&cpu_rq(i)->lock, flags); + } + /* Convert from ns to ms */ + do_div(res, 1000000); + + return res; +} + +static struct cftype cpu_files[] = { + { + .name = "shares", + .read_uint = cpu_shares_read_uint, + .write_uint = cpu_shares_write_uint, + }, + { + .name = "usage", + .read_uint = cpu_usage_read, + }, }; static int cpu_cgroup_populate(struct cgroup_subsys *ss, struct cgroup *cont) { - return cgroup_add_file(cont, ss, &cpu_shares); + return cgroup_add_files(cont, ss, cpu_files, ARRAY_SIZE(cpu_files)); } struct cgroup_subsys cpu_cgroup_subsys = { - .name = "cpu", - .create = cpu_cgroup_create, - .destroy = cpu_cgroup_destroy, - .can_attach = cpu_cgroup_can_attach, - .attach = cpu_cgroup_attach, - .populate = cpu_cgroup_populate, - .subsys_id = cpu_cgroup_subsys_id, + .name = "cpu", + .create = cpu_cgroup_create, + .destroy = cpu_cgroup_destroy, + .can_attach = cpu_cgroup_can_attach, + .attach = cpu_cgroup_attach, + .populate = cpu_cgroup_populate, + .subsys_id = cpu_cgroup_subsys_id, .early_init = 1, }; diff --git a/kernel/sched_fair.c b/kernel/sched_fair.c index 9971831b560..01859f662ab 100644 --- a/kernel/sched_fair.c +++ b/kernel/sched_fair.c @@ -1025,7 +1025,7 @@ static void task_tick_fair(struct rq *rq, struct task_struct *curr) } } -#define swap(a,b) do { typeof(a) tmp = (a); (a) = (b); (b) = tmp; } while (0) +#define swap(a, b) do { typeof(a) tmp = (a); (a) = (b); (b) = tmp; } while (0) /* * Share the fairness runtime between parent and child, thus the diff --git a/kernel/signal.c b/kernel/signal.c index 12006308c7e..909a0cc6bc7 100644 --- a/kernel/signal.c +++ b/kernel/signal.c @@ -124,7 +124,7 @@ void recalc_sigpending_and_wake(struct task_struct *t) void recalc_sigpending(void) { - if (!recalc_sigpending_tsk(current)) + if (!recalc_sigpending_tsk(current) && !freezing(current)) clear_thread_flag(TIF_SIGPENDING); } @@ -732,7 +732,7 @@ static void print_fatal_signal(struct pt_regs *regs, int signr) printk("%s/%d: potentially unexpected fatal signal %d.\n", current->comm, task_pid_nr(current), signr); -#ifdef __i386__ +#if defined(__i386__) && !defined(__arch_um__) printk("code at %08lx: ", regs->eip); { int i; diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c index 10a1347597f..5997456ebbc 100644 --- a/kernel/time/tick-sched.c +++ b/kernel/time/tick-sched.c @@ -320,8 +320,6 @@ ktime_t tick_nohz_get_sleep_length(void) return ts->sleep_length; } -EXPORT_SYMBOL_GPL(tick_nohz_get_sleep_length); - /** * nohz_restart_sched_tick - restart the idle tick from the idle task * diff --git a/kernel/time/timer_list.c b/kernel/time/timer_list.c index fdb2e03d4fe..12c5f4cb6b8 100644 --- a/kernel/time/timer_list.c +++ b/kernel/time/timer_list.c @@ -129,7 +129,8 @@ static void print_cpu(struct seq_file *m, int cpu, u64 now) struct hrtimer_cpu_base *cpu_base = &per_cpu(hrtimer_bases, cpu); int i; - SEQ_printf(m, "\ncpu: %d\n", cpu); + SEQ_printf(m, "\n"); + SEQ_printf(m, "cpu: %d\n", cpu); for (i = 0; i < HRTIMER_MAX_CLOCK_BASES; i++) { SEQ_printf(m, " clock %d:\n", i); print_base(m, cpu_base->clock_base + i, now); @@ -184,7 +185,8 @@ print_tickdevice(struct seq_file *m, struct tick_device *td) { struct clock_event_device *dev = td->evtdev; - SEQ_printf(m, "\nTick Device: mode: %d\n", td->mode); + SEQ_printf(m, "\n"); + SEQ_printf(m, "Tick Device: mode: %d\n", td->mode); SEQ_printf(m, "Clock Event Device: "); if (!dev) { diff --git a/mm/filemap.c b/mm/filemap.c index 5209e47b7fe..7c864363002 100644 --- a/mm/filemap.c +++ b/mm/filemap.c @@ -28,6 +28,7 @@ #include <linux/backing-dev.h> #include <linux/pagevec.h> #include <linux/blkdev.h> +#include <linux/backing-dev.h> #include <linux/security.h> #include <linux/syscalls.h> #include <linux/cpuset.h> diff --git a/mm/nommu.c b/mm/nommu.c index 8f09333f78e..35622c59092 100644 --- a/mm/nommu.c +++ b/mm/nommu.c @@ -12,6 +12,7 @@ * Copyright (c) 2002 Greg Ungerer <gerg@snapgear.com> */ +#include <linux/module.h> #include <linux/mm.h> #include <linux/mman.h> #include <linux/swap.h> diff --git a/mm/shmem.c b/mm/shmem.c index 404e53bb212..253d205914b 100644 --- a/mm/shmem.c +++ b/mm/shmem.c @@ -915,6 +915,21 @@ static int shmem_writepage(struct page *page, struct writeback_control *wbc) struct inode *inode; BUG_ON(!PageLocked(page)); + /* + * shmem_backing_dev_info's capabilities prevent regular writeback or + * sync from ever calling shmem_writepage; but a stacking filesystem + * may use the ->writepage of its underlying filesystem, in which case + * we want to do nothing when that underlying filesystem is tmpfs + * (writing out to swap is useful as a response to memory pressure, but + * of no use to stabilize the data) - just redirty the page, unlock it + * and claim success in this case. AOP_WRITEPAGE_ACTIVATE, and the + * page_mapped check below, must be avoided unless we're in reclaim. + */ + if (!wbc->for_reclaim) { + set_page_dirty(page); + unlock_page(page); + return 0; + } BUG_ON(page_mapped(page)); mapping = page->mapping; diff --git a/mm/slub.c b/mm/slub.c index aac1dd3c657..bcdb2c8941a 100644 --- a/mm/slub.c +++ b/mm/slub.c @@ -2734,7 +2734,7 @@ static void slab_mem_offline_callback(void *arg) * and offline_pages() function shoudn't call this * callback. So, we must fail. */ - BUG_ON(atomic_read(&n->nr_slabs)); + BUG_ON(atomic_long_read(&n->nr_slabs)); s->node[offline_node] = NULL; kmem_cache_free(kmalloc_caches, n); diff --git a/mm/sparse-vmemmap.c b/mm/sparse-vmemmap.c index d3b718b0c20..22620f6a976 100644 --- a/mm/sparse-vmemmap.c +++ b/mm/sparse-vmemmap.c @@ -24,6 +24,7 @@ #include <linux/module.h> #include <linux/spinlock.h> #include <linux/vmalloc.h> +#include <linux/sched.h> #include <asm/dma.h> #include <asm/pgalloc.h> #include <asm/pgtable.h> diff --git a/mm/sparse.c b/mm/sparse.c index 08fb14f5eea..e06f514fe04 100644 --- a/mm/sparse.c +++ b/mm/sparse.c @@ -220,12 +220,6 @@ static int __meminit sparse_init_one_section(struct mem_section *ms, return 1; } -__attribute__((weak)) __init -void *alloc_bootmem_high_node(pg_data_t *pgdat, unsigned long size) -{ - return NULL; -} - static unsigned long usemap_size(void) { unsigned long size_bytes; @@ -267,11 +261,6 @@ struct page __init *sparse_mem_map_populate(unsigned long pnum, int nid) if (map) return map; - map = alloc_bootmem_high_node(NODE_DATA(nid), - sizeof(struct page) * PAGES_PER_SECTION); - if (map) - return map; - map = alloc_bootmem_node(NODE_DATA(nid), sizeof(struct page) * PAGES_PER_SECTION); return map; diff --git a/net/core/dev.c b/net/core/dev.c index 853c8b575f1..02e7d8377c4 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -2172,7 +2172,15 @@ static void net_rx_action(struct softirq_action *h) weight = n->weight; - work = n->poll(n, weight); + /* This NAPI_STATE_SCHED test is for avoiding a race + * with netpoll's poll_napi(). Only the entity which + * obtains the lock and sees NAPI_STATE_SCHED set will + * actually make the ->poll() call. Therefore we avoid + * accidently calling ->poll() when NAPI is not scheduled. + */ + work = 0; + if (test_bit(NAPI_STATE_SCHED, &n->state)) + work = n->poll(n, weight); WARN_ON_ONCE(work > weight); diff --git a/net/core/netpoll.c b/net/core/netpoll.c index bf8d18f1b01..c499b5c69be 100644 --- a/net/core/netpoll.c +++ b/net/core/netpoll.c @@ -116,6 +116,29 @@ static __sum16 checksum_udp(struct sk_buff *skb, struct udphdr *uh, * network adapter, forcing superfluous retries and possibly timeouts. * Thus, we set our budget to greater than 1. */ +static int poll_one_napi(struct netpoll_info *npinfo, + struct napi_struct *napi, int budget) +{ + int work; + + /* net_rx_action's ->poll() invocations and our's are + * synchronized by this test which is only made while + * holding the napi->poll_lock. + */ + if (!test_bit(NAPI_STATE_SCHED, &napi->state)) + return budget; + + npinfo->rx_flags |= NETPOLL_RX_DROP; + atomic_inc(&trapped); + + work = napi->poll(napi, budget); + + atomic_dec(&trapped); + npinfo->rx_flags &= ~NETPOLL_RX_DROP; + + return budget - work; +} + static void poll_napi(struct netpoll *np) { struct netpoll_info *npinfo = np->dev->npinfo; @@ -123,17 +146,13 @@ static void poll_napi(struct netpoll *np) int budget = 16; list_for_each_entry(napi, &np->dev->napi_list, dev_list) { - if (test_bit(NAPI_STATE_SCHED, &napi->state) && - napi->poll_owner != smp_processor_id() && + if (napi->poll_owner != smp_processor_id() && spin_trylock(&napi->poll_lock)) { - npinfo->rx_flags |= NETPOLL_RX_DROP; - atomic_inc(&trapped); - - napi->poll(napi, budget); - - atomic_dec(&trapped); - npinfo->rx_flags &= ~NETPOLL_RX_DROP; + budget = poll_one_napi(npinfo, napi, budget); spin_unlock(&napi->poll_lock); + + if (!budget) + break; } } } diff --git a/net/ipv4/ipvs/ip_vs_sync.c b/net/ipv4/ipvs/ip_vs_sync.c index c99f2a33fb9..0d4d9721cbd 100644 --- a/net/ipv4/ipvs/ip_vs_sync.c +++ b/net/ipv4/ipvs/ip_vs_sync.c @@ -72,7 +72,6 @@ struct ip_vs_sync_thread_data { int state; }; -#define IP_VS_SYNC_CONN_TIMEOUT (3*60*HZ) #define SIMPLE_CONN_SIZE (sizeof(struct ip_vs_sync_conn)) #define FULL_CONN_SIZE \ (sizeof(struct ip_vs_sync_conn) + sizeof(struct ip_vs_sync_conn_options)) @@ -284,6 +283,7 @@ static void ip_vs_process_message(const char *buffer, const size_t buflen) struct ip_vs_sync_conn *s; struct ip_vs_sync_conn_options *opt; struct ip_vs_conn *cp; + struct ip_vs_protocol *pp; char *p; int i; @@ -342,7 +342,8 @@ static void ip_vs_process_message(const char *buffer, const size_t buflen) p += SIMPLE_CONN_SIZE; atomic_set(&cp->in_pkts, sysctl_ip_vs_sync_threshold[0]); - cp->timeout = IP_VS_SYNC_CONN_TIMEOUT; + pp = ip_vs_proto_get(s->protocol); + cp->timeout = pp->timeout_table[cp->state]; ip_vs_conn_put(cp); if (p > buffer+buflen) { diff --git a/net/ipv4/proc.c b/net/ipv4/proc.c index 9be0daa9c0e..ffdccc0972e 100644 --- a/net/ipv4/proc.c +++ b/net/ipv4/proc.c @@ -304,7 +304,7 @@ static void icmp_put(struct seq_file *seq) for (i=0; icmpmibmap[i].name != NULL; i++) seq_printf(seq, " %lu", snmp_fold_field((void **) icmpmsg_statistics, - icmpmibmap[i].index)); + icmpmibmap[i].index | 0x100)); } /* diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index 2e6ad6dbba6..c64072bb504 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -2453,7 +2453,7 @@ void __init tcp_init(void) 0, &tcp_hashinfo.ehash_size, NULL, - 0); + thash_entries ? 0 : 512 * 1024); tcp_hashinfo.ehash_size = 1 << tcp_hashinfo.ehash_size; for (i = 0; i < tcp_hashinfo.ehash_size; i++) { rwlock_init(&tcp_hashinfo.ehash[i].lock); diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index ad759f1c377..d3d8d5dfcee 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -858,16 +858,16 @@ int tcp_v4_md5_do_add(struct sock *sk, __be32 addr, u8 *newkey, u8 newkeylen) { /* Add Key to the list */ - struct tcp4_md5sig_key *key; + struct tcp_md5sig_key *key; struct tcp_sock *tp = tcp_sk(sk); struct tcp4_md5sig_key *keys; - key = (struct tcp4_md5sig_key *)tcp_v4_md5_do_lookup(sk, addr); + key = tcp_v4_md5_do_lookup(sk, addr); if (key) { /* Pre-existing entry - just update that one. */ - kfree(key->base.key); - key->base.key = newkey; - key->base.keylen = newkeylen; + kfree(key->key); + key->key = newkey; + key->keylen = newkeylen; } else { struct tcp_md5sig_info *md5sig; diff --git a/net/ipv4/tcp_vegas.c b/net/ipv4/tcp_vegas.c index b49dedcda52..007304e9984 100644 --- a/net/ipv4/tcp_vegas.c +++ b/net/ipv4/tcp_vegas.c @@ -266,26 +266,25 @@ static void tcp_vegas_cong_avoid(struct sock *sk, u32 ack, */ diff = (old_wnd << V_PARAM_SHIFT) - target_cwnd; - if (tp->snd_cwnd <= tp->snd_ssthresh) { - /* Slow start. */ - if (diff > gamma) { - /* Going too fast. Time to slow down - * and switch to congestion avoidance. - */ - tp->snd_ssthresh = 2; - - /* Set cwnd to match the actual rate - * exactly: - * cwnd = (actual rate) * baseRTT - * Then we add 1 because the integer - * truncation robs us of full link - * utilization. - */ - tp->snd_cwnd = min(tp->snd_cwnd, - (target_cwnd >> - V_PARAM_SHIFT)+1); + if (diff > gamma && tp->snd_ssthresh > 2 ) { + /* Going too fast. Time to slow down + * and switch to congestion avoidance. + */ + tp->snd_ssthresh = 2; + + /* Set cwnd to match the actual rate + * exactly: + * cwnd = (actual rate) * baseRTT + * Then we add 1 because the integer + * truncation robs us of full link + * utilization. + */ + tp->snd_cwnd = min(tp->snd_cwnd, + (target_cwnd >> + V_PARAM_SHIFT)+1); - } + } else if (tp->snd_cwnd <= tp->snd_ssthresh) { + /* Slow start. */ tcp_slow_start(tp); } else { /* Congestion avoidance. */ diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c index 20cfc90d559..36f7dbfb6db 100644 --- a/net/ipv6/ndisc.c +++ b/net/ipv6/ndisc.c @@ -1670,7 +1670,7 @@ int ndisc_ifinfo_sysctl_change(struct ctl_table *ctl, int write, struct file * f filp, buffer, lenp, ppos); else if ((strcmp(ctl->procname, "retrans_time_ms") == 0) || - (strcmp(ctl->procname, "base_reacable_time_ms") == 0)) + (strcmp(ctl->procname, "base_reachable_time_ms") == 0)) ret = proc_dointvec_ms_jiffies(ctl, write, filp, buffer, lenp, ppos); else diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 85208026278..f1523b82cac 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c @@ -561,16 +561,16 @@ static int tcp_v6_md5_do_add(struct sock *sk, struct in6_addr *peer, char *newkey, u8 newkeylen) { /* Add key to the list */ - struct tcp6_md5sig_key *key; + struct tcp_md5sig_key *key; struct tcp_sock *tp = tcp_sk(sk); struct tcp6_md5sig_key *keys; - key = (struct tcp6_md5sig_key*) tcp_v6_md5_do_lookup(sk, peer); + key = tcp_v6_md5_do_lookup(sk, peer); if (key) { /* modify existing entry - just update that one */ - kfree(key->base.key); - key->base.key = newkey; - key->base.keylen = newkeylen; + kfree(key->key); + key->key = newkey; + key->keylen = newkeylen; } else { /* reallocate new list if current one is full. */ if (!tp->md5sig_info) { diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c index 4d6171bc082..000c2fb462d 100644 --- a/net/netfilter/nf_conntrack_core.c +++ b/net/netfilter/nf_conntrack_core.c @@ -999,7 +999,7 @@ struct hlist_head *nf_ct_alloc_hashtable(int *sizep, int *vmalloced) *vmalloced = 0; size = *sizep = roundup(*sizep, PAGE_SIZE / sizeof(struct hlist_head)); - hash = (void*)__get_free_pages(GFP_KERNEL, + hash = (void*)__get_free_pages(GFP_KERNEL|__GFP_NOWARN, get_order(sizeof(struct hlist_head) * size)); if (!hash) { diff --git a/net/sctp/auth.c b/net/sctp/auth.c index 8af1004abef..6d5fa6bb371 100644 --- a/net/sctp/auth.c +++ b/net/sctp/auth.c @@ -556,7 +556,7 @@ struct sctp_hmac *sctp_auth_asoc_get_hmac(const struct sctp_association *asoc) return &sctp_hmac_list[id]; } -static int __sctp_auth_find_hmacid(__u16 *hmacs, int n_elts, __u16 hmac_id) +static int __sctp_auth_find_hmacid(__be16 *hmacs, int n_elts, __be16 hmac_id) { int found = 0; int i; @@ -573,7 +573,7 @@ static int __sctp_auth_find_hmacid(__u16 *hmacs, int n_elts, __u16 hmac_id) /* See if the HMAC_ID is one that we claim as supported */ int sctp_auth_asoc_verify_hmac_id(const struct sctp_association *asoc, - __u16 hmac_id) + __be16 hmac_id) { struct sctp_hmac_algo_param *hmacs; __u16 n_elt; diff --git a/net/socket.c b/net/socket.c index 540013ea862..5d879fd3d01 100644 --- a/net/socket.c +++ b/net/socket.c @@ -1250,11 +1250,14 @@ asmlinkage long sys_socketpair(int family, int type, int protocol, goto out_release_both; fd1 = sock_alloc_fd(&newfile1); - if (unlikely(fd1 < 0)) + if (unlikely(fd1 < 0)) { + err = fd1; goto out_release_both; + } fd2 = sock_alloc_fd(&newfile2); if (unlikely(fd2 < 0)) { + err = fd2; put_filp(newfile1); put_unused_fd(fd1); goto out_release_both; diff --git a/net/sunrpc/sysctl.c b/net/sunrpc/sysctl.c index 864b541bbf5..2be714e9b38 100644 --- a/net/sunrpc/sysctl.c +++ b/net/sunrpc/sysctl.c @@ -87,9 +87,8 @@ proc_dodebug(ctl_table *table, int write, struct file *file, left--, s++; *(unsigned int *) table->data = value; /* Display the RPC tasks on writing to rpc_debug */ - if (table->ctl_name == CTL_RPCDEBUG) { + if (strcmp(table->procname, "rpc_debug") == 0) rpc_show_tasks(); - } } else { if (!access_ok(VERIFY_WRITE, buffer, left)) return -EFAULT; diff --git a/net/sunrpc/xprtrdma/rpc_rdma.c b/net/sunrpc/xprtrdma/rpc_rdma.c index 12db6358042..9e11ce71595 100644 --- a/net/sunrpc/xprtrdma/rpc_rdma.c +++ b/net/sunrpc/xprtrdma/rpc_rdma.c @@ -181,7 +181,7 @@ rpcrdma_create_chunks(struct rpc_rqst *rqst, struct xdr_buf *target, struct rpcrdma_read_chunk *cur_rchunk = NULL; struct rpcrdma_write_array *warray = NULL; struct rpcrdma_write_chunk *cur_wchunk = NULL; - u32 *iptr = headerp->rm_body.rm_chunks; + __be32 *iptr = headerp->rm_body.rm_chunks; if (type == rpcrdma_readch || type == rpcrdma_areadch) { /* a read chunk - server will RDMA Read our memory */ @@ -217,25 +217,25 @@ rpcrdma_create_chunks(struct rpc_rqst *rqst, struct xdr_buf *target, cur_rchunk->rc_target.rs_handle = htonl(seg->mr_rkey); cur_rchunk->rc_target.rs_length = htonl(seg->mr_len); xdr_encode_hyper( - (u32 *)&cur_rchunk->rc_target.rs_offset, + (__be32 *)&cur_rchunk->rc_target.rs_offset, seg->mr_base); dprintk("RPC: %s: read chunk " "elem %d@0x%llx:0x%x pos %d (%s)\n", __func__, - seg->mr_len, seg->mr_base, seg->mr_rkey, pos, - n < nsegs ? "more" : "last"); + seg->mr_len, (unsigned long long)seg->mr_base, + seg->mr_rkey, pos, n < nsegs ? "more" : "last"); cur_rchunk++; r_xprt->rx_stats.read_chunk_count++; } else { /* write/reply */ cur_wchunk->wc_target.rs_handle = htonl(seg->mr_rkey); cur_wchunk->wc_target.rs_length = htonl(seg->mr_len); xdr_encode_hyper( - (u32 *)&cur_wchunk->wc_target.rs_offset, + (__be32 *)&cur_wchunk->wc_target.rs_offset, seg->mr_base); dprintk("RPC: %s: %s chunk " "elem %d@0x%llx:0x%x (%s)\n", __func__, (type == rpcrdma_replych) ? "reply" : "write", - seg->mr_len, seg->mr_base, seg->mr_rkey, - n < nsegs ? "more" : "last"); + seg->mr_len, (unsigned long long)seg->mr_base, + seg->mr_rkey, n < nsegs ? "more" : "last"); cur_wchunk++; if (type == rpcrdma_replych) r_xprt->rx_stats.reply_chunk_count++; @@ -257,14 +257,14 @@ rpcrdma_create_chunks(struct rpc_rqst *rqst, struct xdr_buf *target, * finish off header. If write, marshal discrim and nchunks. */ if (cur_rchunk) { - iptr = (u32 *) cur_rchunk; + iptr = (__be32 *) cur_rchunk; *iptr++ = xdr_zero; /* finish the read chunk list */ *iptr++ = xdr_zero; /* encode a NULL write chunk list */ *iptr++ = xdr_zero; /* encode a NULL reply chunk */ } else { warray->wc_discrim = xdr_one; warray->wc_nchunks = htonl(nchunks); - iptr = (u32 *) cur_wchunk; + iptr = (__be32 *) cur_wchunk; if (type == rpcrdma_writech) { *iptr++ = xdr_zero; /* finish the write chunk list */ *iptr++ = xdr_zero; /* encode a NULL reply chunk */ @@ -559,7 +559,7 @@ rpcrdma_marshal_req(struct rpc_rqst *rqst) * RDMA'd by server. See map at rpcrdma_create_chunks()! :-) */ static int -rpcrdma_count_chunks(struct rpcrdma_rep *rep, int max, int wrchunk, u32 **iptrp) +rpcrdma_count_chunks(struct rpcrdma_rep *rep, int max, int wrchunk, __be32 **iptrp) { unsigned int i, total_len; struct rpcrdma_write_chunk *cur_wchunk; @@ -573,11 +573,11 @@ rpcrdma_count_chunks(struct rpcrdma_rep *rep, int max, int wrchunk, u32 **iptrp) struct rpcrdma_segment *seg = &cur_wchunk->wc_target; ifdebug(FACILITY) { u64 off; - xdr_decode_hyper((u32 *)&seg->rs_offset, &off); + xdr_decode_hyper((__be32 *)&seg->rs_offset, &off); dprintk("RPC: %s: chunk %d@0x%llx:0x%x\n", __func__, ntohl(seg->rs_length), - off, + (unsigned long long)off, ntohl(seg->rs_handle)); } total_len += ntohl(seg->rs_length); @@ -585,7 +585,7 @@ rpcrdma_count_chunks(struct rpcrdma_rep *rep, int max, int wrchunk, u32 **iptrp) } /* check and adjust for properly terminated write chunk */ if (wrchunk) { - u32 *w = (u32 *) cur_wchunk; + __be32 *w = (__be32 *) cur_wchunk; if (*w++ != xdr_zero) return -1; cur_wchunk = (struct rpcrdma_write_chunk *) w; @@ -593,7 +593,7 @@ rpcrdma_count_chunks(struct rpcrdma_rep *rep, int max, int wrchunk, u32 **iptrp) if ((char *) cur_wchunk > rep->rr_base + rep->rr_len) return -1; - *iptrp = (u32 *) cur_wchunk; + *iptrp = (__be32 *) cur_wchunk; return total_len; } @@ -721,7 +721,7 @@ rpcrdma_reply_handler(struct rpcrdma_rep *rep) struct rpc_rqst *rqst; struct rpc_xprt *xprt = rep->rr_xprt; struct rpcrdma_xprt *r_xprt = rpcx_to_rdmax(xprt); - u32 *iptr; + __be32 *iptr; int i, rdmalen, status; /* Check status. If bad, signal disconnect and return rep to pool */ @@ -801,7 +801,7 @@ repost: r_xprt->rx_stats.total_rdma_reply += rdmalen; } else { /* else ordinary inline */ - iptr = (u32 *)((unsigned char *)headerp + 28); + iptr = (__be32 *)((unsigned char *)headerp + 28); rep->rr_len -= 28; /*sizeof *headerp;*/ status = rep->rr_len; } @@ -816,7 +816,7 @@ repost: headerp->rm_body.rm_chunks[2] != xdr_one || req->rl_nchunks == 0) goto badheader; - iptr = (u32 *)((unsigned char *)headerp + 28); + iptr = (__be32 *)((unsigned char *)headerp + 28); rdmalen = rpcrdma_count_chunks(rep, req->rl_nchunks, 0, &iptr); if (rdmalen < 0) goto badheader; |